Skip to content

Commit b3566c1

Browse files
chore: Use SHA-256 utility (#1406)
Use `sha256` utility from `metamask/utils` which has the same implementation. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Switch hashing to `@metamask/utils` `sha256` in signing and verification, removing fallback logic/tests and bumping the utils dependency. > > - **Crypto/Verification**: > - Replace custom/`@noble/hashes` SHA-256 with `sha256` from `@metamask/utils` in `src/verify.ts` and `scripts/sign-registry.ts`. > - Remove internal `sha256` helper and noble imports; adjust signing to hash file bytes before `secp256k1.sign`. > - **Tests**: > - Delete fallback digest tests; retain signature validity tests in `src/verify.test.ts`. > - **Dependencies**: > - Bump `@metamask/utils` to `^11.9.0`. > - Remove `@noble/hashes` from `dependencies` and update lockfile. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 19c4a7d. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 5b73802 commit b3566c1

File tree

5 files changed

+21
-76
lines changed

5 files changed

+21
-76
lines changed

package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,8 @@
3232
},
3333
"dependencies": {
3434
"@metamask/superstruct": "^3.2.1",
35-
"@metamask/utils": "^11.4.0",
36-
"@noble/curves": "^1.2.0",
37-
"@noble/hashes": "^1.3.2"
35+
"@metamask/utils": "^11.9.0",
36+
"@noble/curves": "^1.2.0"
3837
},
3938
"devDependencies": {
4039
"@lavamoat/allow-scripts": "^2.3.1",

scripts/sign-registry.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import {
44
bytesToHex,
55
hexToBytes,
66
isHexString,
7+
sha256,
78
} from '@metamask/utils';
89
import { secp256k1 } from '@noble/curves/secp256k1';
9-
import { sha256 } from '@noble/hashes/sha256';
1010
import * as dotenv from 'dotenv';
1111
import { promises as fs } from 'fs';
1212
import path from 'path';
@@ -66,9 +66,9 @@ async function main() {
6666

6767
const registry = await fs.readFile(registryPath);
6868

69-
const signature = add0x(
70-
secp256k1.sign(sha256(registry), privateKeyBytes).toDERHex(),
71-
);
69+
const hash = await sha256(new Uint8Array(registry));
70+
71+
const signature = add0x(secp256k1.sign(hash, privateKeyBytes).toDERHex());
7272

7373
const signatureObject = format(
7474
JSON.stringify({

src/verify.test.ts

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import * as nobleHashes from '@noble/hashes/sha256';
2-
31
import { verify } from './verify';
42

53
const MOCK_REGISTRY = `test\n`;
@@ -64,44 +62,6 @@ describe('verify', () => {
6462
).toBe(true);
6563
});
6664

67-
it('falls back to noble when digest function is unavailable', async () => {
68-
const nobleSpy = jest.spyOn(nobleHashes, 'sha256');
69-
70-
Object.defineProperty(globalThis.crypto.subtle, 'digest', {
71-
value: undefined,
72-
writable: true,
73-
});
74-
75-
expect(
76-
await verify({
77-
registry: MOCK_REGISTRY,
78-
signature: MOCK_SIGNATURE,
79-
publicKey: MOCK_PUBLIC_KEY,
80-
}),
81-
).toBe(true);
82-
83-
expect(nobleSpy).toHaveBeenCalled();
84-
});
85-
86-
it('falls back to noble when subtle APIs are unavailable', async () => {
87-
const nobleSpy = jest.spyOn(nobleHashes, 'sha256');
88-
89-
Object.defineProperty(globalThis.crypto, 'subtle', {
90-
value: undefined,
91-
writable: true,
92-
});
93-
94-
expect(
95-
await verify({
96-
registry: MOCK_REGISTRY,
97-
signature: MOCK_SIGNATURE,
98-
publicKey: MOCK_PUBLIC_KEY,
99-
}),
100-
).toBe(true);
101-
102-
expect(nobleSpy).toHaveBeenCalled();
103-
});
104-
10565
it('rejects an invalid signature', async () => {
10666
expect(
10767
await verify({

src/verify.ts

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import {
77
stringToBytes,
88
assertStruct,
99
hexToBytes,
10+
sha256,
1011
} from '@metamask/utils';
1112
import { secp256k1 } from '@noble/curves/secp256k1';
12-
import { sha256 as nobleSha256 } from '@noble/hashes/sha256';
1313

1414
export const SignatureStruct = object({
1515
signature: StrictHexStruct,
@@ -25,28 +25,6 @@ type VerifyArgs = {
2525
publicKey: Hex;
2626
};
2727

28-
/**
29-
* Compute a SHA-256 digest for a given byte array.
30-
*
31-
* Uses the native crypto implementation and falls back to noble.
32-
*
33-
* @param bytes - A byte array.
34-
* @returns The SHA-256 hash as a byte array.
35-
*/
36-
async function sha256(bytes: Uint8Array): Promise<Uint8Array> {
37-
// Use crypto.subtle.digest whenever possible as it is faster.
38-
if (
39-
'crypto' in globalThis &&
40-
typeof globalThis.crypto === 'object' &&
41-
// eslint-disable-next-line no-restricted-globals
42-
crypto.subtle?.digest
43-
) {
44-
// eslint-disable-next-line no-restricted-globals
45-
return new Uint8Array(await crypto.subtle.digest('SHA-256', bytes));
46-
}
47-
return nobleSha256(bytes);
48-
}
49-
5028
/**
5129
* Verifies that the Snap Registry is properly signed using a cryptographic key.
5230
*

yarn.lock

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,9 +1303,8 @@ __metadata:
13031303
"@metamask/snaps-sdk": ^8.1.0
13041304
"@metamask/snaps-utils": ^10.1.0
13051305
"@metamask/superstruct": ^3.2.1
1306-
"@metamask/utils": ^11.4.0
1306+
"@metamask/utils": ^11.9.0
13071307
"@noble/curves": ^1.2.0
1308-
"@noble/hashes": ^1.3.2
13091308
"@types/jest": ^28.1.6
13101309
"@types/node": ^17.0.23
13111310
"@typescript-eslint/eslint-plugin": ^5.43.0
@@ -1401,20 +1400,22 @@ __metadata:
14011400
languageName: node
14021401
linkType: hard
14031402

1404-
"@metamask/utils@npm:^11.0.1, @metamask/utils@npm:^11.1.0, @metamask/utils@npm:^11.2.0, @metamask/utils@npm:^11.4.0":
1405-
version: 11.4.0
1406-
resolution: "@metamask/utils@npm:11.4.0"
1403+
"@metamask/utils@npm:^11.0.1, @metamask/utils@npm:^11.1.0, @metamask/utils@npm:^11.2.0, @metamask/utils@npm:^11.4.0, @metamask/utils@npm:^11.9.0":
1404+
version: 11.9.0
1405+
resolution: "@metamask/utils@npm:11.9.0"
14071406
dependencies:
14081407
"@ethereumjs/tx": ^4.2.0
14091408
"@metamask/superstruct": ^3.1.0
14101409
"@noble/hashes": ^1.3.1
14111410
"@scure/base": ^1.1.3
14121411
"@types/debug": ^4.1.7
1412+
"@types/lodash": ^4.17.20
14131413
debug: ^4.3.4
1414+
lodash: ^4.17.21
14141415
pony-cause: ^2.1.10
14151416
semver: ^7.5.4
14161417
uuid: ^9.0.1
1417-
checksum: 18f4ac60221b4651a4c64fe9b2985092537248662634e8c6757afaef752b9dc400bd13fb7f4e8172823f5e5ec96ea129d7622c0fb2f3b9abfec2af8b466fff92
1418+
checksum: 467d9c1835dfe9bf9f67af0e0a472ca1805aa7f7a3969f439e4d14d9db2fa9c8da7611c8299c81f65ef6a63cb72725b227bac28080ed467375115c3ad6227d7a
14181419
languageName: node
14191420
linkType: hard
14201421

@@ -1793,6 +1794,13 @@ __metadata:
17931794
languageName: node
17941795
linkType: hard
17951796

1797+
"@types/lodash@npm:^4.17.20":
1798+
version: 4.17.21
1799+
resolution: "@types/lodash@npm:4.17.21"
1800+
checksum: e09e3eaf29b18b6c8e130fcbafd8e3c4ecc2110f35255079245e7d1bd310a5a8f93e4e70266533dce672f253bba899c721bc6870097e0a8c5448e0b628136d39
1801+
languageName: node
1802+
linkType: hard
1803+
17961804
"@types/ms@npm:*":
17971805
version: 0.7.34
17981806
resolution: "@types/ms@npm:0.7.34"

0 commit comments

Comments
 (0)