Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80785babb4 | ||
|
|
59761086d0 | ||
|
|
05c82721e8 | ||
|
|
1b13cf0eea | ||
|
|
e6777ece62 | ||
|
|
7436976598 | ||
|
|
699ef952c3 | ||
|
|
cd9dc35475 | ||
|
|
ee7923c457 | ||
|
|
bd3f51844c | ||
|
|
986dfe5006 | ||
|
|
1eba41b2e6 | ||
|
|
88c2d16951 | ||
|
|
303a57c4b5 | ||
|
|
7bfca0d40f | ||
|
|
916187dbf2 | ||
|
|
cfc598b30f | ||
|
|
67bfe3a52e | ||
|
|
0299cba18e | ||
|
|
182c6770d1 | ||
|
|
c89ec8a964 | ||
|
|
dc63304735 | ||
|
|
9ce825de94 | ||
|
|
3cb41c3b03 | ||
|
|
b1f9c37f6a | ||
|
|
4a69486993 | ||
|
|
3a7ab0454f | ||
|
|
ecfc262bcd | ||
|
|
776a653f42 | ||
|
|
ee99ffdbb4 | ||
|
|
bda848f484 | ||
|
|
82a63887a6 | ||
|
|
50317d7dc3 | ||
|
|
39e6a3c048 | ||
|
|
db93c3076b | ||
|
|
c8f0ad55c4 | ||
|
|
2104c50bd0 | ||
|
|
7e9b2770b6 | ||
|
|
8bf24c2f85 | ||
|
|
60337a3b55 | ||
|
|
f527c80b5c | ||
|
|
bdd2bcf236 | ||
|
|
cf370febf0 | ||
|
|
715ef6e7db | ||
|
|
cc644e85bf | ||
|
|
c7b8d95097 | ||
|
|
42de7cebe1 | ||
|
|
2e520c933a |
+4
-1
@@ -21,4 +21,7 @@
|
||||
7.8.2
|
||||
7.9.2
|
||||
8.0.2
|
||||
8.0.3
|
||||
8.0.3
|
||||
8.0.4
|
||||
8.0.5
|
||||
8.1.2
|
||||
@@ -3,3 +3,5 @@ exclude_patterns:
|
||||
- "**/*.spec.ts"
|
||||
- "packages/networks/src/substrate.ts"
|
||||
- "packages/util/src/is/utf8.ts"
|
||||
- "packages/x-noble-hashes/src/**.ts"
|
||||
- "packages/x-noble-secp256k1/src/**.ts"
|
||||
|
||||
+2
-1
@@ -1 +1,2 @@
|
||||
packages/util-crypto/src/noble-hashes/lib/*.ts
|
||||
packages/x-noble-hashes/**/*.ts
|
||||
packages/x-noble-secp256k1/**/*.ts
|
||||
|
||||
@@ -2,7 +2,7 @@ name: 'Lock Threads'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '15 1 * * *'
|
||||
- cron: '15 1/3 * * *'
|
||||
|
||||
jobs:
|
||||
lock:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: 'Close stale issues and PRs'
|
||||
on:
|
||||
schedule:
|
||||
- cron: '50 1 * * *'
|
||||
- cron: '50 1/3 * * *'
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
|
||||
+38
-1
@@ -1,11 +1,48 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 8.1.2 Dec 5, 2021
|
||||
|
||||
Changes:
|
||||
|
||||
- Adjustment to non-full-word consecutive uppercase via `string{Camel, Pascal}Case`
|
||||
|
||||
|
||||
## 8.1.1 Dec 5, 2021
|
||||
|
||||
Contributed:
|
||||
|
||||
- Add Picasso genesisHash (Thanks to https://github.com/hussein-aitlahcen)
|
||||
|
||||
Changes:
|
||||
|
||||
- Allow for use of `secp256k1` from `@polkadot/wasm-crypto`
|
||||
- Adjust `isBigInt` to not do `instanceof` check
|
||||
- Ensure consequtive capitals in `stringCamelCase` are lowercased
|
||||
- Use `@polkadot/x-bigint` for `BigInt` constructor
|
||||
- Split `@noble/hashes` fork into `x-noble-hashes`
|
||||
- Add `@noble/secp256k1` fork into `x-noble-secp256k1`, replaces `elliptic`
|
||||
|
||||
|
||||
## 8.0.5 Dec 1, 2021
|
||||
|
||||
Changes:
|
||||
|
||||
- Adjust sha3 expectation of `BigInt` availability
|
||||
|
||||
|
||||
## 8.0.4 Nov 30, 2021
|
||||
|
||||
Changes:
|
||||
|
||||
- Adjust `stringCamelCase` with leading `_`
|
||||
|
||||
|
||||
## 8.0.3 Nov 30, 2021
|
||||
|
||||
Changes:
|
||||
|
||||
- Remove `Buffer` usage in `x-randomvalues`
|
||||
- Adjust `stringCaleCase` for all-caps parts
|
||||
- Adjust `stringCamelCase` for all-caps parts
|
||||
|
||||
|
||||
## 8.0.2 Nov 26, 2021
|
||||
|
||||
+2
-2
@@ -13,8 +13,8 @@ module.exports = Object.assign({}, config, {
|
||||
'@polkadot/util-(crypto)(.*)$': '<rootDir>/packages/util-$1/src/$2',
|
||||
// eslint-disable-next-line sort-keys
|
||||
'@polkadot/util(.*)$': '<rootDir>/packages/util/src/$1',
|
||||
'@polkadot/x-(bigint|global)(.*)$': '<rootDir>/packages/x-$1/src/$2',
|
||||
'@polkadot/x-(fetch|randomvalues|textdecoder|textencoder|ws)(.*)$': '<rootDir>/packages/x-$1/src/node',
|
||||
'@polkadot/x-global(.*)$': '<rootDir>/packages/x-global/src/$1',
|
||||
'@polkadot/x-rxjs(.*)$': '<rootDir>/packages/x-rxjs/src/$1'
|
||||
'@polkadot/x-noble-(hashes|secp256k1)(.*)$': '<rootDir>/packages/x-noble-$1/src/$2'
|
||||
}
|
||||
});
|
||||
|
||||
+3
-3
@@ -10,7 +10,7 @@
|
||||
"url": "https://github.com/polkadot-js/common.git"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"version": "8.0.3",
|
||||
"version": "8.1.2",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
@@ -29,8 +29,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.16.0",
|
||||
"@polkadot/dev": "^0.63.33",
|
||||
"@polkadot/ts": "^0.4.15",
|
||||
"@polkadot/dev": "^0.63.35",
|
||||
"@polkadot/ts": "^0.4.16",
|
||||
"@types/jest": "^27.0.3"
|
||||
},
|
||||
"resolutions": {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
},
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"version": "8.0.3",
|
||||
"version": "8.1.2",
|
||||
"browser": "browser.js",
|
||||
"main": "node.js",
|
||||
"react-native": "react-native.js",
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
// Auto-generated by @polkadot/dev, do not edit
|
||||
|
||||
export const packageInfo = { name: '@polkadot/hw-ledger-transports', version: '8.0.3' };
|
||||
export const packageInfo = { name: '@polkadot/hw-ledger-transports', version: '8.1.2' };
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
"./detectPackage.cjs"
|
||||
],
|
||||
"type": "module",
|
||||
"version": "8.0.3",
|
||||
"version": "8.1.2",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.16.3",
|
||||
"@polkadot/hw-ledger-transports": "8.0.3",
|
||||
"@polkadot/util": "8.0.3",
|
||||
"@polkadot/hw-ledger-transports": "8.1.2",
|
||||
"@polkadot/util": "8.1.2",
|
||||
"@zondax/ledger-substrate": "^0.18.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
// Auto-generated by @polkadot/dev, do not edit
|
||||
|
||||
export const packageInfo = { name: '@polkadot/hw-ledger', version: '8.0.3' };
|
||||
export const packageInfo = { name: '@polkadot/hw-ledger', version: '8.1.2' };
|
||||
|
||||
@@ -20,15 +20,15 @@
|
||||
"./detectPackage.cjs"
|
||||
],
|
||||
"type": "module",
|
||||
"version": "8.0.3",
|
||||
"version": "8.1.2",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.16.3",
|
||||
"@polkadot/util": "8.0.3",
|
||||
"@polkadot/util-crypto": "8.0.3"
|
||||
"@polkadot/util": "8.1.2",
|
||||
"@polkadot/util-crypto": "8.1.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@polkadot/util": "8.0.3",
|
||||
"@polkadot/util-crypto": "8.0.3"
|
||||
"@polkadot/util": "8.1.2",
|
||||
"@polkadot/util-crypto": "8.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
// Auto-generated by @polkadot/dev, do not edit
|
||||
|
||||
export const packageInfo = { name: '@polkadot/keyring', version: '8.0.3' };
|
||||
export const packageInfo = { name: '@polkadot/keyring', version: '8.1.2' };
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
},
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"version": "8.0.3",
|
||||
"version": "8.1.2",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.16.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/util": "8.0.3",
|
||||
"@polkadot/x-fetch": "8.0.3"
|
||||
"@polkadot/util": "8.1.2",
|
||||
"@polkadot/x-fetch": "8.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,9 @@ export const knownGenesis: KnownGenesis = {
|
||||
'nodle-chain': [
|
||||
'0xa3d114c2b8d0627c1aa9b134eafcf7d05ca561fdc19fb388bb9457f81809fb23'
|
||||
],
|
||||
picasso: [
|
||||
'0xe8e7f0f4c4f5a00720b4821dbfddefea7490bcf0b19009961cc46957984e2c1c'
|
||||
],
|
||||
plasm: [
|
||||
'0x3e86364d4b4894021cb2a0390bcf2feb5517d5292f2de2bb9404227e908b0b8b'
|
||||
],
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
// Auto-generated by @polkadot/dev, do not edit
|
||||
|
||||
export const packageInfo = { name: '@polkadot/networks', version: '8.0.3' };
|
||||
export const packageInfo = { name: '@polkadot/networks', version: '8.1.2' };
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
{
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"bugs": "https://github.com/polkadot-js/common/issues",
|
||||
"bundledDependencies": [
|
||||
"@noble/hashes"
|
||||
],
|
||||
"contributors": [],
|
||||
"description": "A collection of useful crypto utilities for @polkadot",
|
||||
"engines": {
|
||||
@@ -25,27 +22,31 @@
|
||||
"./detectPackage.cjs"
|
||||
],
|
||||
"type": "module",
|
||||
"version": "8.0.3",
|
||||
"version": "8.1.2",
|
||||
"browser": {
|
||||
"crypto": false,
|
||||
"stream": false
|
||||
},
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.16.3",
|
||||
"@noble/hashes": "0.4.1",
|
||||
"@polkadot/networks": "8.0.3",
|
||||
"@polkadot/util": "8.0.3",
|
||||
"@polkadot/wasm-crypto": "^4.4.1",
|
||||
"@polkadot/x-randomvalues": "8.0.3",
|
||||
"bn.js": "^4.12.0",
|
||||
"@noble/secp256k1": "^1.3.0",
|
||||
"@polkadot/networks": "8.1.2",
|
||||
"@polkadot/util": "8.1.2",
|
||||
"@polkadot/wasm-crypto": "^4.5.1",
|
||||
"@polkadot/x-bigint": "8.1.2",
|
||||
"@polkadot/x-noble-hashes": "8.1.2",
|
||||
"@polkadot/x-noble-secp256k1": "8.1.2",
|
||||
"@polkadot/x-randomvalues": "8.1.2",
|
||||
"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.3"
|
||||
"@polkadot/util": "8.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@ import type { HexString } from '@polkadot/util/types';
|
||||
|
||||
import { hasBigInt, u8aToU8a } from '@polkadot/util';
|
||||
import { blake2b, isReady } from '@polkadot/wasm-crypto';
|
||||
import { blake2b as blake2bJs } from '@polkadot/x-noble-hashes/blake2b';
|
||||
|
||||
import { createAsHex } from '../helpers';
|
||||
import { blake2b as blake2bJs } from '../noble-hashes/lib/blake2b';
|
||||
|
||||
type BitLength = 64 | 128 | 256 | 384 | 512;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export const BN_BE_OPTS = { isLe: false };
|
||||
export const BN_LE_OPTS = { isLe: true };
|
||||
|
||||
export const BN_LE_16_OPTS = { bitLength: 16, isLe: true };
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import '@polkadot/x-bigint/shim';
|
||||
|
||||
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 => {
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
|
||||
import type { Keypair } from '../../types';
|
||||
|
||||
import nacl from 'tweetnacl';
|
||||
import { randomAsU8a } from '../../random';
|
||||
import { ed25519PairFromSeed } from './fromSeed';
|
||||
|
||||
/**
|
||||
* @name ed25519PairFromRandom
|
||||
@@ -20,5 +21,5 @@ import nacl from 'tweetnacl';
|
||||
* ```
|
||||
*/
|
||||
export function ed25519PairFromRandom (): Keypair {
|
||||
return nacl.sign.keyPair();
|
||||
return ed25519PairFromSeed(randomAsU8a());
|
||||
}
|
||||
|
||||
@@ -25,8 +25,7 @@ import { ed25519PairFromSeed } from './fromSeed';
|
||||
export function ed25519PairFromString (value: string): Keypair {
|
||||
return ed25519PairFromSeed(
|
||||
blake2AsU8a(
|
||||
stringToU8a(value),
|
||||
256
|
||||
stringToU8a(value)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
|
||||
import { hasBigInt, u8aToU8a } from '@polkadot/util';
|
||||
import { hmacSha256, hmacSha512, isReady } from '@polkadot/wasm-crypto';
|
||||
|
||||
import { hmac } from '../noble-hashes/lib/hmac';
|
||||
import { sha256 } from '../noble-hashes/lib/sha256';
|
||||
import { sha512 } from '../noble-hashes/lib/sha512';
|
||||
import { hmac } from '@polkadot/x-noble-hashes/hmac';
|
||||
import { sha256 } from '@polkadot/x-noble-hashes/sha256';
|
||||
import { sha512 } from '@polkadot/x-noble-hashes/sha512';
|
||||
|
||||
type BitLength = 256 | 512;
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ import type { HexString } from '@polkadot/util/types';
|
||||
|
||||
import { hasBigInt, u8aToU8a } from '@polkadot/util';
|
||||
import { isReady, keccak256, keccak512 } from '@polkadot/wasm-crypto';
|
||||
import { keccak_256 as keccak256Js, keccak_512 as keccak512Js } from '@polkadot/x-noble-hashes/sha3';
|
||||
|
||||
import { createAsHex, createBitHasher } from '../helpers';
|
||||
import { keccak_256 as keccak256Js, keccak_512 as keccak512Js } from '../noble-hashes/lib/sha3';
|
||||
|
||||
type BitLength = 256 | 512;
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
/*! noble-hashes - MIT License (c) 2021 Paul Miller (paulmillr.com) */
|
||||
// https://github.com/paulmillr/noble-hashes/pull/13
|
||||
throw new Error(
|
||||
'noble-hashes have no entry-point. Please consult the README.md to learn how to use them'
|
||||
);
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
// Auto-generated by @polkadot/dev, do not edit
|
||||
|
||||
export const packageInfo = { name: '@polkadot/util-crypto', version: '8.0.3' };
|
||||
export const packageInfo = { name: '@polkadot/util-crypto', version: '8.1.2' };
|
||||
|
||||
@@ -5,9 +5,9 @@ import type { HexString } from '@polkadot/util/types';
|
||||
|
||||
import { hasBigInt, u8aToU8a } from '@polkadot/util';
|
||||
import { isReady, pbkdf2 } from '@polkadot/wasm-crypto';
|
||||
import { pbkdf2 as pbkdf2Js } from '@polkadot/x-noble-hashes/pbkdf2';
|
||||
import { sha512 } from '@polkadot/x-noble-hashes/sha512';
|
||||
|
||||
import { pbkdf2 as pbkdf2Js } from '../noble-hashes/lib/pbkdf2';
|
||||
import { sha512 } from '../noble-hashes/lib/sha512';
|
||||
import { randomAsU8a } from '../random/asU8a';
|
||||
|
||||
interface Result {
|
||||
|
||||
@@ -6,8 +6,8 @@ import type { Params } from './types';
|
||||
|
||||
import { hasBigInt, objectSpread, u8aToU8a } from '@polkadot/util';
|
||||
import { isReady, scrypt } from '@polkadot/wasm-crypto';
|
||||
import { scrypt as scryptJs } from '@polkadot/x-noble-hashes/scrypt';
|
||||
|
||||
import { scrypt as scryptJs } from '../noble-hashes/lib/scrypt';
|
||||
import { randomAsU8a } from '../random/asU8a';
|
||||
import { DEFAULT_PARAMS } from './defaults';
|
||||
|
||||
|
||||
@@ -2,17 +2,43 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { hexToU8a } from '@polkadot/util';
|
||||
import { waitReady } from '@polkadot/wasm-crypto';
|
||||
|
||||
import { secp256k1Compress } from './';
|
||||
import { performanceWasm } from '../../test/performance';
|
||||
import { secp256k1Compress } from '.';
|
||||
|
||||
describe('secp256k1Compress', (): void => {
|
||||
it('compresses a known key', (): void => {
|
||||
expect(
|
||||
secp256k1Compress(
|
||||
hexToU8a('0x04b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb1307763fe926c273235fd979a134076d00fd1683cbd35868cb485d4a3a640e52184af')
|
||||
)
|
||||
).toEqual(
|
||||
hexToU8a('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077')
|
||||
);
|
||||
beforeEach(async (): Promise<void> => {
|
||||
await waitReady();
|
||||
});
|
||||
|
||||
describe.each([false, true])('onlyJs=%p', (onlyJs): void => {
|
||||
it('returns a compressed key as-is', (): void => {
|
||||
expect(
|
||||
secp256k1Compress(
|
||||
hexToU8a('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077'),
|
||||
onlyJs
|
||||
)
|
||||
).toEqual(
|
||||
hexToU8a('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077')
|
||||
);
|
||||
});
|
||||
|
||||
it('compresses a known key', (): void => {
|
||||
expect(
|
||||
secp256k1Compress(
|
||||
hexToU8a('0x04b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb1307763fe926c273235fd979a134076d00fd1683cbd35868cb485d4a3a640e52184af'),
|
||||
onlyJs
|
||||
)
|
||||
).toEqual(
|
||||
hexToU8a('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077')
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
performanceWasm('secp256k1Compress', 100000, (input, onlyJs) => secp256k1Compress(input, onlyJs),
|
||||
[[
|
||||
hexToU8a('0x04b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb1307763fe926c273235fd979a134076d00fd1683cbd35868cb485d4a3a640e52184af')
|
||||
]]
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
// 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 { Point } from '@polkadot/x-noble-secp256k1';
|
||||
|
||||
import { secp256k1 } from './secp256k1';
|
||||
export function secp256k1Compress (publicKey: Uint8Array, onlyJs?: boolean): Uint8Array {
|
||||
if (publicKey.length === 33) {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
export function secp256k1Compress (publicKey: Uint8Array): Uint8Array {
|
||||
assert([33, 65].includes(publicKey.length), 'Invalid publicKey provided');
|
||||
assert(publicKey.length === 65, 'Invalid publicKey provided');
|
||||
|
||||
return new Uint8Array(
|
||||
secp256k1
|
||||
.keyFromPublic(publicKey)
|
||||
.getPublic()
|
||||
.encodeCompressed()
|
||||
);
|
||||
return !hasBigInt || (!onlyJs && isReady())
|
||||
? wasm(publicKey)
|
||||
: Point.fromHex(publicKey).toRawBytes(true);
|
||||
}
|
||||
|
||||
@@ -2,27 +2,43 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { hexToU8a } from '@polkadot/util';
|
||||
import { waitReady } from '@polkadot/wasm-crypto';
|
||||
|
||||
import { secp256k1Expand } from './';
|
||||
import { performanceWasm } from '../../test/performance';
|
||||
import { secp256k1Expand } from '.';
|
||||
|
||||
describe('secp256k1Expand', (): void => {
|
||||
it('expands a known key', (): void => {
|
||||
expect(
|
||||
secp256k1Expand(
|
||||
hexToU8a('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077')
|
||||
)
|
||||
).toEqual(
|
||||
hexToU8a('0xb9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb1307763fe926c273235fd979a134076d00fd1683cbd35868cb485d4a3a640e52184af')
|
||||
);
|
||||
beforeEach(async (): Promise<void> => {
|
||||
await waitReady();
|
||||
});
|
||||
|
||||
it('expands a known full key', (): void => {
|
||||
expect(
|
||||
secp256k1Expand(
|
||||
hexToU8a('0x04b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb1307763fe926c273235fd979a134076d00fd1683cbd35868cb485d4a3a640e52184af')
|
||||
)
|
||||
).toEqual(
|
||||
hexToU8a('0xb9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb1307763fe926c273235fd979a134076d00fd1683cbd35868cb485d4a3a640e52184af')
|
||||
);
|
||||
describe.each([false, true])('onlyJs=%p', (onlyJs): void => {
|
||||
it('expands a known key', (): void => {
|
||||
expect(
|
||||
secp256k1Expand(
|
||||
hexToU8a('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077'),
|
||||
onlyJs
|
||||
)
|
||||
).toEqual(
|
||||
hexToU8a('0xb9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb1307763fe926c273235fd979a134076d00fd1683cbd35868cb485d4a3a640e52184af')
|
||||
);
|
||||
});
|
||||
|
||||
it('expands a known full key', (): void => {
|
||||
expect(
|
||||
secp256k1Expand(
|
||||
hexToU8a('0x04b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb1307763fe926c273235fd979a134076d00fd1683cbd35868cb485d4a3a640e52184af'),
|
||||
onlyJs
|
||||
)
|
||||
).toEqual(
|
||||
hexToU8a('0xb9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb1307763fe926c273235fd979a134076d00fd1683cbd35868cb485d4a3a640e52184af')
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
performanceWasm('secp256k1Expand', 2000, (input, onlyJs) => secp256k1Expand(input, onlyJs),
|
||||
[[
|
||||
hexToU8a('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077')
|
||||
]]
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,20 +1,27 @@
|
||||
// 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): Uint8Array {
|
||||
assert([33, 65].includes(publicKey.length), 'Invalid publicKey provided');
|
||||
export function secp256k1Expand (publicKey: Uint8Array, onlyJs?: boolean): Uint8Array {
|
||||
if (publicKey.length === 65) {
|
||||
return publicKey.subarray(1);
|
||||
}
|
||||
|
||||
const expanded = secp256k1
|
||||
.keyFromPublic(publicKey)
|
||||
.getPublic();
|
||||
assert(publicKey.length === 33, 'Invalid publicKey provided');
|
||||
|
||||
if (!hasBigInt || (!onlyJs && isReady())) {
|
||||
return wasm(publicKey).subarray(1);
|
||||
}
|
||||
|
||||
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)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { secp256k1Hasher } from './hasher';
|
||||
|
||||
describe('secp256k1Hasher', (): void => {
|
||||
it('fails with unknown hasher', (): void => {
|
||||
expect(
|
||||
() => secp256k1Hasher('unknown' as 'blake2', 'testing')
|
||||
).toThrow(/Unsupported secp256k1 hasher 'unknown', expected one of blake2, keccak/);
|
||||
});
|
||||
import { hasher } from './hasher';
|
||||
|
||||
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])
|
||||
);
|
||||
@@ -20,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])
|
||||
);
|
||||
|
||||
@@ -6,14 +6,8 @@ import type { HashType } from './types';
|
||||
import { blake2AsU8a } from '../blake2';
|
||||
import { keccakAsU8a } from '../keccak';
|
||||
|
||||
const HASH_TYPES = ['blake2', 'keccak'];
|
||||
|
||||
export function secp256k1Hasher (hashType: HashType, data: Uint8Array | string): Uint8Array {
|
||||
if (hashType === 'blake2') {
|
||||
return blake2AsU8a(data);
|
||||
} else if (hashType === 'keccak') {
|
||||
return keccakAsU8a(data);
|
||||
}
|
||||
|
||||
throw new Error(`Unsupported secp256k1 hasher '${hashType as string}', expected one of ${HASH_TYPES.join(', ')}`);
|
||||
export function hasher (hashType: HashType, data: Uint8Array | string, onlyJs?: boolean): Uint8Array {
|
||||
return hashType === 'keccak'
|
||||
? keccakAsU8a(data, undefined, onlyJs)
|
||||
: blake2AsU8a(data, undefined, undefined, onlyJs);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { hexToU8a, u8aToHex } from '@polkadot/util';
|
||||
import { waitReady } from '@polkadot/wasm-crypto';
|
||||
|
||||
import { performanceWasm } from '../../../test/performance';
|
||||
import { mnemonicToMiniSecret } from '../../mnemonic';
|
||||
import { secp256k1PairFromSeed } from '..';
|
||||
|
||||
@@ -37,23 +39,33 @@ const tests: Test[] = [
|
||||
];
|
||||
|
||||
describe('secp256k1PairFromSeed', (): void => {
|
||||
beforeEach(async (): Promise<void> => {
|
||||
await waitReady();
|
||||
});
|
||||
|
||||
const TEST = hexToU8a('0x4380de832af797688026ce24f85204d508243f201650c1a134929e5458b7fbae');
|
||||
const RESULT = {
|
||||
publicKey: hexToU8a('0x03fd8c74f795ced92064b86191cb2772b1e3a0947740aa0a5a6e379592471fd85b'),
|
||||
secretKey: hexToU8a('0x4380de832af797688026ce24f85204d508243f201650c1a134929e5458b7fbae')
|
||||
};
|
||||
|
||||
it('generates a valid publicKey/secretKey pair (u8a)', (): void => {
|
||||
expect(secp256k1PairFromSeed(TEST)).toEqual(RESULT);
|
||||
});
|
||||
describe.each([false, true])('onlyJs=%p', (onlyJs): void => {
|
||||
it('generates a valid publicKey/secretKey pair (u8a)', (): void => {
|
||||
expect(secp256k1PairFromSeed(TEST, onlyJs)).toEqual(RESULT);
|
||||
});
|
||||
|
||||
tests.forEach(([mnemonic, secretKey, publicKey], index): void => {
|
||||
it(`creates valid against known (${index})`, (): void => {
|
||||
const seed = mnemonicToMiniSecret(mnemonic);
|
||||
const pair = secp256k1PairFromSeed(seed);
|
||||
tests.forEach(([mnemonic, secretKey, publicKey], index): void => {
|
||||
it(`creates valid against known (${index})`, (): void => {
|
||||
const seed = mnemonicToMiniSecret(mnemonic);
|
||||
const pair = secp256k1PairFromSeed(seed, onlyJs);
|
||||
|
||||
expect(u8aToHex(pair.secretKey)).toEqual(secretKey);
|
||||
expect(u8aToHex(pair.publicKey)).toEqual(publicKey);
|
||||
expect(u8aToHex(pair.secretKey)).toEqual(secretKey);
|
||||
expect(u8aToHex(pair.publicKey)).toEqual(publicKey);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
performanceWasm('secp256k1PairFromSeed', 500, (input, onlyJs) =>
|
||||
secp256k1PairFromSeed(input, onlyJs)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -3,22 +3,28 @@
|
||||
|
||||
import type { Keypair } from '../../types';
|
||||
|
||||
import { assert, bnToU8a } from '@polkadot/util';
|
||||
|
||||
import { BN_BE_256_OPTS } from '../../bn';
|
||||
import { secp256k1 } from '../secp256k1';
|
||||
import { assert, hasBigInt } from '@polkadot/util';
|
||||
import { isReady, secp256k1FromSeed } from '@polkadot/wasm-crypto';
|
||||
import { getPublicKey } from '@polkadot/x-noble-secp256k1';
|
||||
|
||||
/**
|
||||
* @name secp256k1PairFromSeed
|
||||
* @description Returns a object containing a `publicKey` & `secretKey` generated from the supplied seed.
|
||||
*/
|
||||
export function secp256k1PairFromSeed (seed: Uint8Array): Keypair {
|
||||
export function secp256k1PairFromSeed (seed: Uint8Array, onlyJs?: boolean): Keypair {
|
||||
assert(seed.length === 32, 'Expected valid 32-byte private key as a seed');
|
||||
|
||||
const key = secp256k1.keyFromPrivate(seed);
|
||||
if (!hasBigInt || (!onlyJs && isReady())) {
|
||||
const full = secp256k1FromSeed(seed);
|
||||
|
||||
return {
|
||||
publicKey: full.slice(32),
|
||||
secretKey: full.slice(0, 32)
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
publicKey: new Uint8Array(key.getPublic().encodeCompressed()),
|
||||
secretKey: bnToU8a(key.getPrivate(), BN_BE_256_OPTS)
|
||||
publicKey: getPublicKey(seed, true),
|
||||
secretKey: seed
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,17 +2,30 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { u8aToHex, u8aToU8a } from '@polkadot/util';
|
||||
import { waitReady } from '@polkadot/wasm-crypto';
|
||||
|
||||
import { performanceWasm } from '../../test/performance';
|
||||
import { keccakAsU8a } from '../keccak';
|
||||
import { secp256k1Recover } from '.';
|
||||
|
||||
describe('secp256k1Recover', (): void => {
|
||||
it('recovers a publicKey', (): void => {
|
||||
const pubKey = '0x93a9fc7154c6da3c826415df01eb0e37fb4da4b0';
|
||||
const sig = '0x7505f2880114da51b3f5d535f8687953c0ab9af4ab81e592eaebebf53b728d2b6dfd9b5bcd70fee412b1f31360e7c2774009305cb84fc50c1d0ff8034dfa5fff';
|
||||
const msg = '0xa30b64ce1eedf409c8afb801d72c05234e64849ea538c15dd3c8cf4ffcf166c9';
|
||||
const res = keccakAsU8a(secp256k1Recover(u8aToU8a(msg), u8aToU8a(sig), 0));
|
||||
const sig = u8aToU8a('0x7505f2880114da51b3f5d535f8687953c0ab9af4ab81e592eaebebf53b728d2b6dfd9b5bcd70fee412b1f31360e7c2774009305cb84fc50c1d0ff8034dfa5fff');
|
||||
const msg = u8aToU8a('0xa30b64ce1eedf409c8afb801d72c05234e64849ea538c15dd3c8cf4ffcf166c9');
|
||||
|
||||
expect(u8aToHex(res.subarray(12))).toEqual(pubKey);
|
||||
describe('secp256k1Recover', (): void => {
|
||||
beforeEach(async (): Promise<void> => {
|
||||
await waitReady();
|
||||
});
|
||||
|
||||
describe.each([false, true])('onlyJs=%p', (onlyJs): void => {
|
||||
it('recovers a publicKey', (): void => {
|
||||
const pubKey = '0x93a9fc7154c6da3c826415df01eb0e37fb4da4b0';
|
||||
const res = keccakAsU8a(secp256k1Recover(msg, sig, 0, undefined, onlyJs));
|
||||
|
||||
expect(u8aToHex(res.subarray(-20))).toEqual(pubKey);
|
||||
});
|
||||
});
|
||||
|
||||
performanceWasm('secp256k1Recover', 200, (_, onlyJs) =>
|
||||
secp256k1Recover(msg, sig, 0, undefined, onlyJs)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,17 +1,30 @@
|
||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { secp256k1 } from './secp256k1';
|
||||
import type { HexString } from '@polkadot/util/types';
|
||||
import type { HashType } from './types';
|
||||
|
||||
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';
|
||||
|
||||
/**
|
||||
* @name secp256k1Recover
|
||||
* @description Recovers a publicKey from the supplied signature
|
||||
*/
|
||||
export function secp256k1Recover (message: Uint8Array, signature: Uint8Array, recovery: number): Uint8Array {
|
||||
return 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');
|
||||
|
||||
return hashType === 'keccak'
|
||||
? secp256k1Expand(publicKey, onlyJs)
|
||||
: secp256k1Compress(publicKey, onlyJs);
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { hexToU8a } from '@polkadot/util';
|
||||
import { waitReady } from '@polkadot/wasm-crypto';
|
||||
|
||||
import { performanceWasm } from '../../test/performance';
|
||||
import { secp256k1PairFromSeed, secp256k1Sign } from '.';
|
||||
|
||||
const pair = secp256k1PairFromSeed(hexToU8a('0x4380de832af797688026ce24f85204d508243f201650c1a134929e5458b7fbae'));
|
||||
const msg = hexToU8a('0xa30b64ce1eedf409c8afb801d72c05234e64849ea538c15dd3c8cf4ffcf166c9');
|
||||
|
||||
describe('sign', (): void => {
|
||||
beforeEach(async (): Promise<void> => {
|
||||
await waitReady();
|
||||
});
|
||||
|
||||
describe.each([false, true])('onlyJs=%p', (onlyJs): void => {
|
||||
it('generates a known signature', (): void => {
|
||||
expect(
|
||||
secp256k1Sign(msg, pair, undefined, onlyJs)
|
||||
).toEqual(hexToU8a(
|
||||
// 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', 1000, (_, onlyJs) =>
|
||||
secp256k1Sign(msg, pair, undefined, onlyJs)
|
||||
);
|
||||
});
|
||||
@@ -4,25 +4,32 @@
|
||||
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
|
||||
* @description Returns message signature of `message`, using the supplied pair
|
||||
*/
|
||||
export function secp256k1Sign (message: Uint8Array | string, { secretKey }: Partial<Keypair>, hashType: HashType = 'blake2'): Uint8Array {
|
||||
export function secp256k1Sign (message: Uint8Array | string, { secretKey }: Partial<Keypair>, hashType: HashType = 'blake2', onlyJs?: boolean): Uint8Array {
|
||||
assert(secretKey?.length === 32, 'Expected valid secp256k1 secretKey, 32-bytes');
|
||||
|
||||
const key = secp256k1.keyFromPrivate(secretKey);
|
||||
const ecsig = key.sign(secp256k1Hasher(hashType, message));
|
||||
const data = hasher(hashType, message, onlyJs);
|
||||
|
||||
if (!hasBigInt || (!onlyJs && isReady())) {
|
||||
return wasm(data, secretKey);
|
||||
}
|
||||
|
||||
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])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
@@ -15,7 +17,7 @@ describe('sign and verify', (): void => {
|
||||
const sig = '0x92fcacf0946bbd10b31dfe16d567ed1d3014e81007dd9e5256e19c0f07eacc1643b151ca29e449a765e16a7ce59b88d800467d6b3412d30ea8ad22307a59664b00';
|
||||
const msg = stringToU8a('secp256k1');
|
||||
|
||||
expect(secp256k1Verify(msg, sig, address)).toBe(true);
|
||||
expect(secp256k1Verify(msg, sig, address)).toEqual(true);
|
||||
});
|
||||
|
||||
it('has 65-byte signatures', (): void => {
|
||||
@@ -27,25 +29,25 @@ 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)).toBe(true);
|
||||
expect(secp256k1Verify(MESSAGE, signature, address)).toEqual(true);
|
||||
});
|
||||
|
||||
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')).toBe(true);
|
||||
expect(secp256k1Verify(MESSAGE, signature, address, 'keccak')).toEqual(true);
|
||||
});
|
||||
|
||||
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')).toBe(false);
|
||||
expect(secp256k1Verify(MESSAGE, signature, address, 'blake2')).toEqual(false);
|
||||
});
|
||||
|
||||
it('works over a range of random keys (blake2)', (): void => {
|
||||
@@ -57,10 +59,10 @@ describe('sign and verify', (): void => {
|
||||
secp256k1Verify(
|
||||
MESSAGE,
|
||||
secp256k1Sign(MESSAGE, pair, 'blake2'),
|
||||
secp256k1Hasher('blake2', pair.publicKey),
|
||||
hasher('blake2', pair.publicKey),
|
||||
'blake2'
|
||||
)
|
||||
).toBe(true);
|
||||
).toEqual(true);
|
||||
} catch (error) {
|
||||
console.error(`blake2 failed on #${i}`);
|
||||
throw error;
|
||||
@@ -77,10 +79,10 @@ describe('sign and verify', (): void => {
|
||||
secp256k1Verify(
|
||||
MESSAGE,
|
||||
secp256k1Sign(MESSAGE, pair, 'keccak'),
|
||||
secp256k1Hasher('keccak', secp256k1Expand(pair.publicKey)),
|
||||
hasher('keccak', secp256k1Expand(pair.publicKey)),
|
||||
'keccak'
|
||||
)
|
||||
).toBe(true);
|
||||
).toEqual(true);
|
||||
} catch (error) {
|
||||
console.error(`keccak failed on #${i}`);
|
||||
throw error;
|
||||
|
||||
@@ -4,13 +4,22 @@
|
||||
import { secp256k1PrivateKeyTweakAdd } from './tweakAdd';
|
||||
|
||||
describe('TweakAdd', (): void => {
|
||||
describe('PrivateKey TweakAdd', (): void => {
|
||||
it('fails for wrong array length', (): void => {
|
||||
const A = new Uint8Array([0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]);
|
||||
const B = new Uint8Array([3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]);
|
||||
|
||||
expect(
|
||||
() => secp256k1PrivateKeyTweakAdd(A, B)
|
||||
).toThrow(/Expected tweak to be an Uint8Array/);
|
||||
});
|
||||
|
||||
describe.each([false, true])('onlyBn=%p', (onlyBn): void => {
|
||||
it('succeeds for a simple case', (): void => {
|
||||
const A = new Uint8Array([0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]);
|
||||
const B = new Uint8Array([3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]);
|
||||
|
||||
expect(
|
||||
secp256k1PrivateKeyTweakAdd(A, B)
|
||||
secp256k1PrivateKeyTweakAdd(A, B, onlyBn)
|
||||
).toEqual(new Uint8Array([
|
||||
3, 4, 3, 4, 3, 4, 3, 4, 3,
|
||||
4, 3, 4, 3, 4, 3, 4, 3, 4,
|
||||
@@ -18,14 +27,5 @@ describe('TweakAdd', (): void => {
|
||||
4, 3, 4, 3, 4
|
||||
]));
|
||||
});
|
||||
|
||||
it('fails for wrong array length', (): void => {
|
||||
const A = new Uint8Array([0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]);
|
||||
const B = new Uint8Array([3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]);
|
||||
|
||||
expect(
|
||||
() => secp256k1PrivateKeyTweakAdd(A, B)
|
||||
).toThrow(/Expected tweak to be an Uint8Array/);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,32 +1,54 @@
|
||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { assert, BN, bnToU8a, isU8a } from '@polkadot/util';
|
||||
import { _0n, assert, BN, bnToU8a, hasBigInt, isU8a, nToU8a, u8aToBigInt } from '@polkadot/util';
|
||||
import { BigInt } from '@polkadot/x-bigint';
|
||||
|
||||
import { BN_BE_256_OPTS } from '../bn';
|
||||
import { BN_BE_256_OPTS, BN_BE_OPTS } from '../bn';
|
||||
|
||||
// pre-defined curve param as lifted form elliptic
|
||||
// https://github.com/indutny/elliptic/blob/e71b2d9359c5fe9437fbf46f1f05096de447de57/lib/elliptic/curves.js#L182
|
||||
const N = new BN(
|
||||
'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141'.replace(/ /g, ''),
|
||||
'hex'
|
||||
);
|
||||
const N = 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141'.replace(/ /g, '');
|
||||
const N_BI = BigInt(`0x${N}`);
|
||||
const N_BN = new BN(N, 'hex');
|
||||
|
||||
export function secp256k1PrivateKeyTweakAdd (seckey: Uint8Array, tweak: Uint8Array): Uint8Array {
|
||||
function addBi (seckey: Uint8Array, tweak: Uint8Array): Uint8Array {
|
||||
let res = u8aToBigInt(tweak, BN_BE_OPTS);
|
||||
|
||||
assert(res < N_BI, 'Tweak parameter is out of range');
|
||||
|
||||
res += u8aToBigInt(seckey, BN_BE_OPTS);
|
||||
|
||||
if (res >= N_BI) {
|
||||
res -= N_BI;
|
||||
}
|
||||
|
||||
assert(res !== _0n, 'Invalid resulting private key');
|
||||
|
||||
return nToU8a(res, BN_BE_256_OPTS);
|
||||
}
|
||||
|
||||
function addBn (seckey: Uint8Array, tweak: Uint8Array): Uint8Array {
|
||||
const res = new BN(tweak);
|
||||
|
||||
assert(res.cmp(N_BN) < 0, 'Tweak parameter is out of range');
|
||||
|
||||
res.iadd(new BN(seckey));
|
||||
|
||||
if (res.cmp(N_BN) >= 0) {
|
||||
res.isub(N_BN);
|
||||
}
|
||||
|
||||
assert(!res.isZero(), 'Invalid resulting private key');
|
||||
|
||||
return bnToU8a(res, BN_BE_256_OPTS);
|
||||
}
|
||||
|
||||
export function secp256k1PrivateKeyTweakAdd (seckey: Uint8Array, tweak: Uint8Array, onlyBn?: boolean): Uint8Array {
|
||||
assert(isU8a(seckey) && seckey.length === 32, 'Expected seckey to be an Uint8Array with length 32');
|
||||
assert(isU8a(tweak) && tweak.length === 32, 'Expected tweak to be an Uint8Array with length 32');
|
||||
|
||||
const bn = new BN(tweak);
|
||||
|
||||
assert(bn.cmp(N) < 0, 'Tweak parameter is out of range');
|
||||
|
||||
bn.iadd(new BN(seckey));
|
||||
|
||||
if (bn.cmp(N) >= 0) {
|
||||
bn.isub(N);
|
||||
}
|
||||
|
||||
assert(!bn.isZero(), 'Invalid resulting private key');
|
||||
|
||||
return bnToU8a(bn, BN_BE_256_OPTS);
|
||||
return !hasBigInt || onlyBn
|
||||
? addBn(seckey, tweak)
|
||||
: addBi(seckey, tweak);
|
||||
}
|
||||
|
||||
@@ -1,19 +1,75 @@
|
||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { secp256k1Verify } from '.';
|
||||
import '../cryptoInit';
|
||||
|
||||
import { hexToU8a } from '@polkadot/util';
|
||||
import { waitReady } from '@polkadot/wasm-crypto';
|
||||
|
||||
import { performanceWasm } from '../../test/performance';
|
||||
import { hasher } from './hasher';
|
||||
import { secp256k1PairFromSeed, secp256k1Verify } from '.';
|
||||
|
||||
const message = 'Pay KSMs to the Kusama account:88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee';
|
||||
|
||||
describe('secp256k1Verify', (): void => {
|
||||
it('validates known ETH against address', (): void => {
|
||||
const message = 'Pay KSMs to the Kusama account:88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee';
|
||||
|
||||
expect(
|
||||
secp256k1Verify(
|
||||
`\x19Ethereum Signed Message:\n${message.length.toString()}${message}`,
|
||||
'0x55bd020bdbbdc02de34e915effc9b18a99002f4c29f64e22e8dcbb69e722ea6c28e1bb53b9484063fbbfd205e49dcc1f620929f520c9c4c3695150f05a28f52a01',
|
||||
'0x002309df96687e44280bb72c3818358faeeb699c',
|
||||
'keccak'
|
||||
)
|
||||
).toBe(true);
|
||||
beforeEach(async (): Promise<void> => {
|
||||
await waitReady();
|
||||
});
|
||||
|
||||
describe.each([false, true])('onlyJs=%p', (onlyJs): void => {
|
||||
it('validates known ETH against address', (): void => {
|
||||
expect(
|
||||
secp256k1Verify(
|
||||
`\x19Ethereum Signed Message:\n${message.length.toString()}${message}`,
|
||||
'0x55bd020bdbbdc02de34e915effc9b18a99002f4c29f64e22e8dcbb69e722ea6c28e1bb53b9484063fbbfd205e49dcc1f620929f520c9c4c3695150f05a28f52a01',
|
||||
'0x002309df96687e44280bb72c3818358faeeb699c',
|
||||
'keccak',
|
||||
onlyJs
|
||||
)
|
||||
).toEqual(true);
|
||||
});
|
||||
|
||||
describe.each([false, true])('validation against known, publicKey=%p', (isPublic): void => {
|
||||
const pair = secp256k1PairFromSeed(hexToU8a('0x4380de832af797688026ce24f85204d508243f201650c1a134929e5458b7fbae'));
|
||||
const msg = hexToU8a('0xa30b64ce1eedf409c8afb801d72c05234e64849ea538c15dd3c8cf4ffcf166c9');
|
||||
const addr = isPublic
|
||||
? pair.publicKey
|
||||
: hasher('blake2', pair.publicKey, onlyJs);
|
||||
|
||||
it('signature from JS', (): void => {
|
||||
expect(
|
||||
secp256k1Verify(
|
||||
msg,
|
||||
'0xdf92f73d9f060cefacf187b5414491cb992998ace017fa48839b5cda3e264ba8c4efa521361678d9b8582744d77aa4b8d886d7380b7808a683174afad9c4700300',
|
||||
addr,
|
||||
'blake2',
|
||||
onlyJs
|
||||
)
|
||||
).toEqual(true);
|
||||
});
|
||||
|
||||
it('signature from wasm', (): void => {
|
||||
expect(
|
||||
secp256k1Verify(
|
||||
msg,
|
||||
'0xdf92f73d9f060cefacf187b5414491cb992998ace017fa48839b5cda3e264ba83b105adec9e9872647a7d8bb28855b45e22805aea3d097953cbb1391f671d13e01',
|
||||
addr,
|
||||
'blake2',
|
||||
onlyJs
|
||||
)
|
||||
).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
performanceWasm('secp256k1Verify', 100, (_, onlyJs) =>
|
||||
secp256k1Verify(
|
||||
`\x19Ethereum Signed Message:\n${message.length.toString()}${message}`,
|
||||
'0x55bd020bdbbdc02de34e915effc9b18a99002f4c29f64e22e8dcbb69e722ea6c28e1bb53b9484063fbbfd205e49dcc1f620929f520c9c4c3695150f05a28f52a01',
|
||||
'0x002309df96687e44280bb72c3818358faeeb699c',
|
||||
'keccak',
|
||||
onlyJs
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -6,36 +6,26 @@ import type { HashType } from './types';
|
||||
|
||||
import { assert, u8aEq, u8aToU8a } from '@polkadot/util';
|
||||
|
||||
import { secp256k1Expand } from './expand';
|
||||
import { secp256k1Hasher } from './hasher';
|
||||
import { secp256k1 } from './secp256k1';
|
||||
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'): boolean {
|
||||
const isEthereum = hashType === 'keccak';
|
||||
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 = new Uint8Array(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-argument
|
||||
secp256k1
|
||||
.recoverPubKey(
|
||||
secp256k1Hasher(hashType, message),
|
||||
{ r: u8a.slice(0, 32), s: u8a.slice(32, 64) },
|
||||
u8a[64]
|
||||
)
|
||||
.encodeCompressed()
|
||||
);
|
||||
|
||||
const signingAddress = secp256k1Hasher(hashType, isEthereum ? secp256k1Expand(publicKey) : publicKey);
|
||||
const inputAddress = u8aToU8a(address);
|
||||
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
|
||||
return isEthereum
|
||||
? u8aEq(signingAddress.slice(-20), inputAddress.slice(-20))
|
||||
: u8aEq(signingAddress, inputAddress);
|
||||
return u8aEq(publicKey, inputAddr) || (
|
||||
hashType === 'keccak'
|
||||
? u8aEq(signerAddr.slice(-20), inputAddr.slice(-20))
|
||||
: u8aEq(signerAddr, inputAddr)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@ import type { HexString } from '@polkadot/util/types';
|
||||
|
||||
import { hasBigInt, u8aToU8a } from '@polkadot/util';
|
||||
import { isReady, sha256, sha512 } from '@polkadot/wasm-crypto';
|
||||
import { sha256 as sha256Js } from '@polkadot/x-noble-hashes/sha256';
|
||||
import { sha512 as sha512Js } from '@polkadot/x-noble-hashes/sha512';
|
||||
|
||||
import { createBitHasher } from '../helpers';
|
||||
import { sha256 as sha256Js } from '../noble-hashes/lib/sha256';
|
||||
import { sha512 as sha512Js } from '../noble-hashes/lib/sha512';
|
||||
|
||||
type BitLength = 256 | 512;
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { _0n, _1n, _n } from '@polkadot/util';
|
||||
import { _0n, _1n } from '@polkadot/util';
|
||||
import { BigInt } from '@polkadot/x-bigint';
|
||||
|
||||
// Adapted from https://github.com/pierrec/js-xxhash/blob/0504e76f3d31a21ae8528a7f590c7289c9e431d2/lib/xxhash64.js
|
||||
//
|
||||
@@ -26,29 +27,29 @@ interface State {
|
||||
v4: bigint;
|
||||
}
|
||||
|
||||
const P64_1 = _n('11400714785074694791');
|
||||
const P64_2 = _n('14029467366897019727');
|
||||
const P64_3 = _n('1609587929392839161');
|
||||
const P64_4 = _n('9650029242287828579');
|
||||
const P64_5 = _n('2870177450012600261');
|
||||
const P64_1 = BigInt('11400714785074694791');
|
||||
const P64_2 = BigInt('14029467366897019727');
|
||||
const P64_3 = BigInt('1609587929392839161');
|
||||
const P64_4 = BigInt('9650029242287828579');
|
||||
const P64_5 = BigInt('2870177450012600261');
|
||||
|
||||
// mask for a u64, all bits set
|
||||
const U64 = _n('0xffffffffffffffff');
|
||||
const U64 = BigInt('0xffffffffffffffff');
|
||||
|
||||
// various constants
|
||||
const _7n = _n(7);
|
||||
const _11n = _n(11);
|
||||
const _12n = _n(12);
|
||||
const _16n = _n(16);
|
||||
const _18n = _n(18);
|
||||
const _23n = _n(23);
|
||||
const _27n = _n(27);
|
||||
const _29n = _n(29);
|
||||
const _31n = _n(31);
|
||||
const _32n = _n(32);
|
||||
const _33n = _n(33);
|
||||
const _64n = _n(64);
|
||||
const _256n = _n(256);
|
||||
const _7n = BigInt(7);
|
||||
const _11n = BigInt(11);
|
||||
const _12n = BigInt(12);
|
||||
const _16n = BigInt(16);
|
||||
const _18n = BigInt(18);
|
||||
const _23n = BigInt(23);
|
||||
const _27n = BigInt(27);
|
||||
const _29n = BigInt(29);
|
||||
const _31n = BigInt(31);
|
||||
const _32n = BigInt(32);
|
||||
const _33n = BigInt(33);
|
||||
const _64n = BigInt(64);
|
||||
const _256n = BigInt(256);
|
||||
|
||||
function rotl (a: bigint, b: bigint): bigint {
|
||||
const c = a & U64;
|
||||
|
||||
@@ -10,8 +10,8 @@ type ExecFn = (input: Uint8Array, onlyJs: boolean) => unknown;
|
||||
|
||||
const GENERATED = arrayRange(256).map(() => [randomAsU8a()]);
|
||||
|
||||
export function performanceWasm (name: string, count: number, exec: ExecFn): void {
|
||||
performanceCmp(name, ['WebAssembly', 'JavaScript'], count, GENERATED, exec);
|
||||
export function performanceWasm (name: string, count: number, exec: ExecFn, inputs = GENERATED): void {
|
||||
performanceCmp(name, ['WebAssembly', 'JavaScript'], count, inputs, exec);
|
||||
}
|
||||
|
||||
export { performance, performanceCmp };
|
||||
|
||||
@@ -34,12 +34,14 @@
|
||||
"./detectPackage.cjs"
|
||||
],
|
||||
"type": "module",
|
||||
"version": "8.0.3",
|
||||
"version": "8.1.2",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.16.3",
|
||||
"@polkadot/x-textdecoder": "8.0.3",
|
||||
"@polkadot/x-textencoder": "8.0.3",
|
||||
"@polkadot/x-bigint": "8.1.2",
|
||||
"@polkadot/x-global": "8.1.2",
|
||||
"@polkadot/x-textdecoder": "8.1.2",
|
||||
"@polkadot/x-textencoder": "8.1.2",
|
||||
"@types/bn.js": "^4.11.6",
|
||||
"bn.js": "^4.12.0",
|
||||
"ip-regex": "^4.3.0"
|
||||
|
||||
@@ -1,39 +1,31 @@
|
||||
// Copyright 2017-2021 @polkadot/util authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
type NewBigInt = (value: string | number | bigint | boolean) => bigint;
|
||||
|
||||
/**
|
||||
* @name _n
|
||||
* @description Creates a new instance of BigInt in environments that do support it
|
||||
*/
|
||||
export const _n: NewBigInt = typeof BigInt !== 'undefined'
|
||||
? BigInt
|
||||
: () => Number.NaN as unknown as bigint;
|
||||
import { BigInt } from '@polkadot/x-bigint';
|
||||
|
||||
/**
|
||||
* @name _0n
|
||||
* @summary BigInt constant for 0.
|
||||
*/
|
||||
export const _0n = _n(0);
|
||||
export const _0n = BigInt(0);
|
||||
|
||||
/**
|
||||
* @name _1n
|
||||
* @summary BigInt constant for 1.
|
||||
*/
|
||||
export const _1n = _n(1);
|
||||
export const _1n = BigInt(1);
|
||||
|
||||
/**
|
||||
* @name _1Mn
|
||||
* @summary BigInt constant for 1,000,000.
|
||||
*/
|
||||
export const _1Mn = _n(1_000_000);
|
||||
export const _1Mn = BigInt(1_000_000);
|
||||
|
||||
/**
|
||||
* @name _1Bn
|
||||
* @summary BigInt constant for 1,000,000,000.
|
||||
*/
|
||||
export const _1Bn = _n(1_000_000_000);
|
||||
export const _1Bn = BigInt(1_000_000_000);
|
||||
|
||||
/**
|
||||
* @name _1Qn
|
||||
@@ -45,4 +37,4 @@ export const _1Qn = _1Bn * _1Bn;
|
||||
* @name _2pow53n
|
||||
* @summary BigInt constant for MAX_SAFE_INTEGER
|
||||
*/
|
||||
export const _2pow53n = _n(Number.MAX_SAFE_INTEGER);
|
||||
export const _2pow53n = BigInt(Number.MAX_SAFE_INTEGER);
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
import type { BN } from '../bn';
|
||||
import type { ToBigInt, ToBn } from '../types';
|
||||
|
||||
import { BigInt } from '@polkadot/x-bigint';
|
||||
|
||||
import { assert } from '../assert';
|
||||
import { _0n, _1n, _2pow53n, _n } from './consts';
|
||||
import { _0n, _1n, _2pow53n } from './consts';
|
||||
import { nToBigInt } from './toBigInt';
|
||||
|
||||
const _sqrt2pow53n = _n(94906265);
|
||||
const _sqrt2pow53n = BigInt(94906265);
|
||||
|
||||
/**
|
||||
* @name nSqrt
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
import type { BN } from '../bn/bn';
|
||||
import type { HexString, ToBigInt, ToBn } from '../types';
|
||||
|
||||
import { BigInt } from '@polkadot/x-bigint';
|
||||
|
||||
import { hexToBigInt } from '../hex/toBigInt';
|
||||
import { isBn } from '../is/bn';
|
||||
import { isHex } from '../is/hex';
|
||||
|
||||
@@ -4,16 +4,18 @@
|
||||
import type { BN } from '../bn/bn';
|
||||
import type { ToBigInt, ToBn, ToBnOptions } from '../types';
|
||||
|
||||
import { BigInt } from '@polkadot/x-bigint';
|
||||
|
||||
import { objectSpread } from '../object/spread';
|
||||
import { _0n, _1n, _n } from './consts';
|
||||
import { _0n, _1n } from './consts';
|
||||
import { nToBigInt } from './toBigInt';
|
||||
|
||||
interface Options extends ToBnOptions {
|
||||
bitLength?: number;
|
||||
}
|
||||
|
||||
const DIV = _n(256);
|
||||
const NEG_MASK = _n(0xff);
|
||||
const DIV = BigInt(256);
|
||||
const NEG_MASK = BigInt(0xff);
|
||||
|
||||
function createEmpty ({ bitLength = 0 }: Options): Uint8Array {
|
||||
return bitLength === -1
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright 2017-2021 @polkadot/util authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export const hasBigInt = typeof BigInt !== 'undefined';
|
||||
import { BigInt } from '@polkadot/x-bigint';
|
||||
|
||||
export const hasBigInt = typeof BigInt === 'function' && typeof BigInt.asIntN === 'function';
|
||||
export const hasBuffer = typeof Buffer !== 'undefined';
|
||||
export const hasDirname = typeof __dirname !== 'undefined';
|
||||
export const hasProcess = typeof process === 'object';
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
import type { ToBnOptions } from '../types';
|
||||
|
||||
import { BigInt } from '@polkadot/x-bigint';
|
||||
|
||||
import { objectSpread } from '../object/spread';
|
||||
import { u8aToBigInt } from '../u8a/toBigInt';
|
||||
import { hexToU8a } from './toU8a';
|
||||
|
||||
@@ -16,5 +16,5 @@
|
||||
* ```
|
||||
*/
|
||||
export function isBigInt (value: unknown): value is bigint {
|
||||
return typeof value === 'bigint' || value instanceof BigInt;
|
||||
return typeof value === 'bigint';
|
||||
}
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
// Auto-generated by @polkadot/dev, do not edit
|
||||
|
||||
export const packageInfo = { name: '@polkadot/util', version: '8.0.3' };
|
||||
export const packageInfo = { name: '@polkadot/util', version: '8.1.2' };
|
||||
|
||||
@@ -33,8 +33,8 @@ const randomWords = arrayRange(256).map((): [string] => {
|
||||
describe('stringCamelCase', (): void => {
|
||||
it('works correctly', (): void => {
|
||||
expect(
|
||||
stringCamelCase('Snake_case-...Something spaced')
|
||||
).toBe('snakeCaseSomethingSpaced');
|
||||
stringCamelCase('Snake_case-...SomethingSomething spaced')
|
||||
).toBe('snakeCaseSomethingSomethingSpaced');
|
||||
});
|
||||
|
||||
it('works correctly for String (class', (): void => {
|
||||
@@ -47,6 +47,39 @@ describe('stringCamelCase', (): void => {
|
||||
expect(
|
||||
stringCamelCase('DEDUP_KEY_PREFIX')
|
||||
).toEqual('dedupKeyPrefix');
|
||||
expect(
|
||||
stringCamelCase('SOMETHING')
|
||||
).toEqual('something');
|
||||
expect(
|
||||
stringCamelCase('NMap')
|
||||
).toEqual('nMap');
|
||||
});
|
||||
|
||||
it('adjusts all-uppercase + digits', (): void => {
|
||||
expect(
|
||||
stringCamelCase('SS58 PreFIX')
|
||||
).toEqual('ss58PreFIX');
|
||||
expect(
|
||||
stringCamelCase('SS58Prefix')
|
||||
).toEqual('ss58Prefix');
|
||||
expect(
|
||||
stringCamelCase('UUID64')
|
||||
).toEqual('uuid64');
|
||||
expect(
|
||||
stringCamelCase('BLAKE2B')
|
||||
).toEqual('blake2b');
|
||||
});
|
||||
|
||||
it('adjusts with leading _', (): void => {
|
||||
expect(
|
||||
stringCamelCase('_reserved')
|
||||
).toEqual('reserved');
|
||||
});
|
||||
|
||||
it('adjusts with minimal chars per part', (): void => {
|
||||
expect(
|
||||
stringCamelCase('_a_b_c_def')
|
||||
).toEqual('aBCDef');
|
||||
});
|
||||
|
||||
performance('stringCamelCase', 64000, randomWords, stringCamelCase);
|
||||
|
||||
@@ -3,29 +3,40 @@
|
||||
|
||||
import type { AnyString } from '../types';
|
||||
|
||||
// Adapted from https://stackoverflow.com/a/2970667
|
||||
// Inspired from https://stackoverflow.com/a/2970667
|
||||
//
|
||||
// this is not as optimal as the original asnwer (we split into multiple),
|
||||
// this is not as optimal as the original answer (we split into multiple),
|
||||
// however it does pass the tests (which the original doesn't) and it is still
|
||||
// a 10+x improvement over the original camelcase npm package (at running)
|
||||
//
|
||||
// original: 20.88 μs/op
|
||||
// this: 1.75 μs/op
|
||||
// this: 2.97 μs/op
|
||||
//
|
||||
// Caveat of this: only Ascii, but acceptable for the intended usecase
|
||||
function converter (fn: (w: string, i: number) => string): (value: AnyString) => string {
|
||||
const format = (w: string, i: number) => fn(w[0], i) + w.slice(1);
|
||||
|
||||
return (value: AnyString): string =>
|
||||
value
|
||||
.toString()
|
||||
// replace all seperators (including consequtive) with spaces
|
||||
.replace(/[-_., ]+/g, ' ')
|
||||
// we don't want leading or trailing spaces
|
||||
.trim()
|
||||
// split into words
|
||||
.split(' ')
|
||||
// apply the formatting
|
||||
.map((w, i) =>
|
||||
fn(w[0], i) + (
|
||||
format(
|
||||
w.toUpperCase() === w
|
||||
? w.slice(1).toLowerCase()
|
||||
: w.slice(1)
|
||||
// all full uppercase + letters are changed to lowercase
|
||||
? w.toLowerCase()
|
||||
// all consecutive capitals + letters are changed to lowercase
|
||||
: w.replace(/[A-Z]{2,}[0-9]{2,}/g, (w) => w.toLowerCase()),
|
||||
i
|
||||
)
|
||||
)
|
||||
// combine into a single word
|
||||
.join('');
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
|
||||
import type { ToBnOptions } from '../types';
|
||||
|
||||
import { _1n, _n } from '../bi/consts';
|
||||
import { BigInt } from '@polkadot/x-bigint';
|
||||
|
||||
import { _1n } from '../bi/consts';
|
||||
import { objectSpread } from '../object/spread';
|
||||
|
||||
const U8_MAX = _n(256);
|
||||
const U16_MAX = _n(256 * 256);
|
||||
const U8_MAX = BigInt(256);
|
||||
const U16_MAX = BigInt(256 * 256);
|
||||
|
||||
function xor (input: Uint8Array): Uint8Array {
|
||||
const result = new Uint8Array(input.length);
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# @polkadot/x-bigint
|
||||
|
||||
A cross-environment BigInt.
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"bugs": "https://github.com/polkadot-js/common/issues",
|
||||
"contributors": [],
|
||||
"description": "A cross-environment BigInt replacement",
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"homepage": "https://github.com/polkadot-js/common/tree/master/packages/x-bigint#readme",
|
||||
"license": "Apache-2.0",
|
||||
"maintainers": [],
|
||||
"name": "@polkadot/x-bigint",
|
||||
"repository": {
|
||||
"directory": "packages/x-bigint",
|
||||
"type": "git",
|
||||
"url": "https://github.com/polkadot-js/common.git"
|
||||
},
|
||||
"sideEffects": [
|
||||
"./shim.js",
|
||||
"./shim.cjs"
|
||||
],
|
||||
"type": "module",
|
||||
"version": "8.1.2",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.16.3",
|
||||
"@polkadot/x-global": "8.1.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright 2017-2021 @polkadot/x-bigint authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { xglobal } from '@polkadot/x-global';
|
||||
|
||||
export { packageInfo } from './packageInfo';
|
||||
|
||||
export const BigInt: BigIntConstructor = typeof xglobal.BigInt === 'function' && typeof xglobal.BigInt.asIntN === 'function'
|
||||
? xglobal.BigInt
|
||||
: (() => Number.NaN) as unknown as BigIntConstructor;
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2017-2021 @polkadot/x-bigint authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Auto-generated by @polkadot/dev, do not edit
|
||||
|
||||
export const packageInfo = { name: '@polkadot/x-bigint', version: '8.1.2' };
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright 2017-2021 @polkadot/x-bigint authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { BigInt } from '@polkadot/x-bigint';
|
||||
import { xglobal } from '@polkadot/x-global';
|
||||
|
||||
if (typeof xglobal.BigInt !== 'function') {
|
||||
(xglobal as Record<string, unknown>).BigInt = BigInt;
|
||||
}
|
||||
@@ -17,11 +17,11 @@
|
||||
},
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"version": "8.0.3",
|
||||
"version": "8.1.2",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.16.3",
|
||||
"@polkadot/util": "8.0.3",
|
||||
"@polkadot/util": "8.1.2",
|
||||
"buffer-es6": "^4.9.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
// Auto-generated by @polkadot/dev, do not edit
|
||||
|
||||
export const packageInfo = { name: '@polkadot/x-bundle', version: '8.0.3' };
|
||||
export const packageInfo = { name: '@polkadot/x-bundle', version: '8.1.2' };
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
},
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"version": "8.0.3",
|
||||
"version": "8.1.2",
|
||||
"browser": "browser.js",
|
||||
"main": "node.js",
|
||||
"react-native": "react-native.js",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.16.3",
|
||||
"@polkadot/x-global": "8.0.3",
|
||||
"@polkadot/x-global": "8.1.2",
|
||||
"@types/node-fetch": "^2.5.12",
|
||||
"node-fetch": "^2.6.6"
|
||||
}
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
// Auto-generated by @polkadot/dev, do not edit
|
||||
|
||||
export const packageInfo = { name: '@polkadot/x-fetch', version: '8.0.3' };
|
||||
export const packageInfo = { name: '@polkadot/x-fetch', version: '8.1.2' };
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright 2017-2021 @polkadot/x-fetch authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { fetch } from '@polkadot/x-fetch';
|
||||
import { xglobal } from '@polkadot/x-global';
|
||||
|
||||
if (typeof xglobal.fetch !== 'function') {
|
||||
(xglobal as Record<string, unknown>).fetch = fetch;
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
},
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"version": "8.0.3",
|
||||
"version": "8.1.2",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.16.3"
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
// Auto-generated by @polkadot/dev, do not edit
|
||||
|
||||
export const packageInfo = { name: '@polkadot/x-global', version: '8.0.3' };
|
||||
export const packageInfo = { name: '@polkadot/x-global', version: '8.1.2' };
|
||||
|
||||
+33
-33
@@ -38,7 +38,7 @@ Use NPM in node.js / browser, or include single file from
|
||||
The library does not have an entry point. It allows you to select specific primitives and drop everything else. If you only want to use sha256, just use the library with rollup or other bundlers. This is done to make your bundles tiny.
|
||||
|
||||
```js
|
||||
const { sha256 } = require('../noble-hashes/lib/sha256');
|
||||
const { sha256 } = require('@noble/hashes/lib/sha256');
|
||||
console.log(sha256(new Uint8Array([1, 2, 3])));
|
||||
// Uint8Array(32) [3, 144, 88, 198, 242, 192, 203, 73, ...]
|
||||
|
||||
@@ -46,30 +46,30 @@ console.log(sha256(new Uint8Array([1, 2, 3])));
|
||||
console.log(sha256('abc'))); // == sha256(new TextEncoder().encode('abc'))
|
||||
|
||||
// sha384 is here, because it uses same internals as sha512
|
||||
const { sha512, sha512_256, sha384 } = require('../noble-hashes/lib/sha512');
|
||||
const { sha512, sha512_256, sha384 } = require('@noble/hashes/lib/sha512');
|
||||
// prettier-ignore
|
||||
const {
|
||||
sha3_224, sha3_256, sha3_384, sha3_512,
|
||||
keccak_224, keccak_256, keccak_384, keccak_512,
|
||||
shake128, shake256
|
||||
} = require('../noble-hashes/lib/sha3');
|
||||
} = require('@noble/hashes/lib/sha3');
|
||||
// prettier-ignore
|
||||
const {
|
||||
cshake128, cshake256, kmac128, kmac256,
|
||||
k12, m14,
|
||||
tuplehash256, parallelhash256, keccakprg
|
||||
} = require('../noble-hashes/lib/sha3-addons');
|
||||
const { ripemd160 } = require('../noble-hashes/lib/ripemd160');
|
||||
const { blake3 } = require('../noble-hashes/lib/blake3');
|
||||
const { blake2b } = require('../noble-hashes/lib/blake2b');
|
||||
const { blake2s } = require('../noble-hashes/lib/blake2s');
|
||||
const { hmac } = require('../noble-hashes/lib/hmac');
|
||||
const { hkdf } = require('../noble-hashes/lib/hkdf');
|
||||
const { pbkdf2, pbkdf2Async } = require('../noble-hashes/lib/pbkdf2');
|
||||
const { scrypt, scryptAsync } = require('../noble-hashes/lib/scrypt');
|
||||
} = require('@noble/hashes/lib/sha3-addons');
|
||||
const { ripemd160 } = require('@noble/hashes/lib/ripemd160');
|
||||
const { blake3 } = require('@noble/hashes/lib/blake3');
|
||||
const { blake2b } = require('@noble/hashes/lib/blake2b');
|
||||
const { blake2s } = require('@noble/hashes/lib/blake2s');
|
||||
const { hmac } = require('@noble/hashes/lib/hmac');
|
||||
const { hkdf } = require('@noble/hashes/lib/hkdf');
|
||||
const { pbkdf2, pbkdf2Async } = require('@noble/hashes/lib/pbkdf2');
|
||||
const { scrypt, scryptAsync } = require('@noble/hashes/lib/scrypt');
|
||||
|
||||
// small utility method that converts bytes to hex
|
||||
const { bytesToHex as toHex } = require('../noble-hashes/lib/utils');
|
||||
const { bytesToHex as toHex } = require('@noble/hashes/lib/utils');
|
||||
console.log(toHex(sha256('abc')));
|
||||
// ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
|
||||
```
|
||||
@@ -124,7 +124,7 @@ _Some_ hash functions can also receive `options` object, which can be either pas
|
||||
##### SHA2 (sha256, sha384, sha512, sha512_256)
|
||||
|
||||
```typescript
|
||||
import { sha256 } from '../noble-hashes/lib/sha256.js';
|
||||
import { sha256 } from '@noble/hashes/lib/sha256.js';
|
||||
const h1a = sha256('abc');
|
||||
const h1b = sha256
|
||||
.create()
|
||||
@@ -133,7 +133,7 @@ const h1b = sha256
|
||||
```
|
||||
|
||||
```typescript
|
||||
import { sha512 } from '../noble-hashes/lib/sha512.js';
|
||||
import { sha512 } from '@noble/hashes/lib/sha512.js';
|
||||
const h2a = sha512('abc');
|
||||
const h2b = sha512
|
||||
.create()
|
||||
@@ -141,7 +141,7 @@ const h2b = sha512
|
||||
.digest();
|
||||
|
||||
// SHA512/256 variant
|
||||
import { sha512_256 } from '../noble-hashes/lib/sha512.js';
|
||||
import { sha512_256 } from '@noble/hashes/lib/sha512.js';
|
||||
const h3a = sha512_256('abc');
|
||||
const h3b = sha512_256
|
||||
.create()
|
||||
@@ -149,7 +149,7 @@ const h3b = sha512_256
|
||||
.digest();
|
||||
|
||||
// SHA384
|
||||
import { sha384 } from '../noble-hashes/lib/sha512.js';
|
||||
import { sha384 } from '@noble/hashes/lib/sha512.js';
|
||||
const h4a = sha384('abc');
|
||||
const h4b = sha384
|
||||
.create()
|
||||
@@ -173,7 +173,7 @@ import {
|
||||
keccak_512,
|
||||
shake128,
|
||||
shake256,
|
||||
} from '../noble-hashes/lib/sha3.js';
|
||||
} from '@noble/hashes/lib/sha3.js';
|
||||
const h5a = sha3_256('abc');
|
||||
const h5b = sha3_256
|
||||
.create()
|
||||
@@ -203,7 +203,7 @@ import {
|
||||
parallelhash128,
|
||||
parallelhash256,
|
||||
keccakprg,
|
||||
} from '../noble-hashes/lib/sha3-addons.js';
|
||||
} from '@noble/hashes/lib/sha3-addons.js';
|
||||
const h7c = cshake128('abc', { personalization: 'def' });
|
||||
const h7d = cshake256('abc', { personalization: 'def' });
|
||||
const h7e = kmac128('key', 'message');
|
||||
@@ -228,7 +228,7 @@ const rand1b = p.fetch(1);
|
||||
##### RIPEMD-160
|
||||
|
||||
```typescript
|
||||
import { ripemd160 } from '../noble-hashes/lib/ripemd160.js';
|
||||
import { ripemd160 } from '@noble/hashes/lib/ripemd160.js';
|
||||
// function ripemd160(data: Uint8Array): Uint8Array;
|
||||
const hash8 = ripemd160('abc');
|
||||
const hash9 = ripemd160()
|
||||
@@ -242,8 +242,8 @@ See [RFC 2286](https://datatracker.ietf.org/doc/html/rfc2286), [Website](https:/
|
||||
##### BLAKE2b, BLAKE2s
|
||||
|
||||
```typescript
|
||||
import { blake2b } from '../noble-hashes/lib/blake2b.js';
|
||||
import { blake2s } from '../noble-hashes/lib/blake2s.js';
|
||||
import { blake2b } from '@noble/hashes/lib/blake2b.js';
|
||||
import { blake2s } from '@noble/hashes/lib/blake2s.js';
|
||||
const h10a = blake2s('abc');
|
||||
const b2params = { key: new Uint8Array([1]), personalization: t, salt: t, dkLen: 32 };
|
||||
const h10b = blake2s('abc', b2params);
|
||||
@@ -258,7 +258,7 @@ See [RFC 7693](https://datatracker.ietf.org/doc/html/rfc7693), [Website](https:/
|
||||
##### BLAKE3
|
||||
|
||||
```typescript
|
||||
import { blake3 } from '../noble-hashes/lib/blake3.js';
|
||||
import { blake3 } from '@noble/hashes/lib/blake3.js';
|
||||
// All params are optional
|
||||
const h11 = blake3('abc', { dkLen: 256, key: 'def', context: 'fji' });
|
||||
```
|
||||
@@ -268,8 +268,8 @@ See [Website](https://blake3.io).
|
||||
##### HMAC
|
||||
|
||||
```typescript
|
||||
import { hmac } from '../noble-hashes/lib/hmac.js';
|
||||
import { sha256 } from '../noble-hashes/lib/sha256.js';
|
||||
import { hmac } from '@noble/hashes/lib/hmac.js';
|
||||
import { sha256 } from '@noble/hashes/lib/sha256.js';
|
||||
const mac1 = hmac(sha256, 'key', 'message');
|
||||
const mac2 = hmac.create(sha256, Uint8Array.from([1, 2, 3])).update(Uint8Array.from([4, 5, 6]).digest();
|
||||
```
|
||||
@@ -279,8 +279,8 @@ Matches [RFC 2104](https://datatracker.ietf.org/doc/html/rfc2104).
|
||||
##### HKDF
|
||||
|
||||
```typescript
|
||||
import { hkdf } from '../noble-hashes/lib/kdf.js';
|
||||
import { sha256 } from '../noble-hashes/lib/sha256.js';
|
||||
import { hkdf } from '@noble/hashes/lib/kdf.js';
|
||||
import { sha256 } from '@noble/hashes/lib/sha256.js';
|
||||
import { randomBytes } from '../noble-hashes/utils.js';
|
||||
const inputKey = randomBytes(32);
|
||||
const salt = randomBytes(32);
|
||||
@@ -289,8 +289,8 @@ const dkLen = 32;
|
||||
const hk1 = hkdf(sha256, inputKey, salt, info, dkLen);
|
||||
|
||||
// == same as
|
||||
import { hkdf_extract, hkdf_expand } from '../noble-hashes/lib/kdf.js';
|
||||
import { sha256 } from '../noble-hashes/lib/sha256.js';
|
||||
import { hkdf_extract, hkdf_expand } from '@noble/hashes/lib/kdf.js';
|
||||
import { sha256 } from '@noble/hashes/lib/sha256.js';
|
||||
const prk = hkdf_extract(sha256, inputKey, salt);
|
||||
const hk2 = hkdf_expand(sha256, prk, info, dkLen);
|
||||
```
|
||||
@@ -300,8 +300,8 @@ Matches [RFC 5869](https://datatracker.ietf.org/doc/html/rfc5869).
|
||||
##### PBKDF2
|
||||
|
||||
```typescript
|
||||
import { pbkdf2, pbkdf2Async } from '../noble-hashes/lib/pbkdf2.js';
|
||||
import { sha256 } from '../noble-hashes/lib/sha256.js';
|
||||
import { pbkdf2, pbkdf2Async } from '@noble/hashes/lib/pbkdf2.js';
|
||||
import { sha256 } from '@noble/hashes/lib/sha256.js';
|
||||
const pbkey1 = pbkdf2(sha256, 'password', 'salt', { c: 32, dkLen: 32 });
|
||||
const pbkey2 = await pbkdf2Async(sha256, 'password', 'salt', { c: 32, dkLen: 32 });
|
||||
const pbkey3 = await pbkdf2Async(sha256, Uint8Array.from([1, 2, 3]), Uint8Array.from([4, 5, 6]), {
|
||||
@@ -315,7 +315,7 @@ Matches [RFC 2898](https://datatracker.ietf.org/doc/html/rfc2898).
|
||||
##### Scrypt
|
||||
|
||||
```typescript
|
||||
import { scrypt, scryptAsync } from '../noble-hashes/lib/scrypt.js';
|
||||
import { scrypt, scryptAsync } from '@noble/hashes/lib/scrypt.js';
|
||||
const scr1 = scrypt('password', 'salt', { N: 2 ** 16, r: 8, p: 1, dkLen: 32 });
|
||||
const scr2 = await scryptAsync('password', 'salt', { N: 2 ** 16, r: 8, p: 1, dkLen: 32 });
|
||||
const scr3 = await scryptAsync(Uint8Array.from([1, 2, 3]), Uint8Array.from([4, 5, 6]), {
|
||||
@@ -348,7 +348,7 @@ arrays bigger than 4GB impossible, but we're looking into other possible solutio
|
||||
##### utils
|
||||
|
||||
```typescript
|
||||
import { bytesToHex as toHex, randomBytes } from '../noble-hashes/lib/scrypt.js';
|
||||
import { bytesToHex as toHex, randomBytes } from '@noble/hashes/lib/scrypt.js';
|
||||
console.log(toHex(randomBytes(32)));
|
||||
```
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"bugs": "https://github.com/polkadot-js/common/issues",
|
||||
"contributors": [],
|
||||
"description": "An fork of @noble/hashes with extra protection on BigInt usage",
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"homepage": "https://github.com/polkadot-js/common/tree/master/packages/x-noble-hashes#readme",
|
||||
"license": "MIT",
|
||||
"maintainers": [],
|
||||
"name": "@polkadot/x-noble-hashes",
|
||||
"repository": {
|
||||
"directory": "packages/x-noble-hashes",
|
||||
"type": "git",
|
||||
"url": "https://github.com/polkadot-js/common.git"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"version": "8.1.2",
|
||||
"browser": {
|
||||
"crypto": false
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.16.3"
|
||||
}
|
||||
}
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
/*! noble-hashes - MIT License (c) 2021 Paul Miller (paulmillr.com) */
|
||||
// https://github.com/paulmillr/noble-hashes/pull/13
|
||||
import { assertNumber, Hash, Input, toBytes, u32 } from './utils';
|
||||
// prettier-ignore
|
||||
export const SIGMA = new Uint8Array([
|
||||
+5
-7
@@ -1,16 +1,14 @@
|
||||
/*! noble-hashes - MIT License (c) 2021 Paul Miller (paulmillr.com) */
|
||||
// https://github.com/paulmillr/noble-hashes/pull/13
|
||||
import { _n, Hash, createView, Input, toBytes } from './utils';
|
||||
|
||||
const _32n = _n(32);
|
||||
const _u32_max = _n(0xffffffff);
|
||||
import { Hash, createView, Input, toBytes } from './utils';
|
||||
|
||||
// Polyfill for Safari 14
|
||||
function setBigUint64(view: DataView, byteOffset: number, value: bigint, isLE: boolean): void {
|
||||
if (typeof view.setBigUint64 === 'function') return view.setBigUint64(byteOffset, value, isLE);
|
||||
const _32n = BigInt(32);
|
||||
const _u32_max = BigInt(0xffffffff);
|
||||
const wh = Number((value >> _32n) & _u32_max);
|
||||
const wl = Number(value & _u32_max);
|
||||
const [h, l] = isLE ? [4, 0] : [0, 4];
|
||||
const h = isLE ? 4 : 0;
|
||||
const l = isLE ? 0 : 4;
|
||||
view.setUint32(byteOffset + h, wh, isLE);
|
||||
view.setUint32(byteOffset + l, wl, isLE);
|
||||
}
|
||||
+4
-8
@@ -1,10 +1,5 @@
|
||||
/*! noble-hashes - MIT License (c) 2021 Paul Miller (paulmillr.com) */
|
||||
// https://github.com/paulmillr/noble-hashes/pull/13
|
||||
import { _n } from './utils';
|
||||
|
||||
const U32_MASK64 = _n(2 ** 32 - 1);
|
||||
|
||||
const _32n = _n(32);
|
||||
const U32_MASK64 = BigInt(2 ** 32 - 1);
|
||||
const _32n = BigInt(32);
|
||||
|
||||
export function fromBig(n: bigint, le = false) {
|
||||
if (le) return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) };
|
||||
@@ -12,7 +7,8 @@ export function fromBig(n: bigint, le = false) {
|
||||
}
|
||||
|
||||
export function split(lst: bigint[], le = false) {
|
||||
let [Ah, Al] = [new Uint32Array(lst.length), new Uint32Array(lst.length)];
|
||||
let Ah = new Uint32Array(lst.length);
|
||||
let Al = new Uint32Array(lst.length);
|
||||
for (let i = 0; i < lst.length; i++) {
|
||||
const { h, l } = fromBig(lst[i], le);
|
||||
[Ah[i], Al[i]] = [h, l];
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
/*! noble-hashes - MIT License (c) 2021 Paul Miller (paulmillr.com) */
|
||||
// https://github.com/paulmillr/noble-hashes/pull/13
|
||||
import * as blake2 from './_blake2';
|
||||
import * as u64 from './_u64';
|
||||
import { toBytes, u32, wrapConstructorWithOpts } from './utils';
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
/*! noble-hashes - MIT License (c) 2021 Paul Miller (paulmillr.com) */
|
||||
// https://github.com/paulmillr/noble-hashes/pull/13
|
||||
import * as u64 from './_u64';
|
||||
import * as blake2 from './_blake2';
|
||||
import { rotr, toBytes, wrapConstructorWithOpts, u32 } from './utils';
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
/*! noble-hashes - MIT License (c) 2021 Paul Miller (paulmillr.com) */
|
||||
// https://github.com/paulmillr/noble-hashes/pull/13
|
||||
import * as u64 from './_u64';
|
||||
import * as blake2 from './_blake2';
|
||||
import * as blake2s from './blake2s';
|
||||
@@ -0,0 +1,6 @@
|
||||
import nodeCrypto from 'crypto';
|
||||
|
||||
export const crypto: { node?: any; web?: any } = {
|
||||
node: nodeCrypto,
|
||||
web: undefined,
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
// Global symbol available in browsers only
|
||||
declare const self: Record<string, any> | undefined;
|
||||
export const crypto: { node?: any; web?: any } = {
|
||||
node: undefined,
|
||||
web: typeof self === 'object' && 'crypto' in self ? self.crypto : undefined,
|
||||
};
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
/*! noble-hashes - MIT License (c) 2021 Paul Miller (paulmillr.com) */
|
||||
// https://github.com/paulmillr/noble-hashes/pull/13
|
||||
// prettier-ignore
|
||||
import {
|
||||
assertHash, assertNumber, CHash, Input, toBytes
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
/*! noble-hashes - MIT License (c) 2021 Paul Miller (paulmillr.com) */
|
||||
// https://github.com/paulmillr/noble-hashes/pull/13
|
||||
import { assertHash, Hash, CHash, Input, toBytes } from './utils';
|
||||
// HMAC (RFC 2104)
|
||||
class HMAC<T extends Hash<T>> extends Hash<HMAC<T>> {
|
||||
@@ -0,0 +1,3 @@
|
||||
throw new Error(
|
||||
'noble-hashes have no entry-point. Please consult the README.md to learn how to use them'
|
||||
);
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2017-2021 @polkadot/x-noble-hashes authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Auto-generated by @polkadot/dev, do not edit
|
||||
|
||||
export const packageInfo = { name: '@polkadot/x-noble-hashes', version: '8.1.2' };
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
/*! noble-hashes - MIT License (c) 2021 Paul Miller (paulmillr.com) */
|
||||
// https://github.com/paulmillr/noble-hashes/pull/13
|
||||
import { hmac } from './hmac';
|
||||
// prettier-ignore
|
||||
import {
|
||||
+2
-3
@@ -1,5 +1,3 @@
|
||||
/*! noble-hashes - MIT License (c) 2021 Paul Miller (paulmillr.com) */
|
||||
// https://github.com/paulmillr/noble-hashes/pull/13
|
||||
import { SHA2 } from './_sha2';
|
||||
|
||||
import { wrapConstructor } from './utils';
|
||||
@@ -9,7 +7,8 @@ import { wrapConstructor } from './utils';
|
||||
const Rho = new Uint8Array([7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8]);
|
||||
const Id = Uint8Array.from({ length: 16 }, (_, i) => i);
|
||||
const Pi = Id.map((i) => (9 * i + 5) % 16);
|
||||
let [idxL, idxR] = [[Id], [Pi]];
|
||||
let idxL = [Id];
|
||||
let idxR = [Pi];
|
||||
for (let i = 0; i < 4; i++) for (let j of [idxL, idxR]) j.push(j[i].map((k) => Rho[k]));
|
||||
|
||||
const shifts = [
|
||||
+2
-3
@@ -1,5 +1,3 @@
|
||||
/*! noble-hashes - MIT License (c) 2021 Paul Miller (paulmillr.com) */
|
||||
// https://github.com/paulmillr/noble-hashes/pull/13
|
||||
import { sha256 } from './sha256';
|
||||
import { pbkdf2 } from './pbkdf2';
|
||||
import { assertNumber, asyncLoop, checkOpts, Input, u32 } from './utils';
|
||||
@@ -63,7 +61,8 @@ function XorAndSalsa(
|
||||
|
||||
function BlockMix(input: Uint32Array, ii: number, out: Uint32Array, oi: number, r: number) {
|
||||
// The block B is r 128-byte chunks (which is equivalent of 2r 64-byte chunks)
|
||||
let [head, tail] = [oi + 0, oi + 16 * r];
|
||||
let head = oi + 0;
|
||||
let tail = oi + 16 * r;
|
||||
for (let i = 0; i < 16; i++) out[tail + i] = input[ii + (2 * r - 1) * 16 + i]; // X ← B[2r−1]
|
||||
for (let i = 0; i < r; i++, head += 16, ii += 16) {
|
||||
// We write odd & even Yi at same time. Even: 0bXXXXX0 Odd: 0bXXXXX1
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
/*! noble-hashes - MIT License (c) 2021 Paul Miller (paulmillr.com) */
|
||||
// https://github.com/paulmillr/noble-hashes/pull/13
|
||||
import { SHA2 } from './_sha2';
|
||||
import { rotr, wrapConstructor } from './utils';
|
||||
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
/*! noble-hashes - MIT License (c) 2021 Paul Miller (paulmillr.com) */
|
||||
// https://github.com/paulmillr/noble-hashes/pull/13
|
||||
import { Input, toBytes, wrapConstructorWithOpts, assertNumber, u32, Hash, HashXOF } from './utils';
|
||||
import { Keccak, ShakeOpts } from './sha3';
|
||||
// cSHAKE && KMAC (NIST SP800-185)
|
||||
+6
-10
@@ -1,8 +1,5 @@
|
||||
/*! noble-hashes - MIT License (c) 2021 Paul Miller (paulmillr.com) */
|
||||
// https://github.com/paulmillr/noble-hashes/pull/13
|
||||
import * as u64 from './_u64';
|
||||
import {
|
||||
_n,
|
||||
Hash,
|
||||
u32,
|
||||
Input,
|
||||
@@ -13,15 +10,14 @@ import {
|
||||
HashXOF,
|
||||
} from './utils';
|
||||
|
||||
const _0n = _n(0);
|
||||
const _1n = _n(1);
|
||||
const _2n = _n(2);
|
||||
const _7n = _n(7);
|
||||
const _256n = _n(256);
|
||||
const _0x71n = _n(0x71);
|
||||
|
||||
// Various per round constants calculations
|
||||
const [SHA3_PI, SHA3_ROTL, _SHA3_IOTA]: [number[], number[], bigint[]] = [[], [], []];
|
||||
const _0n = BigInt(0);
|
||||
const _1n = BigInt(1);
|
||||
const _2n = BigInt(2);
|
||||
const _7n = BigInt(7);
|
||||
const _256n = BigInt(256);
|
||||
const _0x71n = BigInt(0x71);
|
||||
for (let round = 0, R = _1n, x = 1, y = 0; round < 24; round++) {
|
||||
// Pi
|
||||
[x, y] = [y, (2 * x + 3 * y) % 5];
|
||||
+22
-24
@@ -1,33 +1,31 @@
|
||||
/*! noble-hashes - MIT License (c) 2021 Paul Miller (paulmillr.com) */
|
||||
// https://github.com/paulmillr/noble-hashes/pull/13
|
||||
import { SHA2 } from './_sha2';
|
||||
import * as u64 from './_u64';
|
||||
import { _n, wrapConstructor } from './utils';
|
||||
import { wrapConstructor } from './utils';
|
||||
|
||||
// Round contants (first 32 bits of the fractional parts of the cube roots of the first 80 primes 2..409):
|
||||
// prettier-ignore
|
||||
const [SHA512_Kh, SHA512_Kl] = u64.split([
|
||||
_n('0x428a2f98d728ae22'), _n('0x7137449123ef65cd'), _n('0xb5c0fbcfec4d3b2f'), _n('0xe9b5dba58189dbbc'),
|
||||
_n('0x3956c25bf348b538'), _n('0x59f111f1b605d019'), _n('0x923f82a4af194f9b'), _n('0xab1c5ed5da6d8118'),
|
||||
_n('0xd807aa98a3030242'), _n('0x12835b0145706fbe'), _n('0x243185be4ee4b28c'), _n('0x550c7dc3d5ffb4e2'),
|
||||
_n('0x72be5d74f27b896f'), _n('0x80deb1fe3b1696b1'), _n('0x9bdc06a725c71235'), _n('0xc19bf174cf692694'),
|
||||
_n('0xe49b69c19ef14ad2'), _n('0xefbe4786384f25e3'), _n('0x0fc19dc68b8cd5b5'), _n('0x240ca1cc77ac9c65'),
|
||||
_n('0x2de92c6f592b0275'), _n('0x4a7484aa6ea6e483'), _n('0x5cb0a9dcbd41fbd4'), _n('0x76f988da831153b5'),
|
||||
_n('0x983e5152ee66dfab'), _n('0xa831c66d2db43210'), _n('0xb00327c898fb213f'), _n('0xbf597fc7beef0ee4'),
|
||||
_n('0xc6e00bf33da88fc2'), _n('0xd5a79147930aa725'), _n('0x06ca6351e003826f'), _n('0x142929670a0e6e70'),
|
||||
_n('0x27b70a8546d22ffc'), _n('0x2e1b21385c26c926'), _n('0x4d2c6dfc5ac42aed'), _n('0x53380d139d95b3df'),
|
||||
_n('0x650a73548baf63de'), _n('0x766a0abb3c77b2a8'), _n('0x81c2c92e47edaee6'), _n('0x92722c851482353b'),
|
||||
_n('0xa2bfe8a14cf10364'), _n('0xa81a664bbc423001'), _n('0xc24b8b70d0f89791'), _n('0xc76c51a30654be30'),
|
||||
_n('0xd192e819d6ef5218'), _n('0xd69906245565a910'), _n('0xf40e35855771202a'), _n('0x106aa07032bbd1b8'),
|
||||
_n('0x19a4c116b8d2d0c8'), _n('0x1e376c085141ab53'), _n('0x2748774cdf8eeb99'), _n('0x34b0bcb5e19b48a8'),
|
||||
_n('0x391c0cb3c5c95a63'), _n('0x4ed8aa4ae3418acb'), _n('0x5b9cca4f7763e373'), _n('0x682e6ff3d6b2b8a3'),
|
||||
_n('0x748f82ee5defb2fc'), _n('0x78a5636f43172f60'), _n('0x84c87814a1f0ab72'), _n('0x8cc702081a6439ec'),
|
||||
_n('0x90befffa23631e28'), _n('0xa4506cebde82bde9'), _n('0xbef9a3f7b2c67915'), _n('0xc67178f2e372532b'),
|
||||
_n('0xca273eceea26619c'), _n('0xd186b8c721c0c207'), _n('0xeada7dd6cde0eb1e'), _n('0xf57d4f7fee6ed178'),
|
||||
_n('0x06f067aa72176fba'), _n('0x0a637dc5a2c898a6'), _n('0x113f9804bef90dae'), _n('0x1b710b35131c471b'),
|
||||
_n('0x28db77f523047d84'), _n('0x32caab7b40c72493'), _n('0x3c9ebe0a15c9bebc'), _n('0x431d67c49c100d4c'),
|
||||
_n('0x4cc5d4becb3e42b6'), _n('0x597f299cfc657e2a'), _n('0x5fcb6fab3ad6faec'), _n('0x6c44198c4a475817')
|
||||
]);
|
||||
'0x428a2f98d728ae22', '0x7137449123ef65cd', '0xb5c0fbcfec4d3b2f', '0xe9b5dba58189dbbc',
|
||||
'0x3956c25bf348b538', '0x59f111f1b605d019', '0x923f82a4af194f9b', '0xab1c5ed5da6d8118',
|
||||
'0xd807aa98a3030242', '0x12835b0145706fbe', '0x243185be4ee4b28c', '0x550c7dc3d5ffb4e2',
|
||||
'0x72be5d74f27b896f', '0x80deb1fe3b1696b1', '0x9bdc06a725c71235', '0xc19bf174cf692694',
|
||||
'0xe49b69c19ef14ad2', '0xefbe4786384f25e3', '0x0fc19dc68b8cd5b5', '0x240ca1cc77ac9c65',
|
||||
'0x2de92c6f592b0275', '0x4a7484aa6ea6e483', '0x5cb0a9dcbd41fbd4', '0x76f988da831153b5',
|
||||
'0x983e5152ee66dfab', '0xa831c66d2db43210', '0xb00327c898fb213f', '0xbf597fc7beef0ee4',
|
||||
'0xc6e00bf33da88fc2', '0xd5a79147930aa725', '0x06ca6351e003826f', '0x142929670a0e6e70',
|
||||
'0x27b70a8546d22ffc', '0x2e1b21385c26c926', '0x4d2c6dfc5ac42aed', '0x53380d139d95b3df',
|
||||
'0x650a73548baf63de', '0x766a0abb3c77b2a8', '0x81c2c92e47edaee6', '0x92722c851482353b',
|
||||
'0xa2bfe8a14cf10364', '0xa81a664bbc423001', '0xc24b8b70d0f89791', '0xc76c51a30654be30',
|
||||
'0xd192e819d6ef5218', '0xd69906245565a910', '0xf40e35855771202a', '0x106aa07032bbd1b8',
|
||||
'0x19a4c116b8d2d0c8', '0x1e376c085141ab53', '0x2748774cdf8eeb99', '0x34b0bcb5e19b48a8',
|
||||
'0x391c0cb3c5c95a63', '0x4ed8aa4ae3418acb', '0x5b9cca4f7763e373', '0x682e6ff3d6b2b8a3',
|
||||
'0x748f82ee5defb2fc', '0x78a5636f43172f60', '0x84c87814a1f0ab72', '0x8cc702081a6439ec',
|
||||
'0x90befffa23631e28', '0xa4506cebde82bde9', '0xbef9a3f7b2c67915', '0xc67178f2e372532b',
|
||||
'0xca273eceea26619c', '0xd186b8c721c0c207', '0xeada7dd6cde0eb1e', '0xf57d4f7fee6ed178',
|
||||
'0x06f067aa72176fba', '0x0a637dc5a2c898a6', '0x113f9804bef90dae', '0x1b710b35131c471b',
|
||||
'0x28db77f523047d84', '0x32caab7b40c72493', '0x3c9ebe0a15c9bebc', '0x431d67c49c100d4c',
|
||||
'0x4cc5d4becb3e42b6', '0x597f299cfc657e2a', '0x5fcb6fab3ad6faec', '0x6c44198c4a475817'
|
||||
].map(n => BigInt(n)));
|
||||
|
||||
// Temporary buffer, not used to store anything between runs
|
||||
const SHA512_W_H = new Uint32Array(80);
|
||||
+12
-14
@@ -1,14 +1,13 @@
|
||||
/*! noble-hashes - MIT License (c) 2021 Paul Miller (paulmillr.com) */
|
||||
// https://github.com/paulmillr/noble-hashes/pull/13
|
||||
|
||||
// The import here is via the package name. This is to ensure
|
||||
// that exports mapping/resolution does fall into place.
|
||||
import { crypto } from '@polkadot/x-noble-hashes/crypto';
|
||||
|
||||
// prettier-ignore
|
||||
export type TypedArray = Int8Array | Uint8ClampedArray | Uint8Array |
|
||||
Uint16Array | Int16Array | Uint32Array | Int32Array;
|
||||
|
||||
// helper to protect against older bundlers
|
||||
export const _n: (value: string | number | bigint | boolean) => bigint =
|
||||
typeof BigInt !== 'undefined' ? BigInt : () => Number.NaN as unknown as bigint;
|
||||
|
||||
// Cast array to different type
|
||||
export const u8 = (arr: TypedArray) => new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);
|
||||
export const u32 = (arr: TypedArray) =>
|
||||
@@ -65,6 +64,14 @@ export async function asyncLoop(iters: number, tick: number, cb: (i: number) =>
|
||||
}
|
||||
}
|
||||
|
||||
// Global symbols in both browsers and Node.js since v11
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder
|
||||
// https://nodejs.org/docs/latest-v12.x/api/util.html#util_class_util_textencoder
|
||||
// https://nodejs.org/docs/latest-v12.x/api/util.html#util_class_util_textdecoder
|
||||
// See https://github.com/microsoft/TypeScript/issues/31535
|
||||
declare const TextEncoder: any;
|
||||
declare const TextDecoder: any;
|
||||
export type Input = Uint8Array | string;
|
||||
export function toBytes(data: Input) {
|
||||
if (typeof data === 'string') data = new TextEncoder().encode(data);
|
||||
@@ -157,15 +164,6 @@ export function wrapConstructorWithOpts<H extends Hash<H>, T extends Object>(
|
||||
return hashC;
|
||||
}
|
||||
|
||||
export const crypto: { node?: any; web?: any } = (() => {
|
||||
const webCrypto = typeof self === 'object' && 'crypto' in self ? self.crypto : undefined;
|
||||
const nodeRequire = typeof module !== 'undefined' && typeof require === 'function';
|
||||
return {
|
||||
node: nodeRequire && !webCrypto ? require('crypto') : undefined,
|
||||
web: webCrypto,
|
||||
};
|
||||
})();
|
||||
|
||||
export function randomBytes(bytesLength = 32): Uint8Array {
|
||||
if (crypto.web) {
|
||||
return crypto.web.getRandomValues(new Uint8Array(bytesLength));
|
||||
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019 Paul Miller (https://paulmillr.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the “Software”), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -0,0 +1,314 @@
|
||||
# noble-secp256k1  [](https://github.com/prettier/prettier)
|
||||
|
||||
[Fastest](#speed) JS implementation of [secp256k1](https://www.secg.org/sec2-v2.pdf),
|
||||
an elliptic curve that could be used for asymmetric encryption,
|
||||
ECDH key agreement protocol and signature schemes. Supports deterministic **ECDSA** from RFC6979 and **Schnorr** signatures from BIP0340.
|
||||
|
||||
[**Audited**](#security) with crowdfunding by an independent security firm. Tested against thousands of test vectors from a different library. Check out [the online demo](https://paulmillr.com/ecc) and blog post: [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/)
|
||||
|
||||
### This library belongs to *noble* crypto
|
||||
|
||||
> **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools.
|
||||
|
||||
- No dependencies, one small file
|
||||
- Easily auditable TypeScript/JS code
|
||||
- Supported in all major browsers and stable node.js versions
|
||||
- All releases are signed with PGP keys
|
||||
- Check out all libraries:
|
||||
[secp256k1](https://github.com/paulmillr/noble-secp256k1),
|
||||
[ed25519](https://github.com/paulmillr/noble-ed25519),
|
||||
[bls12-381](https://github.com/paulmillr/noble-bls12-381),
|
||||
[hashes](https://github.com/paulmillr/noble-hashes)
|
||||
|
||||
## Usage
|
||||
|
||||
Use NPM in node.js / browser, or include single file from
|
||||
[GitHub's releases page](https://github.com/paulmillr/noble-secp256k1/releases):
|
||||
|
||||
> npm install @noble/secp256k1
|
||||
|
||||
```js
|
||||
import * as secp from "@noble/secp256k1";
|
||||
// if you're using single file, use global variable nobleSecp256k1 instead
|
||||
|
||||
(async () => {
|
||||
// You pass either a hex string, or Uint8Array
|
||||
const privateKey = "6b911fd37cdf5c81d4c0adb1ab7fa822ed253ab0ad9aa18d77257c88b29b718e";
|
||||
const messageHash = "a33321f98e4ff1c283c76998f14f57447545d339b3db534c6d886decb4209f28";
|
||||
const publicKey = secp.getPublicKey(privateKey);
|
||||
const signature = await secp.sign(messageHash, privateKey);
|
||||
const isSigned = secp.verify(signature, messageHash, publicKey);
|
||||
|
||||
// Supports Schnorr signatures
|
||||
const rpub = secp.schnorr.getPublicKey(privateKey);
|
||||
const rsignature = await secp.schnorr.sign(messageHash, privateKey);
|
||||
const risSigned = await secp.schnorr.verify(rsignature, messageHash, rpub);
|
||||
})();
|
||||
```
|
||||
|
||||
Deno:
|
||||
|
||||
```typescript
|
||||
import * as secp from "https://deno.land/x/secp256k1/mod.ts";
|
||||
const publicKey = secp.getPublicKey("6b911fd37cdf5c81d4c0adb1ab7fa822ed253ab0ad9aa18d77257c88b29b718e");
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
- [`getPublicKey(privateKey)`](#getpublickeyprivatekey)
|
||||
- [`getSharedSecret(privateKeyA, publicKeyB)`](#getsharedsecretprivatekeya-publickeyb)
|
||||
- [`sign(hash, privateKey)`](#signhash-privatekey)
|
||||
- [`verify(signature, hash, publicKey)`](#verifysignature-hash-publickey)
|
||||
- [`recoverPublicKey(hash, signature, recovery)`](#recoverpublickeyhash-signature-recovery)
|
||||
- [`schnorr.getPublicKey(privateKey)`](#schnorrgetpublickeyprivatekey)
|
||||
- [`schnorr.sign(hash, privateKey)`](#schnorrsignhash-privatekey)
|
||||
- [`schnorr.verify(signature, hash, publicKey)`](#schnorrverifysignature-hash-publickey)
|
||||
- [Helpers](#helpers)
|
||||
|
||||
##### `getPublicKey(privateKey)`
|
||||
```typescript
|
||||
function getPublicKey(privateKey: Uint8Array, isCompressed?: false): Uint8Array;
|
||||
function getPublicKey(privateKey: string, isCompressed?: false): string;
|
||||
function getPublicKey(privateKey: bigint): Uint8Array;
|
||||
```
|
||||
`privateKey` will be used to generate public key.
|
||||
Public key is generated by doing scalar multiplication of a base Point(x, y) by a fixed
|
||||
integer. The result is another `Point(x, y)` which we will by default encode to hex Uint8Array.
|
||||
`isCompressed` (default is `false`) determines whether the output should contain `y` coordinate of the point.
|
||||
|
||||
To get Point instance, use `Point.fromPrivateKey(privateKey)`.
|
||||
|
||||
##### `getSharedSecret(privateKeyA, publicKeyB)`
|
||||
```typescript
|
||||
function getSharedSecret(privateKeyA: Uint8Array, publicKeyB: Uint8Array): Uint8Array;
|
||||
function getSharedSecret(privateKeyA: string, publicKeyB: string): string;
|
||||
function getSharedSecret(privateKeyA: bigint, publicKeyB: Point): Uint8Array;
|
||||
```
|
||||
|
||||
Computes ECDH (Elliptic Curve Diffie-Hellman) shared secret between a private key and a different public key.
|
||||
|
||||
To get Point instance, use `Point.fromHex(publicKeyB).multiply(privateKeyA)`.
|
||||
|
||||
To speed-up the function massively by precomputing EC multiplications,
|
||||
use `getSharedSecret(privateKeyA, secp.utils.precompute(8, publicKeyB))`
|
||||
|
||||
|
||||
##### `sign(hash, privateKey)`
|
||||
```typescript
|
||||
function sign(msgHash: Uint8Array, privateKey: Uint8Array, opts?: Options): Promise<Uint8Array>;
|
||||
function sign(msgHash: string, privateKey: string, opts?: Options): Promise<string>;
|
||||
function sign(msgHash: Uint8Array, privateKey: Uint8Array, opts?: Options): Promise<[Uint8Array | string, number]>;
|
||||
```
|
||||
|
||||
Generates deterministic ECDSA signature as per RFC6979.
|
||||
|
||||
- `msgHash: Uint8Array | string` - message hash which would be signed
|
||||
- `privateKey: Uint8Array | string | bigint` - private key which will sign the hash
|
||||
- `options?: Options` - *optional* object related to signature value and format
|
||||
- `options?.recovered: boolean = false` - whether the recovered bit should be included in the result. In this case, the result would be an array of two items.
|
||||
- `options?.canonical: boolean = false` - whether a signature `s` should be no more than 1/2 prime order
|
||||
- `options?.der: boolean = true` - whether the returned signature should be in DER format. If `false`, it would be in Compact format (32-byte r + 32-byte s)
|
||||
|
||||
The function is asynchronous because we're utilizing built-in HMAC API to not rely on dependencies.
|
||||
|
||||
`signSync` counterpart could also be used, you need to set `utils.hmacSha256Sync` to a function with signature `key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array`. Example with `noble-hashes` package:
|
||||
|
||||
```ts
|
||||
const { hmac } = require('noble-hashes/lib/hmac');
|
||||
const { sha256 } = require('noble-hashes/lib/sha256');
|
||||
secp256k1.utils.hmacSha256Sync = (key: Uint8Array, ...msgs: Uint8Array[]) => {
|
||||
const h = hmac.create(sha256, key);
|
||||
msgs.forEach(msg => h.update(msg));
|
||||
return h.digest();
|
||||
};
|
||||
|
||||
// Can be used now
|
||||
secp256k1.signSync(msgHash, privateKey)
|
||||
```
|
||||
|
||||
##### `verify(signature, hash, publicKey)`
|
||||
```typescript
|
||||
function verify(signature: Uint8Array, msgHash: Uint8Array, publicKey: Uint8Array): boolean
|
||||
function verify(signature: string, msgHash: string, publicKey: string): boolean
|
||||
```
|
||||
- `signature: Uint8Array | string | { r: bigint, s: bigint }` - object returned by the `sign` function
|
||||
- `msgHash: Uint8Array | string` - message hash that needs to be verified
|
||||
- `publicKey: Uint8Array | string | Point` - e.g. that was generated from `privateKey` by `getPublicKey`
|
||||
- Returns `boolean`: `true` if `signature == hash`; otherwise `false`
|
||||
|
||||
##### `recoverPublicKey(hash, signature, recovery)`
|
||||
```typescript
|
||||
function recoverPublicKey(msgHash: Uint8Array, signature: Uint8Array, recovery: number): Uint8Array | undefined;
|
||||
function recoverPublicKey(msgHash: string, signature: string, recovery: number): string | undefined;
|
||||
```
|
||||
- `msgHash: Uint8Array | string` - message hash which would be signed
|
||||
- `signature: Uint8Array | string | { r: bigint, s: bigint }` - object returned by the `sign` function
|
||||
- `recovery: number` - recovery bit returned by `sign` with `recovered` option
|
||||
Public key is generated by doing scalar multiplication of a base Point(x, y) by a fixed
|
||||
integer. The result is another `Point(x, y)` which we will by default encode to hex Uint8Array.
|
||||
If signature is invalid - function will return `undefined` as result.
|
||||
|
||||
To get Point instance, use `Point.fromSignature(hash, signature, recovery)`.
|
||||
|
||||
##### `schnorr.getPublicKey(privateKey)`
|
||||
```typescript
|
||||
function schnorrGetPublicKey(privateKey: Uint8Array): Uint8Array;
|
||||
function schnorrGetPublicKey(privateKey: string): string;
|
||||
```
|
||||
|
||||
Returns 32-byte public key. *Warning:* it is incompatible with non-schnorr pubkey.
|
||||
|
||||
Specifically, its *y* coordinate may be flipped. See BIP0340 for clarification.
|
||||
|
||||
##### `schnorr.sign(hash, privateKey)`
|
||||
```typescript
|
||||
function schnorrSign(msgHash: Uint8Array, privateKey: Uint8Array, auxilaryRandom?: Uint8Array): Promise<Uint8Array>;
|
||||
function schnorrSign(msgHash: string, privateKey: string, auxilaryRandom?: string): Promise<string>;
|
||||
```
|
||||
|
||||
Generates Schnorr signature as per BIP0340. Asynchronous, so use `await`.
|
||||
|
||||
- `msgHash: Uint8Array | string` - message hash which would be signed
|
||||
- `privateKey: Uint8Array | string | bigint` - private key which will sign the hash
|
||||
- `auxilaryRandom?: Uint8Array` — optional 32 random bytes. By default, the method gathers cryptogarphically secure random.
|
||||
- Returns Schnorr signature in Hex format.
|
||||
|
||||
##### `schnorr.verify(signature, hash, publicKey)`
|
||||
```typescript
|
||||
function schnorrVerify(signature: Uint8Array | string, msgHash: Uint8Array | string, publicKey: Uint8Array | string): boolean
|
||||
```
|
||||
- `signature: Uint8Array | string | { r: bigint, s: bigint }` - object returned by the `sign` function
|
||||
- `msgHash: Uint8Array | string` - message hash that needs to be verified
|
||||
- `publicKey: Uint8Array | string | Point` - e.g. that was generated from `privateKey` by `getPublicKey`
|
||||
- Returns `boolean`: `true` if `signature == hash`; otherwise `false`
|
||||
|
||||
#### Point methods
|
||||
|
||||
##### Helpers
|
||||
|
||||
###### `utils.randomPrivateKey(): Uint8Array`
|
||||
|
||||
Returns `Uint8Array` of 32 cryptographically secure random bytes that can be used as private key. The signature is:
|
||||
|
||||
```ts
|
||||
(key: Uint8Array, ...msgs: Uint8Array[]): Uint8Array;
|
||||
```
|
||||
|
||||
###### `utils.hmacSha256Sync`
|
||||
|
||||
The function is not defined by default, but could be used to implement `signSync` method (see above).
|
||||
|
||||
###### `utils.precompute(W = 8, point = BASE_POINT): Point`
|
||||
|
||||
Returns cached point which you can use to pass to `getSharedSecret` or to `#multiply` by it.
|
||||
|
||||
This is done by default, no need to run it unless you want to
|
||||
disable precomputation or change window size.
|
||||
|
||||
We're doing scalar multiplication (used in getPublicKey etc) with
|
||||
precomputed BASE_POINT values.
|
||||
|
||||
This slows down first getPublicKey() by milliseconds (see Speed section),
|
||||
but allows to speed-up subsequent getPublicKey() calls up to 20x.
|
||||
|
||||
You may want to precompute values for your own point.
|
||||
|
||||
```typescript
|
||||
secp256k1.CURVE.P // Field, 2 ** 256 - 2 ** 32 - 977
|
||||
secp256k1.CURVE.n // Order, 2 ** 256 - 432420386565659656852420866394968145599
|
||||
secp256k1.Point.BASE // new secp256k1.Point(Gx, Gy) where
|
||||
// Gx = 55066263022277343669578718895168534326250603453777594175500187360389116729240n
|
||||
// Gy = 32670510020758816978083085130507043184471273380659243275938904335757337482424n;
|
||||
|
||||
// Elliptic curve point in Affine (x, y) coordinates.
|
||||
secp256k1.Point {
|
||||
constructor(x: bigint, y: bigint);
|
||||
// Supports compressed and non-compressed hex
|
||||
static fromHex(hex: Uint8Array | string);
|
||||
static fromPrivateKey(privateKey: Uint8Array | string | number | bigint);
|
||||
static fromSignature(
|
||||
msgHash: Hex,
|
||||
signature: Signature,
|
||||
recovery: number | bigint
|
||||
): Point | undefined {
|
||||
toRawBytes(isCompressed = false): Uint8Array;
|
||||
toHex(isCompressed = false): string;
|
||||
equals(other: Point): boolean;
|
||||
negate(): Point;
|
||||
add(other: Point): Point;
|
||||
subtract(other: Point): Point;
|
||||
// Constant-time scalar multiplication.
|
||||
multiply(scalar: bigint | Uint8Array): Point;
|
||||
}
|
||||
secp256k1.Signature {
|
||||
constructor(r: bigint, s: bigint);
|
||||
// DER encoded ECDSA signature
|
||||
static fromDER(hex: Uint8Array | string);
|
||||
// R, S 32-byte each
|
||||
static fromCompact(hex: Uint8Array | string);
|
||||
toDERRawBytes(): Uint8Array;
|
||||
toDERHex(): string;
|
||||
toCompactRawBytes(): Uint8Array;
|
||||
toCompactHex(): string;
|
||||
}
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
Noble is production-ready.
|
||||
|
||||
1. The library has been audited by an independent security firm cure53: [PDF](https://cure53.de/pentest-report_noble-lib.pdf). The audit has been [crowdfunded](https://gitcoin.co/grants/2451/audit-of-noble-secp256k1-cryptographic-library) by community with help of [Umbra.cash](https://umbra.cash).
|
||||
2. The library has also been fuzzed by [Guido Vranken's cryptofuzz](https://github.com/guidovranken/cryptofuzz). You can run the fuzzer by yourself to check it.
|
||||
|
||||
We're using built-in JS `BigInt`, which is "unsuitable for use in cryptography" as [per official spec](https://github.com/tc39/proposal-bigint#cryptography). This means that the lib is potentially vulnerable to [timing attacks](https://en.wikipedia.org/wiki/Timing_attack). But, *JIT-compiler* and *Garbage Collector* make "constant time" extremely hard to achieve in a scripting language. Which means *any other JS library doesn't use constant-time bigints*. Including bn.js or anything else. Even statically typed Rust, a language without GC, [makes it harder to achieve constant-time](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security) for some cases. If your goal is absolute security, don't use any JS lib — including bindings to native ones. Use low-level libraries & languages. Nonetheless we've hardened implementation of koblitz curve multiplication to be algorithmically constant time.
|
||||
|
||||
We however consider infrastructure attacks like rogue NPM modules very important; that's why it's crucial to minimize the amount of 3rd-party dependencies & native bindings. If your app uses 500 dependencies, any dep could get hacked and you'll be downloading rootkits with every `npm install`. Our goal is to minimize this attack vector.
|
||||
|
||||
## Speed
|
||||
|
||||
Benchmarks measured with Apple M1.
|
||||
|
||||
getPublicKey(utils.randomPrivateKey()) x 6,121 ops/sec @ 163μs/op
|
||||
sign x 4,679 ops/sec @ 213μs/op
|
||||
verify x 923 ops/sec @ 1ms/op
|
||||
recoverPublicKey x 491 ops/sec @ 2ms/op
|
||||
getSharedSecret aka ecdh x 534 ops/sec @ 1ms/op
|
||||
getSharedSecret (precomputed) x 7,105 ops/sec @ 140μs/op
|
||||
Point.fromHex (decompression) x 12,171 ops/sec @ 82μs/op
|
||||
schnorr.sign x 409 ops/sec @ 2ms/op
|
||||
schnorr.verify x 504 ops/sec @ 1ms/op
|
||||
|
||||
Compare to other libraries (`openssl` uses native bindings, not JS):
|
||||
|
||||
elliptic#getPublicKey x 1,940 ops/sec
|
||||
sjcl#getPublicKey x 211 ops/sec
|
||||
|
||||
elliptic#sign x 1,808 ops/sec
|
||||
sjcl#sign x 199 ops/sec
|
||||
openssl#sign x 4,243 ops/sec
|
||||
ecdsa#sign x 116 ops/sec
|
||||
bip-schnorr#sign x 60 ops/sec
|
||||
|
||||
elliptic#verify x 812 ops/sec
|
||||
sjcl#verify x 166 ops/sec
|
||||
openssl#verify x 4,452 ops/sec
|
||||
ecdsa#verify x 80 ops/sec
|
||||
bip-schnorr#verify x 56 ops/sec
|
||||
|
||||
elliptic#ecdh x 971 ops/sec
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
Check out a blog post about this library: [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/).
|
||||
|
||||
1. Clone the repository.
|
||||
2. `npm install` to install build dependencies like TypeScript
|
||||
3. `npm run compile` to compile TypeScript code
|
||||
4. `npm run test` to run jest on `test/index.ts`
|
||||
|
||||
Special thanks to [Roman Koblov](https://github.com/romankoblov), who have helped to improve scalar multiplication speed.
|
||||
|
||||
## License
|
||||
|
||||
MIT (c) Paul Miller [(https://paulmillr.com)](https://paulmillr.com), see LICENSE file.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user