Skip to content

Commit

Permalink
separate ecdsa padding code
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewCLu committed Feb 5, 2024
1 parent 7de130e commit 6be9903
Showing 1 changed file with 21 additions and 13 deletions.
34 changes: 21 additions & 13 deletions packages/lib/src/ecdsa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,28 @@ export const getECDSAMessageHash = (msg: string | Buffer): string => {
const truncatedBits = hashBits.slice(0, babyjubjub.scalarFieldBitLength);
const msgHash = BigInt("0b" + truncatedBits);

// This addresses a quirk of the ellptic.js library where
// the message hash is truncated oddly. For some reason, the
// truncation is based on the byte length of the message hash * 8
// rather than the bit length, which means the truncation is
// incorrect when we have a message hash that is not a multiple
// of 8 bits. This addresses that issue by padding the message
// with some zeros which will be truncated by the library.
// https://github.com/indutny/elliptic/blob/43ac7f230069bd1575e1e4a58394a512303ba803/lib/elliptic/ec/index.js#L82
let msgHashPadded = msgHash;
const msgHashBN = new BN(bigIntToHex(msgHash), 16);
return bigIntToHex(msgHash);
};

// This addresses a quirk of the ellptic.js library where
// the message hash is truncated oddly. For some reason, the
// truncation is based on the byte length of the message hash * 8
// rather than the bit length, which means the truncation is
// incorrect when we have a message hash that is not a multiple
// of 8 bits. This addresses that issue by padding the message
// with some zeros which will be truncated by the library.
// https://github.com/indutny/elliptic/blob/43ac7f230069bd1575e1e4a58394a512303ba803/lib/elliptic/ec/index.js#L82
const padECDSAMessageHash = (msgHash: string): string => {
let msgHashPadded = hexToBigInt(msgHash);
const msgHashBN = new BN(msgHash, 16);
const delta = msgHashBN.byteLength() * 8 - babyjubjub.ec.n.bitLength();

// Given that we expect the message hash to be truncated to at most 251 bits,
// the following condition is only true if delta is equal to 5
if (delta > 0) {
msgHashPadded = BigInt("0b" + msgHash.toString(2) + "0".repeat(delta));
msgHashPadded = BigInt(
"0b" + msgHashPadded.toString(2) + "0".repeat(delta)
);
}

return bigIntToHex(msgHashPadded);
Expand Down Expand Up @@ -80,7 +86,8 @@ export const generateSignatureKeyPair = (): {
export const sign = (signingKey: string, data: string | Buffer): string => {
const key = babyjubjub.ec.keyFromPrivate(signingKey, "hex");
const msgHash = getECDSAMessageHash(data);
const signature = key.sign(msgHash, "hex", {
const paddedMsgHash = padECDSAMessageHash(msgHash); // See comment on padECDSAMessageHash - only needed for elliptic.js
const signature = key.sign(paddedMsgHash, "hex", {
canonical: true,
});
const signatureDER = signature.toDER();
Expand All @@ -101,9 +108,10 @@ export const verify = (
): boolean => {
const key = babyjubjub.ec.keyFromPublic(verifyingKey, "hex");
const msgHash = getECDSAMessageHash(data);
const paddedMsgHash = padECDSAMessageHash(msgHash); // See comment on padECDSAMessageHash - only needed for elliptic.js
const sig = derDecodeSignature(signature);
return babyjubjub.ec.verify(
msgHash,
paddedMsgHash,
new ECSignature({
r: sig.r.toString(16),
s: sig.s.toString(16),
Expand Down

0 comments on commit 6be9903

Please sign in to comment.