Skip to content

Commit

Permalink
🔏 [FIX]: Trustchain "Expected signature to be an Uint8Array with leng…
Browse files Browse the repository at this point in the history
…th 64" error (#7719)

* Test the verification of problematic signatures
From occasionaly returned from the Apdu device reponses

* Fix the "Expected signature to be an Uint8Array with length 64" error

* Update change log

* Keep `NobleCryptoSecp256k1.derDecode` private

---------

Co-authored-by: Theophile Sandoz <Theophile Sandoz>
  • Loading branch information
thesan authored Sep 2, 2024
1 parent bb1ca23 commit 8e0ac04
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/shaggy-crabs-approve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ledgerhq/hw-trustchain": patch
---

Fix the "Expected signature to be an Uint8Array with length 64" error
18 changes: 17 additions & 1 deletion libs/hw-trustchain/src/NobleCrypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ export class NobleCryptoSecp256k1 implements Crypto {
6 + signature[3],
6 + signature[3] + signature[5 + signature[3]],
);
return { R: R.slice(R.length - PRIVATE_KEY_SIZE), S: S.slice(S.length - PRIVATE_KEY_SIZE) };
return {
R: this.enforceLength(R, PRIVATE_KEY_SIZE),
S: this.enforceLength(S, PRIVATE_KEY_SIZE),
};
}

async sign(message: Uint8Array, keyPair: KeyPair): Promise<Uint8Array> {
Expand Down Expand Up @@ -105,6 +108,19 @@ export class NobleCryptoSecp256k1 implements Crypto {
return c;
}

private enforceLength(buffer: Uint8Array, length: number): Uint8Array {
if (buffer.length > length) {
return buffer.slice(buffer.length - length); // truncate extra bytes from the start
} else if (buffer.length < length) {
const padded = new Uint8Array(length);
const start = length - buffer.length;
padded.set(Array(start).fill(0));
padded.set(buffer, start);
return padded;
}
return buffer;
}

private pad(message: Uint8Array): Uint8Array {
// ISO9797M2 implementation
const padLength = AES_BLOCK_SIZE - (message.length % AES_BLOCK_SIZE);
Expand Down
14 changes: 14 additions & 0 deletions libs/hw-trustchain/src/__tests__/crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,18 @@ describe("Sodium wrapper tester", () => {
const decrypted = await crypto.decryptUserData(keypair.privateKey, encrypted);
expect(crypto.to_hex(decrypted)).toBe(crypto.to_hex(data));
});

it("should verify truncated signature by padding 0s from the start", async () => {
const hash = crypto.from_hex(
"19514a2e50bfad4a6de397ebde776191cbb720e8bbfcc3c165385c3664c03341",
);
const signature = crypto.from_hex(
// Here the "S" part of the signature is only 31 bytes long it should be padded with a 0
"3043022052a82876fcd4d9d8383ce12a7e4d96bb4c1d9e71e857cd087c092b87cec6baeb021f6b86b9a3bab1e7794ca6ef081c66cb6e6dff06cceddbd23e1f25089e311784",
);
const issuer = crypto.from_hex(
"026e7bf1e015da491674be5796b15d6fabd1f454aad478a6a223934e5a872719e0",
);
expect(await crypto.verify(hash, signature, issuer)).toBe(true);
});
});

0 comments on commit 8e0ac04

Please sign in to comment.