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 | ||
|
|
5d1dd0dd27 | ||
|
|
154f9f22f1 | ||
|
|
98e398954e | ||
|
|
3643c2e306 | ||
|
|
80195f6d11 | ||
|
|
6bc648bfe0 | ||
|
|
c29b12d3b5 | ||
|
|
8a5b514944 | ||
|
|
64fd66bd2a | ||
|
|
75aa7ba2c7 | ||
|
|
25196c3367 | ||
|
|
eeb68c7e0f | ||
|
|
1604b92771 | ||
|
|
1881b564c5 | ||
|
|
3bd4b56eb0 | ||
|
|
ce46e6da0c | ||
|
|
bd1efcbba0 | ||
|
|
f2e4fa0d34 | ||
|
|
adbf452c8d | ||
|
|
56a5a079dd | ||
|
|
0791b2dc9e | ||
|
|
9821eba11f | ||
|
|
b0b0151071 | ||
|
|
8422e0da66 | ||
|
|
5faa0fd544 | ||
|
|
b16396b9b3 | ||
|
|
f342348ad2 | ||
|
|
a8f13bd387 | ||
|
|
dbb77f35b6 | ||
|
|
c60e35ee9e | ||
|
|
b102d9c2b3 | ||
|
|
0ee4bc81f5 | ||
|
|
b05abf869a | ||
|
|
bc014f11dd | ||
|
|
f1429f10af | ||
|
|
be8cabbd1e | ||
|
|
8d0a0ed2b7 | ||
|
|
39baaa2b6d | ||
|
|
821980f64e | ||
|
|
6688ff0a43 | ||
|
|
ee18b661ad | ||
|
|
9a5998b921 | ||
|
|
f27f705f0c | ||
|
|
5e16b1e84c | ||
|
|
25a53e43fd | ||
|
|
75b60b9999 | ||
|
|
e8813aa110 | ||
|
|
b55cdb25f6 | ||
|
|
05e852337a | ||
|
|
cdd2d9ace5 | ||
|
|
a2d9538b31 | ||
|
|
391ab49b8f | ||
|
|
b390714285 | ||
|
|
277c80eb96 | ||
|
|
28f0040080 | ||
|
|
5f280aabb8 |
+6
-1
@@ -19,4 +19,9 @@
|
|||||||
7.0.3
|
7.0.3
|
||||||
7.1.2
|
7.1.2
|
||||||
7.8.2
|
7.8.2
|
||||||
7.9.2
|
7.9.2
|
||||||
|
8.0.2
|
||||||
|
8.0.3
|
||||||
|
8.0.4
|
||||||
|
8.0.5
|
||||||
|
8.1.2
|
||||||
@@ -3,3 +3,5 @@ exclude_patterns:
|
|||||||
- "**/*.spec.ts"
|
- "**/*.spec.ts"
|
||||||
- "packages/networks/src/substrate.ts"
|
- "packages/networks/src/substrate.ts"
|
||||||
- "packages/util/src/is/utf8.ts"
|
- "packages/util/src/is/utf8.ts"
|
||||||
|
- "packages/x-noble-hashes/src/**.ts"
|
||||||
|
- "packages/x-noble-secp256k1/src/**.ts"
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
packages/x-noble-hashes/**/*.ts
|
||||||
|
packages/x-noble-secp256k1/**/*.ts
|
||||||
@@ -2,7 +2,7 @@ name: 'Lock Threads'
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '30 1/2 * * *'
|
- cron: '15 1/3 * * *'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lock:
|
lock:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: 'Close stale issues and PRs'
|
name: 'Close stale issues and PRs'
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '30 2/2 * * *'
|
- cron: '50 1/3 * * *'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
stale:
|
stale:
|
||||||
|
|||||||
@@ -1,5 +1,75 @@
|
|||||||
# CHANGELOG
|
# 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 `stringCamelCase` for all-caps parts
|
||||||
|
|
||||||
|
|
||||||
|
## 8.0.2 Nov 26, 2021
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Explicitly include BigInt patched versions
|
||||||
|
|
||||||
|
|
||||||
|
## 8.0.1 Nov 26, 2021
|
||||||
|
|
||||||
|
**Important** In the 8.0 version the hashing utilities have been consolidated around an optimized and audited version from `@noble/hashes`. As in the past the WASM hashing will be used by default if the environment is initialized.
|
||||||
|
|
||||||
|
**Breaking change** The `schnorrkel*` functions have been renamed to `sr25519*`. Likewise the `ed25519` operations have been renamed from `nacl*` to `ed25519*`. Additionally the `{ed, sr, secp256k1}25519KeyPairFrom*` functions have been renamed to `{ed, sr, secp256k1}25519PairFrom*`.
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Introduce `ed25519*` & `sr25519*` functions
|
||||||
|
- Replace camelcase dep with simplified/optimized version
|
||||||
|
- Replace (most) hashing operations with `@noble/hashes`
|
||||||
|
- Replace JS fallback for `xxhash`
|
||||||
|
- Adjust `BigInt` utility exports (with capability detection)
|
||||||
|
- Previously added `bi*` functions renamed to `n*`
|
||||||
|
- Extend performance tests with implementation compares
|
||||||
|
- Remove non-significant Node Buffer concat fill
|
||||||
|
|
||||||
|
|
||||||
## 7.9.2 Nov 22, 2021
|
## 7.9.2 Nov 22, 2021
|
||||||
|
|
||||||
Changes:
|
Changes:
|
||||||
|
|||||||
+2
-2
@@ -13,8 +13,8 @@ module.exports = Object.assign({}, config, {
|
|||||||
'@polkadot/util-(crypto)(.*)$': '<rootDir>/packages/util-$1/src/$2',
|
'@polkadot/util-(crypto)(.*)$': '<rootDir>/packages/util-$1/src/$2',
|
||||||
// eslint-disable-next-line sort-keys
|
// eslint-disable-next-line sort-keys
|
||||||
'@polkadot/util(.*)$': '<rootDir>/packages/util/src/$1',
|
'@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-(fetch|randomvalues|textdecoder|textencoder|ws)(.*)$': '<rootDir>/packages/x-$1/src/node',
|
||||||
'@polkadot/x-global(.*)$': '<rootDir>/packages/x-global/src/$1',
|
'@polkadot/x-noble-(hashes|secp256k1)(.*)$': '<rootDir>/packages/x-noble-$1/src/$2'
|
||||||
'@polkadot/x-rxjs(.*)$': '<rootDir>/packages/x-rxjs/src/$1'
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
+3
-3
@@ -10,7 +10,7 @@
|
|||||||
"url": "https://github.com/polkadot-js/common.git"
|
"url": "https://github.com/polkadot-js/common.git"
|
||||||
},
|
},
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"version": "7.9.2",
|
"version": "8.1.2",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
@@ -29,8 +29,8 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.16.0",
|
"@babel/core": "^7.16.0",
|
||||||
"@polkadot/dev": "^0.63.29",
|
"@polkadot/dev": "^0.63.35",
|
||||||
"@polkadot/ts": "^0.4.14",
|
"@polkadot/ts": "^0.4.16",
|
||||||
"@types/jest": "^27.0.3"
|
"@types/jest": "^27.0.3"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
},
|
},
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "7.9.2",
|
"version": "8.1.2",
|
||||||
"browser": "browser.js",
|
"browser": "browser.js",
|
||||||
"main": "node.js",
|
"main": "node.js",
|
||||||
"react-native": "react-native.js",
|
"react-native": "react-native.js",
|
||||||
|
|||||||
@@ -3,4 +3,4 @@
|
|||||||
|
|
||||||
// Auto-generated by @polkadot/dev, do not edit
|
// Auto-generated by @polkadot/dev, do not edit
|
||||||
|
|
||||||
export const packageInfo = { name: '@polkadot/hw-ledger-transports', version: '7.9.2' };
|
export const packageInfo = { name: '@polkadot/hw-ledger-transports', version: '8.1.2' };
|
||||||
|
|||||||
@@ -19,12 +19,12 @@
|
|||||||
"./detectPackage.cjs"
|
"./detectPackage.cjs"
|
||||||
],
|
],
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "7.9.2",
|
"version": "8.1.2",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.16.3",
|
"@babel/runtime": "^7.16.3",
|
||||||
"@polkadot/hw-ledger-transports": "7.9.2",
|
"@polkadot/hw-ledger-transports": "8.1.2",
|
||||||
"@polkadot/util": "7.9.2",
|
"@polkadot/util": "8.1.2",
|
||||||
"@zondax/ledger-substrate": "^0.18.0"
|
"@zondax/ledger-substrate": "^0.18.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,4 +3,4 @@
|
|||||||
|
|
||||||
// Auto-generated by @polkadot/dev, do not edit
|
// Auto-generated by @polkadot/dev, do not edit
|
||||||
|
|
||||||
export const packageInfo = { name: '@polkadot/hw-ledger', version: '7.9.2' };
|
export const packageInfo = { name: '@polkadot/hw-ledger', version: '8.1.2' };
|
||||||
|
|||||||
@@ -20,15 +20,15 @@
|
|||||||
"./detectPackage.cjs"
|
"./detectPackage.cjs"
|
||||||
],
|
],
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "7.9.2",
|
"version": "8.1.2",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.16.3",
|
"@babel/runtime": "^7.16.3",
|
||||||
"@polkadot/util": "7.9.2",
|
"@polkadot/util": "8.1.2",
|
||||||
"@polkadot/util-crypto": "7.9.2"
|
"@polkadot/util-crypto": "8.1.2"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@polkadot/util": "7.9.2",
|
"@polkadot/util": "8.1.2",
|
||||||
"@polkadot/util-crypto": "7.9.2"
|
"@polkadot/util-crypto": "8.1.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,17 +5,17 @@ import type { EncryptedJsonEncoding, Keypair, KeypairType } from '@polkadot/util
|
|||||||
import type { KeyringInstance, KeyringOptions, KeyringPair, KeyringPair$Json, KeyringPair$Meta } from './types';
|
import type { KeyringInstance, KeyringOptions, KeyringPair, KeyringPair$Json, KeyringPair$Meta } from './types';
|
||||||
|
|
||||||
import { assert, hexToU8a, isHex, isUndefined, stringToU8a } from '@polkadot/util';
|
import { assert, hexToU8a, isHex, isUndefined, stringToU8a } from '@polkadot/util';
|
||||||
import { base64Decode, decodeAddress, encodeAddress, ethereumEncode, hdEthereum, keyExtractSuri, keyFromPath, mnemonicToLegacySeed, mnemonicToMiniSecret, naclKeypairFromSeed as naclFromSeed, schnorrkelKeypairFromSeed as schnorrkelFromSeed, secp256k1KeypairFromSeed as secp256k1FromSeed } from '@polkadot/util-crypto';
|
import { base64Decode, decodeAddress, ed25519PairFromSeed as ed25519FromSeed, encodeAddress, ethereumEncode, hdEthereum, keyExtractSuri, keyFromPath, mnemonicToLegacySeed, mnemonicToMiniSecret, secp256k1PairFromSeed as secp256k1FromSeed, sr25519PairFromSeed as sr25519FromSeed } from '@polkadot/util-crypto';
|
||||||
|
|
||||||
import { DEV_PHRASE } from './defaults';
|
import { DEV_PHRASE } from './defaults';
|
||||||
import { createPair } from './pair';
|
import { createPair } from './pair';
|
||||||
import { Pairs } from './pairs';
|
import { Pairs } from './pairs';
|
||||||
|
|
||||||
const keypairFromSeed = {
|
const PairFromSeed = {
|
||||||
ecdsa: (seed: Uint8Array): Keypair => secp256k1FromSeed(seed),
|
ecdsa: (seed: Uint8Array): Keypair => secp256k1FromSeed(seed),
|
||||||
ed25519: (seed: Uint8Array): Keypair => naclFromSeed(seed),
|
ed25519: (seed: Uint8Array): Keypair => ed25519FromSeed(seed),
|
||||||
ethereum: (seed: Uint8Array): Keypair => secp256k1FromSeed(seed),
|
ethereum: (seed: Uint8Array): Keypair => secp256k1FromSeed(seed),
|
||||||
sr25519: (seed: Uint8Array): Keypair => schnorrkelFromSeed(seed)
|
sr25519: (seed: Uint8Array): Keypair => sr25519FromSeed(seed)
|
||||||
};
|
};
|
||||||
|
|
||||||
function pairToPublic ({ publicKey }: KeyringPair): Uint8Array {
|
function pairToPublic ({ publicKey }: KeyringPair): Uint8Array {
|
||||||
@@ -142,7 +142,7 @@ export class Keyring implements KeyringInstance {
|
|||||||
*/
|
*/
|
||||||
public addFromSeed (seed: Uint8Array, meta: KeyringPair$Meta = {}, type: KeypairType = this.type): KeyringPair {
|
public addFromSeed (seed: Uint8Array, meta: KeyringPair$Meta = {}, type: KeypairType = this.type): KeyringPair {
|
||||||
return this.addPair(
|
return this.addPair(
|
||||||
createPair({ toSS58: this.encodeAddress, type }, keypairFromSeed[type](seed), meta, null)
|
createPair({ toSS58: this.encodeAddress, type }, PairFromSeed[type](seed), meta, null)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,9 +224,9 @@ export class Keyring implements KeyringInstance {
|
|||||||
|
|
||||||
const derived = type === 'ethereum'
|
const derived = type === 'ethereum'
|
||||||
? isPhraseHex
|
? isPhraseHex
|
||||||
? keypairFromSeed[type](seed) // for eth, if the private key is provided as suri, it must be derived only once
|
? PairFromSeed[type](seed) // for eth, if the private key is provided as suri, it must be derived only once
|
||||||
: hdEthereum(seed, derivePath.substring(1))
|
: hdEthereum(seed, derivePath.substring(1))
|
||||||
: keyFromPath(keypairFromSeed[type](seed), path, type);
|
: keyFromPath(PairFromSeed[type](seed), path, type);
|
||||||
|
|
||||||
return createPair({ toSS58: this.encodeAddress, type }, derived, meta, null);
|
return createPair({ toSS58: this.encodeAddress, type }, derived, meta, null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,4 +3,4 @@
|
|||||||
|
|
||||||
// Auto-generated by @polkadot/dev, do not edit
|
// Auto-generated by @polkadot/dev, do not edit
|
||||||
|
|
||||||
export const packageInfo = { name: '@polkadot/keyring', version: '7.9.2' };
|
export const packageInfo = { name: '@polkadot/keyring', version: '8.1.2' };
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import type { KeyringPair, KeyringPair$Json, KeyringPair$Meta, SignOptions } fro
|
|||||||
import type { PairInfo } from './types';
|
import type { PairInfo } from './types';
|
||||||
|
|
||||||
import { assert, objectSpread, u8aConcat, u8aEmpty, u8aEq, u8aToHex, u8aToU8a } from '@polkadot/util';
|
import { assert, objectSpread, u8aConcat, u8aEmpty, u8aEq, u8aToHex, u8aToU8a } from '@polkadot/util';
|
||||||
import { blake2AsU8a, convertPublicKeyToCurve25519, convertSecretKeyToCurve25519, ethereumEncode, keccakAsU8a, keyExtractPath, keyFromPath, naclKeypairFromSeed as naclFromSeed, naclOpen, naclSeal, naclSign, schnorrkelKeypairFromSeed as schnorrkelFromSeed, schnorrkelSign, schnorrkelVrfSign, schnorrkelVrfVerify, secp256k1Compress, secp256k1Expand, secp256k1KeypairFromSeed as secp256k1FromSeed, secp256k1Sign, signatureVerify } from '@polkadot/util-crypto';
|
import { blake2AsU8a, convertPublicKeyToCurve25519, convertSecretKeyToCurve25519, ed25519PairFromSeed as ed25519FromSeed, ed25519Sign, ethereumEncode, keccakAsU8a, keyExtractPath, keyFromPath, naclOpen, naclSeal, secp256k1Compress, secp256k1Expand, secp256k1PairFromSeed as secp256k1FromSeed, secp256k1Sign, signatureVerify, sr25519PairFromSeed as sr25519FromSeed, sr25519Sign, sr25519VrfSign, sr25519VrfVerify } from '@polkadot/util-crypto';
|
||||||
|
|
||||||
import { decodePair } from './decode';
|
import { decodePair } from './decode';
|
||||||
import { encodePair } from './encode';
|
import { encodePair } from './encode';
|
||||||
@@ -22,9 +22,9 @@ const SIG_TYPE_NONE = new Uint8Array();
|
|||||||
|
|
||||||
const TYPE_FROM_SEED = {
|
const TYPE_FROM_SEED = {
|
||||||
ecdsa: secp256k1FromSeed,
|
ecdsa: secp256k1FromSeed,
|
||||||
ed25519: naclFromSeed,
|
ed25519: ed25519FromSeed,
|
||||||
ethereum: secp256k1FromSeed,
|
ethereum: secp256k1FromSeed,
|
||||||
sr25519: schnorrkelFromSeed
|
sr25519: sr25519FromSeed
|
||||||
};
|
};
|
||||||
|
|
||||||
const TYPE_PREFIX = {
|
const TYPE_PREFIX = {
|
||||||
@@ -36,9 +36,9 @@ const TYPE_PREFIX = {
|
|||||||
|
|
||||||
const TYPE_SIGNATURE = {
|
const TYPE_SIGNATURE = {
|
||||||
ecdsa: (m: Uint8Array, p: Partial<Keypair>) => secp256k1Sign(m, p, 'blake2'),
|
ecdsa: (m: Uint8Array, p: Partial<Keypair>) => secp256k1Sign(m, p, 'blake2'),
|
||||||
ed25519: naclSign,
|
ed25519: ed25519Sign,
|
||||||
ethereum: (m: Uint8Array, p: Partial<Keypair>) => secp256k1Sign(m, p, 'keccak'),
|
ethereum: (m: Uint8Array, p: Partial<Keypair>) => secp256k1Sign(m, p, 'keccak'),
|
||||||
sr25519: schnorrkelSign
|
sr25519: sr25519Sign
|
||||||
};
|
};
|
||||||
|
|
||||||
const TYPE_ADDRESS = {
|
const TYPE_ADDRESS = {
|
||||||
@@ -215,7 +215,7 @@ export function createPair ({ toSS58, type }: Setup, { publicKey, secretKey }: P
|
|||||||
assert(!isLocked(secretKey), 'Cannot sign with a locked key pair');
|
assert(!isLocked(secretKey), 'Cannot sign with a locked key pair');
|
||||||
|
|
||||||
if (type === 'sr25519') {
|
if (type === 'sr25519') {
|
||||||
return schnorrkelVrfSign(message, { secretKey }, context, extra);
|
return sr25519VrfSign(message, { secretKey }, context, extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
const proof = TYPE_SIGNATURE[type](u8aToU8a(message), { publicKey, secretKey });
|
const proof = TYPE_SIGNATURE[type](u8aToU8a(message), { publicKey, secretKey });
|
||||||
@@ -224,7 +224,7 @@ export function createPair ({ toSS58, type }: Setup, { publicKey, secretKey }: P
|
|||||||
},
|
},
|
||||||
vrfVerify: (message: HexString | string | Uint8Array, vrfResult: Uint8Array, signerPublic: HexString | Uint8Array | string, context?: HexString | string | Uint8Array, extra?: HexString | string | Uint8Array): boolean => {
|
vrfVerify: (message: HexString | string | Uint8Array, vrfResult: Uint8Array, signerPublic: HexString | Uint8Array | string, context?: HexString | string | Uint8Array, extra?: HexString | string | Uint8Array): boolean => {
|
||||||
if (type === 'sr25519') {
|
if (type === 'sr25519') {
|
||||||
return schnorrkelVrfVerify(message, vrfResult, publicKey, context, extra);
|
return sr25519VrfVerify(message, vrfResult, publicKey, context, extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = signatureVerify(message, u8aConcat(TYPE_PREFIX[type], vrfResult.subarray(32)), TYPE_ADDRESS[type](u8aToU8a(signerPublic)));
|
const result = signatureVerify(message, u8aConcat(TYPE_PREFIX[type], vrfResult.subarray(32)), TYPE_ADDRESS[type](u8aToU8a(signerPublic)));
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import type { KeyringPair } from '../types';
|
import type { KeyringPair } from '../types';
|
||||||
|
|
||||||
import { u8aToHex } from '@polkadot/util';
|
import { u8aToHex } from '@polkadot/util';
|
||||||
import { cryptoWaitReady, encodeAddress as toSS58, naclKeypairFromSeed, randomAsU8a, schnorrkelKeypairFromSeed, secp256k1KeypairFromSeed } from '@polkadot/util-crypto';
|
import { cryptoWaitReady, ed25519PairFromSeed, encodeAddress as toSS58, randomAsU8a, secp256k1PairFromSeed, sr25519PairFromSeed } from '@polkadot/util-crypto';
|
||||||
|
|
||||||
import { createPair } from '.';
|
import { createPair } from '.';
|
||||||
|
|
||||||
@@ -19,9 +19,9 @@ describe('vrf', (): void => {
|
|||||||
beforeAll(async (): Promise<void> => {
|
beforeAll(async (): Promise<void> => {
|
||||||
await cryptoWaitReady();
|
await cryptoWaitReady();
|
||||||
|
|
||||||
ecdsa = createPair({ toSS58, type: 'ecdsa' }, secp256k1KeypairFromSeed(randomAsU8a()));
|
ecdsa = createPair({ toSS58, type: 'ecdsa' }, secp256k1PairFromSeed(randomAsU8a()));
|
||||||
ed25519 = createPair({ toSS58, type: 'ed25519' }, naclKeypairFromSeed(randomAsU8a()));
|
ed25519 = createPair({ toSS58, type: 'ed25519' }, ed25519PairFromSeed(randomAsU8a()));
|
||||||
sr25519 = createPair({ toSS58, type: 'sr25519' }, schnorrkelKeypairFromSeed(randomAsU8a()));
|
sr25519 = createPair({ toSS58, type: 'sr25519' }, sr25519PairFromSeed(randomAsU8a()));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('has deterministic signature values for ecdsa', (): void => {
|
it('has deterministic signature values for ecdsa', (): void => {
|
||||||
|
|||||||
@@ -17,13 +17,13 @@
|
|||||||
},
|
},
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "7.9.2",
|
"version": "8.1.2",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.16.3"
|
"@babel/runtime": "^7.16.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@polkadot/util": "7.9.2",
|
"@polkadot/util": "8.1.2",
|
||||||
"@polkadot/x-fetch": "7.9.2"
|
"@polkadot/x-fetch": "8.1.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ export const knownGenesis: KnownGenesis = {
|
|||||||
'nodle-chain': [
|
'nodle-chain': [
|
||||||
'0xa3d114c2b8d0627c1aa9b134eafcf7d05ca561fdc19fb388bb9457f81809fb23'
|
'0xa3d114c2b8d0627c1aa9b134eafcf7d05ca561fdc19fb388bb9457f81809fb23'
|
||||||
],
|
],
|
||||||
|
picasso: [
|
||||||
|
'0xe8e7f0f4c4f5a00720b4821dbfddefea7490bcf0b19009961cc46957984e2c1c'
|
||||||
|
],
|
||||||
plasm: [
|
plasm: [
|
||||||
'0x3e86364d4b4894021cb2a0390bcf2feb5517d5292f2de2bb9404227e908b0b8b'
|
'0x3e86364d4b4894021cb2a0390bcf2feb5517d5292f2de2bb9404227e908b0b8b'
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -3,4 +3,4 @@
|
|||||||
|
|
||||||
// Auto-generated by @polkadot/dev, do not edit
|
// Auto-generated by @polkadot/dev, do not edit
|
||||||
|
|
||||||
export const packageInfo = { name: '@polkadot/networks', version: '7.9.2' };
|
export const packageInfo = { name: '@polkadot/networks', version: '8.1.2' };
|
||||||
|
|||||||
@@ -22,35 +22,31 @@
|
|||||||
"./detectPackage.cjs"
|
"./detectPackage.cjs"
|
||||||
],
|
],
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "7.9.2",
|
"version": "8.1.2",
|
||||||
|
"browser": {
|
||||||
|
"crypto": false,
|
||||||
|
"stream": false
|
||||||
|
},
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.16.3",
|
"@babel/runtime": "^7.16.3",
|
||||||
"@polkadot/networks": "7.9.2",
|
"@noble/hashes": "0.4.1",
|
||||||
"@polkadot/util": "7.9.2",
|
"@noble/secp256k1": "^1.3.0",
|
||||||
"@polkadot/wasm-crypto": "^4.4.1",
|
"@polkadot/networks": "8.1.2",
|
||||||
"@polkadot/x-randomvalues": "7.9.2",
|
"@polkadot/util": "8.1.2",
|
||||||
"blakejs": "^1.1.1",
|
"@polkadot/wasm-crypto": "^4.5.1",
|
||||||
"bn.js": "^4.12.0",
|
"@polkadot/x-bigint": "8.1.2",
|
||||||
"create-hash": "^1.2.0",
|
"@polkadot/x-noble-hashes": "8.1.2",
|
||||||
|
"@polkadot/x-noble-secp256k1": "8.1.2",
|
||||||
|
"@polkadot/x-randomvalues": "8.1.2",
|
||||||
"ed2curve": "^0.3.0",
|
"ed2curve": "^0.3.0",
|
||||||
"elliptic": "^6.5.4",
|
|
||||||
"hash.js": "^1.1.7",
|
|
||||||
"js-sha3": "^0.8.0",
|
|
||||||
"micro-base": "^0.9.0",
|
"micro-base": "^0.9.0",
|
||||||
"scryptsy": "^2.1.0",
|
"tweetnacl": "^1.0.3"
|
||||||
"tweetnacl": "^1.0.3",
|
|
||||||
"xxhashjs": "^0.2.2"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bn.js": "^4.11.6",
|
"@types/ed2curve": "^0.2.2"
|
||||||
"@types/create-hash": "^1.2.2",
|
|
||||||
"@types/ed2curve": "^0.2.2",
|
|
||||||
"@types/elliptic": "^6.4.14",
|
|
||||||
"@types/scryptsy": "^2.0.0",
|
|
||||||
"@types/xxhashjs": "^0.2.2"
|
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@polkadot/util": "7.9.2"
|
"@polkadot/util": "8.1.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import type { Prefix } from './types';
|
|||||||
import { assert } from '@polkadot/util';
|
import { assert } from '@polkadot/util';
|
||||||
|
|
||||||
import { keyExtractPath } from '../key';
|
import { keyExtractPath } from '../key';
|
||||||
import { schnorrkelDerivePublic } from '../schnorrkel';
|
import { sr25519DerivePublic } from '../sr25519';
|
||||||
import { decodeAddress } from './decode';
|
import { decodeAddress } from './decode';
|
||||||
import { encodeAddress } from './encode';
|
import { encodeAddress } from './encode';
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ export function deriveAddress (who: HexString | Uint8Array | string, suri: strin
|
|||||||
let publicKey = decodeAddress(who);
|
let publicKey = decodeAddress(who);
|
||||||
|
|
||||||
for (const { chainCode } of path) {
|
for (const { chainCode } of path) {
|
||||||
publicKey = schnorrkelDerivePublic(publicKey, chainCode);
|
publicKey = sr25519DerivePublic(publicKey, chainCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
return encodeAddress(publicKey, ss58Format);
|
return encodeAddress(publicKey, ss58Format);
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import type { HexString } from '@polkadot/util/types';
|
|||||||
import type { HashType } from '../secp256k1/types';
|
import type { HashType } from '../secp256k1/types';
|
||||||
import type { Prefix } from './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';
|
import { encodeAddress } from './encode';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -15,15 +15,9 @@ import { encodeAddress } from './encode';
|
|||||||
* @summary Converts an EVM address to its corresponding SS58 address.
|
* @summary Converts an EVM address to its corresponding SS58 address.
|
||||||
*/
|
*/
|
||||||
export function evmToAddress (evmAddress: HexString | string | Uint8Array, ss58Format?: Prefix, hashType: HashType = 'blake2'): string {
|
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);
|
const message = u8aConcat('evm:', evmAddress);
|
||||||
|
|
||||||
if (message.length !== 24) {
|
assert(message.length === 24, () => `Converting ${evmAddress as string}: Invalid evm address length`);
|
||||||
throw new Error(wrapError('Invalid evm address length'));
|
|
||||||
}
|
|
||||||
|
|
||||||
const address = secp256k1Hasher(hashType, message);
|
return encodeAddress(hasher(hashType, message), ss58Format);
|
||||||
|
|
||||||
return encodeAddress(address, ss58Format);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,20 +5,20 @@ import { utils } from 'micro-base';
|
|||||||
|
|
||||||
import { createDecode, createEncode, createIs, createValidate } from './helpers';
|
import { createDecode, createEncode, createIs, createValidate } from './helpers';
|
||||||
|
|
||||||
const BASE32_ALPHABET = 'abcdefghijklmnopqrstuvwxyz234567';
|
const chars = 'abcdefghijklmnopqrstuvwxyz234567';
|
||||||
|
|
||||||
const BASE32_CONFIG = {
|
const config = {
|
||||||
alphabet: BASE32_ALPHABET,
|
chars,
|
||||||
coder: utils.chain(
|
coder: utils.chain(
|
||||||
// We define our own chain, the default base32 has padding
|
// We define our own chain, the default base32 has padding
|
||||||
utils.radix2(5),
|
utils.radix2(5),
|
||||||
utils.alphabet(BASE32_ALPHABET),
|
utils.alphabet(chars),
|
||||||
{
|
{
|
||||||
decode: (input: string) => input.split(''),
|
decode: (input: string) => input.split(''),
|
||||||
encode: (input: string[]) => input.join('')
|
encode: (input: string[]) => input.join('')
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
ipfsChar: 'b',
|
ipfs: 'b',
|
||||||
type: 'base32'
|
type: 'base32'
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ const BASE32_CONFIG = {
|
|||||||
* @description
|
* @description
|
||||||
* Validates that the supplied value is valid base32, throwing exceptions if not
|
* Validates that the supplied value is valid base32, throwing exceptions if not
|
||||||
*/
|
*/
|
||||||
export const base32Validate = createValidate(BASE32_CONFIG);
|
export const base32Validate = createValidate(config);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name isBase32
|
* @name isBase32
|
||||||
@@ -42,7 +42,7 @@ export const isBase32 = createIs(base32Validate);
|
|||||||
* @description
|
* @description
|
||||||
* From the provided input, decode the base32 and return the result as an `Uint8Array`.
|
* From the provided input, decode the base32 and return the result as an `Uint8Array`.
|
||||||
*/
|
*/
|
||||||
export const base32Decode = createDecode(BASE32_CONFIG, base32Validate);
|
export const base32Decode = createDecode(config, base32Validate);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name base32Encode
|
* @name base32Encode
|
||||||
@@ -50,4 +50,4 @@ export const base32Decode = createDecode(BASE32_CONFIG, base32Validate);
|
|||||||
* @description
|
* @description
|
||||||
* From the provided input, create the base32 and return the result as a string.
|
* From the provided input, create the base32 and return the result as a string.
|
||||||
*/
|
*/
|
||||||
export const base32Encode = createEncode(BASE32_CONFIG);
|
export const base32Encode = createEncode(config);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { assert, u8aToU8a } from '@polkadot/util';
|
|||||||
//
|
//
|
||||||
// ends up in the build-generated code as
|
// ends up in the build-generated code as
|
||||||
//
|
//
|
||||||
// import("../../../util/src/types").U8aLike
|
// impor("../../../util/src/types").U8aLike
|
||||||
//
|
//
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
type U8aLike = number[] | Buffer | Uint8Array | string | String;
|
type U8aLike = number[] | Buffer | Uint8Array | string | String;
|
||||||
@@ -21,9 +21,9 @@ interface Coder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Config {
|
interface Config {
|
||||||
alphabet: string;
|
chars: string;
|
||||||
coder: Coder;
|
coder: Coder;
|
||||||
ipfsChar?: string;
|
ipfs?: string;
|
||||||
regex?: RegExp;
|
regex?: RegExp;
|
||||||
type: string;
|
type: string;
|
||||||
}
|
}
|
||||||
@@ -34,24 +34,24 @@ type EncodeFn = (value: U8aLike, ipfsCompat?: boolean) => string;
|
|||||||
|
|
||||||
type ValidateFn = (value?: unknown, ipfsCompat?: boolean) => value is string;
|
type ValidateFn = (value?: unknown, ipfsCompat?: boolean) => value is string;
|
||||||
|
|
||||||
export function createDecode ({ coder, ipfsChar }: Config, validate: ValidateFn): DecodeFn {
|
export function createDecode ({ coder, ipfs }: Config, validate: ValidateFn): DecodeFn {
|
||||||
return (value: string, ipfsCompat?: boolean): Uint8Array => {
|
return (value: string, ipfsCompat?: boolean): Uint8Array => {
|
||||||
validate(value, ipfsCompat);
|
validate(value, ipfsCompat);
|
||||||
|
|
||||||
return coder.decode(
|
return coder.decode(
|
||||||
ipfsChar && ipfsCompat
|
ipfs && ipfsCompat
|
||||||
? value.substr(1)
|
? value.substr(1)
|
||||||
: value
|
: value
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createEncode ({ coder, ipfsChar }: Config): EncodeFn {
|
export function createEncode ({ coder, ipfs }: Config): EncodeFn {
|
||||||
return (value: U8aLike, ipfsCompat?: boolean): string => {
|
return (value: U8aLike, ipfsCompat?: boolean): string => {
|
||||||
const out = coder.encode(u8aToU8a(value));
|
const out = coder.encode(u8aToU8a(value));
|
||||||
|
|
||||||
return ipfsChar && ipfsCompat
|
return ipfs && ipfsCompat
|
||||||
? `${ipfsChar}${out}`
|
? `${ipfs}${out}`
|
||||||
: out;
|
: out;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -66,20 +66,24 @@ export function createIs (validate: ValidateFn): ValidateFn {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createValidate ({ alphabet, ipfsChar, regex, type }: Config): ValidateFn {
|
export function createValidate ({ chars, ipfs, type }: Config): ValidateFn {
|
||||||
return (value?: unknown, ipfsCompat?: boolean): value is string => {
|
return (value?: unknown, ipfsCompat?: boolean): value is string => {
|
||||||
assert(value && typeof value === 'string', () => `Expected non-null, non-empty ${type} string input`);
|
assert(value && typeof value === 'string', () => `Expected non-null, non-empty ${type} string input`);
|
||||||
|
|
||||||
if (ipfsChar && ipfsCompat) {
|
if (ipfs && ipfsCompat) {
|
||||||
assert(value[0] === ipfsChar, () => `Expected ipfs-compatible ${type} to start with '${ipfsChar}'`);
|
assert(value[0] === ipfs, () => `Expected ipfs-compatible ${type} to start with '${ipfs}'`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (regex) {
|
for (let i = (ipfsCompat ? 1 : 0); i < value.length; i++) {
|
||||||
assert(regex.test(value), `Invalid ${type} encoding`);
|
assert(
|
||||||
} else {
|
chars.includes(value[i]) || (
|
||||||
for (let i = (ipfsCompat ? 1 : 0); i < value.length; i++) {
|
value[i] === '=' && (
|
||||||
assert(alphabet.includes(value[i]), () => `Invalid ${type} character "${value[i]}" (0x${value.charCodeAt(i).toString(16)}) at index ${i}`);
|
(i === value.length - 1) ||
|
||||||
}
|
!chars.includes(value[i + 1])
|
||||||
|
)
|
||||||
|
),
|
||||||
|
() => `Invalid ${type} character "${value[i]}" (0x${value.charCodeAt(i).toString(16)}) at index ${i}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import { base58 } from 'micro-base';
|
|||||||
|
|
||||||
import { createDecode, createEncode, createIs, createValidate } from '../base32/helpers';
|
import { createDecode, createEncode, createIs, createValidate } from '../base32/helpers';
|
||||||
|
|
||||||
const BASE58_CONFIG = {
|
const config = {
|
||||||
alphabet: '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz',
|
chars: '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz',
|
||||||
coder: base58,
|
coder: base58,
|
||||||
ipfsChar: 'z',
|
ipfs: 'z',
|
||||||
type: 'base58'
|
type: 'base58'
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ const BASE58_CONFIG = {
|
|||||||
* @description
|
* @description
|
||||||
* Validates that the supplied value is valid base58, throwing exceptions if not
|
* Validates that the supplied value is valid base58, throwing exceptions if not
|
||||||
*/
|
*/
|
||||||
export const base58Validate = createValidate(BASE58_CONFIG);
|
export const base58Validate = createValidate(config);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name base58Decode
|
* @name base58Decode
|
||||||
@@ -26,7 +26,7 @@ export const base58Validate = createValidate(BASE58_CONFIG);
|
|||||||
* @description
|
* @description
|
||||||
* From the provided input, decode the base58 and return the result as an `Uint8Array`.
|
* From the provided input, decode the base58 and return the result as an `Uint8Array`.
|
||||||
*/
|
*/
|
||||||
export const base58Decode = createDecode(BASE58_CONFIG, base58Validate);
|
export const base58Decode = createDecode(config, base58Validate);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name base58Encode
|
* @name base58Encode
|
||||||
@@ -34,7 +34,7 @@ export const base58Decode = createDecode(BASE58_CONFIG, base58Validate);
|
|||||||
* @description
|
* @description
|
||||||
* From the provided input, create the base58 and return the result as a string.
|
* From the provided input, create the base58 and return the result as a string.
|
||||||
*/
|
*/
|
||||||
export const base58Encode = createEncode(BASE58_CONFIG);
|
export const base58Encode = createEncode(config);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name isBase58
|
* @name isBase58
|
||||||
|
|||||||
@@ -5,10 +5,9 @@ import { base64 } from 'micro-base';
|
|||||||
|
|
||||||
import { createDecode, createEncode, createIs, createValidate } from '../base32/helpers';
|
import { createDecode, createEncode, createIs, createValidate } from '../base32/helpers';
|
||||||
|
|
||||||
const BASE64_CONFIG = {
|
const config = {
|
||||||
alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
|
chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
|
||||||
coder: base64,
|
coder: base64,
|
||||||
regex: /^(?:[A-Za-z0-9+/]{2}[A-Za-z0-9+/]{2})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/,
|
|
||||||
type: 'base64'
|
type: 'base64'
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -18,7 +17,7 @@ const BASE64_CONFIG = {
|
|||||||
* @description
|
* @description
|
||||||
* Validates that the supplied value is valid base64
|
* Validates that the supplied value is valid base64
|
||||||
*/
|
*/
|
||||||
export const base64Validate = createValidate(BASE64_CONFIG);
|
export const base64Validate = createValidate(config);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name isBase64
|
* @name isBase64
|
||||||
@@ -32,7 +31,7 @@ export const isBase64 = createIs(base64Validate);
|
|||||||
* @description
|
* @description
|
||||||
* From the provided input, decode the base64 and return the result as an `Uint8Array`.
|
* From the provided input, decode the base64 and return the result as an `Uint8Array`.
|
||||||
*/
|
*/
|
||||||
export const base64Decode = createDecode(BASE64_CONFIG, base64Validate);
|
export const base64Decode = createDecode(config, base64Validate);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name base64Encode
|
* @name base64Encode
|
||||||
@@ -40,4 +39,4 @@ export const base64Decode = createDecode(BASE64_CONFIG, base64Validate);
|
|||||||
* @description
|
* @description
|
||||||
* From the provided input, create the base64 and return the result as a string.
|
* From the provided input, create the base64 and return the result as a string.
|
||||||
*/
|
*/
|
||||||
export const base64Encode = createEncode(BASE64_CONFIG);
|
export const base64Encode = createEncode(config);
|
||||||
|
|||||||
@@ -6,11 +6,27 @@ import { stringToU8a } from '@polkadot/util';
|
|||||||
import { base64Decode } from '.';
|
import { base64Decode } from '.';
|
||||||
|
|
||||||
describe('base64Decode', (): void => {
|
describe('base64Decode', (): void => {
|
||||||
it('decodes a mixed base64 utf8 string', (): void => {
|
it('decodes a mixed base64 utf8 string (1)', (): void => {
|
||||||
expect(
|
expect(
|
||||||
base64Decode('aGVsbG8gd29ybGQg0J/RgNC40LLQtdGC0YHRgtCy0YPRjiDQvNC4IOS9oOWlvQ==')
|
base64Decode('aGVsbG8gd29ybGQg0J/RgNC40LLQtdGC0YHRgtCy0YPRjiDQvNC4IOS9oOWlvQ==')
|
||||||
).toEqual(
|
).toEqual(
|
||||||
stringToU8a('hello world Приветствую ми 你好')
|
stringToU8a('hello world Приветствую ми 你好')
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('decodes a mixed base64 utf8 string (2)', (): void => {
|
||||||
|
expect(
|
||||||
|
base64Decode('4pyTIMOgIGxhIG1vZGU=')
|
||||||
|
).toEqual(
|
||||||
|
stringToU8a('✓ à la mode')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('decodes a mixed base64 utf8 string (3)', (): void => {
|
||||||
|
expect(
|
||||||
|
base64Decode('SGVsbG8gV29ybGQh')
|
||||||
|
).toEqual(
|
||||||
|
stringToU8a('Hello World!')
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ describe('base64Validate', (): void => {
|
|||||||
it('validates a mixed base64 utf8 string', (): void => {
|
it('validates a mixed base64 utf8 string', (): void => {
|
||||||
expect(
|
expect(
|
||||||
() => base64Validate('aGVsbG8gd29ybGQg0J/RgNC40LLQtd^GC0YHRgtCy0YPRjiDQvNC4IOS9oOWlvQ==')
|
() => base64Validate('aGVsbG8gd29ybGQg0J/RgNC40LLQtd^GC0YHRgtCy0YPRjiDQvNC4IOS9oOWlvQ==')
|
||||||
).toThrow(/Invalid base64 encoding/);
|
).toThrow(/Invalid base64 character "\^" \(0x5e\) at index 30/);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import { hexToU8a } from '@polkadot/util';
|
import { hexToU8a } from '@polkadot/util';
|
||||||
import { waitReady } from '@polkadot/wasm-crypto';
|
import { waitReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
import { performanceTest } from '../../test/performance';
|
import { performanceWasm } from '../../test/performance';
|
||||||
import { blake2AsU8a } from '.';
|
import { blake2AsU8a } from '.';
|
||||||
|
|
||||||
describe('blake2AsU8a', (): void => {
|
describe('blake2AsU8a', (): void => {
|
||||||
@@ -61,7 +61,7 @@ describe('blake2AsU8a', (): void => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe.each([256, 512] as (256 | 512)[])('bitLength=$p', (bitLength): void => {
|
describe.each([256, 512] as (256 | 512)[])('bitLength=$p', (bitLength): void => {
|
||||||
performanceTest(`blake2AsU8a, bitLength=${bitLength}`, 64000, (input, onlyJs) =>
|
performanceWasm(`blake2AsU8a, bitLength=${bitLength}`, 64000, (input, onlyJs) =>
|
||||||
blake2AsU8a(input, bitLength, null, onlyJs)
|
blake2AsU8a(input, bitLength, null, onlyJs)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,12 +3,13 @@
|
|||||||
|
|
||||||
import type { HexString } from '@polkadot/util/types';
|
import type { HexString } from '@polkadot/util/types';
|
||||||
|
|
||||||
import js from 'blakejs';
|
import { hasBigInt, u8aToU8a } from '@polkadot/util';
|
||||||
|
import { blake2b, isReady } from '@polkadot/wasm-crypto';
|
||||||
|
import { blake2b as blake2bJs } from '@polkadot/x-noble-hashes/blake2b';
|
||||||
|
|
||||||
import { u8aToU8a } from '@polkadot/util';
|
import { createAsHex } from '../helpers';
|
||||||
import { blake2b } from '@polkadot/wasm-crypto';
|
|
||||||
|
|
||||||
import { createAsHex, isWasmOnly } from '../helpers';
|
type BitLength = 64 | 128 | 256 | 384 | 512;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name blake2AsU8a
|
* @name blake2AsU8a
|
||||||
@@ -24,13 +25,13 @@ import { createAsHex, isWasmOnly } from '../helpers';
|
|||||||
* blake2AsU8a('abc'); // => [0xba, 0x80, 0xa5, 0x3f, 0x98, 0x1c, 0x4d, 0x0d]
|
* blake2AsU8a('abc'); // => [0xba, 0x80, 0xa5, 0x3f, 0x98, 0x1c, 0x4d, 0x0d]
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function blake2AsU8a (data: HexString | Uint8Array | string, bitLength = 256, key?: Uint8Array | null, onlyJs?: boolean): Uint8Array {
|
export function blake2AsU8a (data: HexString | Uint8Array | string, bitLength: BitLength = 256, key?: Uint8Array | null, onlyJs?: boolean): Uint8Array {
|
||||||
const byteLength = Math.ceil(bitLength / 8);
|
const byteLength = Math.ceil(bitLength / 8);
|
||||||
const u8a = u8aToU8a(data);
|
const u8a = u8aToU8a(data);
|
||||||
|
|
||||||
return isWasmOnly(onlyJs)
|
return !hasBigInt || (!onlyJs && isReady())
|
||||||
? blake2b(u8a, u8aToU8a(key), byteLength)
|
? blake2b(u8a, u8aToU8a(key), byteLength)
|
||||||
: js.blake2b(u8a, key || undefined, byteLength);
|
: blake2bJs(u8a, { dkLen: byteLength, key: key || undefined });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
export const BN_BE_OPTS = { isLe: false };
|
||||||
export const BN_LE_OPTS = { isLe: true };
|
export const BN_LE_OPTS = { isLe: true };
|
||||||
|
|
||||||
export const BN_LE_16_OPTS = { bitLength: 16, isLe: true };
|
export const BN_LE_16_OPTS = { bitLength: 16, isLe: true };
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export * from './base58';
|
|||||||
export * from './base64';
|
export * from './base64';
|
||||||
export * from './blake2';
|
export * from './blake2';
|
||||||
export * from './crypto';
|
export * from './crypto';
|
||||||
|
export * from './ed25519';
|
||||||
export * from './ethereum';
|
export * from './ethereum';
|
||||||
export * from './hd';
|
export * from './hd';
|
||||||
export * from './hmac';
|
export * from './hmac';
|
||||||
@@ -23,9 +24,9 @@ export * from './networks';
|
|||||||
export * from './nacl';
|
export * from './nacl';
|
||||||
export * from './pbkdf2';
|
export * from './pbkdf2';
|
||||||
export * from './random';
|
export * from './random';
|
||||||
export * from './schnorrkel';
|
|
||||||
export * from './scrypt';
|
export * from './scrypt';
|
||||||
export * from './secp256k1';
|
export * from './secp256k1';
|
||||||
export * from './sha';
|
export * from './sha';
|
||||||
export * from './signature';
|
export * from './signature';
|
||||||
|
export * from './sr25519';
|
||||||
export * from './xxhash';
|
export * from './xxhash';
|
||||||
|
|||||||
@@ -1,7 +1,18 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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 { 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
|
// start init process immediately
|
||||||
cryptoWaitReady().catch((): void => {
|
cryptoWaitReady().catch((): void => {
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ import { blake2AsU8a } from '../blake2/asU8a';
|
|||||||
|
|
||||||
const HDKD = compactAddLength(stringToU8a('Ed25519HDKD'));
|
const HDKD = compactAddLength(stringToU8a('Ed25519HDKD'));
|
||||||
|
|
||||||
export function naclDeriveHard (seed: Uint8Array, chainCode: Uint8Array): Uint8Array {
|
export function ed25519DeriveHard (seed: Uint8Array, chainCode: Uint8Array): Uint8Array {
|
||||||
assert(isU8a(chainCode) && chainCode.length === 32, 'Invalid chainCode passed to derive');
|
assert(isU8a(chainCode) && chainCode.length === 32, 'Invalid chainCode passed to derive');
|
||||||
|
|
||||||
return blake2AsU8a(
|
return blake2AsU8a(
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Implements ed25519 operations
|
||||||
|
*/
|
||||||
|
export { convertPublicKeyToCurve25519, convertSecretKeyToCurve25519 } from './convertKey';
|
||||||
|
export { ed25519DeriveHard } from './deriveHard';
|
||||||
|
export { ed25519PairFromRandom } from './pair/fromRandom';
|
||||||
|
export { ed25519PairFromSecret } from './pair/fromSecret';
|
||||||
|
export { ed25519PairFromSeed } from './pair/fromSeed';
|
||||||
|
export { ed25519PairFromString } from './pair/fromString';
|
||||||
|
export { ed25519Sign } from './sign';
|
||||||
|
export { ed25519Verify } from './verify';
|
||||||
+3
-3
@@ -3,13 +3,13 @@
|
|||||||
|
|
||||||
import type { Keypair } from '../../types';
|
import type { Keypair } from '../../types';
|
||||||
|
|
||||||
import { naclKeypairFromRandom } from '..';
|
import { ed25519PairFromRandom } from '..';
|
||||||
|
|
||||||
describe('naclKeypairFromRandom', (): void => {
|
describe('ed25519PairFromRandom', (): void => {
|
||||||
let keypair: Keypair;
|
let keypair: Keypair;
|
||||||
|
|
||||||
beforeEach((): void => {
|
beforeEach((): void => {
|
||||||
keypair = naclKeypairFromRandom();
|
keypair = ed25519PairFromRandom();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('generates a valid publicKey', (): void => {
|
it('generates a valid publicKey', (): void => {
|
||||||
+7
-6
@@ -3,10 +3,11 @@
|
|||||||
|
|
||||||
import type { Keypair } from '../../types';
|
import type { Keypair } from '../../types';
|
||||||
|
|
||||||
import nacl from 'tweetnacl';
|
import { randomAsU8a } from '../../random';
|
||||||
|
import { ed25519PairFromSeed } from './fromSeed';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name naclKeypairFromRandom
|
* @name ed25519PairFromRandom
|
||||||
* @summary Creates a new public/secret keypair.
|
* @summary Creates a new public/secret keypair.
|
||||||
* @description
|
* @description
|
||||||
* Returns a new generate object containing a `publicKey` & `secretKey`.
|
* Returns a new generate object containing a `publicKey` & `secretKey`.
|
||||||
@@ -14,11 +15,11 @@ import nacl from 'tweetnacl';
|
|||||||
* <BR>
|
* <BR>
|
||||||
*
|
*
|
||||||
* ```javascript
|
* ```javascript
|
||||||
* import { naclKeypairFromRandom } from '@polkadot/util-crypto';
|
* import { ed25519PairFromRandom } from '@polkadot/util-crypto';
|
||||||
*
|
*
|
||||||
* naclKeypairFromRandom(); // => { secretKey: [...], publicKey: [...] }
|
* ed25519PairFromRandom(); // => { secretKey: [...], publicKey: [...] }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function naclKeypairFromRandom (): Keypair {
|
export function ed25519PairFromRandom (): Keypair {
|
||||||
return nacl.sign.keyPair();
|
return ed25519PairFromSeed(randomAsU8a());
|
||||||
}
|
}
|
||||||
+3
-3
@@ -1,9 +1,9 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { naclKeypairFromSecret } from '..';
|
import { ed25519PairFromSecret } from '..';
|
||||||
|
|
||||||
describe('naclKeypairFromSecret', (): void => {
|
describe('ed25519PairFromSecret', (): void => {
|
||||||
const secretKey = new Uint8Array([
|
const secretKey = new Uint8Array([
|
||||||
18, 52, 86, 120, 144, 18, 52, 86,
|
18, 52, 86, 120, 144, 18, 52, 86,
|
||||||
120, 144, 18, 52, 86, 120, 144, 18,
|
120, 144, 18, 52, 86, 120, 144, 18,
|
||||||
@@ -17,7 +17,7 @@ describe('naclKeypairFromSecret', (): void => {
|
|||||||
|
|
||||||
it('generates a valid publicKey/secretKey pair', (): void => {
|
it('generates a valid publicKey/secretKey pair', (): void => {
|
||||||
expect(
|
expect(
|
||||||
naclKeypairFromSecret(secretKey)
|
ed25519PairFromSecret(secretKey)
|
||||||
).toEqual({
|
).toEqual({
|
||||||
publicKey: new Uint8Array([
|
publicKey: new Uint8Array([
|
||||||
180, 114, 93, 155, 165, 255, 217, 82,
|
180, 114, 93, 155, 165, 255, 217, 82,
|
||||||
+4
-4
@@ -6,7 +6,7 @@ import type { Keypair } from '../../types';
|
|||||||
import nacl from 'tweetnacl';
|
import nacl from 'tweetnacl';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name naclKeypairFromSecret
|
* @name ed25519PairFromSecret
|
||||||
* @summary Creates a new public/secret keypair from a secret.
|
* @summary Creates a new public/secret keypair from a secret.
|
||||||
* @description
|
* @description
|
||||||
* Returns a object containing a `publicKey` & `secretKey` generated from the supplied secret.
|
* Returns a object containing a `publicKey` & `secretKey` generated from the supplied secret.
|
||||||
@@ -14,11 +14,11 @@ import nacl from 'tweetnacl';
|
|||||||
* <BR>
|
* <BR>
|
||||||
*
|
*
|
||||||
* ```javascript
|
* ```javascript
|
||||||
* import { naclKeypairFromSecret } from '@polkadot/util-crypto';
|
* import { ed25519PairFromSecret } from '@polkadot/util-crypto';
|
||||||
*
|
*
|
||||||
* naclKeypairFromSecret(...); // => { secretKey: [...], publicKey: [...] }
|
* ed25519PairFromSecret(...); // => { secretKey: [...], publicKey: [...] }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function naclKeypairFromSecret (secret: Uint8Array): Keypair {
|
export function ed25519PairFromSecret (secret: Uint8Array): Keypair {
|
||||||
return nacl.sign.keyPair.fromSecretKey(secret);
|
return nacl.sign.keyPair.fromSecretKey(secret);
|
||||||
}
|
}
|
||||||
+3
-3
@@ -4,9 +4,9 @@
|
|||||||
import { stringToU8a } from '@polkadot/util';
|
import { stringToU8a } from '@polkadot/util';
|
||||||
import { waitReady } from '@polkadot/wasm-crypto';
|
import { waitReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
import { naclKeypairFromSeed } from '..';
|
import { ed25519PairFromSeed } from '..';
|
||||||
|
|
||||||
describe('naclKeypairFromSeed', (): void => {
|
describe('ed25519PairFromSeed', (): void => {
|
||||||
// NOTE: Aligned with Rust test, b"12345678901234567890123456789012"
|
// NOTE: Aligned with Rust test, b"12345678901234567890123456789012"
|
||||||
const TEST = stringToU8a('12345678901234567890123456789012');
|
const TEST = stringToU8a('12345678901234567890123456789012');
|
||||||
const RESULT = {
|
const RESULT = {
|
||||||
@@ -33,7 +33,7 @@ describe('naclKeypairFromSeed', (): void => {
|
|||||||
it('generates a valid publicKey/secretKey pair (u8a)', (): void => {
|
it('generates a valid publicKey/secretKey pair (u8a)', (): void => {
|
||||||
[true, false].forEach((onlyJs): void => {
|
[true, false].forEach((onlyJs): void => {
|
||||||
expect(
|
expect(
|
||||||
naclKeypairFromSeed(TEST, onlyJs)
|
ed25519PairFromSeed(TEST, onlyJs)
|
||||||
).toEqual(RESULT);
|
).toEqual(RESULT);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
+4
-4
@@ -8,7 +8,7 @@ import nacl from 'tweetnacl';
|
|||||||
import { ed25519KeypairFromSeed, isReady } from '@polkadot/wasm-crypto';
|
import { ed25519KeypairFromSeed, isReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name naclKeypairFromSeed
|
* @name ed25519PairFromSeed
|
||||||
* @summary Creates a new public/secret keypair from a seed.
|
* @summary Creates a new public/secret keypair from a seed.
|
||||||
* @description
|
* @description
|
||||||
* Returns a object containing a `publicKey` & `secretKey` generated from the supplied seed.
|
* Returns a object containing a `publicKey` & `secretKey` generated from the supplied seed.
|
||||||
@@ -16,12 +16,12 @@ import { ed25519KeypairFromSeed, isReady } from '@polkadot/wasm-crypto';
|
|||||||
* <BR>
|
* <BR>
|
||||||
*
|
*
|
||||||
* ```javascript
|
* ```javascript
|
||||||
* import { naclKeypairFromSeed } from '@polkadot/util-crypto';
|
* import { ed25519PairFromSeed } from '@polkadot/util-crypto';
|
||||||
*
|
*
|
||||||
* naclKeypairFromSeed(...); // => { secretKey: [...], publicKey: [...] }
|
* ed25519PairFromSeed(...); // => { secretKey: [...], publicKey: [...] }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function naclKeypairFromSeed (seed: Uint8Array, onlyJs?: boolean): Keypair {
|
export function ed25519PairFromSeed (seed: Uint8Array, onlyJs?: boolean): Keypair {
|
||||||
if (!onlyJs && isReady()) {
|
if (!onlyJs && isReady()) {
|
||||||
const full = ed25519KeypairFromSeed(seed);
|
const full = ed25519KeypairFromSeed(seed);
|
||||||
|
|
||||||
+3
-3
@@ -1,12 +1,12 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { naclKeypairFromString } from '..';
|
import { ed25519PairFromString } from '..';
|
||||||
|
|
||||||
describe('naclKeypairFromSeed', (): void => {
|
describe('ed25519PairFromSeed', (): void => {
|
||||||
it('generates a valid publicKey/secretKey pair', (): void => {
|
it('generates a valid publicKey/secretKey pair', (): void => {
|
||||||
expect(
|
expect(
|
||||||
naclKeypairFromString('test')
|
ed25519PairFromString('test')
|
||||||
).toEqual({
|
).toEqual({
|
||||||
publicKey: new Uint8Array([188, 108, 179, 142, 36, 142, 76, 87, 77, 193, 147, 139, 254, 110, 196, 217, 117, 233, 167, 165, 250, 150, 247, 237, 198, 68, 129, 4, 211, 209, 136, 48]),
|
publicKey: new Uint8Array([188, 108, 179, 142, 36, 142, 76, 87, 77, 193, 147, 139, 254, 110, 196, 217, 117, 233, 167, 165, 250, 150, 247, 237, 198, 68, 129, 4, 211, 209, 136, 48]),
|
||||||
secretKey: new Uint8Array([146, 139, 32, 54, 105, 67, 226, 175, 209, 30, 188, 14, 174, 46, 83, 169, 59, 241, 119, 164, 252, 243, 91, 204, 100, 213, 3, 112, 78, 101, 226, 2, 188, 108, 179, 142, 36, 142, 76, 87, 77, 193, 147, 139, 254, 110, 196, 217, 117, 233, 167, 165, 250, 150, 247, 237, 198, 68, 129, 4, 211, 209, 136, 48])
|
secretKey: new Uint8Array([146, 139, 32, 54, 105, 67, 226, 175, 209, 30, 188, 14, 174, 46, 83, 169, 59, 241, 119, 164, 252, 243, 91, 204, 100, 213, 3, 112, 78, 101, 226, 2, 188, 108, 179, 142, 36, 142, 76, 87, 77, 193, 147, 139, 254, 110, 196, 217, 117, 233, 167, 165, 250, 150, 247, 237, 198, 68, 129, 4, 211, 209, 136, 48])
|
||||||
+7
-8
@@ -6,10 +6,10 @@ import type { Keypair } from '../../types';
|
|||||||
import { stringToU8a } from '@polkadot/util';
|
import { stringToU8a } from '@polkadot/util';
|
||||||
|
|
||||||
import { blake2AsU8a } from '../../blake2/asU8a';
|
import { blake2AsU8a } from '../../blake2/asU8a';
|
||||||
import { naclKeypairFromSeed } from './fromSeed';
|
import { ed25519PairFromSeed } from './fromSeed';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name naclKeypairFromString
|
* @name ed25519PairFromString
|
||||||
* @summary Creates a new public/secret keypair from a string.
|
* @summary Creates a new public/secret keypair from a string.
|
||||||
* @description
|
* @description
|
||||||
* Returns a object containing a `publicKey` & `secretKey` generated from the supplied string. The string is hashed and the value used as the input seed.
|
* Returns a object containing a `publicKey` & `secretKey` generated from the supplied string. The string is hashed and the value used as the input seed.
|
||||||
@@ -17,16 +17,15 @@ import { naclKeypairFromSeed } from './fromSeed';
|
|||||||
* <BR>
|
* <BR>
|
||||||
*
|
*
|
||||||
* ```javascript
|
* ```javascript
|
||||||
* import { naclKeypairFromString } from '@polkadot/util-crypto';
|
* import { ed25519PairFromString } from '@polkadot/util-crypto';
|
||||||
*
|
*
|
||||||
* naclKeypairFromString('test'); // => { secretKey: [...], publicKey: [...] }
|
* ed25519PairFromString('test'); // => { secretKey: [...], publicKey: [...] }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function naclKeypairFromString (value: string): Keypair {
|
export function ed25519PairFromString (value: string): Keypair {
|
||||||
return naclKeypairFromSeed(
|
return ed25519PairFromSeed(
|
||||||
blake2AsU8a(
|
blake2AsU8a(
|
||||||
stringToU8a(value),
|
stringToU8a(value)
|
||||||
256
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
+7
-7
@@ -4,14 +4,14 @@
|
|||||||
import { stringToU8a } from '@polkadot/util';
|
import { stringToU8a } from '@polkadot/util';
|
||||||
import { waitReady } from '@polkadot/wasm-crypto';
|
import { waitReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
import { performanceTest } from '../../test/performance';
|
import { performanceWasm } from '../../test/performance';
|
||||||
import { naclKeypairFromSeed, naclSign } from '.';
|
import { ed25519PairFromSeed, ed25519Sign } from '.';
|
||||||
|
|
||||||
const PAIR = naclKeypairFromSeed(
|
const PAIR = ed25519PairFromSeed(
|
||||||
stringToU8a('12345678901234567890123456789012')
|
stringToU8a('12345678901234567890123456789012')
|
||||||
);
|
);
|
||||||
|
|
||||||
describe('naclSign', (): void => {
|
describe('ed25519Sign', (): void => {
|
||||||
beforeEach(async (): Promise<void> => {
|
beforeEach(async (): Promise<void> => {
|
||||||
await waitReady();
|
await waitReady();
|
||||||
});
|
});
|
||||||
@@ -19,7 +19,7 @@ describe('naclSign', (): void => {
|
|||||||
describe.each([false, true])('onlyJs=%p', (onlyJs): void => {
|
describe.each([false, true])('onlyJs=%p', (onlyJs): void => {
|
||||||
it('returns a valid signature for the message', (): void => {
|
it('returns a valid signature for the message', (): void => {
|
||||||
expect(
|
expect(
|
||||||
naclSign(
|
ed25519Sign(
|
||||||
new Uint8Array([0x61, 0x62, 0x63, 0x64]),
|
new Uint8Array([0x61, 0x62, 0x63, 0x64]),
|
||||||
PAIR,
|
PAIR,
|
||||||
onlyJs
|
onlyJs
|
||||||
@@ -30,7 +30,7 @@ describe('naclSign', (): void => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
performanceTest('naclSign', 250, (input, onlyJs) =>
|
performanceWasm('ed25519Sign', 250, (input, onlyJs) =>
|
||||||
naclSign(input, PAIR, onlyJs)
|
ed25519Sign(input, PAIR, onlyJs)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -7,12 +7,10 @@ import type { Keypair } from '../types';
|
|||||||
import nacl from 'tweetnacl';
|
import nacl from 'tweetnacl';
|
||||||
|
|
||||||
import { assert, u8aToU8a } from '@polkadot/util';
|
import { assert, u8aToU8a } from '@polkadot/util';
|
||||||
import { ed25519Sign } from '@polkadot/wasm-crypto';
|
import { ed25519Sign as wasmSign, isReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
import { isWasmOnly } from '../helpers';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name naclSign
|
* @name ed25519Sign
|
||||||
* @summary Signs a message using the supplied secretKey
|
* @summary Signs a message using the supplied secretKey
|
||||||
* @description
|
* @description
|
||||||
* Returns message signature of `message`, using the `secretKey`.
|
* Returns message signature of `message`, using the `secretKey`.
|
||||||
@@ -20,17 +18,17 @@ import { isWasmOnly } from '../helpers';
|
|||||||
* <BR>
|
* <BR>
|
||||||
*
|
*
|
||||||
* ```javascript
|
* ```javascript
|
||||||
* import { naclSign } from '@polkadot/util-crypto';
|
* import { ed25519Sign } from '@polkadot/util-crypto';
|
||||||
*
|
*
|
||||||
* naclSign([...], [...]); // => [...]
|
* ed25519Sign([...], [...]); // => [...]
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function naclSign (message: HexString | Uint8Array | string, { publicKey, secretKey }: Partial<Keypair>, onlyJs?: boolean): Uint8Array {
|
export function ed25519Sign (message: HexString | Uint8Array | string, { publicKey, secretKey }: Partial<Keypair>, onlyJs?: boolean): Uint8Array {
|
||||||
assert(secretKey, 'Expected a valid secretKey');
|
assert(secretKey, 'Expected a valid secretKey');
|
||||||
|
|
||||||
const messageU8a = u8aToU8a(message);
|
const messageU8a = u8aToU8a(message);
|
||||||
|
|
||||||
return isWasmOnly(onlyJs)
|
return !onlyJs && isReady()
|
||||||
? ed25519Sign(publicKey as Uint8Array, secretKey.subarray(0, 32), messageU8a)
|
? wasmSign(publicKey as Uint8Array, secretKey.subarray(0, 32), messageU8a)
|
||||||
: nacl.sign.detached(messageU8a, secretKey);
|
: nacl.sign.detached(messageU8a, secretKey);
|
||||||
}
|
}
|
||||||
+8
-8
@@ -4,16 +4,16 @@
|
|||||||
import { stringToU8a } from '@polkadot/util';
|
import { stringToU8a } from '@polkadot/util';
|
||||||
import { waitReady } from '@polkadot/wasm-crypto';
|
import { waitReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
import { naclKeypairFromSeed, naclVerify } from '.';
|
import { ed25519PairFromSeed, ed25519Verify } from '.';
|
||||||
|
|
||||||
describe('naclVerify', (): void => {
|
describe('ed25519Verify', (): void => {
|
||||||
let publicKey: Uint8Array;
|
let publicKey: Uint8Array;
|
||||||
let signature: Uint8Array;
|
let signature: Uint8Array;
|
||||||
|
|
||||||
beforeEach(async (): Promise<void> => {
|
beforeEach(async (): Promise<void> => {
|
||||||
await waitReady();
|
await waitReady();
|
||||||
|
|
||||||
publicKey = naclKeypairFromSeed(
|
publicKey = ed25519PairFromSeed(
|
||||||
stringToU8a('12345678901234567890123456789012')
|
stringToU8a('12345678901234567890123456789012')
|
||||||
).publicKey;
|
).publicKey;
|
||||||
signature = new Uint8Array([28, 58, 206, 239, 249, 70, 59, 191, 166, 40, 219, 218, 235, 170, 25, 79, 10, 94, 9, 197, 34, 126, 1, 150, 246, 68, 28, 238, 36, 26, 172, 163, 168, 90, 202, 211, 126, 246, 57, 212, 43, 24, 88, 197, 240, 113, 118, 76, 37, 81, 91, 110, 236, 50, 144, 134, 100, 223, 220, 238, 34, 185, 211, 7]);
|
signature = new Uint8Array([28, 58, 206, 239, 249, 70, 59, 191, 166, 40, 219, 218, 235, 170, 25, 79, 10, 94, 9, 197, 34, 126, 1, 150, 246, 68, 28, 238, 36, 26, 172, 163, 168, 90, 202, 211, 126, 246, 57, 212, 43, 24, 88, 197, 240, 113, 118, 76, 37, 81, 91, 110, 236, 50, 144, 134, 100, 223, 220, 238, 34, 185, 211, 7]);
|
||||||
@@ -22,7 +22,7 @@ describe('naclVerify', (): void => {
|
|||||||
describe.each([false, true])('onlyJs=%p', (onlyJs): void => {
|
describe.each([false, true])('onlyJs=%p', (onlyJs): void => {
|
||||||
it('validates a correctly signed message', (): void => {
|
it('validates a correctly signed message', (): void => {
|
||||||
expect(
|
expect(
|
||||||
naclVerify(
|
ed25519Verify(
|
||||||
new Uint8Array([0x61, 0x62, 0x63, 0x64]),
|
new Uint8Array([0x61, 0x62, 0x63, 0x64]),
|
||||||
signature,
|
signature,
|
||||||
publicKey,
|
publicKey,
|
||||||
@@ -33,7 +33,7 @@ describe('naclVerify', (): void => {
|
|||||||
|
|
||||||
it('fails a correctly signed message (message changed)', (): void => {
|
it('fails a correctly signed message (message changed)', (): void => {
|
||||||
expect(
|
expect(
|
||||||
naclVerify(
|
ed25519Verify(
|
||||||
new Uint8Array([0x61, 0x62, 0x63, 0x64, 0x65]),
|
new Uint8Array([0x61, 0x62, 0x63, 0x64, 0x65]),
|
||||||
signature,
|
signature,
|
||||||
publicKey,
|
publicKey,
|
||||||
@@ -46,7 +46,7 @@ describe('naclVerify', (): void => {
|
|||||||
signature[0] = 0xff;
|
signature[0] = 0xff;
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
naclVerify(
|
ed25519Verify(
|
||||||
new Uint8Array([0x61, 0x62, 0x63, 0x64]),
|
new Uint8Array([0x61, 0x62, 0x63, 0x64]),
|
||||||
signature,
|
signature,
|
||||||
publicKey,
|
publicKey,
|
||||||
@@ -57,7 +57,7 @@ describe('naclVerify', (): void => {
|
|||||||
|
|
||||||
it('throws error when publicKey lengths do not match', (): void => {
|
it('throws error when publicKey lengths do not match', (): void => {
|
||||||
expect(
|
expect(
|
||||||
() => naclVerify(
|
() => ed25519Verify(
|
||||||
new Uint8Array([0x61, 0x62, 0x63, 0x64]),
|
new Uint8Array([0x61, 0x62, 0x63, 0x64]),
|
||||||
signature,
|
signature,
|
||||||
new Uint8Array([1, 2]),
|
new Uint8Array([1, 2]),
|
||||||
@@ -68,7 +68,7 @@ describe('naclVerify', (): void => {
|
|||||||
|
|
||||||
it('throws error when signature lengths do not match', (): void => {
|
it('throws error when signature lengths do not match', (): void => {
|
||||||
expect(
|
expect(
|
||||||
() => naclVerify(
|
() => ed25519Verify(
|
||||||
new Uint8Array([0x61, 0x62, 0x63, 0x64]),
|
new Uint8Array([0x61, 0x62, 0x63, 0x64]),
|
||||||
new Uint8Array([1, 2]),
|
new Uint8Array([1, 2]),
|
||||||
publicKey,
|
publicKey,
|
||||||
+7
-9
@@ -6,12 +6,10 @@ import type { HexString } from '@polkadot/util/types';
|
|||||||
import nacl from 'tweetnacl';
|
import nacl from 'tweetnacl';
|
||||||
|
|
||||||
import { assert, u8aToU8a } from '@polkadot/util';
|
import { assert, u8aToU8a } from '@polkadot/util';
|
||||||
import { ed25519Verify } from '@polkadot/wasm-crypto';
|
import { ed25519Verify as wasmVerify, isReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
import { isWasmOnly } from '../helpers';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name naclSign
|
* @name ed25519Sign
|
||||||
* @summary Verifies the signature on the supplied message.
|
* @summary Verifies the signature on the supplied message.
|
||||||
* @description
|
* @description
|
||||||
* Verifies the `signature` on `message` with the supplied `publicKey`. Returns `true` on sucess, `false` otherwise.
|
* Verifies the `signature` on `message` with the supplied `publicKey`. Returns `true` on sucess, `false` otherwise.
|
||||||
@@ -19,12 +17,12 @@ import { isWasmOnly } from '../helpers';
|
|||||||
* <BR>
|
* <BR>
|
||||||
*
|
*
|
||||||
* ```javascript
|
* ```javascript
|
||||||
* import { naclVerify } from '@polkadot/util-crypto';
|
* import { ed25519Verify } from '@polkadot/util-crypto';
|
||||||
*
|
*
|
||||||
* naclVerify([...], [...], [...]); // => true/false
|
* ed25519Verify([...], [...], [...]); // => true/false
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function naclVerify (message: HexString | Uint8Array | string, signature: HexString | Uint8Array | string, publicKey: HexString | Uint8Array | string, onlyJs?: boolean): boolean {
|
export function ed25519Verify (message: HexString | Uint8Array | string, signature: HexString | Uint8Array | string, publicKey: HexString | Uint8Array | string, onlyJs?: boolean): boolean {
|
||||||
const messageU8a = u8aToU8a(message);
|
const messageU8a = u8aToU8a(message);
|
||||||
const publicKeyU8a = u8aToU8a(publicKey);
|
const publicKeyU8a = u8aToU8a(publicKey);
|
||||||
const signatureU8a = u8aToU8a(signature);
|
const signatureU8a = u8aToU8a(signature);
|
||||||
@@ -32,7 +30,7 @@ export function naclVerify (message: HexString | Uint8Array | string, signature:
|
|||||||
assert(publicKeyU8a.length === 32, () => `Invalid publicKey, received ${publicKeyU8a.length}, expected 32`);
|
assert(publicKeyU8a.length === 32, () => `Invalid publicKey, received ${publicKeyU8a.length}, expected 32`);
|
||||||
assert(signatureU8a.length === 64, () => `Invalid signature, received ${signatureU8a.length} bytes, expected 64`);
|
assert(signatureU8a.length === 64, () => `Invalid signature, received ${signatureU8a.length} bytes, expected 64`);
|
||||||
|
|
||||||
return isWasmOnly(onlyJs)
|
return !onlyJs && isReady()
|
||||||
? ed25519Verify(signatureU8a, messageU8a, publicKeyU8a)
|
? wasmVerify(signatureU8a, messageU8a, publicKeyU8a)
|
||||||
: nacl.sign.detached.verify(messageU8a, signatureU8a, publicKeyU8a);
|
: nacl.sign.detached.verify(messageU8a, signatureU8a, publicKeyU8a);
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ import { assert, bnToU8a, stringToU8a, u8aConcat } from '@polkadot/util';
|
|||||||
|
|
||||||
import { BN_BE_32_OPTS } from '../../bn';
|
import { BN_BE_32_OPTS } from '../../bn';
|
||||||
import { hmacShaAsU8a } from '../../hmac';
|
import { hmacShaAsU8a } from '../../hmac';
|
||||||
import { secp256k1KeypairFromSeed, secp256k1PrivateKeyTweakAdd } from '../../secp256k1';
|
import { secp256k1PairFromSeed, secp256k1PrivateKeyTweakAdd } from '../../secp256k1';
|
||||||
import { HARDENED, hdValidatePath } from '../validatePath';
|
import { HARDENED, hdValidatePath } from '../validatePath';
|
||||||
|
|
||||||
interface CodedKeypair extends Keypair {
|
interface CodedKeypair extends Keypair {
|
||||||
@@ -19,7 +19,7 @@ const MASTER_SECRET = stringToU8a('Bitcoin seed');
|
|||||||
function createCoded (secretKey: Uint8Array, chainCode: Uint8Array): CodedKeypair {
|
function createCoded (secretKey: Uint8Array, chainCode: Uint8Array): CodedKeypair {
|
||||||
return {
|
return {
|
||||||
chainCode,
|
chainCode,
|
||||||
publicKey: secp256k1KeypairFromSeed(secretKey).publicKey,
|
publicKey: secp256k1PairFromSeed(secretKey).publicKey,
|
||||||
secretKey
|
secretKey
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import type { Keypair } from '../../types';
|
|||||||
|
|
||||||
import { assert } from '@polkadot/util';
|
import { assert } from '@polkadot/util';
|
||||||
|
|
||||||
|
import { ed25519PairFromSeed } from '../../ed25519';
|
||||||
import { mnemonicValidate } from '../../mnemonic';
|
import { mnemonicValidate } from '../../mnemonic';
|
||||||
import { naclKeypairFromSeed } from '../../nacl';
|
|
||||||
import { HARDENED, hdValidatePath } from '../validatePath';
|
import { HARDENED, hdValidatePath } from '../validatePath';
|
||||||
import { ledgerDerivePrivate } from './derivePrivate';
|
import { ledgerDerivePrivate } from './derivePrivate';
|
||||||
import { ledgerMaster } from './master';
|
import { ledgerMaster } from './master';
|
||||||
@@ -35,5 +35,5 @@ export function hdLedger (_mnemonic: string, path: string): Keypair {
|
|||||||
seed = ledgerDerivePrivate(seed, (n < HARDENED) ? (n + HARDENED) : n);
|
seed = ledgerDerivePrivate(seed, (n < HARDENED) ? (n + HARDENED) : n);
|
||||||
}
|
}
|
||||||
|
|
||||||
return naclKeypairFromSeed(seed.slice(0, 32));
|
return ed25519PairFromSeed(seed.slice(0, 32));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
import type { HexString } from '@polkadot/util/types';
|
import type { HexString } from '@polkadot/util/types';
|
||||||
|
|
||||||
import { u8aToHex } from '@polkadot/util';
|
import { u8aToHex } from '@polkadot/util';
|
||||||
import { isReady } from '@polkadot/wasm-crypto';
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export function createAsHex <T extends (...args: any[]) => Uint8Array> (fn: T): (...args: Parameters<T>) => HexString {
|
export function createAsHex <T extends (...args: any[]) => Uint8Array> (fn: T): (...args: Parameters<T>) => HexString {
|
||||||
@@ -16,7 +15,3 @@ export function createBitHasher <T> (bitLength: T, fn: (data: HexString | Buffer
|
|||||||
return (data: HexString | Buffer | Uint8Array | string, onlyJs?: boolean): Uint8Array =>
|
return (data: HexString | Buffer | Uint8Array | string, onlyJs?: boolean): Uint8Array =>
|
||||||
fn(data, bitLength, onlyJs);
|
fn(data, bitLength, onlyJs);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isWasmOnly (onlyJs?: boolean): boolean {
|
|
||||||
return isReady() && !onlyJs;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import { hexToU8a, stringToU8a } from '@polkadot/util';
|
import { hexToU8a, stringToU8a } from '@polkadot/util';
|
||||||
import { waitReady } from '@polkadot/wasm-crypto';
|
import { waitReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
import { performanceTest } from '../../test/performance';
|
import { performanceWasm } from '../../test/performance';
|
||||||
import { hmacShaAsU8a } from '.';
|
import { hmacShaAsU8a } from '.';
|
||||||
|
|
||||||
describe('hmacShaAsU8a', (): void => {
|
describe('hmacShaAsU8a', (): void => {
|
||||||
@@ -23,7 +23,7 @@ describe('hmacShaAsU8a', (): void => {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
describe.each([256, 512] as (256 | 512)[])('bitLength=$p', (bitLength): void => {
|
describe.each([256, 512] as (256 | 512)[])('bitLength=%p', (bitLength): void => {
|
||||||
describe.each([false, true])('onlyJs=%p', (onlyJs): void => {
|
describe.each([false, true])('onlyJs=%p', (onlyJs): void => {
|
||||||
it('returns an hex representation (string)', (): void => {
|
it('returns an hex representation (string)', (): void => {
|
||||||
expect(
|
expect(
|
||||||
@@ -32,7 +32,7 @@ describe('hmacShaAsU8a', (): void => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
performanceTest(`hmacShaAsU8a, bitLength=${bitLength}`, 16000, (input, onlyJs) =>
|
performanceWasm(`hmacShaAsU8a, bitLength=${bitLength}`, 16000, (input, onlyJs) =>
|
||||||
hmacShaAsU8a(input, input, bitLength, onlyJs)
|
hmacShaAsU8a(input, input, bitLength, onlyJs)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,38 +1,44 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import hash from 'hash.js';
|
import { hasBigInt, u8aToU8a } from '@polkadot/util';
|
||||||
|
import { hmacSha256, hmacSha512, isReady } from '@polkadot/wasm-crypto';
|
||||||
|
import { hmac } from '@polkadot/x-noble-hashes/hmac';
|
||||||
|
import { sha256 } from '@polkadot/x-noble-hashes/sha256';
|
||||||
|
import { sha512 } from '@polkadot/x-noble-hashes/sha512';
|
||||||
|
|
||||||
import { u8aToU8a } from '@polkadot/util';
|
type BitLength = 256 | 512;
|
||||||
import { hmacSha256, hmacSha512 } from '@polkadot/wasm-crypto';
|
|
||||||
|
|
||||||
import { isWasmOnly } from '../helpers';
|
function createSha (bitLength: BitLength): (key: Uint8Array | string, data: Uint8Array, onlyJs?: boolean) => Uint8Array {
|
||||||
|
|
||||||
type HashFn = (key: Uint8Array | string, data: Uint8Array, onlyJs?: boolean) => Uint8Array;
|
|
||||||
|
|
||||||
function createSha (bitLength: 256 | 512 = 256): HashFn {
|
|
||||||
return (key: Uint8Array | string, data: Uint8Array, onlyJs?: boolean): Uint8Array =>
|
return (key: Uint8Array | string, data: Uint8Array, onlyJs?: boolean): Uint8Array =>
|
||||||
hmacShaAsU8a(key, data, bitLength, onlyJs);
|
hmacShaAsU8a(key, data, bitLength, onlyJs);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hmacShaAsU8a (key: Uint8Array | string, data: Uint8Array, bitLength: 256 | 512 = 256, onlyJs?: boolean): Uint8Array {
|
/**
|
||||||
|
* @name hmacShaAsU8a
|
||||||
|
* @description creates a Hmac Sha (256/512) Uint8Array from the key & data
|
||||||
|
*/
|
||||||
|
export function hmacShaAsU8a (key: Uint8Array | string, data: Uint8Array, bitLength: BitLength = 256, onlyJs?: boolean): Uint8Array {
|
||||||
const is256 = bitLength === 256;
|
const is256 = bitLength === 256;
|
||||||
const u8aKey = u8aToU8a(key);
|
const u8aKey = u8aToU8a(key);
|
||||||
|
|
||||||
return isWasmOnly(onlyJs)
|
return !hasBigInt || (!onlyJs && isReady())
|
||||||
? is256
|
? is256
|
||||||
? hmacSha256(u8aKey, data)
|
? hmacSha256(u8aKey, data)
|
||||||
: hmacSha512(u8aKey, data)
|
: hmacSha512(u8aKey, data)
|
||||||
: new Uint8Array(
|
: is256
|
||||||
is256
|
? hmac(sha256, u8aKey, data)
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
: hmac(sha512, u8aKey, data);
|
||||||
// @ts-ignore
|
|
||||||
? hash.hmac(hash.sha256, u8aKey).update(data).digest()
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
: hash.hmac(hash.sha512, u8aKey).update(data).digest()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name hmacSha256AsU8a
|
||||||
|
* @description creates a Hmac Sha256 Uint8Array from the key & data
|
||||||
|
*/
|
||||||
export const hmacSha256AsU8a = createSha(256);
|
export const hmacSha256AsU8a = createSha(256);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name hmacSha512AsU8a
|
||||||
|
* @description creates a Hmac Sha512 Uint8Array from the key & data
|
||||||
|
*/
|
||||||
export const hmacSha512AsU8a = createSha(512);
|
export const hmacSha512AsU8a = createSha(512);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import { hexToU8a, stringToU8a } from '@polkadot/util';
|
import { hexToU8a, stringToU8a } from '@polkadot/util';
|
||||||
import { waitReady } from '@polkadot/wasm-crypto';
|
import { waitReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
import { performanceTest } from '../../test/performance';
|
import { performanceWasm } from '../../test/performance';
|
||||||
import { keccakAsU8a } from '.';
|
import { keccakAsU8a } from '.';
|
||||||
|
|
||||||
describe('keccakAsU8a', (): void => {
|
describe('keccakAsU8a', (): void => {
|
||||||
@@ -43,7 +43,7 @@ describe('keccakAsU8a', (): void => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
performanceTest(`keccakAsU8a, bitLength=${bitLength}`, 128000, (input, onlyJs) =>
|
performanceWasm(`keccakAsU8a, bitLength=${bitLength}`, 128000, (input, onlyJs) =>
|
||||||
keccakAsU8a(input, bitLength, onlyJs)
|
keccakAsU8a(input, bitLength, onlyJs)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,12 +3,13 @@
|
|||||||
|
|
||||||
import type { HexString } from '@polkadot/util/types';
|
import type { HexString } from '@polkadot/util/types';
|
||||||
|
|
||||||
import js from 'js-sha3';
|
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 { u8aToU8a } from '@polkadot/util';
|
import { createAsHex, createBitHasher } from '../helpers';
|
||||||
import { keccak256, keccak512 } from '@polkadot/wasm-crypto';
|
|
||||||
|
|
||||||
import { createAsHex, createBitHasher, isWasmOnly } from '../helpers';
|
type BitLength = 256 | 512;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name keccakAsU8a
|
* @name keccakAsU8a
|
||||||
@@ -24,19 +25,17 @@ import { createAsHex, createBitHasher, isWasmOnly } from '../helpers';
|
|||||||
* keccakAsU8a('123'); // => Uint8Array
|
* keccakAsU8a('123'); // => Uint8Array
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function keccakAsU8a (value: HexString | Buffer | Uint8Array | string, bitLength: 256 | 512 = 256, onlyJs?: boolean): Uint8Array {
|
export function keccakAsU8a (value: HexString | Buffer | Uint8Array | string, bitLength: BitLength = 256, onlyJs?: boolean): Uint8Array {
|
||||||
const is256 = bitLength === 256;
|
const is256 = bitLength === 256;
|
||||||
const u8a = u8aToU8a(value);
|
const u8a = u8aToU8a(value);
|
||||||
|
|
||||||
return isWasmOnly(onlyJs)
|
return !hasBigInt || (!onlyJs && isReady())
|
||||||
? is256
|
? is256
|
||||||
? keccak256(u8a)
|
? keccak256(u8a)
|
||||||
: keccak512(u8a)
|
: keccak512(u8a)
|
||||||
: new Uint8Array(
|
: is256
|
||||||
is256
|
? keccak256Js(u8a)
|
||||||
? js.keccak256.update(u8a).arrayBuffer()
|
: keccak512Js(u8a);
|
||||||
: js.keccak512.update(u8a).arrayBuffer()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { secp256k1DeriveHard } from '../secp256k1/deriveHard';
|
import { secp256k1DeriveHard } from '../secp256k1/deriveHard';
|
||||||
import { secp256k1KeypairFromSeed } from '../secp256k1/keypair/fromSeed';
|
import { secp256k1PairFromSeed } from '../secp256k1/pair/fromSeed';
|
||||||
import { createSeedDeriveFn } from './hdkdDerive';
|
import { createSeedDeriveFn } from './hdkdDerive';
|
||||||
|
|
||||||
export const keyHdkdEcdsa = createSeedDeriveFn(secp256k1KeypairFromSeed, secp256k1DeriveHard);
|
export const keyHdkdEcdsa = createSeedDeriveFn(secp256k1PairFromSeed, secp256k1DeriveHard);
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { naclDeriveHard } from '../nacl/deriveHard';
|
import { ed25519DeriveHard, ed25519PairFromSeed } from '../ed25519';
|
||||||
import { naclKeypairFromSeed } from '../nacl/keypair/fromSeed';
|
|
||||||
import { createSeedDeriveFn } from './hdkdDerive';
|
import { createSeedDeriveFn } from './hdkdDerive';
|
||||||
|
|
||||||
export const keyHdkdEd25519 = createSeedDeriveFn(naclKeypairFromSeed, naclDeriveHard);
|
export const keyHdkdEd25519 = createSeedDeriveFn(ed25519PairFromSeed, ed25519DeriveHard);
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
|
|
||||||
import type { Keypair } from '../types';
|
import type { Keypair } from '../types';
|
||||||
|
|
||||||
import { schnorrkelDeriveHard } from '../schnorrkel/deriveHard';
|
import { sr25519DeriveHard } from '../sr25519/deriveHard';
|
||||||
import { schnorrkelDeriveSoft } from '../schnorrkel/deriveSoft';
|
import { sr25519DeriveSoft } from '../sr25519/deriveSoft';
|
||||||
import { DeriveJunction } from './DeriveJunction';
|
import { DeriveJunction } from './DeriveJunction';
|
||||||
|
|
||||||
export function keyHdkdSr25519 (keypair: Keypair, { chainCode, isSoft }: DeriveJunction): Keypair {
|
export function keyHdkdSr25519 (keypair: Keypair, { chainCode, isSoft }: DeriveJunction): Keypair {
|
||||||
return isSoft
|
return isSoft
|
||||||
? schnorrkelDeriveSoft(keypair, chainCode)
|
? sr25519DeriveSoft(keypair, chainCode)
|
||||||
: schnorrkelDeriveHard(keypair, chainCode);
|
: sr25519DeriveHard(keypair, chainCode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { bip39Generate } from '@polkadot/wasm-crypto';
|
import { hasBigInt } from '@polkadot/util';
|
||||||
|
import { bip39Generate, isReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
import { isWasmOnly } from '../helpers';
|
|
||||||
import { generateMnemonic } from './bip39';
|
import { generateMnemonic } from './bip39';
|
||||||
|
|
||||||
export type WordCount = 12 | 15 | 18 | 21 | 24;
|
export type WordCount = 12 | 15 | 18 | 21 | 24;
|
||||||
@@ -30,7 +30,7 @@ const STRENGTH_MAP = {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function mnemonicGenerate (numWords: WordCount = 12, onlyJs?: boolean): string {
|
export function mnemonicGenerate (numWords: WordCount = 12, onlyJs?: boolean): string {
|
||||||
return isWasmOnly(onlyJs)
|
return !hasBigInt || (!onlyJs && isReady())
|
||||||
? bip39Generate(numWords)
|
? bip39Generate(numWords)
|
||||||
: generateMnemonic(STRENGTH_MAP[numWords]);
|
: generateMnemonic(STRENGTH_MAP[numWords]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
import { u8aToHex } from '@polkadot/util';
|
import { u8aToHex } from '@polkadot/util';
|
||||||
|
|
||||||
import tests from '../schnorrkel/keypair/testing';
|
import tests from '../sr25519/pair/testing.spec';
|
||||||
import { cryptoWaitReady } from '..';
|
import { cryptoWaitReady } from '..';
|
||||||
import { mnemonicToEntropy } from './toEntropy';
|
import { mnemonicToEntropy } from './toEntropy';
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { bip39ToEntropy } from '@polkadot/wasm-crypto';
|
import { hasBigInt } from '@polkadot/util';
|
||||||
|
import { bip39ToEntropy, isReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
import { isWasmOnly } from '../helpers';
|
|
||||||
import { mnemonicToEntropy as jsToEntropy } from './bip39';
|
import { mnemonicToEntropy as jsToEntropy } from './bip39';
|
||||||
|
|
||||||
export function mnemonicToEntropy (mnemonic: string, onlyJs?: boolean): Uint8Array {
|
export function mnemonicToEntropy (mnemonic: string, onlyJs?: boolean): Uint8Array {
|
||||||
return isWasmOnly(onlyJs)
|
return !hasBigInt || (!onlyJs && isReady())
|
||||||
? bip39ToEntropy(mnemonic)
|
? bip39ToEntropy(mnemonic)
|
||||||
: jsToEntropy(mnemonic);
|
: jsToEntropy(mnemonic);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { assert } from '@polkadot/util';
|
import { assert, hasBigInt } from '@polkadot/util';
|
||||||
import { bip39ToSeed } from '@polkadot/wasm-crypto';
|
import { bip39ToSeed, isReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
import { isWasmOnly } from '../helpers';
|
|
||||||
import { mnemonicToSeedSync } from './bip39';
|
import { mnemonicToSeedSync } from './bip39';
|
||||||
import { mnemonicValidate } from './validate';
|
import { mnemonicValidate } from './validate';
|
||||||
|
|
||||||
@@ -29,13 +28,9 @@ export function mnemonicToLegacySeed (mnemonic: string, password = '', onlyJs?:
|
|||||||
assert(mnemonicValidate(mnemonic), 'Invalid bip39 mnemonic specified');
|
assert(mnemonicValidate(mnemonic), 'Invalid bip39 mnemonic specified');
|
||||||
assert([32, 64].includes(byteLength), () => `Invalid seed length ${byteLength}, expected 32 or 64`);
|
assert([32, 64].includes(byteLength), () => `Invalid seed length ${byteLength}, expected 32 or 64`);
|
||||||
|
|
||||||
if (byteLength === 32) {
|
return byteLength === 32
|
||||||
return isWasmOnly(onlyJs)
|
? !hasBigInt || (!onlyJs && isReady())
|
||||||
? bip39ToSeed(mnemonic, password)
|
? bip39ToSeed(mnemonic, password)
|
||||||
: mnemonicToSeedSync(mnemonic, password).subarray(0, 32);
|
: mnemonicToSeedSync(mnemonic, password).subarray(0, 32)
|
||||||
} else if (byteLength === 64) {
|
: mnemonicToSeedSync(mnemonic, password);
|
||||||
return mnemonicToSeedSync(mnemonic, password);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Uint8Array();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
import { u8aEq, u8aToHex } from '@polkadot/util';
|
import { u8aEq, u8aToHex } from '@polkadot/util';
|
||||||
|
|
||||||
import tests from '../schnorrkel/keypair/testing';
|
import tests from '../sr25519/pair/testing.spec';
|
||||||
import { cryptoWaitReady } from '..';
|
import { cryptoWaitReady } from '..';
|
||||||
import { mnemonicToMiniSecret } from './toMiniSecret';
|
import { mnemonicToMiniSecret } from './toMiniSecret';
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,8 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { assert, stringToU8a } from '@polkadot/util';
|
import { assert, stringToU8a } from '@polkadot/util';
|
||||||
import { bip39ToMiniSecret } from '@polkadot/wasm-crypto';
|
import { bip39ToMiniSecret, isReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
import { isWasmOnly } from '../helpers';
|
|
||||||
import { pbkdf2Encode } from '../pbkdf2';
|
import { pbkdf2Encode } from '../pbkdf2';
|
||||||
import { mnemonicToEntropy } from './toEntropy';
|
import { mnemonicToEntropy } from './toEntropy';
|
||||||
import { mnemonicValidate } from './validate';
|
import { mnemonicValidate } from './validate';
|
||||||
@@ -12,7 +11,7 @@ import { mnemonicValidate } from './validate';
|
|||||||
export function mnemonicToMiniSecret (mnemonic: string, password = '', onlyJs?: boolean): Uint8Array {
|
export function mnemonicToMiniSecret (mnemonic: string, password = '', onlyJs?: boolean): Uint8Array {
|
||||||
assert(mnemonicValidate(mnemonic), 'Invalid bip39 mnemonic specified');
|
assert(mnemonicValidate(mnemonic), 'Invalid bip39 mnemonic specified');
|
||||||
|
|
||||||
if (isWasmOnly(onlyJs)) {
|
if (!onlyJs && isReady()) {
|
||||||
return bip39ToMiniSecret(mnemonic, password);
|
return bip39ToMiniSecret(mnemonic, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
import { arrayRange, u8aEq } from '@polkadot/util';
|
import { arrayRange, u8aEq } from '@polkadot/util';
|
||||||
|
|
||||||
import { cryptoWaitReady, mnemonicGenerate, mnemonicToMiniSecret, naclKeypairFromSeed, schnorrkelKeypairFromSeed } from '..';
|
import { cryptoWaitReady, ed25519PairFromSeed, mnemonicGenerate, mnemonicToMiniSecret, sr25519PairFromSeed } from '..';
|
||||||
|
|
||||||
// NOTE: This basically controls how long stuff runs for, YMMV
|
// NOTE: This basically controls how long stuff runs for, YMMV
|
||||||
//
|
//
|
||||||
@@ -29,8 +29,8 @@ describe.each([true, false])('mnemonicToMiniSecret (compare), onlyJsMnemonic=%p'
|
|||||||
// do iterations to check and re-check that all matches
|
// do iterations to check and re-check that all matches
|
||||||
it.concurrent.each(arrayRange(NUM_CHECKS))('check=%p', (count): void => {
|
it.concurrent.each(arrayRange(NUM_CHECKS))('check=%p', (count): void => {
|
||||||
const minisecret = mnemonicToMiniSecret(mnemonic, count ? `${count}` : '', onlyJsMnemonic);
|
const minisecret = mnemonicToMiniSecret(mnemonic, count ? `${count}` : '', onlyJsMnemonic);
|
||||||
const edpub = naclKeypairFromSeed(minisecret).publicKey;
|
const edpub = ed25519PairFromSeed(minisecret).publicKey;
|
||||||
const srpub = schnorrkelKeypairFromSeed(minisecret).publicKey;
|
const srpub = sr25519PairFromSeed(minisecret).publicKey;
|
||||||
|
|
||||||
const testmini = mnemonicToMiniSecret(mnemonic, count ? `${count}` : '', onlyJsMini);
|
const testmini = mnemonicToMiniSecret(mnemonic, count ? `${count}` : '', onlyJsMini);
|
||||||
|
|
||||||
@@ -41,13 +41,13 @@ describe.each([true, false])('mnemonicToMiniSecret (compare), onlyJsMnemonic=%p'
|
|||||||
|
|
||||||
// compare the sr25519 keypair generated
|
// compare the sr25519 keypair generated
|
||||||
expect(
|
expect(
|
||||||
u8aEq(srpub, schnorrkelKeypairFromSeed(testmini).publicKey)
|
u8aEq(srpub, sr25519PairFromSeed(testmini).publicKey)
|
||||||
).toEqual(true);
|
).toEqual(true);
|
||||||
|
|
||||||
// compare ed both in WASM and JS
|
// compare ed both in WASM and JS
|
||||||
[true, false].forEach((onlyJsEd): void => {
|
[true, false].forEach((onlyJsEd): void => {
|
||||||
expect(
|
expect(
|
||||||
u8aEq(edpub, naclKeypairFromSeed(testmini, onlyJsEd).publicKey)
|
u8aEq(edpub, ed25519PairFromSeed(testmini, onlyJsEd).publicKey)
|
||||||
).toEqual(true);
|
).toEqual(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { bip39Validate } from '@polkadot/wasm-crypto';
|
import { hasBigInt } from '@polkadot/util';
|
||||||
|
import { bip39Validate, isReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
import { isWasmOnly } from '../helpers';
|
|
||||||
import { validateMnemonic } from './bip39';
|
import { validateMnemonic } from './bip39';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,7 +20,7 @@ import { validateMnemonic } from './bip39';
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function mnemonicValidate (mnemonic: string, onlyJs?: boolean): boolean {
|
export function mnemonicValidate (mnemonic: string, onlyJs?: boolean): boolean {
|
||||||
return isWasmOnly(onlyJs)
|
return !hasBigInt || (!onlyJs && isReady())
|
||||||
? bip39Validate(mnemonic)
|
? bip39Validate(mnemonic)
|
||||||
: validateMnemonic(mnemonic);
|
: validateMnemonic(mnemonic);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { naclBoxKeypairFromSecret } from '..';
|
import { naclBoxPairFromSecret } from '..';
|
||||||
|
|
||||||
describe('naclBoxKeypairFromSecret', (): void => {
|
describe('naclBoxPairFromSecret', (): void => {
|
||||||
const secretKey = new Uint8Array([
|
const secretKey = new Uint8Array([
|
||||||
18, 52, 86, 120, 144, 18, 52, 86,
|
18, 52, 86, 120, 144, 18, 52, 86,
|
||||||
120, 144, 18, 52, 86, 120, 144, 18,
|
120, 144, 18, 52, 86, 120, 144, 18,
|
||||||
@@ -13,7 +13,7 @@ describe('naclBoxKeypairFromSecret', (): void => {
|
|||||||
|
|
||||||
it('generates a valid publicKey/secretKey pair', (): void => {
|
it('generates a valid publicKey/secretKey pair', (): void => {
|
||||||
expect(
|
expect(
|
||||||
naclBoxKeypairFromSecret(secretKey)
|
naclBoxPairFromSecret(secretKey)
|
||||||
).toEqual({
|
).toEqual({
|
||||||
publicKey: new Uint8Array([
|
publicKey: new Uint8Array([
|
||||||
206, 110, 228, 222, 155, 43, 229, 254,
|
206, 110, 228, 222, 155, 43, 229, 254,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import type { Keypair } from '../../types';
|
|||||||
import nacl from 'tweetnacl';
|
import nacl from 'tweetnacl';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name naclBoxKeypairFromSecret
|
* @name naclBoxPairFromSecret
|
||||||
* @summary Creates a new public/secret box keypair from a secret.
|
* @summary Creates a new public/secret box keypair from a secret.
|
||||||
* @description
|
* @description
|
||||||
* Returns a object containing a box `publicKey` & `secretKey` generated from the supplied secret.
|
* Returns a object containing a box `publicKey` & `secretKey` generated from the supplied secret.
|
||||||
@@ -14,11 +14,11 @@ import nacl from 'tweetnacl';
|
|||||||
* <BR>
|
* <BR>
|
||||||
*
|
*
|
||||||
* ```javascript
|
* ```javascript
|
||||||
* import { naclBoxKeypairFromSecret } from '@polkadot/util-crypto';
|
* import { naclBoxPairFromSecret } from '@polkadot/util-crypto';
|
||||||
*
|
*
|
||||||
* naclBoxKeypairFromSecret(...); // => { secretKey: [...], publicKey: [...] }
|
* naclBoxPairFromSecret(...); // => { secretKey: [...], publicKey: [...] }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function naclBoxKeypairFromSecret (secret: Uint8Array): Keypair {
|
export function naclBoxPairFromSecret (secret: Uint8Array): Keypair {
|
||||||
return nacl.box.keyPair.fromSecretKey(secret.slice(0, 32));
|
return nacl.box.keyPair.fromSecretKey(secret.slice(0, 32));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,17 +2,10 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Implements [NaCl](http://nacl.cr.yp.to/) secret-key authenticated encryption, public-key authenticated encryption, hashing, and public-key signatures
|
* @summary Implements [NaCl](http://nacl.cr.yp.to/) secret-key authenticated encryption, public-key authenticated encryption
|
||||||
*/
|
*/
|
||||||
export { naclDecrypt } from './decrypt';
|
export { naclDecrypt } from './decrypt';
|
||||||
export { naclEncrypt } from './encrypt';
|
export { naclEncrypt } from './encrypt';
|
||||||
export { naclKeypairFromRandom } from './keypair/fromRandom';
|
export { naclBoxPairFromSecret } from './box/fromSecret';
|
||||||
export { naclKeypairFromSecret } from './keypair/fromSecret';
|
|
||||||
export { naclKeypairFromSeed } from './keypair/fromSeed';
|
|
||||||
export { naclKeypairFromString } from './keypair/fromString';
|
|
||||||
export { naclSign } from './sign';
|
|
||||||
export { naclVerify } from './verify';
|
|
||||||
export { naclBoxKeypairFromSecret } from './box/fromSecret';
|
|
||||||
export { naclOpen } from './open';
|
export { naclOpen } from './open';
|
||||||
export { naclSeal } from './seal';
|
export { naclSeal } from './seal';
|
||||||
export { convertSecretKeyToCurve25519, convertPublicKeyToCurve25519 } from './convertKey';
|
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import { ed25519PairFromString } from '../ed25519';
|
||||||
import { keyExtractPath } from '../key';
|
import { keyExtractPath } from '../key';
|
||||||
import { keyFromPath } from '../key/fromPath';
|
import { keyFromPath } from '../key/fromPath';
|
||||||
import { naclBoxKeypairFromSecret, naclKeypairFromString, naclOpen, naclSeal } from '.';
|
import { naclBoxPairFromSecret, naclOpen, naclSeal } from '.';
|
||||||
|
|
||||||
describe('naclOpen', (): void => {
|
describe('naclOpen', (): void => {
|
||||||
it('opens a sealed message by the sender', (): void => {
|
it('opens a sealed message by the sender', (): void => {
|
||||||
const message = new Uint8Array([1, 2, 3, 4, 5, 4, 3, 2, 1]);
|
const message = new Uint8Array([1, 2, 3, 4, 5, 4, 3, 2, 1]);
|
||||||
const sender = naclKeypairFromString('sender');
|
const sender = ed25519PairFromString('sender');
|
||||||
const receiver = naclKeypairFromString('receiver');
|
const receiver = ed25519PairFromString('receiver');
|
||||||
const senderBox = naclBoxKeypairFromSecret(sender.secretKey);
|
const senderBox = naclBoxPairFromSecret(sender.secretKey);
|
||||||
const receiverBox = naclBoxKeypairFromSecret(receiver.secretKey);
|
const receiverBox = naclBoxPairFromSecret(receiver.secretKey);
|
||||||
const { nonce, sealed } = naclSeal(message, senderBox.secretKey, receiverBox.publicKey);
|
const { nonce, sealed } = naclSeal(message, senderBox.secretKey, receiverBox.publicKey);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
@@ -22,20 +23,20 @@ describe('naclOpen', (): void => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('polkadot does double ratchet', () => {
|
it('polkadot does double ratchet', () => {
|
||||||
const sender = naclKeypairFromString('sender');
|
const sender = ed25519PairFromString('sender');
|
||||||
const receiver = naclKeypairFromString('receiver');
|
const receiver = ed25519PairFromString('receiver');
|
||||||
|
|
||||||
// Make id key for identifying each other
|
// Make id key for identifying each other
|
||||||
const senderIdKey = keyFromPath(sender, keyExtractPath('//1//1//1//1').path, 'ed25519');
|
const senderIdKey = keyFromPath(sender, keyExtractPath('//1//1//1//1').path, 'ed25519');
|
||||||
const receiverIdKey = keyFromPath(receiver, keyExtractPath('//2//2//2//2').path, 'ed25519');
|
const receiverIdKey = keyFromPath(receiver, keyExtractPath('//2//2//2//2').path, 'ed25519');
|
||||||
|
|
||||||
// Receiver sends encrypting public key to receive message to decrypt with his private key
|
// Receiver sends encrypting public key to receive message to decrypt with his private key
|
||||||
const receiverIdBoxKey = naclBoxKeypairFromSecret(receiverIdKey.secretKey);
|
const receiverIdBoxKey = naclBoxPairFromSecret(receiverIdKey.secretKey);
|
||||||
|
|
||||||
// console.log(`Receiver sends receiver's public key to sender ${receiverIdBoxKey.publicKey.toString()}`);
|
// console.log(`Receiver sends receiver's public key to sender ${receiverIdBoxKey.publicKey.toString()}`);
|
||||||
|
|
||||||
// Sender encrypts message to send with the public key the receiver sent and send it to receiver
|
// Sender encrypts message to send with the public key the receiver sent and send it to receiver
|
||||||
const senderIdBoxKey = naclBoxKeypairFromSecret(senderIdKey.secretKey);
|
const senderIdBoxKey = naclBoxPairFromSecret(senderIdKey.secretKey);
|
||||||
const message = new Uint8Array([1, 2, 3, 4, 5, 4, 3, 2, 1]);
|
const message = new Uint8Array([1, 2, 3, 4, 5, 4, 3, 2, 1]);
|
||||||
const { nonce, sealed } = naclSeal(message, senderIdBoxKey.secretKey, receiverIdBoxKey.publicKey);
|
const { nonce, sealed } = naclSeal(message, senderIdBoxKey.secretKey, receiverIdBoxKey.publicKey);
|
||||||
|
|
||||||
@@ -51,12 +52,12 @@ describe('naclOpen', (): void => {
|
|||||||
const receiverIdKey2 = keyFromPath(receiver, keyExtractPath('//2//2//2//3').path, 'ed25519');
|
const receiverIdKey2 = keyFromPath(receiver, keyExtractPath('//2//2//2//3').path, 'ed25519');
|
||||||
|
|
||||||
// Receiver sends encrypting public key to receive message to decrypt with his private key
|
// Receiver sends encrypting public key to receive message to decrypt with his private key
|
||||||
const receiverIdBoxKey2 = naclBoxKeypairFromSecret(receiverIdKey2.secretKey);
|
const receiverIdBoxKey2 = naclBoxPairFromSecret(receiverIdKey2.secretKey);
|
||||||
|
|
||||||
// console.log(`Receiver sends receiver's public key to sender ${receiverIdBoxKey2.publicKey.toString()}`);
|
// console.log(`Receiver sends receiver's public key to sender ${receiverIdBoxKey2.publicKey.toString()}`);
|
||||||
|
|
||||||
// Sender encrypts message to send with the public key the receiver sent and send it to receiver
|
// Sender encrypts message to send with the public key the receiver sent and send it to receiver
|
||||||
const senderIdBoxKey2 = naclBoxKeypairFromSecret(senderIdKey2.secretKey);
|
const senderIdBoxKey2 = naclBoxPairFromSecret(senderIdKey2.secretKey);
|
||||||
const message2 = new Uint8Array([1, 2, 3, 4, 5, 4, 3, 2, 1]);
|
const message2 = new Uint8Array([1, 2, 3, 4, 5, 4, 3, 2, 1]);
|
||||||
let ctx = naclSeal(message2, senderIdBoxKey2.secretKey, receiverIdBoxKey2.publicKey);
|
let ctx = naclSeal(message2, senderIdBoxKey2.secretKey, receiverIdBoxKey2.publicKey);
|
||||||
const sealed2 = ctx.sealed;
|
const sealed2 = ctx.sealed;
|
||||||
@@ -70,12 +71,12 @@ describe('naclOpen', (): void => {
|
|||||||
|
|
||||||
// This time derive key for each message to send and receive
|
// This time derive key for each message to send and receive
|
||||||
// Receiver sends encrypting public key to receive message to decrypt with his private key
|
// Receiver sends encrypting public key to receive message to decrypt with his private key
|
||||||
const receiverIdBoxKey2One = naclBoxKeypairFromSecret(receiverIdBoxKey2.secretKey);
|
const receiverIdBoxKey2One = naclBoxPairFromSecret(receiverIdBoxKey2.secretKey);
|
||||||
|
|
||||||
// console.log(`Receiver sends receiver's public key to sender ${receiverIdBoxKey2One.publicKey.toString()}`);
|
// console.log(`Receiver sends receiver's public key to sender ${receiverIdBoxKey2One.publicKey.toString()}`);
|
||||||
|
|
||||||
// Sender encrypts message to send with the public key the receiver sent and send it to receiver
|
// Sender encrypts message to send with the public key the receiver sent and send it to receiver
|
||||||
const senderIdBoxKey2One = naclBoxKeypairFromSecret(senderIdBoxKey2.secretKey);
|
const senderIdBoxKey2One = naclBoxPairFromSecret(senderIdBoxKey2.secretKey);
|
||||||
const message3 = new Uint8Array([1, 2, 3, 4, 5, 4, 3, 2, 1]);
|
const message3 = new Uint8Array([1, 2, 3, 4, 5, 4, 3, 2, 1]);
|
||||||
|
|
||||||
ctx = naclSeal(message3, senderIdBoxKey2One.secretKey, receiverIdBoxKey2One.publicKey);
|
ctx = naclSeal(message3, senderIdBoxKey2One.secretKey, receiverIdBoxKey2One.publicKey);
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { naclBoxKeypairFromSecret, naclKeypairFromString, naclSeal } from '.';
|
import { ed25519PairFromString } from '../ed25519';
|
||||||
|
import { naclBoxPairFromSecret, naclSeal } from '.';
|
||||||
|
|
||||||
describe('naclSeal', (): void => {
|
describe('naclSeal', (): void => {
|
||||||
it('seals a message', (): void => {
|
it('seals a message', (): void => {
|
||||||
const message = new Uint8Array([1, 2, 3, 4, 5, 4, 3, 2, 1]);
|
const message = new Uint8Array([1, 2, 3, 4, 5, 4, 3, 2, 1]);
|
||||||
const sender = naclKeypairFromString('sender');
|
const sender = ed25519PairFromString('sender');
|
||||||
const receiver = naclKeypairFromString('receiver');
|
const receiver = ed25519PairFromString('receiver');
|
||||||
const senderBox = naclBoxKeypairFromSecret(sender.secretKey);
|
const senderBox = naclBoxPairFromSecret(sender.secretKey);
|
||||||
const receiverBox = naclBoxKeypairFromSecret(receiver.secretKey);
|
const receiverBox = naclBoxPairFromSecret(receiver.secretKey);
|
||||||
const senderBoxSecret = senderBox.secretKey;
|
const senderBoxSecret = senderBox.secretKey;
|
||||||
const receiverBoxPublic = receiverBox.publicKey;
|
const receiverBoxPublic = receiverBox.publicKey;
|
||||||
|
|
||||||
|
|||||||
@@ -3,4 +3,4 @@
|
|||||||
|
|
||||||
// Auto-generated by @polkadot/dev, do not edit
|
// Auto-generated by @polkadot/dev, do not edit
|
||||||
|
|
||||||
export const packageInfo = { name: '@polkadot/util-crypto', version: '7.9.2' };
|
export const packageInfo = { name: '@polkadot/util-crypto', version: '8.1.2' };
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
import { u8aEq, u8aToHex } from '@polkadot/util';
|
import { u8aEq, u8aToHex } from '@polkadot/util';
|
||||||
import { waitReady } from '@polkadot/wasm-crypto';
|
import { waitReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
|
import { performanceWasm } from '../../test/performance';
|
||||||
import { randomAsU8a } from '../random/asU8a';
|
import { randomAsU8a } from '../random/asU8a';
|
||||||
import { pbkdf2Encode } from '.';
|
import { pbkdf2Encode } from '.';
|
||||||
|
|
||||||
@@ -40,4 +41,8 @@ describe('pbkdf2Encode', (): void => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
performanceWasm('pbkdf2Encode', 8, (input, onlyJs) =>
|
||||||
|
pbkdf2Encode(input, input, undefined, onlyJs)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
|
|
||||||
import type { HexString } from '@polkadot/util/types';
|
import type { HexString } from '@polkadot/util/types';
|
||||||
|
|
||||||
import { u8aToU8a } from '@polkadot/util';
|
import { hasBigInt, u8aToU8a } from '@polkadot/util';
|
||||||
import { pbkdf2 } from '@polkadot/wasm-crypto';
|
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 { isWasmOnly } from '../helpers';
|
|
||||||
import { randomAsU8a } from '../random/asU8a';
|
import { randomAsU8a } from '../random/asU8a';
|
||||||
import { pbkdf2Sync } from './pbkdf2';
|
|
||||||
|
|
||||||
interface Result {
|
interface Result {
|
||||||
password: Uint8Array;
|
password: Uint8Array;
|
||||||
@@ -21,9 +21,9 @@ export function pbkdf2Encode (passphrase?: HexString | Buffer | Uint8Array | str
|
|||||||
const u8aSalt = u8aToU8a(salt);
|
const u8aSalt = u8aToU8a(salt);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
password: isWasmOnly(onlyJs)
|
password: !hasBigInt || (!onlyJs && isReady())
|
||||||
? pbkdf2(u8aPass, u8aSalt, rounds)
|
? pbkdf2(u8aPass, u8aSalt, rounds)
|
||||||
: pbkdf2Sync(u8aPass, u8aSalt, rounds),
|
: pbkdf2Js(sha512, u8aPass, u8aSalt, { c: rounds, dkLen: 64 }),
|
||||||
rounds,
|
rounds,
|
||||||
salt
|
salt
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
// Adapted from https://gist.github.com/calvinmetcalf/91e8e84dc63c75f2aa53
|
|
||||||
|
|
||||||
import { bnToU8a, u8aConcat } from '@polkadot/util';
|
|
||||||
|
|
||||||
import { BN_BE_32_OPTS } from '../bn';
|
|
||||||
import { hmacShaAsU8a } from '../hmac';
|
|
||||||
|
|
||||||
export function pbkdf2Sync (password: Uint8Array, salt: Uint8Array, rounds: number, len = 64): Uint8Array {
|
|
||||||
let out = new Uint8Array();
|
|
||||||
let num = 0;
|
|
||||||
const block = u8aConcat(salt, new Uint8Array(4));
|
|
||||||
|
|
||||||
while (out.length < len) {
|
|
||||||
num++;
|
|
||||||
block.set(bnToU8a(num, BN_BE_32_OPTS), salt.length);
|
|
||||||
|
|
||||||
let prev = hmacShaAsU8a(password, block, 512);
|
|
||||||
const md = prev;
|
|
||||||
let i = 0;
|
|
||||||
|
|
||||||
while (++i < rounds) {
|
|
||||||
prev = hmacShaAsU8a(password, prev, 512);
|
|
||||||
|
|
||||||
let j = -1;
|
|
||||||
|
|
||||||
while (++j < prev.length) {
|
|
||||||
md[j] ^= prev[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out = u8aConcat(out, md);
|
|
||||||
}
|
|
||||||
|
|
||||||
return out.slice(0, len);
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
export { schnorrkelAgreement } from './agreement';
|
|
||||||
export { schnorrkelDeriveHard } from './deriveHard';
|
|
||||||
export { schnorrkelDerivePublic } from './derivePublic';
|
|
||||||
export { schnorrkelDeriveSoft } from './deriveSoft';
|
|
||||||
export { schnorrkelKeypairFromSeed } from './keypair/fromSeed';
|
|
||||||
export { schnorrkelSign } from './sign';
|
|
||||||
export { schnorrkelVerify } from './verify';
|
|
||||||
export { schnorrkelVrfSign } from './vrfSign';
|
|
||||||
export { schnorrkelVrfVerify } from './vrfVerify';
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
import { waitReady } from '@polkadot/wasm-crypto';
|
import { waitReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
import { performanceTest } from '../../test/performance';
|
import { performanceWasm } from '../../test/performance';
|
||||||
import { DEFAULT_PARAMS } from './defaults';
|
import { DEFAULT_PARAMS } from './defaults';
|
||||||
import { scryptEncode } from '.';
|
import { scryptEncode } from '.';
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ describe('scryptEncode', (): void => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
performanceTest('scryptEncode', 2, (input, onlyJs) =>
|
performanceWasm('scryptEncode', 4, (input, onlyJs) =>
|
||||||
scryptEncode(input, input, undefined, onlyJs)
|
scryptEncode(input, input, undefined, onlyJs)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,12 +4,10 @@
|
|||||||
import type { HexString } from '@polkadot/util/types';
|
import type { HexString } from '@polkadot/util/types';
|
||||||
import type { Params } from './types';
|
import type { Params } from './types';
|
||||||
|
|
||||||
import scryptsy from 'scryptsy';
|
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 { bufferToU8a, u8aToBuffer, u8aToU8a } from '@polkadot/util';
|
|
||||||
import { scrypt } from '@polkadot/wasm-crypto';
|
|
||||||
|
|
||||||
import { isWasmOnly } from '../helpers';
|
|
||||||
import { randomAsU8a } from '../random/asU8a';
|
import { randomAsU8a } from '../random/asU8a';
|
||||||
import { DEFAULT_PARAMS } from './defaults';
|
import { DEFAULT_PARAMS } from './defaults';
|
||||||
|
|
||||||
@@ -22,11 +20,11 @@ interface Result {
|
|||||||
export function scryptEncode (passphrase?: HexString | Uint8Array | string, salt = randomAsU8a(), params = DEFAULT_PARAMS, onlyJs?: boolean): Result {
|
export function scryptEncode (passphrase?: HexString | Uint8Array | string, salt = randomAsU8a(), params = DEFAULT_PARAMS, onlyJs?: boolean): Result {
|
||||||
const u8a = u8aToU8a(passphrase);
|
const u8a = u8aToU8a(passphrase);
|
||||||
|
|
||||||
const password = isWasmOnly(onlyJs)
|
return {
|
||||||
? scrypt(u8a, salt, Math.log2(params.N), params.r, params.p)
|
params,
|
||||||
: bufferToU8a(
|
password: !hasBigInt || (!onlyJs && isReady())
|
||||||
scryptsy(u8aToBuffer(u8a), u8aToBuffer(salt), params.N, params.r, params.p, 64)
|
? scrypt(u8a, salt, Math.log2(params.N), params.r, params.p)
|
||||||
);
|
: scryptJs(u8a, salt, objectSpread({ dkLen: 64 }, params)),
|
||||||
|
salt
|
||||||
return { params, password, salt };
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,17 +2,43 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { hexToU8a } from '@polkadot/util';
|
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 => {
|
describe('secp256k1Compress', (): void => {
|
||||||
it('compresses a known key', (): void => {
|
beforeEach(async (): Promise<void> => {
|
||||||
expect(
|
await waitReady();
|
||||||
secp256k1Compress(
|
|
||||||
hexToU8a('0x04b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb1307763fe926c273235fd979a134076d00fd1683cbd35868cb485d4a3a640e52184af')
|
|
||||||
)
|
|
||||||
).toEqual(
|
|
||||||
hexToU8a('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077')
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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(publicKey.length === 65, 'Invalid publicKey provided');
|
||||||
assert([33, 65].includes(publicKey.length), 'Invalid publicKey provided');
|
|
||||||
|
|
||||||
return new Uint8Array(
|
return !hasBigInt || (!onlyJs && isReady())
|
||||||
secp256k1
|
? wasm(publicKey)
|
||||||
.keyFromPublic(publicKey)
|
: Point.fromHex(publicKey).toRawBytes(true);
|
||||||
.getPublic()
|
|
||||||
.encodeCompressed()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,27 +2,43 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { hexToU8a } from '@polkadot/util';
|
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 => {
|
describe('secp256k1Expand', (): void => {
|
||||||
it('expands a known key', (): void => {
|
beforeEach(async (): Promise<void> => {
|
||||||
expect(
|
await waitReady();
|
||||||
secp256k1Expand(
|
|
||||||
hexToU8a('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077')
|
|
||||||
)
|
|
||||||
).toEqual(
|
|
||||||
hexToU8a('0xb9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb1307763fe926c273235fd979a134076d00fd1683cbd35868cb485d4a3a640e52184af')
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('expands a known full key', (): void => {
|
describe.each([false, true])('onlyJs=%p', (onlyJs): void => {
|
||||||
expect(
|
it('expands a known key', (): void => {
|
||||||
secp256k1Expand(
|
expect(
|
||||||
hexToU8a('0x04b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb1307763fe926c273235fd979a134076d00fd1683cbd35868cb485d4a3a640e52184af')
|
secp256k1Expand(
|
||||||
)
|
hexToU8a('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077'),
|
||||||
).toEqual(
|
onlyJs
|
||||||
hexToU8a('0xb9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb1307763fe926c273235fd979a134076d00fd1683cbd35868cb485d4a3a640e52184af')
|
)
|
||||||
);
|
).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
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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 { BN_BE_256_OPTS } from '../bn';
|
||||||
import { secp256k1 } from './secp256k1';
|
|
||||||
|
|
||||||
export function secp256k1Expand (publicKey: Uint8Array): Uint8Array {
|
export function secp256k1Expand (publicKey: Uint8Array, onlyJs?: boolean): Uint8Array {
|
||||||
assert([33, 65].includes(publicKey.length), 'Invalid publicKey provided');
|
if (publicKey.length === 65) {
|
||||||
|
return publicKey.subarray(1);
|
||||||
|
}
|
||||||
|
|
||||||
const expanded = secp256k1
|
assert(publicKey.length === 33, 'Invalid publicKey provided');
|
||||||
.keyFromPublic(publicKey)
|
|
||||||
.getPublic();
|
if (!hasBigInt || (!onlyJs && isReady())) {
|
||||||
|
return wasm(publicKey).subarray(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { x, y } = Point.fromHex(publicKey);
|
||||||
|
|
||||||
return u8aConcat(
|
return u8aConcat(
|
||||||
bnToU8a(expanded.getX(), BN_BE_256_OPTS),
|
bnToU8a(x, BN_BE_256_OPTS),
|
||||||
bnToU8a(expanded.getY(), BN_BE_256_OPTS)
|
bnToU8a(y, BN_BE_256_OPTS)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,12 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { secp256k1Hasher } from './hasher';
|
import { hasher } 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/);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
describe('hasher', (): void => {
|
||||||
it('creates a blake2 hash', (): void => {
|
it('creates a blake2 hash', (): void => {
|
||||||
expect(
|
expect(
|
||||||
secp256k1Hasher('blake2', 'abc')
|
hasher('blake2', 'abc')
|
||||||
).toEqual(
|
).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])
|
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 => {
|
it('creates a keccak hash', (): void => {
|
||||||
expect(
|
expect(
|
||||||
secp256k1Hasher('keccak', 'abc')
|
hasher('keccak', 'abc')
|
||||||
).toEqual(
|
).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])
|
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 { blake2AsU8a } from '../blake2';
|
||||||
import { keccakAsU8a } from '../keccak';
|
import { keccakAsU8a } from '../keccak';
|
||||||
|
|
||||||
const HASH_TYPES = ['blake2', 'keccak'];
|
export function hasher (hashType: HashType, data: Uint8Array | string, onlyJs?: boolean): Uint8Array {
|
||||||
|
return hashType === 'keccak'
|
||||||
export function secp256k1Hasher (hashType: HashType, data: Uint8Array | string): Uint8Array {
|
? keccakAsU8a(data, undefined, onlyJs)
|
||||||
if (hashType === 'blake2') {
|
: blake2AsU8a(data, undefined, undefined, onlyJs);
|
||||||
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(', ')}`);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
export { secp256k1Compress } from './compress';
|
export { secp256k1Compress } from './compress';
|
||||||
export { secp256k1Expand } from './expand';
|
export { secp256k1Expand } from './expand';
|
||||||
export { secp256k1KeypairFromSeed } from './keypair/fromSeed';
|
export { secp256k1PairFromSeed } from './pair/fromSeed';
|
||||||
export { secp256k1Recover } from './recover';
|
export { secp256k1Recover } from './recover';
|
||||||
export { secp256k1Sign } from './sign';
|
export { secp256k1Sign } from './sign';
|
||||||
export { secp256k1PrivateKeyTweakAdd } from './tweakAdd';
|
export { secp256k1PrivateKeyTweakAdd } from './tweakAdd';
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
import type { Keypair } from '../../types';
|
|
||||||
|
|
||||||
import { assert, bnToU8a } from '@polkadot/util';
|
|
||||||
|
|
||||||
import { BN_BE_256_OPTS } from '../../bn';
|
|
||||||
import { secp256k1 } from '../secp256k1';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name secp256k1KeypairFromSeed
|
|
||||||
* @description Returns a object containing a `publicKey` & `secretKey` generated from the supplied seed.
|
|
||||||
*/
|
|
||||||
export function secp256k1KeypairFromSeed (seed: Uint8Array): Keypair {
|
|
||||||
assert(seed.length === 32, 'Expected valid 32-byte private key as a seed');
|
|
||||||
|
|
||||||
const key = secp256k1.keyFromPrivate(seed);
|
|
||||||
|
|
||||||
return {
|
|
||||||
publicKey: new Uint8Array(key.getPublic().encodeCompressed()),
|
|
||||||
secretKey: bnToU8a(key.getPrivate(), BN_BE_256_OPTS)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
+23
-11
@@ -2,9 +2,11 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { hexToU8a, u8aToHex } from '@polkadot/util';
|
import { hexToU8a, u8aToHex } from '@polkadot/util';
|
||||||
|
import { waitReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
|
import { performanceWasm } from '../../../test/performance';
|
||||||
import { mnemonicToMiniSecret } from '../../mnemonic';
|
import { mnemonicToMiniSecret } from '../../mnemonic';
|
||||||
import { secp256k1KeypairFromSeed } from '..';
|
import { secp256k1PairFromSeed } from '..';
|
||||||
|
|
||||||
// mnemonic, secret, public, account_id
|
// mnemonic, secret, public, account_id
|
||||||
type Test = [string, string, string, string];
|
type Test = [string, string, string, string];
|
||||||
@@ -36,24 +38,34 @@ const tests: Test[] = [
|
|||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
describe('secp256k1KeypairFromSeed', (): void => {
|
describe('secp256k1PairFromSeed', (): void => {
|
||||||
|
beforeEach(async (): Promise<void> => {
|
||||||
|
await waitReady();
|
||||||
|
});
|
||||||
|
|
||||||
const TEST = hexToU8a('0x4380de832af797688026ce24f85204d508243f201650c1a134929e5458b7fbae');
|
const TEST = hexToU8a('0x4380de832af797688026ce24f85204d508243f201650c1a134929e5458b7fbae');
|
||||||
const RESULT = {
|
const RESULT = {
|
||||||
publicKey: hexToU8a('0x03fd8c74f795ced92064b86191cb2772b1e3a0947740aa0a5a6e379592471fd85b'),
|
publicKey: hexToU8a('0x03fd8c74f795ced92064b86191cb2772b1e3a0947740aa0a5a6e379592471fd85b'),
|
||||||
secretKey: hexToU8a('0x4380de832af797688026ce24f85204d508243f201650c1a134929e5458b7fbae')
|
secretKey: hexToU8a('0x4380de832af797688026ce24f85204d508243f201650c1a134929e5458b7fbae')
|
||||||
};
|
};
|
||||||
|
|
||||||
it('generates a valid publicKey/secretKey pair (u8a)', (): void => {
|
describe.each([false, true])('onlyJs=%p', (onlyJs): void => {
|
||||||
expect(secp256k1KeypairFromSeed(TEST)).toEqual(RESULT);
|
it('generates a valid publicKey/secretKey pair (u8a)', (): void => {
|
||||||
});
|
expect(secp256k1PairFromSeed(TEST, onlyJs)).toEqual(RESULT);
|
||||||
|
});
|
||||||
|
|
||||||
tests.forEach(([mnemonic, secretKey, publicKey], index): void => {
|
tests.forEach(([mnemonic, secretKey, publicKey], index): void => {
|
||||||
it(`creates valid against known (${index})`, (): void => {
|
it(`creates valid against known (${index})`, (): void => {
|
||||||
const seed = mnemonicToMiniSecret(mnemonic);
|
const seed = mnemonicToMiniSecret(mnemonic);
|
||||||
const pair = secp256k1KeypairFromSeed(seed);
|
const pair = secp256k1PairFromSeed(seed, onlyJs);
|
||||||
|
|
||||||
expect(u8aToHex(pair.secretKey)).toEqual(secretKey);
|
expect(u8aToHex(pair.secretKey)).toEqual(secretKey);
|
||||||
expect(u8aToHex(pair.publicKey)).toEqual(publicKey);
|
expect(u8aToHex(pair.publicKey)).toEqual(publicKey);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
performanceWasm('secp256k1PairFromSeed', 500, (input, onlyJs) =>
|
||||||
|
secp256k1PairFromSeed(input, onlyJs)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import type { Keypair } from '../../types';
|
||||||
|
|
||||||
|
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, onlyJs?: boolean): Keypair {
|
||||||
|
assert(seed.length === 32, 'Expected valid 32-byte private key as a seed');
|
||||||
|
|
||||||
|
if (!hasBigInt || (!onlyJs && isReady())) {
|
||||||
|
const full = secp256k1FromSeed(seed);
|
||||||
|
|
||||||
|
return {
|
||||||
|
publicKey: full.slice(32),
|
||||||
|
secretKey: full.slice(0, 32)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
publicKey: getPublicKey(seed, true),
|
||||||
|
secretKey: seed
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -2,17 +2,30 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { u8aToHex, u8aToU8a } from '@polkadot/util';
|
import { u8aToHex, u8aToU8a } from '@polkadot/util';
|
||||||
|
import { waitReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
|
import { performanceWasm } from '../../test/performance';
|
||||||
import { keccakAsU8a } from '../keccak';
|
import { keccakAsU8a } from '../keccak';
|
||||||
import { secp256k1Recover } from '.';
|
import { secp256k1Recover } from '.';
|
||||||
|
|
||||||
describe('secp256k1Recover', (): void => {
|
const sig = u8aToU8a('0x7505f2880114da51b3f5d535f8687953c0ab9af4ab81e592eaebebf53b728d2b6dfd9b5bcd70fee412b1f31360e7c2774009305cb84fc50c1d0ff8034dfa5fff');
|
||||||
it('recovers a publicKey', (): void => {
|
const msg = u8aToU8a('0xa30b64ce1eedf409c8afb801d72c05234e64849ea538c15dd3c8cf4ffcf166c9');
|
||||||
const pubKey = '0x93a9fc7154c6da3c826415df01eb0e37fb4da4b0';
|
|
||||||
const sig = '0x7505f2880114da51b3f5d535f8687953c0ab9af4ab81e592eaebebf53b728d2b6dfd9b5bcd70fee412b1f31360e7c2774009305cb84fc50c1d0ff8034dfa5fff';
|
|
||||||
const msg = '0xa30b64ce1eedf409c8afb801d72c05234e64849ea538c15dd3c8cf4ffcf166c9';
|
|
||||||
const res = keccakAsU8a(secp256k1Recover(u8aToU8a(msg), u8aToU8a(sig), 0));
|
|
||||||
|
|
||||||
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
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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
|
* @name secp256k1Recover
|
||||||
* @description Recovers a publicKey from the supplied signature
|
* @description Recovers a publicKey from the supplied signature
|
||||||
*/
|
*/
|
||||||
export function secp256k1Recover (message: Uint8Array, signature: Uint8Array, recovery: number): Uint8Array {
|
export function secp256k1Recover (msgHash: HexString | Uint8Array | string, signature: HexString | Uint8Array | string, recovery: number, hashType: HashType = 'blake2', onlyJs?: boolean): Uint8Array {
|
||||||
return new Uint8Array(
|
const sig = u8aToU8a(signature).subarray(0, 64);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-argument
|
const msg = u8aToU8a(msgHash);
|
||||||
secp256k1
|
const publicKey = !hasBigInt || (!onlyJs && isReady())
|
||||||
.recoverPubKey(message, { r: signature.slice(0, 32), s: signature.slice(32, 64) }, recovery)
|
? wasm(msg, sig, recovery)
|
||||||
.encode(null, true)
|
: 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 { Keypair } from '../types';
|
||||||
import type { HashType } 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 { BN_BE_256_OPTS } from '../bn';
|
||||||
import { secp256k1Hasher } from './hasher';
|
import { hasher } from './hasher';
|
||||||
import { secp256k1 } from './secp256k1';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name secp256k1Sign
|
* @name secp256k1Sign
|
||||||
* @description Returns message signature of `message`, using the supplied pair
|
* @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');
|
assert(secretKey?.length === 32, 'Expected valid secp256k1 secretKey, 32-bytes');
|
||||||
|
|
||||||
const key = secp256k1.keyFromPrivate(secretKey);
|
const data = hasher(hashType, message, onlyJs);
|
||||||
const ecsig = key.sign(secp256k1Hasher(hashType, message));
|
|
||||||
|
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(
|
return u8aConcat(
|
||||||
bnToU8a(ecsig.r, BN_BE_256_OPTS),
|
bnToU8a(r, BN_BE_256_OPTS),
|
||||||
bnToU8a(ecsig.s, BN_BE_256_OPTS),
|
bnToU8a(s, BN_BE_256_OPTS),
|
||||||
new Uint8Array([ecsig.recoveryParam || 0])
|
new Uint8Array([recoveryParam || 0])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import '../cryptoInit';
|
||||||
|
|
||||||
import { stringToU8a } from '@polkadot/util';
|
import { stringToU8a } from '@polkadot/util';
|
||||||
|
|
||||||
import { randomAsU8a } from '../random/asU8a';
|
import { randomAsU8a } from '../random/asU8a';
|
||||||
import { secp256k1Hasher } from './hasher';
|
import { hasher } from './hasher';
|
||||||
import { secp256k1Expand, secp256k1KeypairFromSeed, secp256k1Sign, secp256k1Verify } from '.';
|
import { secp256k1Expand, secp256k1PairFromSeed, secp256k1Sign, secp256k1Verify } from '.';
|
||||||
|
|
||||||
const MESSAGE = stringToU8a('this is a message');
|
const MESSAGE = stringToU8a('this is a message');
|
||||||
|
|
||||||
@@ -15,52 +17,52 @@ describe('sign and verify', (): void => {
|
|||||||
const sig = '0x92fcacf0946bbd10b31dfe16d567ed1d3014e81007dd9e5256e19c0f07eacc1643b151ca29e449a765e16a7ce59b88d800467d6b3412d30ea8ad22307a59664b00';
|
const sig = '0x92fcacf0946bbd10b31dfe16d567ed1d3014e81007dd9e5256e19c0f07eacc1643b151ca29e449a765e16a7ce59b88d800467d6b3412d30ea8ad22307a59664b00';
|
||||||
const msg = stringToU8a('secp256k1');
|
const msg = stringToU8a('secp256k1');
|
||||||
|
|
||||||
expect(secp256k1Verify(msg, sig, address)).toBe(true);
|
expect(secp256k1Verify(msg, sig, address)).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('has 65-byte signatures', (): void => {
|
it('has 65-byte signatures', (): void => {
|
||||||
const pair = secp256k1KeypairFromSeed(randomAsU8a());
|
const pair = secp256k1PairFromSeed(randomAsU8a());
|
||||||
|
|
||||||
expect(secp256k1Sign(MESSAGE, pair)).toHaveLength(65);
|
expect(secp256k1Sign(MESSAGE, pair)).toHaveLength(65);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('signs/verifies a message by random key (blake2)', (): void => {
|
it('signs/verifies a message by random key (blake2)', (): void => {
|
||||||
const pair = secp256k1KeypairFromSeed(randomAsU8a());
|
const pair = secp256k1PairFromSeed(randomAsU8a());
|
||||||
const signature = secp256k1Sign(MESSAGE, pair);
|
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 => {
|
it('signs/verifies a message by random key (keccak)', (): void => {
|
||||||
const pair = secp256k1KeypairFromSeed(randomAsU8a());
|
const pair = secp256k1PairFromSeed(randomAsU8a());
|
||||||
const signature = secp256k1Sign(MESSAGE, pair, 'keccak');
|
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 => {
|
it('fails verification on hasher mismatches', (): void => {
|
||||||
const pair = secp256k1KeypairFromSeed(randomAsU8a());
|
const pair = secp256k1PairFromSeed(randomAsU8a());
|
||||||
const signature = secp256k1Sign(MESSAGE, pair, 'keccak');
|
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 => {
|
it('works over a range of random keys (blake2)', (): void => {
|
||||||
for (let i = 0; i < 256; i++) {
|
for (let i = 0; i < 256; i++) {
|
||||||
const pair = secp256k1KeypairFromSeed(randomAsU8a());
|
const pair = secp256k1PairFromSeed(randomAsU8a());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
expect(
|
expect(
|
||||||
secp256k1Verify(
|
secp256k1Verify(
|
||||||
MESSAGE,
|
MESSAGE,
|
||||||
secp256k1Sign(MESSAGE, pair, 'blake2'),
|
secp256k1Sign(MESSAGE, pair, 'blake2'),
|
||||||
secp256k1Hasher('blake2', pair.publicKey),
|
hasher('blake2', pair.publicKey),
|
||||||
'blake2'
|
'blake2'
|
||||||
)
|
)
|
||||||
).toBe(true);
|
).toEqual(true);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`blake2 failed on #${i}`);
|
console.error(`blake2 failed on #${i}`);
|
||||||
throw error;
|
throw error;
|
||||||
@@ -70,17 +72,17 @@ describe('sign and verify', (): void => {
|
|||||||
|
|
||||||
it('works over a range of random keys (keccak)', (): void => {
|
it('works over a range of random keys (keccak)', (): void => {
|
||||||
for (let i = 0; i < 256; i++) {
|
for (let i = 0; i < 256; i++) {
|
||||||
const pair = secp256k1KeypairFromSeed(randomAsU8a());
|
const pair = secp256k1PairFromSeed(randomAsU8a());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
expect(
|
expect(
|
||||||
secp256k1Verify(
|
secp256k1Verify(
|
||||||
MESSAGE,
|
MESSAGE,
|
||||||
secp256k1Sign(MESSAGE, pair, 'keccak'),
|
secp256k1Sign(MESSAGE, pair, 'keccak'),
|
||||||
secp256k1Hasher('keccak', secp256k1Expand(pair.publicKey)),
|
hasher('keccak', secp256k1Expand(pair.publicKey)),
|
||||||
'keccak'
|
'keccak'
|
||||||
)
|
)
|
||||||
).toBe(true);
|
).toEqual(true);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`keccak failed on #${i}`);
|
console.error(`keccak failed on #${i}`);
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@@ -4,13 +4,22 @@
|
|||||||
import { secp256k1PrivateKeyTweakAdd } from './tweakAdd';
|
import { secp256k1PrivateKeyTweakAdd } from './tweakAdd';
|
||||||
|
|
||||||
describe('TweakAdd', (): void => {
|
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 => {
|
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 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]);
|
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(
|
expect(
|
||||||
secp256k1PrivateKeyTweakAdd(A, B)
|
secp256k1PrivateKeyTweakAdd(A, B, onlyBn)
|
||||||
).toEqual(new Uint8Array([
|
).toEqual(new Uint8Array([
|
||||||
3, 4, 3, 4, 3, 4, 3, 4, 3,
|
3, 4, 3, 4, 3, 4, 3, 4, 3,
|
||||||
4, 3, 4, 3, 4, 3, 4, 3, 4,
|
4, 3, 4, 3, 4, 3, 4, 3, 4,
|
||||||
@@ -18,14 +27,5 @@ describe('TweakAdd', (): void => {
|
|||||||
4, 3, 4, 3, 4
|
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
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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
|
// pre-defined curve param as lifted form elliptic
|
||||||
// https://github.com/indutny/elliptic/blob/e71b2d9359c5fe9437fbf46f1f05096de447de57/lib/elliptic/curves.js#L182
|
// https://github.com/indutny/elliptic/blob/e71b2d9359c5fe9437fbf46f1f05096de447de57/lib/elliptic/curves.js#L182
|
||||||
const N = new BN(
|
const N = 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141'.replace(/ /g, '');
|
||||||
'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141'.replace(/ /g, ''),
|
const N_BI = BigInt(`0x${N}`);
|
||||||
'hex'
|
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(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');
|
assert(isU8a(tweak) && tweak.length === 32, 'Expected tweak to be an Uint8Array with length 32');
|
||||||
|
|
||||||
const bn = new BN(tweak);
|
return !hasBigInt || onlyBn
|
||||||
|
? addBn(seckey, tweak)
|
||||||
assert(bn.cmp(N) < 0, 'Tweak parameter is out of range');
|
: addBi(seckey, tweak);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,75 @@
|
|||||||
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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 => {
|
describe('secp256k1Verify', (): void => {
|
||||||
it('validates known ETH against address', (): void => {
|
beforeEach(async (): Promise<void> => {
|
||||||
const message = 'Pay KSMs to the Kusama account:88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee';
|
await waitReady();
|
||||||
|
|
||||||
expect(
|
|
||||||
secp256k1Verify(
|
|
||||||
`\x19Ethereum Signed Message:\n${message.length.toString()}${message}`,
|
|
||||||
'0x55bd020bdbbdc02de34e915effc9b18a99002f4c29f64e22e8dcbb69e722ea6c28e1bb53b9484063fbbfd205e49dcc1f620929f520c9c4c3695150f05a28f52a01',
|
|
||||||
'0x002309df96687e44280bb72c3818358faeeb699c',
|
|
||||||
'keccak'
|
|
||||||
)
|
|
||||||
).toBe(true);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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 { assert, u8aEq, u8aToU8a } from '@polkadot/util';
|
||||||
|
|
||||||
import { secp256k1Expand } from './expand';
|
import { hasher } from './hasher';
|
||||||
import { secp256k1Hasher } from './hasher';
|
import { secp256k1Recover } from './recover';
|
||||||
import { secp256k1 } from './secp256k1';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name secp256k1Verify
|
* @name secp256k1Verify
|
||||||
* @description Verifies the signature of `message`, using the supplied pair
|
* @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 {
|
export function secp256k1Verify (msgHash: HexString | Uint8Array | string, signature: HexString | Uint8Array | string, address: HexString | Uint8Array | string, hashType: HashType = 'blake2', onlyJs?: boolean): boolean {
|
||||||
const isEthereum = hashType === 'keccak';
|
const sig = u8aToU8a(signature);
|
||||||
const u8a = 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(
|
const publicKey = secp256k1Recover(hasher(hashType, msgHash), sig, sig[64], hashType, onlyJs);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-argument
|
const signerAddr = hasher(hashType, publicKey, onlyJs);
|
||||||
secp256k1
|
const inputAddr = u8aToU8a(address);
|
||||||
.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);
|
|
||||||
|
|
||||||
// for Ethereum (keccak) the last 20 bytes is the address
|
// for Ethereum (keccak) the last 20 bytes is the address
|
||||||
return isEthereum
|
return u8aEq(publicKey, inputAddr) || (
|
||||||
? u8aEq(signingAddress.slice(-20), inputAddress.slice(-20))
|
hashType === 'keccak'
|
||||||
: u8aEq(signingAddress, inputAddress);
|
? u8aEq(signerAddr.slice(-20), inputAddr.slice(-20))
|
||||||
|
: u8aEq(signerAddr, inputAddr)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user