Compare commits

...
46 Commits
Author SHA1 Message Date
github-actions[bot] 80785babb4 [CI Skip] release/stable 8.1.2
skip-checks: true
2021-12-05 11:20:24 +00:00
Jaco 59761086d0 8.1.2 (#1284)
* 8.1.2

* Adjust

* Adjust
2021-12-05 13:14:40 +02:00
github-actions[bot] 05c82721e8 [CI Skip] release/stable 8.1.1
skip-checks: true
2021-12-05 08:58:29 +00:00
Jaco 1b13cf0eea 8.1.1 (#1283) 2021-12-05 10:54:07 +02:00
github-actions[bot] e6777ece62 [CI Skip] release/beta 8.0.6-18
skip-checks: true
2021-12-05 08:15:04 +00:00
Jaco 7436976598 Add shims for x-* (not used, convenience) (#1282)
* Add shims for x-* (not used, convenience)

* Update packages/x-ws/src/shim.ts

* Remove (now) unused dependencies
2021-12-05 10:09:47 +02:00
github-actions[bot] 699ef952c3 [CI Skip] release/beta 8.0.6-17
skip-checks: true
2021-12-04 11:02:06 +00:00
Jaco cd9dc35475 Align x-noble with upstream (#1281)
* Align x-noble with upstream

* Remove own version of hashes

* @noble/hashes from master
2021-12-04 12:57:36 +02:00
github-actions[bot] ee7923c457 [CI Skip] release/beta 8.0.6-16
skip-checks: true
2021-12-04 07:16:16 +00:00
Jaco bd3f51844c Add BigInt shim (#1280) 2021-12-04 09:11:16 +02:00
github-actions[bot] 986dfe5006 [CI Skip] release/beta 8.0.6-15
skip-checks: true
2021-12-03 15:29:06 +00:00
Jaco 1eba41b2e6 Use @noble/secp256k1 (#1189)
* Use @noble/secp256k1

* Remove elliptic

* Remove @types

* -19

* verify uses recover internally

* fromSeed

* Init Noble utils inside cryptoInit

* remove bn.js dep (used from @polkadot/util)

* With x-noble-secp256k1

* Adjust

* Remove unused functions

* CHANGELOG

* Fix useless assignment

* Cleanup cryptoInit

* adjust hasher

* bn.js only via util

* align versions

* Remove x-secp256k1 (to be pulled in from master merge)

* Remove (now) invalid test

* Remove assertBigInt

* hasBigInt

* cleanups

* Apply suggestions from code review

* evmAddress fixes

* Extra comment
2021-12-03 17:23:46 +02:00
github-actions[bot] 88c2d16951 [CI Skip] release/beta 8.0.6-14
skip-checks: true
2021-12-03 14:28:20 +00:00
Jaco 303a57c4b5 Use secp256k1 from wasm (#1276)
* Use secp256k1 from wasm

* Expand & recover

* sign (tests failing)

* Pass onlyJs flags everywhere

* Adjust, all ready to actually pass... they don't

* naming

* Fix verify tests

* Adjust verify with non-hashing

* bump wasm

* Allow verify against address or publicKey

* Passing tests

* comment for wasm

* bi/bn versions for tweakadd

* Bumps

* Adjust
2021-12-03 16:23:41 +02:00
github-actions[bot] 7bfca0d40f [CI Skip] release/beta 8.0.6-13
skip-checks: true
2021-12-03 13:47:26 +00:00
Jaco 916187dbf2 Add x-noble-secp256k1 (#1279)
* Add x-noble-secp256k1

* Ignores

* Remove unused functions

* Fix jest
2021-12-03 15:42:57 +02:00
github-actions[bot] cfc598b30f [CI Skip] release/beta 8.0.6-12
skip-checks: true
2021-12-03 12:06:48 +00:00
Jaco 67bfe3a52e Bump deps (#1278) 2021-12-03 14:01:30 +02:00
github-actions[bot] 0299cba18e [CI Skip] release/beta 8.0.6-11
skip-checks: true
2021-12-02 13:51:53 +00:00
Jaco 182c6770d1 Bump dev (#1277) 2021-12-02 15:46:22 +02:00
github-actions[bot] c89ec8a964 [CI Skip] release/beta 8.0.6-10
skip-checks: true
2021-12-02 06:53:44 +00:00
Jaco dc63304735 Remove unused x-noble-hashes functions (#1275) 2021-12-02 08:48:44 +02:00
github-actions[bot] 9ce825de94 [CI Skip] release/beta 8.0.6-9
skip-checks: true
2021-12-02 05:37:08 +00:00
Jaco 3cb41c3b03 CHANGELOG 2021-12-02 07:32:47 +02:00
Jaco b1f9c37f6a x-bigint package (#1274)
* x-bigint package

* x-bigint in has*

* 8.0.6-8

* Adjust

* Adjust

* jest config

* Adjust

* Remove commented code

* Update README

* CHANGELOG
2021-12-02 07:29:44 +02:00
github-actions[bot] 4a69486993 [CI Skip] release/beta 8.0.6-8
skip-checks: true
2021-12-01 19:41:34 +00:00
Jaco 3a7ab0454f instanceof BigInt (#1273) 2021-12-01 21:37:21 +02:00
github-actions[bot] ecfc262bcd [CI Skip] release/beta 8.0.6-7
skip-checks: true
2021-12-01 18:41:25 +00:00
Jaco 776a653f42 Use BigInt only via xglobal (#1272)
* Use BigInt only via xglobal

* Adjust

* yarn
2021-12-01 20:37:11 +02:00
github-actions[bot] ee99ffdbb4 [CI Skip] release/beta 8.0.6-6
skip-checks: true
2021-12-01 16:15:34 +00:00
Jaco bda848f484 Expand has checks (#1271) 2021-12-01 18:11:03 +02:00
github-actions[bot] 82a63887a6 [CI Skip] release/beta 8.0.6-5
skip-checks: true
2021-12-01 14:25:07 +00:00
Jaco 50317d7dc3 Adjust for anon (#1269) 2021-12-01 16:19:50 +02:00
github-actions[bot] 39e6a3c048 [CI Skip] release/beta 8.0.6-4
skip-checks: true
2021-12-01 13:33:02 +00:00
Jaco db93c3076b Revert "Remove ed2curve dependency (#1265)" (#1267)
* Revert "Remove ed2curve dependency (#1265)"

This reverts commit 7e9b2770b6.

* Adjust
2021-12-01 15:28:42 +02:00
Jaco c8f0ad55c4 Split into @polkadot/x-noble-hashes (indicating diff from upstream) (#1268)
* Aplit @noble/hashes fork

* Re-add original (non-eslint)

* Original package imports in README

* package.json

* Update packages/x-noble-hashes/package.json

* CC ignore

* jest
2021-12-01 15:27:29 +02:00
github-actions[bot] 2104c50bd0 [CI Skip] release/beta 8.0.6-3
skip-checks: true
2021-12-01 09:56:10 +00:00
Jaco 7e9b2770b6 Remove ed2curve dependency (#1265)
* Remove edcurve dependency

* browser overrides

* Remove bundledDependencies
2021-12-01 11:51:55 +02:00
github-actions[bot] 8bf24c2f85 [CI Skip] release/beta 8.0.6-2
skip-checks: true
2021-12-01 08:04:23 +00:00
Jaco 60337a3b55 Adjust stale cron (#1264) 2021-12-01 09:59:19 +02:00
github-actions[bot] f527c80b5c [CI Skip] release/beta 8.0.6-1
skip-checks: true
2021-12-01 07:26:29 +00:00
Jaco bdd2bcf236 camelCase with mixed uppercase/numbers (#1260)
* camelCase with mixed uppercase/numbers

* consequtive capitals

* CHANGELOG

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

Some files were not shown because too many files have changed in this diff Show More