Skip to content

Commit

Permalink
fix(message-signing): add working utility fn
Browse files Browse the repository at this point in the history
  • Loading branch information
kyranjamie authored and janniks committed May 19, 2022
1 parent 8ad4d83 commit 20b721c
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 15 deletions.
1 change: 1 addition & 0 deletions packages/common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export * from './fetchUtil';
export * from './logger';
export * from './utils';
export * from './constants';
export * from './signatures';
export * from './keys';
16 changes: 16 additions & 0 deletions packages/common/src/signatures.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { hexToInt } from './utils';

export function parseRecoverableSignature(signature: string) {
const coordinateValueBytes = 32;
if (signature.length < coordinateValueBytes * 2 * 2 + 1) {
throw new Error('Invalid signature');
}
const recoveryParamHex = signature.substr(0, 2);
const r = signature.substr(2, coordinateValueBytes * 2);
const s = signature.substr(2 + coordinateValueBytes * 2, coordinateValueBytes * 2);
return {
recoveryParam: hexToInt(recoveryParamHex),
r,
s,
};
}
33 changes: 32 additions & 1 deletion packages/encryption/src/ec.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
import { hmac } from '@noble/hashes/hmac';
import { sha256 } from '@noble/hashes/sha256';
import { getPublicKey, getSharedSecret, Point, signSync, utils, verify } from '@noble/secp256k1';
import {
Signature,
getPublicKey,
getSharedSecret,
Point,
signSync,
utils,
verify,
} from '@noble/secp256k1';
import {
Buffer,
toBuffer,
FailedDecryptionError,
concatBytes,
hexToBytes,
bytesToHex,
hexToBigInt,
parseRecoverableSignature,
} from '@stacks/common';
import { createCipher } from './aesCipher';
import { createHmacSha256 } from './hmacSha256';
import { getPublicKeyFromPrivate } from './keys';
import { hashMessage } from './messageSignature';
import { hashSha256Sync, hashSha512Sync } from './sha2Hash';
import { getAesCbcOutputLength, getBase64OutputLength } from './utils';

Expand Down Expand Up @@ -502,3 +513,23 @@ export function verifyECDSA(
const contentHash = hashSha256Sync(contentBuffer);
return verify(signature, contentHash, publicKey);
}

interface VerifyMessageSignatureArgs {
signature: string;
message: string | Buffer;
publicKey: string;
}

/**
* Verify message signature with recoverable public key
*/
export function verifyMessageSignature({
signature,
message,
publicKey,
}: VerifyMessageSignatureArgs) {
const { r, s } = parseRecoverableSignature(signature);
const sig = new Signature(hexToBigInt(r), hexToBigInt(s));
const hashedMsg = typeof message === 'string' ? hashMessage(message) : message;
return verify(sig, hashedMsg, publicKey);
}
20 changes: 6 additions & 14 deletions packages/transactions/src/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
intToHex,
privateKeyToBuffer,
PRIVATE_KEY_COMPRESSED_LENGTH,
parseRecoverableSignature as parseRecoverableSignatureFromCommon,
} from '@stacks/common';
import { c32address } from 'c32check';
import { BufferReader } from './bufferReader';
Expand Down Expand Up @@ -179,20 +180,11 @@ export function getSignatureRecoveryParam(signature: string) {
return hexToInt(recoveryParamHex);
}

export function parseRecoverableSignature(signature: string) {
const coordinateValueBytes = 32;
if (signature.length < coordinateValueBytes * 2 * 2 + 1) {
throw new Error('Invalid signature');
}
const recoveryParamHex = signature.substr(0, 2);
const r = signature.substr(2, coordinateValueBytes * 2);
const s = signature.substr(2 + coordinateValueBytes * 2, coordinateValueBytes * 2);
return {
recoveryParam: hexToInt(recoveryParamHex),
r,
s,
};
}
/**
* @deprecated
* This method is now exported from `@stacks/common` {@link parseRecoverableSignature}
*/
export const parseRecoverableSignature = parseRecoverableSignatureFromCommon;

export function getPublicKey(privateKey: StacksPrivateKey): StacksPublicKey {
return pubKeyfromPrivKey(privateKey.data);
Expand Down

1 comment on commit 20b721c

@vercel
Copy link

@vercel vercel bot commented on 20b721c May 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.