diff --git a/CHANGELOG.md b/CHANGELOG.md index a16d93892..00ac08b56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,8 @@ Changes: - Adjust `isBigInt` to not do `instanceof` check - Use `@polkadot/x-bigint` for `BigInt` constructor -- Split `@noble/hashes` fork into `x-noble-hashes` (with above `BigInt`) +- Split `@noble/hashes` fork into `x-noble-hashes` (w/ above `BigInt`) +- Add `@noble/hashes` fork as `x-noble-secp256k1` (w/ above `BigInt`), replaces `elliptic` - Ensure consequtive capitals in `stringCamelCase` are lowercased diff --git a/packages/util-crypto/package.json b/packages/util-crypto/package.json index db048af38..82db735a3 100644 --- a/packages/util-crypto/package.json +++ b/packages/util-crypto/package.json @@ -31,22 +31,20 @@ "dependencies": { "@babel/runtime": "^7.16.3", "@noble/hashes": "0.4.1", + "@noble/secp256k1": "^1.3.0", "@polkadot/networks": "8.0.6-14", "@polkadot/util": "8.0.6-14", "@polkadot/wasm-crypto": "^4.5.1", "@polkadot/x-bigint": "8.0.6-14", "@polkadot/x-noble-hashes": "8.0.6-14", + "@polkadot/x-noble-secp256k1": "8.0.6-14", "@polkadot/x-randomvalues": "8.0.6-14", - "bn.js": "^4.12.0", "ed2curve": "^0.3.0", - "elliptic": "^6.5.4", "micro-base": "^0.9.0", "tweetnacl": "^1.0.3" }, "devDependencies": { - "@types/bn.js": "^4.11.6", - "@types/ed2curve": "^0.2.2", - "@types/elliptic": "^6.4.14" + "@types/ed2curve": "^0.2.2" }, "peerDependencies": { "@polkadot/util": "8.0.6-14" diff --git a/packages/util-crypto/src/address/evmToAddress.ts b/packages/util-crypto/src/address/evmToAddress.ts index 1fd25f112..a822320c4 100644 --- a/packages/util-crypto/src/address/evmToAddress.ts +++ b/packages/util-crypto/src/address/evmToAddress.ts @@ -5,9 +5,9 @@ import type { HexString } from '@polkadot/util/types'; import type { HashType } from '../secp256k1/types'; import type { Prefix } from './types'; -import { u8aConcat } from '@polkadot/util'; +import { assert, u8aConcat } from '@polkadot/util'; -import { secp256k1Hasher } from '../secp256k1/hasher'; +import { hasher } from '../secp256k1/hasher'; import { encodeAddress } from './encode'; /** @@ -15,15 +15,9 @@ import { encodeAddress } from './encode'; * @summary Converts an EVM address to its corresponding SS58 address. */ export function evmToAddress (evmAddress: HexString | string | Uint8Array, ss58Format?: Prefix, hashType: HashType = 'blake2'): string { - const wrapError = (message: string) => `Converting ${evmAddress as string}: ${message}`; - const message = u8aConcat('evm:', evmAddress); - if (message.length !== 24) { - throw new Error(wrapError('Invalid evm address length')); - } + assert(message.length === 24, () => `Converting ${evmAddress as string}: Invalid evm address length`); - const address = secp256k1Hasher(hashType, message); - - return encodeAddress(address, ss58Format); + return encodeAddress(hasher(hashType, message), ss58Format); } diff --git a/packages/util-crypto/src/cryptoInit.ts b/packages/util-crypto/src/cryptoInit.ts index ea6ce7512..f8fb514ba 100644 --- a/packages/util-crypto/src/cryptoInit.ts +++ b/packages/util-crypto/src/cryptoInit.ts @@ -1,7 +1,16 @@ // Copyright 2017-2021 @polkadot/util-crypto authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { u8aConcat } from '@polkadot/util'; +import { utils as utilsNobleSecp256k1 } from '@polkadot/x-noble-secp256k1'; + import { cryptoWaitReady } from './crypto'; +import { hmacSha256AsU8a } from './hmac'; + +// Set overrides on the secp256k1 utils +// - hmacShaSync - This needs to be set, unset by default +utilsNobleSecp256k1.hmacSha256Sync = (key: Uint8Array, ...messages: Uint8Array[]) => + hmacSha256AsU8a(key, u8aConcat(...messages)); // start init process immediately cryptoWaitReady().catch((): void => { diff --git a/packages/util-crypto/src/secp256k1/compress.ts b/packages/util-crypto/src/secp256k1/compress.ts index 3938f92c3..f24ae8a5e 100644 --- a/packages/util-crypto/src/secp256k1/compress.ts +++ b/packages/util-crypto/src/secp256k1/compress.ts @@ -1,10 +1,9 @@ // Copyright 2017-2021 @polkadot/util-crypto authors & contributors // SPDX-License-Identifier: Apache-2.0 -import { assert } from '@polkadot/util'; +import { assert, hasBigInt } from '@polkadot/util'; import { isReady, secp256k1Compress as wasm } from '@polkadot/wasm-crypto'; - -import { secp256k1 } from './secp256k1'; +import { Point } from '@polkadot/x-noble-secp256k1'; export function secp256k1Compress (publicKey: Uint8Array, onlyJs?: boolean): Uint8Array { if (publicKey.length === 33) { @@ -13,12 +12,7 @@ export function secp256k1Compress (publicKey: Uint8Array, onlyJs?: boolean): Uin assert(publicKey.length === 65, 'Invalid publicKey provided'); - return !onlyJs && isReady() + return !hasBigInt || (!onlyJs && isReady()) ? wasm(publicKey) - : new Uint8Array( - secp256k1 - .keyFromPublic(publicKey) - .getPublic() - .encodeCompressed() - ); + : Point.fromHex(publicKey).toRawBytes(true); } diff --git a/packages/util-crypto/src/secp256k1/expand.ts b/packages/util-crypto/src/secp256k1/expand.ts index 10e76dbcb..a61e707e9 100644 --- a/packages/util-crypto/src/secp256k1/expand.ts +++ b/packages/util-crypto/src/secp256k1/expand.ts @@ -1,11 +1,11 @@ // Copyright 2017-2021 @polkadot/util-crypto authors & contributors // SPDX-License-Identifier: Apache-2.0 -import { assert, bnToU8a, u8aConcat } from '@polkadot/util'; +import { assert, bnToU8a, hasBigInt, u8aConcat } from '@polkadot/util'; import { isReady, secp256k1Expand as wasm } from '@polkadot/wasm-crypto'; +import { Point } from '@polkadot/x-noble-secp256k1'; import { BN_BE_256_OPTS } from '../bn'; -import { secp256k1 } from './secp256k1'; export function secp256k1Expand (publicKey: Uint8Array, onlyJs?: boolean): Uint8Array { if (publicKey.length === 65) { @@ -14,16 +14,14 @@ export function secp256k1Expand (publicKey: Uint8Array, onlyJs?: boolean): Uint8 assert(publicKey.length === 33, 'Invalid publicKey provided'); - if (!onlyJs && isReady()) { + if (!hasBigInt || (!onlyJs && isReady())) { return wasm(publicKey).subarray(1); } - const expanded = secp256k1 - .keyFromPublic(publicKey) - .getPublic(); + const { x, y } = Point.fromHex(publicKey); return u8aConcat( - bnToU8a(expanded.getX(), BN_BE_256_OPTS), - bnToU8a(expanded.getY(), BN_BE_256_OPTS) + bnToU8a(x, BN_BE_256_OPTS), + bnToU8a(y, BN_BE_256_OPTS) ); } diff --git a/packages/util-crypto/src/secp256k1/hasher.spec.ts b/packages/util-crypto/src/secp256k1/hasher.spec.ts index 807bda3a8..113c591a8 100644 --- a/packages/util-crypto/src/secp256k1/hasher.spec.ts +++ b/packages/util-crypto/src/secp256k1/hasher.spec.ts @@ -1,12 +1,12 @@ // Copyright 2017-2021 @polkadot/util-crypto authors & contributors // SPDX-License-Identifier: Apache-2.0 -import { secp256k1Hasher } from './hasher'; +import { hasher } from './hasher'; -describe('secp256k1Hasher', (): void => { +describe('hasher', (): void => { it('creates a blake2 hash', (): void => { expect( - secp256k1Hasher('blake2', 'abc') + hasher('blake2', 'abc') ).toEqual( new Uint8Array([189, 221, 129, 60, 99, 66, 57, 114, 49, 113, 239, 63, 238, 152, 87, 155, 148, 150, 78, 59, 177, 203, 62, 66, 114, 98, 200, 192, 104, 213, 35, 25]) ); @@ -14,7 +14,7 @@ describe('secp256k1Hasher', (): void => { it('creates a keccak hash', (): void => { expect( - secp256k1Hasher('keccak', 'abc') + hasher('keccak', 'abc') ).toEqual( new Uint8Array([78, 3, 101, 122, 234, 69, 169, 79, 199, 212, 123, 168, 38, 200, 214, 103, 192, 209, 230, 227, 58, 100, 160, 54, 236, 68, 245, 143, 161, 45, 108, 69]) ); diff --git a/packages/util-crypto/src/secp256k1/hasher.ts b/packages/util-crypto/src/secp256k1/hasher.ts index a00524382..e526d07e8 100644 --- a/packages/util-crypto/src/secp256k1/hasher.ts +++ b/packages/util-crypto/src/secp256k1/hasher.ts @@ -6,7 +6,7 @@ import type { HashType } from './types'; import { blake2AsU8a } from '../blake2'; import { keccakAsU8a } from '../keccak'; -export function secp256k1Hasher (hashType: HashType, data: Uint8Array | string, onlyJs?: boolean): Uint8Array { +export function hasher (hashType: HashType, data: Uint8Array | string, onlyJs?: boolean): Uint8Array { return hashType === 'keccak' ? keccakAsU8a(data, undefined, onlyJs) : blake2AsU8a(data, undefined, undefined, onlyJs); diff --git a/packages/util-crypto/src/secp256k1/pair/fromSeed.ts b/packages/util-crypto/src/secp256k1/pair/fromSeed.ts index b7ca7ee13..a860a9b38 100644 --- a/packages/util-crypto/src/secp256k1/pair/fromSeed.ts +++ b/packages/util-crypto/src/secp256k1/pair/fromSeed.ts @@ -3,11 +3,9 @@ import type { Keypair } from '../../types'; -import { assert, bnToU8a } from '@polkadot/util'; +import { assert, hasBigInt } from '@polkadot/util'; import { isReady, secp256k1FromSeed } from '@polkadot/wasm-crypto'; - -import { BN_BE_256_OPTS } from '../../bn'; -import { secp256k1 } from '../secp256k1'; +import { getPublicKey } from '@polkadot/x-noble-secp256k1'; /** * @name secp256k1PairFromSeed @@ -16,7 +14,7 @@ import { secp256k1 } from '../secp256k1'; export function secp256k1PairFromSeed (seed: Uint8Array, onlyJs?: boolean): Keypair { assert(seed.length === 32, 'Expected valid 32-byte private key as a seed'); - if (!onlyJs && isReady()) { + if (!hasBigInt || (!onlyJs && isReady())) { const full = secp256k1FromSeed(seed); return { @@ -25,10 +23,8 @@ export function secp256k1PairFromSeed (seed: Uint8Array, onlyJs?: boolean): Keyp }; } - const key = secp256k1.keyFromPrivate(seed); - return { - publicKey: new Uint8Array(key.getPublic().encodeCompressed()), - secretKey: bnToU8a(key.getPrivate(), BN_BE_256_OPTS) + publicKey: getPublicKey(seed, true), + secretKey: seed }; } diff --git a/packages/util-crypto/src/secp256k1/recover.ts b/packages/util-crypto/src/secp256k1/recover.ts index 78ef502da..1e9d3afd3 100644 --- a/packages/util-crypto/src/secp256k1/recover.ts +++ b/packages/util-crypto/src/secp256k1/recover.ts @@ -1,28 +1,26 @@ // Copyright 2017-2021 @polkadot/util-crypto authors & contributors // SPDX-License-Identifier: Apache-2.0 +import type { HexString } from '@polkadot/util/types'; import type { HashType } from './types'; -import { assert } from '@polkadot/util'; +import { assert, hasBigInt, u8aToU8a } from '@polkadot/util'; import { isReady, secp256k1Recover as wasm } from '@polkadot/wasm-crypto'; +import { recoverPublicKey, Signature } from '@polkadot/x-noble-secp256k1'; import { secp256k1Compress } from './compress'; import { secp256k1Expand } from './expand'; -import { secp256k1 } from './secp256k1'; /** * @name secp256k1Recover * @description Recovers a publicKey from the supplied signature */ -export function secp256k1Recover (message: Uint8Array, signature: Uint8Array, recovery: number, hashType: HashType = 'blake2', onlyJs?: boolean): Uint8Array { - const publicKey = !onlyJs && isReady() - ? wasm(message, signature.slice(0, 64), recovery) - : new Uint8Array( - // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-argument - secp256k1 - .recoverPubKey(message, { r: signature.slice(0, 32), s: signature.slice(32, 64) }, recovery) - .encode(null, true) - ); +export function secp256k1Recover (msgHash: HexString | Uint8Array | string, signature: HexString | Uint8Array | string, recovery: number, hashType: HashType = 'blake2', onlyJs?: boolean): Uint8Array { + const sig = u8aToU8a(signature).subarray(0, 64); + const msg = u8aToU8a(msgHash); + const publicKey = !hasBigInt || (!onlyJs && isReady()) + ? wasm(msg, sig, recovery) + : recoverPublicKey(msg, Signature.fromCompact(sig).toRawBytes(), recovery); assert(publicKey, 'Unable to recover publicKey from signature'); diff --git a/packages/util-crypto/src/secp256k1/secp256k1.ts b/packages/util-crypto/src/secp256k1/secp256k1.ts deleted file mode 100644 index 9180efbb1..000000000 --- a/packages/util-crypto/src/secp256k1/secp256k1.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2017-2021 @polkadot/util-crypto authors & contributors -// SPDX-License-Identifier: Apache-2.0 - -import elliptic from 'elliptic'; - -// eslint-disable-next-line new-cap -export const secp256k1 = new elliptic.ec('secp256k1'); diff --git a/packages/util-crypto/src/secp256k1/sign.spec.ts b/packages/util-crypto/src/secp256k1/sign.spec.ts index fb7926057..ead119a58 100644 --- a/packages/util-crypto/src/secp256k1/sign.spec.ts +++ b/packages/util-crypto/src/secp256k1/sign.spec.ts @@ -5,7 +5,7 @@ import { hexToU8a } from '@polkadot/util'; import { waitReady } from '@polkadot/wasm-crypto'; import { performanceWasm } from '../../test/performance'; -import { secp256k1PairFromSeed, secp256k1Recover, secp256k1Sign } from '.'; +import { secp256k1PairFromSeed, secp256k1Sign } from '.'; const pair = secp256k1PairFromSeed(hexToU8a('0x4380de832af797688026ce24f85204d508243f201650c1a134929e5458b7fbae')); const msg = hexToU8a('0xa30b64ce1eedf409c8afb801d72c05234e64849ea538c15dd3c8cf4ffcf166c9'); @@ -20,19 +20,16 @@ describe('sign', (): void => { expect( secp256k1Sign(msg, pair, undefined, onlyJs) ).toEqual(hexToU8a( - // as of libsecp256k1 0.7.0 the wasm yields different s & v values - onlyJs - ? '0xdf92f73d9f060cefacf187b5414491cb992998ace017fa48839b5cda3e264ba8c4efa521361678d9b8582744d77aa4b8d886d7380b7808a683174afad9c4700300' - : '0xdf92f73d9f060cefacf187b5414491cb992998ace017fa48839b5cda3e264ba83b105adec9e9872647a7d8bb28855b45e22805aea3d097953cbb1391f671d13e01' + // from elliptic, this is - 0xdf92f73d9f060cefacf187b5414491cb992998ace017fa48839b5cda3e264ba8c4efa521361678d9b8582744d77aa4b8d886d7380b7808a683174afad9c4700300 + // libsecp256k1 & @noble/hashes do agree here... + '0xdf92f73d9f060cefacf187b5414491cb992998ace017fa48839b5cda3e264ba83b105adec9e9872647a7d8bb28855b45e22805aea3d097953cbb1391f671d13e01' )); }); }); // since the libsecp256k1 signatures don't match (but can be verified), we // do both signing and verification here (checking the extracted key) - performanceWasm('secp256k1Sign/Verify', 100, (_, onlyJs) => { - const sig = secp256k1Sign(msg, pair, undefined, onlyJs); - - return secp256k1Recover(msg, sig, sig[64], undefined, onlyJs); - }); + performanceWasm('secp256k1Sign', 1000, (_, onlyJs) => + secp256k1Sign(msg, pair, undefined, onlyJs) + ); }); diff --git a/packages/util-crypto/src/secp256k1/sign.ts b/packages/util-crypto/src/secp256k1/sign.ts index 21bc55d97..ea78cb1e5 100644 --- a/packages/util-crypto/src/secp256k1/sign.ts +++ b/packages/util-crypto/src/secp256k1/sign.ts @@ -4,12 +4,12 @@ import type { Keypair } from '../types'; import type { HashType } from './types'; -import { assert, bnToU8a, u8aConcat } from '@polkadot/util'; +import { assert, bnToU8a, hasBigInt, u8aConcat } from '@polkadot/util'; import { isReady, secp256k1Sign as wasm } from '@polkadot/wasm-crypto'; +import { Signature, signSync } from '@polkadot/x-noble-secp256k1'; import { BN_BE_256_OPTS } from '../bn'; -import { secp256k1Hasher } from './hasher'; -import { secp256k1 } from './secp256k1'; +import { hasher } from './hasher'; /** * @name secp256k1Sign @@ -18,18 +18,18 @@ import { secp256k1 } from './secp256k1'; export function secp256k1Sign (message: Uint8Array | string, { secretKey }: Partial, hashType: HashType = 'blake2', onlyJs?: boolean): Uint8Array { assert(secretKey?.length === 32, 'Expected valid secp256k1 secretKey, 32-bytes'); - const data = secp256k1Hasher(hashType, message, onlyJs); + const data = hasher(hashType, message, onlyJs); - if (!onlyJs && isReady()) { + if (!hasBigInt || (!onlyJs && isReady())) { return wasm(data, secretKey); } - const key = secp256k1.keyFromPrivate(secretKey); - const ecsig = key.sign(data); + const [sigBytes, recoveryParam] = signSync(data, secretKey, { canonical: true, recovered: true }); + const { r, s } = Signature.fromHex(sigBytes); return u8aConcat( - bnToU8a(ecsig.r, BN_BE_256_OPTS), - bnToU8a(ecsig.s, BN_BE_256_OPTS), - new Uint8Array([ecsig.recoveryParam || 0]) + bnToU8a(r, BN_BE_256_OPTS), + bnToU8a(s, BN_BE_256_OPTS), + new Uint8Array([recoveryParam || 0]) ); } diff --git a/packages/util-crypto/src/secp256k1/signVerify.spec.ts b/packages/util-crypto/src/secp256k1/signVerify.spec.ts index 8be13805d..634c79c23 100644 --- a/packages/util-crypto/src/secp256k1/signVerify.spec.ts +++ b/packages/util-crypto/src/secp256k1/signVerify.spec.ts @@ -1,10 +1,12 @@ // Copyright 2017-2021 @polkadot/util-crypto authors & contributors // SPDX-License-Identifier: Apache-2.0 +import '../cryptoInit'; + import { stringToU8a } from '@polkadot/util'; import { randomAsU8a } from '../random/asU8a'; -import { secp256k1Hasher } from './hasher'; +import { hasher } from './hasher'; import { secp256k1Expand, secp256k1PairFromSeed, secp256k1Sign, secp256k1Verify } from '.'; const MESSAGE = stringToU8a('this is a message'); @@ -27,7 +29,7 @@ describe('sign and verify', (): void => { it('signs/verifies a message by random key (blake2)', (): void => { const pair = secp256k1PairFromSeed(randomAsU8a()); const signature = secp256k1Sign(MESSAGE, pair); - const address = secp256k1Hasher('blake2', pair.publicKey); + const address = hasher('blake2', pair.publicKey); expect(secp256k1Verify(MESSAGE, signature, address)).toEqual(true); }); @@ -35,7 +37,7 @@ describe('sign and verify', (): void => { it('signs/verifies a message by random key (keccak)', (): void => { const pair = secp256k1PairFromSeed(randomAsU8a()); const signature = secp256k1Sign(MESSAGE, pair, 'keccak'); - const address = secp256k1Hasher('keccak', secp256k1Expand(pair.publicKey)); + const address = hasher('keccak', secp256k1Expand(pair.publicKey)); expect(secp256k1Verify(MESSAGE, signature, address, 'keccak')).toEqual(true); }); @@ -43,7 +45,7 @@ describe('sign and verify', (): void => { it('fails verification on hasher mismatches', (): void => { const pair = secp256k1PairFromSeed(randomAsU8a()); const signature = secp256k1Sign(MESSAGE, pair, 'keccak'); - const address = secp256k1Hasher('keccak', secp256k1Expand(pair.publicKey)); + const address = hasher('keccak', secp256k1Expand(pair.publicKey)); expect(secp256k1Verify(MESSAGE, signature, address, 'blake2')).toEqual(false); }); @@ -57,7 +59,7 @@ describe('sign and verify', (): void => { secp256k1Verify( MESSAGE, secp256k1Sign(MESSAGE, pair, 'blake2'), - secp256k1Hasher('blake2', pair.publicKey), + hasher('blake2', pair.publicKey), 'blake2' ) ).toEqual(true); @@ -77,7 +79,7 @@ describe('sign and verify', (): void => { secp256k1Verify( MESSAGE, secp256k1Sign(MESSAGE, pair, 'keccak'), - secp256k1Hasher('keccak', secp256k1Expand(pair.publicKey)), + hasher('keccak', secp256k1Expand(pair.publicKey)), 'keccak' ) ).toEqual(true); diff --git a/packages/util-crypto/src/secp256k1/verify.spec.ts b/packages/util-crypto/src/secp256k1/verify.spec.ts index 7abb7efa1..66d86e624 100644 --- a/packages/util-crypto/src/secp256k1/verify.spec.ts +++ b/packages/util-crypto/src/secp256k1/verify.spec.ts @@ -1,11 +1,13 @@ // Copyright 2017-2021 @polkadot/util-crypto authors & contributors // SPDX-License-Identifier: Apache-2.0 +import '../cryptoInit'; + import { hexToU8a } from '@polkadot/util'; import { waitReady } from '@polkadot/wasm-crypto'; import { performanceWasm } from '../../test/performance'; -import { secp256k1Hasher } from './hasher'; +import { hasher } from './hasher'; import { secp256k1PairFromSeed, secp256k1Verify } from '.'; const message = 'Pay KSMs to the Kusama account:88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee'; @@ -33,7 +35,7 @@ describe('secp256k1Verify', (): void => { const msg = hexToU8a('0xa30b64ce1eedf409c8afb801d72c05234e64849ea538c15dd3c8cf4ffcf166c9'); const addr = isPublic ? pair.publicKey - : secp256k1Hasher('blake2', pair.publicKey, onlyJs); + : hasher('blake2', pair.publicKey, onlyJs); it('signature from JS', (): void => { expect( diff --git a/packages/util-crypto/src/secp256k1/verify.ts b/packages/util-crypto/src/secp256k1/verify.ts index 4012878d2..8174ce3be 100644 --- a/packages/util-crypto/src/secp256k1/verify.ts +++ b/packages/util-crypto/src/secp256k1/verify.ts @@ -6,26 +6,20 @@ import type { HashType } from './types'; import { assert, u8aEq, u8aToU8a } from '@polkadot/util'; -import { secp256k1Hasher } from './hasher'; +import { hasher } from './hasher'; import { secp256k1Recover } from './recover'; /** * @name secp256k1Verify * @description Verifies the signature of `message`, using the supplied pair */ -export function secp256k1Verify (message: HexString | Uint8Array | string, signature: HexString | Uint8Array | string, address: HexString | Uint8Array | string, hashType: HashType = 'blake2', onlyJs?: boolean): boolean { - const u8a = u8aToU8a(signature); +export function secp256k1Verify (msgHash: HexString | Uint8Array | string, signature: HexString | Uint8Array | string, address: HexString | Uint8Array | string, hashType: HashType = 'blake2', onlyJs?: boolean): boolean { + const sig = u8aToU8a(signature); - assert(u8a.length === 65, `Expected signature with 65 bytes, ${u8a.length} found instead`); + assert(sig.length === 65, `Expected signature with 65 bytes, ${sig.length} found instead`); - const publicKey = secp256k1Recover( - secp256k1Hasher(hashType, message), - u8a.subarray(0, 64), - u8a[64], - hashType, - onlyJs - ); - const signerAddr = secp256k1Hasher(hashType, publicKey, onlyJs); + const publicKey = secp256k1Recover(hasher(hashType, msgHash), sig, sig[64], hashType, onlyJs); + const signerAddr = hasher(hashType, publicKey, onlyJs); const inputAddr = u8aToU8a(address); // for Ethereum (keccak) the last 20 bytes is the address diff --git a/yarn.lock b/yarn.lock index 960bf52dd..24a6781c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1777,6 +1777,13 @@ __metadata: languageName: node linkType: hard +"@noble/secp256k1@npm:^1.3.0": + version: 1.3.0 + resolution: "@noble/secp256k1@npm:1.3.0" + checksum: 4bf5e2a905e0dacbf3b557da74e4073d208b8407f4e1fc95e244c17c6af686fd1870668d231b9f2e774091d72be79baf1c0e50f5ddc9db6fb82b206e23b9b335 + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.4": version: 2.1.4 resolution: "@nodelib/fs.scandir@npm:2.1.4" @@ -2091,18 +2098,16 @@ __metadata: dependencies: "@babel/runtime": ^7.16.3 "@noble/hashes": 0.4.1 + "@noble/secp256k1": ^1.3.0 "@polkadot/networks": 8.0.6-14 "@polkadot/util": 8.0.6-14 "@polkadot/wasm-crypto": ^4.5.1 "@polkadot/x-bigint": 8.0.6-14 "@polkadot/x-noble-hashes": 8.0.6-14 + "@polkadot/x-noble-secp256k1": 8.0.6-14 "@polkadot/x-randomvalues": 8.0.6-14 - "@types/bn.js": ^4.11.6 "@types/ed2curve": ^0.2.2 - "@types/elliptic": ^6.4.14 - bn.js: ^4.12.0 ed2curve: ^0.3.0 - elliptic: ^6.5.4 micro-base: ^0.9.0 tweetnacl: ^1.0.3 peerDependencies: @@ -2204,7 +2209,7 @@ __metadata: languageName: unknown linkType: soft -"@polkadot/x-noble-secp256k1@workspace:packages/x-noble-secp256k1": +"@polkadot/x-noble-secp256k1@8.0.6-14, @polkadot/x-noble-secp256k1@workspace:packages/x-noble-secp256k1": version: 0.0.0-use.local resolution: "@polkadot/x-noble-secp256k1@workspace:packages/x-noble-secp256k1" dependencies: @@ -2422,7 +2427,7 @@ __metadata: languageName: node linkType: hard -"@types/bn.js@npm:*, @types/bn.js@npm:^4.11.6": +"@types/bn.js@npm:^4.11.6": version: 4.11.6 resolution: "@types/bn.js@npm:4.11.6" dependencies: @@ -2450,15 +2455,6 @@ __metadata: languageName: node linkType: hard -"@types/elliptic@npm:^6.4.14": - version: 6.4.14 - resolution: "@types/elliptic@npm:6.4.14" - dependencies: - "@types/bn.js": "*" - checksum: d5a64f540e0ed4b74a12dfa5cc88c0aa7b531eab3b7a9fab17948ffbfc6e01814230e63d7417ce1b607dbd8b5d70e1b64f5afac632deabf96e44875aaac0ae1b - languageName: node - linkType: hard - "@types/estree@npm:*": version: 0.0.49 resolution: "@types/estree@npm:0.0.49" @@ -4565,7 +4561,7 @@ __metadata: languageName: node linkType: hard -"elliptic@npm:^6.4.0, elliptic@npm:^6.4.1, elliptic@npm:^6.5.4": +"elliptic@npm:^6.4.0, elliptic@npm:^6.4.1": version: 6.5.4 resolution: "elliptic@npm:6.5.4" dependencies: