Skip to content

Commit

Permalink
fix: use spending conditions key encoding to properly recover public key
Browse files Browse the repository at this point in the history
  • Loading branch information
reedrosenbluth committed Mar 26, 2021
1 parent 88af9d4 commit a0dbba8
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 17 deletions.
18 changes: 9 additions & 9 deletions packages/transactions/src/authorization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ export function makeSigHashPreSign(

function makeSigHashPostSign(
curSigHash: string,
pubKeyEncoding: PubKeyEncoding,
pubKey: StacksPublicKey,
signature: MessageSignature
): string {
// new hash combines the previous hash and all the new data this signature will add. This
Expand All @@ -376,13 +376,16 @@ function makeSigHashPostSign(
// * the signature
const hashLength = 32 + 1 + RECOVERABLE_ECDSA_SIG_LENGTH_BYTES;

const pubKeyEncoding = isCompressed(pubKey) ? PubKeyEncoding.Compressed : PubKeyEncoding.Uncompressed;

const sigHash = curSigHash + leftPadHex(pubKeyEncoding.toString(16)) + signature.data;

if (Buffer.from(sigHash, 'hex').byteLength > hashLength) {
const sigHashBuffer = Buffer.from(sigHash, 'hex')
if (sigHashBuffer.byteLength > hashLength) {
throw Error('Invalid signature hash length');
}

return txidFromData(Buffer.from(sigHash, 'hex'));
return txidFromData(sigHashBuffer);
}

export function nextSignature(
Expand All @@ -399,10 +402,7 @@ export function nextSignature(

const signature = signWithKey(privateKey, sigHashPreSign);
const publicKey = getPublicKey(privateKey);
const publicKeyEncoding = isCompressed(publicKey)
? PubKeyEncoding.Compressed
: PubKeyEncoding.Uncompressed;
const nextSigHash = makeSigHashPostSign(sigHashPreSign, publicKeyEncoding, signature);
const nextSigHash = makeSigHashPostSign(sigHashPreSign, publicKey, signature);

return {
nextSig: signature,
Expand All @@ -421,9 +421,9 @@ export function nextVerification(
) {
const sigHashPreSign = makeSigHashPreSign(initialSigHash, authType, fee, nonce);

const publicKey = createStacksPublicKey(publicKeyFromSignature(sigHashPreSign, signature));
const publicKey = createStacksPublicKey(publicKeyFromSignature(sigHashPreSign, signature, pubKeyEncoding));

const nextSigHash = makeSigHashPostSign(sigHashPreSign, PubKeyEncoding.Compressed, signature);
const nextSigHash = makeSigHashPostSign(sigHashPreSign, publicKey, signature);

return {
pubKey: publicKey,
Expand Down
2 changes: 1 addition & 1 deletion packages/transactions/src/builders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1136,7 +1136,7 @@ export async function sponsorTransaction(
break;
default:
throw new Error(
`Spnsored transactions not supported for transaction type ${
`Sponsored transactions not supported for transaction type ${
PayloadType[options.transaction.payload.payloadType]
}`
);
Expand Down
19 changes: 12 additions & 7 deletions packages/transactions/src/keys.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
import {
AddressHashMode,
AddressVersion,
COMPRESSED_PUBKEY_LENGTH_BYTES,
UNCOMPRESSED_PUBKEY_LENGTH_BYTES,
StacksMessageType,
AddressHashMode,
TransactionVersion,
PubKeyEncoding,
} from './constants';

import {
BufferArray,
leftPadHexToLength,
intToHexString,
randomBytes,
hash160,
hashP2PKH,
hexStringToInt,
intToHexString,
leftPadHexToLength,
randomBytes,
} from './utils';

import { ec as EC } from 'elliptic';

import { MessageSignature, createMessageSignature } from './authorization';
import { BufferReader } from './bufferReader';
import { AddressVersion } from './constants';
import { c32address } from 'c32check';
import { addressHashModeToVersion, addressFromVersionHash, addressToString } from './types';

Expand Down Expand Up @@ -59,7 +60,7 @@ export function createStacksPublicKey(key: string): StacksPublicKey {
};
}

export function publicKeyFromSignature(message: string, messageSignature: MessageSignature) {
export function publicKeyFromSignature(message: string, messageSignature: MessageSignature, pubKeyEncoding = PubKeyEncoding.Compressed) {
const ec = new EC('secp256k1');
const messageBN = ec.keyFromPrivate(message, 'hex').getPrivate().toString(10);

Expand All @@ -70,7 +71,11 @@ export function publicKeyFromSignature(message: string, messageSignature: Messag
parsedSignature,
parsedSignature.recoveryParam,
'hex'
) as { encodeCompressed: (enc: string) => string };
);

if (pubKeyEncoding == PubKeyEncoding.Uncompressed) {
return publicKey.encode('hex');
}

return publicKey.encodeCompressed('hex');
}
Expand Down

0 comments on commit a0dbba8

Please sign in to comment.