Re-implement bip39 (#966)
* Re-implement bip39 * Use pbkdf2 from subtle * Pull out and fix getSubtle() * Remove unused pbkdf2 dependency * Remove stream fallback (remove stream-browserify) * Pull out pbkdf2Sha512 * Pull out pbkdf2Sha512Subtle * Pull out pbkdf2Sha512Crypto * Disable "Test Case 4" because it takes a long time * Deactivate pbkdf2Sha512Subtle/pbkdf2Sha512Crypto tests when API unavailable * Let getCryptoModule detect fallback modules * Create noble implementation of pbkdf2Sha512 * Add CHANGELOG entry
This commit is contained in:
@@ -841,10 +841,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
"bindings",
|
||||
"npm:1.5.0"
|
||||
],
|
||||
[
|
||||
"bip39",
|
||||
"npm:3.0.4"
|
||||
],
|
||||
[
|
||||
"bl",
|
||||
"npm:4.1.0"
|
||||
@@ -929,10 +925,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
"chrome-trace-event",
|
||||
"npm:1.0.3"
|
||||
],
|
||||
[
|
||||
"cipher-base",
|
||||
"npm:1.0.4"
|
||||
],
|
||||
[
|
||||
"clean-stack",
|
||||
"npm:2.2.0"
|
||||
@@ -1037,14 +1029,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
"cosmjs-types",
|
||||
"npm:0.4.0"
|
||||
],
|
||||
[
|
||||
"create-hash",
|
||||
"npm:1.2.0"
|
||||
],
|
||||
[
|
||||
"create-hmac",
|
||||
"npm:1.1.7"
|
||||
],
|
||||
[
|
||||
"cross-spawn",
|
||||
"npm:7.0.3"
|
||||
@@ -1913,10 +1897,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
"marked",
|
||||
"npm:4.0.10"
|
||||
],
|
||||
[
|
||||
"md5.js",
|
||||
"npm:1.3.5"
|
||||
],
|
||||
[
|
||||
"media-typer",
|
||||
"npm:0.3.0"
|
||||
@@ -2181,10 +2161,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
"path-type",
|
||||
"npm:4.0.0"
|
||||
],
|
||||
[
|
||||
"pbkdf2",
|
||||
"npm:3.1.2"
|
||||
],
|
||||
[
|
||||
"picomatch",
|
||||
"npm:2.2.3"
|
||||
@@ -2379,7 +2355,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
],
|
||||
[
|
||||
"safe-buffer",
|
||||
"npm:5.2.1"
|
||||
"npm:5.1.2"
|
||||
],
|
||||
[
|
||||
"safer-buffer",
|
||||
@@ -2409,10 +2385,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
"setprototypeof",
|
||||
"npm:1.1.1"
|
||||
],
|
||||
[
|
||||
"sha.js",
|
||||
"npm:2.4.11"
|
||||
],
|
||||
[
|
||||
"shallow-clone",
|
||||
"npm:3.0.1"
|
||||
@@ -2521,10 +2493,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
"statuses",
|
||||
"npm:1.5.0"
|
||||
],
|
||||
[
|
||||
"stream-browserify",
|
||||
"npm:3.0.0"
|
||||
],
|
||||
[
|
||||
"streamroller",
|
||||
"npm:3.0.2"
|
||||
@@ -3220,7 +3188,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
["prettier", "npm:2.4.1"],
|
||||
["ses", "npm:0.11.1"],
|
||||
["source-map-support", "npm:0.5.19"],
|
||||
["stream-browserify", "npm:3.0.0"],
|
||||
["ts-node", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:8.10.2"],
|
||||
["typedoc", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:0.22.11"],
|
||||
["typescript", "patch:typescript@npm%3A4.4.4#~builtin<compat/typescript>::version=4.4.4&hash=ddd1e8"],
|
||||
@@ -3328,7 +3295,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
["readonly-date", "npm:1.0.0"],
|
||||
["ses", "npm:0.11.1"],
|
||||
["source-map-support", "npm:0.5.19"],
|
||||
["stream-browserify", "npm:3.0.0"],
|
||||
["ts-node", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:8.10.2"],
|
||||
["typedoc", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:0.22.11"],
|
||||
["typescript", "patch:typescript@npm%3A4.4.4#~builtin<compat/typescript>::version=4.4.4&hash=ddd1e8"],
|
||||
@@ -3359,7 +3325,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
["@types/node", "npm:15.3.1"],
|
||||
["@typescript-eslint/eslint-plugin", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:4.28.4"],
|
||||
["@typescript-eslint/parser", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:4.28.4"],
|
||||
["bip39", "npm:3.0.4"],
|
||||
["bn.js", "npm:5.2.0"],
|
||||
["buffer", "npm:6.0.3"],
|
||||
["elliptic", "npm:6.5.4"],
|
||||
@@ -3384,7 +3349,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
["prettier", "npm:2.4.1"],
|
||||
["ses", "npm:0.11.1"],
|
||||
["source-map-support", "npm:0.5.19"],
|
||||
["stream-browserify", "npm:3.0.0"],
|
||||
["ts-node", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:8.10.2"],
|
||||
["typedoc", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:0.22.11"],
|
||||
["typescript", "patch:typescript@npm%3A4.4.4#~builtin<compat/typescript>::version=4.4.4&hash=ddd1e8"],
|
||||
@@ -3706,7 +3670,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
["protobufjs", "npm:6.10.2"],
|
||||
["ses", "npm:0.11.1"],
|
||||
["source-map-support", "npm:0.5.19"],
|
||||
["stream-browserify", "npm:3.0.0"],
|
||||
["ts-node", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:8.10.2"],
|
||||
["typedoc", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:0.22.11"],
|
||||
["typescript", "patch:typescript@npm%3A4.4.4#~builtin<compat/typescript>::version=4.4.4&hash=ddd1e8"],
|
||||
@@ -3811,7 +3774,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
["readonly-date", "npm:1.0.0"],
|
||||
["ses", "npm:0.11.1"],
|
||||
["source-map-support", "npm:0.5.19"],
|
||||
["stream-browserify", "npm:3.0.0"],
|
||||
["ts-node", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:8.10.2"],
|
||||
["typedoc", "virtual:4f1584ad4aba8733a24be7c8aebbffafef25607f2d00f4b314cf96717145c692763628a31c2b85d4686fbb091ff21ebffa3cc337399c042c19a32b9bdb786464#npm:0.22.11"],
|
||||
["typescript", "patch:typescript@npm%3A4.4.4#~builtin<compat/typescript>::version=4.4.4&hash=ddd1e8"],
|
||||
@@ -4716,13 +4678,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
}]
|
||||
]],
|
||||
["@types/node", [
|
||||
["npm:11.11.6", {
|
||||
"packageLocation": "./.yarn/cache/@types-node-npm-11.11.6-40abad0842-075f1c011c.zip/node_modules/@types/node/",
|
||||
"packageDependencies": [
|
||||
["@types/node", "npm:11.11.6"]
|
||||
],
|
||||
"linkType": "HARD",
|
||||
}],
|
||||
["npm:13.13.52", {
|
||||
"packageLocation": "./.yarn/cache/@types-node-npm-13.13.52-95159539bb-8f1afff497.zip/node_modules/@types/node/",
|
||||
"packageDependencies": [
|
||||
@@ -6287,19 +6242,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["bip39", [
|
||||
["npm:3.0.4", {
|
||||
"packageLocation": "./.yarn/cache/bip39-npm-3.0.4-7c69c9182f-79ce1600a0.zip/node_modules/bip39/",
|
||||
"packageDependencies": [
|
||||
["bip39", "npm:3.0.4"],
|
||||
["@types/node", "npm:11.11.6"],
|
||||
["create-hash", "npm:1.2.0"],
|
||||
["pbkdf2", "npm:3.1.2"],
|
||||
["randombytes", "npm:2.1.0"]
|
||||
],
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["bl", [
|
||||
["npm:4.1.0", {
|
||||
"packageLocation": "./.yarn/cache/bl-npm-4.1.0-7f94cdcf3f-9e8521fa7e.zip/node_modules/bl/",
|
||||
@@ -6580,17 +6522,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["cipher-base", [
|
||||
["npm:1.0.4", {
|
||||
"packageLocation": "./.yarn/cache/cipher-base-npm-1.0.4-2e98b97140-47d3568dbc.zip/node_modules/cipher-base/",
|
||||
"packageDependencies": [
|
||||
["cipher-base", "npm:1.0.4"],
|
||||
["inherits", "npm:2.0.4"],
|
||||
["safe-buffer", "npm:5.2.1"]
|
||||
],
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["clean-stack", [
|
||||
["npm:2.2.0", {
|
||||
"packageLocation": "./.yarn/cache/clean-stack-npm-2.2.0-a8ce435a5c-2ac8cd2b2f.zip/node_modules/clean-stack/",
|
||||
@@ -6900,35 +6831,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["create-hash", [
|
||||
["npm:1.2.0", {
|
||||
"packageLocation": "./.yarn/cache/create-hash-npm-1.2.0-afd048e1ce-02a6ae3bb9.zip/node_modules/create-hash/",
|
||||
"packageDependencies": [
|
||||
["create-hash", "npm:1.2.0"],
|
||||
["cipher-base", "npm:1.0.4"],
|
||||
["inherits", "npm:2.0.4"],
|
||||
["md5.js", "npm:1.3.5"],
|
||||
["ripemd160", "npm:2.0.2"],
|
||||
["sha.js", "npm:2.4.11"]
|
||||
],
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["create-hmac", [
|
||||
["npm:1.1.7", {
|
||||
"packageLocation": "./.yarn/cache/create-hmac-npm-1.1.7-b4ef32668a-ba12bb2257.zip/node_modules/create-hmac/",
|
||||
"packageDependencies": [
|
||||
["create-hmac", "npm:1.1.7"],
|
||||
["cipher-base", "npm:1.0.4"],
|
||||
["create-hash", "npm:1.2.0"],
|
||||
["inherits", "npm:2.0.4"],
|
||||
["ripemd160", "npm:2.0.2"],
|
||||
["safe-buffer", "npm:5.2.1"],
|
||||
["sha.js", "npm:2.4.11"]
|
||||
],
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["cross-spawn", [
|
||||
["npm:7.0.3", {
|
||||
"packageLocation": "./.yarn/cache/cross-spawn-npm-7.0.3-e4ff3e65b3-671cc7c728.zip/node_modules/cross-spawn/",
|
||||
@@ -9615,18 +9517,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["md5.js", [
|
||||
["npm:1.3.5", {
|
||||
"packageLocation": "./.yarn/cache/md5.js-npm-1.3.5-130901125a-098494d885.zip/node_modules/md5.js/",
|
||||
"packageDependencies": [
|
||||
["md5.js", "npm:1.3.5"],
|
||||
["hash-base", "npm:3.1.0"],
|
||||
["inherits", "npm:2.0.4"],
|
||||
["safe-buffer", "npm:5.2.1"]
|
||||
],
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["media-typer", [
|
||||
["npm:0.3.0", {
|
||||
"packageLocation": "./.yarn/cache/media-typer-npm-0.3.0-8674f8f0f5-af1b38516c.zip/node_modules/media-typer/",
|
||||
@@ -10410,20 +10300,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["pbkdf2", [
|
||||
["npm:3.1.2", {
|
||||
"packageLocation": "./.yarn/cache/pbkdf2-npm-3.1.2-d67bbb584f-2c950a100b.zip/node_modules/pbkdf2/",
|
||||
"packageDependencies": [
|
||||
["pbkdf2", "npm:3.1.2"],
|
||||
["create-hash", "npm:1.2.0"],
|
||||
["create-hmac", "npm:1.1.7"],
|
||||
["ripemd160", "npm:2.0.2"],
|
||||
["safe-buffer", "npm:5.2.1"],
|
||||
["sha.js", "npm:2.4.11"]
|
||||
],
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["picomatch", [
|
||||
["npm:2.2.3", {
|
||||
"packageLocation": "./.yarn/cache/picomatch-npm-2.2.3-3797e21cf0-45e2b882b5.zip/node_modules/picomatch/",
|
||||
@@ -11134,17 +11010,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["sha.js", [
|
||||
["npm:2.4.11", {
|
||||
"packageLocation": "./.yarn/cache/sha.js-npm-2.4.11-14868df4ca-ebd3f59d4b.zip/node_modules/sha.js/",
|
||||
"packageDependencies": [
|
||||
["sha.js", "npm:2.4.11"],
|
||||
["inherits", "npm:2.0.4"],
|
||||
["safe-buffer", "npm:5.2.1"]
|
||||
],
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["shallow-clone", [
|
||||
["npm:3.0.1", {
|
||||
"packageLocation": "./.yarn/cache/shallow-clone-npm-3.0.1-dab5873d0d-39b3dd9630.zip/node_modules/shallow-clone/",
|
||||
@@ -11443,17 +11308,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["stream-browserify", [
|
||||
["npm:3.0.0", {
|
||||
"packageLocation": "./.yarn/cache/stream-browserify-npm-3.0.0-4c0bd97245-4c47ef64d6.zip/node_modules/stream-browserify/",
|
||||
"packageDependencies": [
|
||||
["stream-browserify", "npm:3.0.0"],
|
||||
["inherits", "npm:2.0.4"],
|
||||
["readable-stream", "npm:3.6.0"]
|
||||
],
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["streamroller", [
|
||||
["npm:3.0.2", {
|
||||
"packageLocation": "./.yarn/cache/streamroller-npm-3.0.2-6d7ba8035a-1f323824f0.zip/node_modules/streamroller/",
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
@@ -39,9 +39,13 @@ and this project adheres to
|
||||
- @cosmjs/ledger-amino: Renamed `LaunchpadLedger` to `LedgerConnector` ([#955])
|
||||
- @cosmjs/encoding: Created `toBech32()` and `fromBech32()`. Class Bech32 is now
|
||||
deprecated and should not longer be used. ([#1053])
|
||||
- @cosmjs/crypto: Use a custom BIP-39 implementation to reduce external
|
||||
dependencies. This should also reduce the bundle size as only the English
|
||||
wordlist is shipped. ([#966])
|
||||
|
||||
[#927]: https://github.com/cosmos/cosmjs/issues/927
|
||||
[#955]: https://github.com/cosmos/cosmjs/issues/955
|
||||
[#966]: https://github.com/cosmos/cosmjs/pull/966
|
||||
[#989]: https://github.com/cosmos/cosmjs/issues/989
|
||||
[#994]: https://github.com/cosmos/cosmjs/issues/994
|
||||
[#1011]: https://github.com/cosmos/cosmjs/issues/1011
|
||||
|
||||
@@ -23,6 +23,9 @@ The code in packages/json-rpc was forked from https://github.com/iov-one/iov-cor
|
||||
|
||||
The code in packages/socket and scripts/socketserver was forked from the folders packages/iov-socket and scripts/socketserver respectively of https://github.com/iov-one/iov-core at tag v2.5.0 on 2020-06-24.
|
||||
|
||||
The code in packages/crypto/src/bip39.ts contains code forked from bitcoinjs/bip39 (https://github.com/bitcoinjs/bip39/blob/v3.0.4/LICENSE)
|
||||
on 2021-12-16. Copyright (c) 2014, Wei Lu and Daniel Cousens.
|
||||
|
||||
Copyright 2018-2020 IOV SAS
|
||||
Copyright 2020-2021 Confio OÜ
|
||||
Copyright 2020 Simon Warta
|
||||
|
||||
@@ -74,7 +74,6 @@
|
||||
"prettier": "^2.4.1",
|
||||
"ses": "^0.11.0",
|
||||
"source-map-support": "^0.5.19",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"ts-node": "^8",
|
||||
"typedoc": "^0.22",
|
||||
"typescript": "~4.4",
|
||||
|
||||
@@ -26,7 +26,7 @@ module.exports = [
|
||||
crypto: false,
|
||||
events: false,
|
||||
path: false,
|
||||
stream: require.resolve("stream-browserify"),
|
||||
stream: false,
|
||||
string_decoder: false,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -84,7 +84,6 @@
|
||||
"readonly-date": "^1.0.0",
|
||||
"ses": "^0.11.0",
|
||||
"source-map-support": "^0.5.19",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"ts-node": "^8",
|
||||
"typedoc": "^0.22",
|
||||
"typescript": "~4.4",
|
||||
|
||||
@@ -29,7 +29,7 @@ module.exports = [
|
||||
crypto: false,
|
||||
events: false,
|
||||
path: false,
|
||||
stream: require.resolve("stream-browserify"),
|
||||
stream: false,
|
||||
string_decoder: false,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
"@cosmjs/math": "workspace:packages/math",
|
||||
"@cosmjs/utils": "workspace:packages/utils",
|
||||
"@noble/hashes": "^1",
|
||||
"bip39": "^3.0.2",
|
||||
"bn.js": "^5.2.0",
|
||||
"elliptic": "^6.5.3",
|
||||
"libsodium-wrappers": "^0.7.6"
|
||||
@@ -84,7 +83,6 @@
|
||||
"prettier": "^2.4.1",
|
||||
"ses": "^0.11.0",
|
||||
"source-map-support": "^0.5.19",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"ts-node": "^8",
|
||||
"typedoc": "^0.22",
|
||||
"typescript": "~4.4",
|
||||
|
||||
@@ -1,8 +1,49 @@
|
||||
import { fromHex } from "@cosmjs/encoding";
|
||||
import { fromAscii, fromBase64, fromHex } from "@cosmjs/encoding";
|
||||
|
||||
import { Bip39 } from "./bip39";
|
||||
import { EnglishMnemonic } from "./englishmnemonic";
|
||||
import { Bip39, EnglishMnemonic, entropyToMnemonic, mnemonicToEntropy } from "./bip39";
|
||||
import { sha256 } from "./sha";
|
||||
import bip39Vectors from "./testdata/bip39.json";
|
||||
import wordlists from "./testdata/bip39_wordlists.json";
|
||||
|
||||
describe("entropyToMnemonic", () => {
|
||||
it("works", () => {
|
||||
// From https://iancoleman.io/bip39/
|
||||
expect(entropyToMnemonic(fromHex("a323224e6b13d31942509dc4e2e579be3d5bb7f2"))).toEqual(
|
||||
"permit boil near stomach diamond million announce beauty shaft blame fury ladder stick swim slab",
|
||||
);
|
||||
});
|
||||
|
||||
it("works for all the test vectors", () => {
|
||||
// Test vectors from https://github.com/trezor/python-mnemonic/blob/b502451a33a440783926e04428115e0bed87d01f/vectors.json
|
||||
// plus similar vectors generated for the missing lengths 15 and 21 words
|
||||
const { "12": vec12, "15": vec15, "18": vec18, "21": vec21, "24": vec24 } = bip39Vectors.encoding;
|
||||
for (const vectors of [vec12, vec15, vec18, vec21, vec24]) {
|
||||
for (const { entropy, mnemonic } of vectors) {
|
||||
expect(entropyToMnemonic(fromHex(entropy)).toString()).toEqual(mnemonic);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("mnemonicToEntropy", () => {
|
||||
it("works", () => {
|
||||
// From https://iancoleman.io/bip39/
|
||||
expect(
|
||||
mnemonicToEntropy(
|
||||
"permit boil near stomach diamond million announce beauty shaft blame fury ladder stick swim slab",
|
||||
),
|
||||
).toEqual(fromHex("a323224e6b13d31942509dc4e2e579be3d5bb7f2"));
|
||||
});
|
||||
|
||||
it("works for all the test vectors", () => {
|
||||
const { "12": vec12, "15": vec15, "18": vec18, "21": vec21, "24": vec24 } = bip39Vectors.encoding;
|
||||
for (const vectors of [vec12, vec15, vec18, vec21, vec24]) {
|
||||
for (const { entropy, mnemonic } of vectors) {
|
||||
expect(mnemonicToEntropy(mnemonic)).toEqual(fromHex(entropy));
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("Bip39", () => {
|
||||
describe("encode", () => {
|
||||
@@ -414,3 +455,240 @@ describe("Bip39", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("EnglishMnemonic", () => {
|
||||
describe("wordlist", () => {
|
||||
it("matches the words from the bitcoin/bips/bip-0039 spec", () => {
|
||||
const lineFeed = 0x0a;
|
||||
const bip39EnglishTxt = fromBase64(wordlists.english);
|
||||
|
||||
// Ensure we loaded the correct english.txt from https://github.com/bitcoin/bips/tree/master/bip-0039
|
||||
const checksum = sha256(bip39EnglishTxt);
|
||||
expect(checksum).toEqual(fromHex("2f5eed53a4727b4bf8880d8f3f199efc90e58503646d9ff8eff3a2ed3b24dbda"));
|
||||
|
||||
const wordsFromSpec: string[] = [];
|
||||
|
||||
let start = 0; // the start cursor marks the first byte of the word
|
||||
let end = 0; // the end cursor marks the line feed byte
|
||||
while (end < bip39EnglishTxt.length - 1) {
|
||||
end = start;
|
||||
while (bip39EnglishTxt[end] !== lineFeed) end++;
|
||||
const slice = bip39EnglishTxt.slice(start, end);
|
||||
wordsFromSpec.push(fromAscii(slice));
|
||||
start = end + 1;
|
||||
}
|
||||
|
||||
expect(EnglishMnemonic.wordlist).toEqual(wordsFromSpec);
|
||||
});
|
||||
});
|
||||
|
||||
it("works for valid inputs", () => {
|
||||
expect(() => {
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
);
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon address",
|
||||
);
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent",
|
||||
);
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon admit",
|
||||
);
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art",
|
||||
);
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it("rejects invalid whitespacing", () => {
|
||||
// extra space (leading, middle, trailing)
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
" abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about ",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
|
||||
// newline, tab
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon\nabandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon\tabandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
});
|
||||
|
||||
it("rejects disallowed letters", () => {
|
||||
// Disallowed letters in words (capital, number, special char)
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"Abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon Abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"route66 abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon route66 abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"lötkolben abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon lötkolben abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
});
|
||||
|
||||
it("word counts other than 12, 15, 18, 21, 24", () => {
|
||||
// too few and too many words (11, 13, 17, 19, 23, 25)
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid word count(.*)got: 11/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid word count(.*)got: 13/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent",
|
||||
),
|
||||
).toThrowError(/invalid word count(.*)got: 17/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent",
|
||||
),
|
||||
).toThrowError(/invalid word count(.*)got: 19/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art",
|
||||
),
|
||||
).toThrowError(/invalid word count(.*)got: 23/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art",
|
||||
),
|
||||
).toThrowError(/invalid word count(.*)got: 25/i);
|
||||
});
|
||||
|
||||
it("rejects invalid checksums", () => {
|
||||
// 12x, 15x, 18x, 21x, 24x "zoo"
|
||||
expect(() => new EnglishMnemonic("zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo")).toThrowError(
|
||||
/invalid mnemonic checksum/i,
|
||||
);
|
||||
expect(
|
||||
() => new EnglishMnemonic("zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo"),
|
||||
).toThrowError(/invalid mnemonic checksum/i);
|
||||
expect(
|
||||
() => new EnglishMnemonic("zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo"),
|
||||
).toThrowError(/invalid mnemonic checksum/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic checksum/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic checksum/i);
|
||||
});
|
||||
|
||||
it("rejects valid mnemonics of other languages", () => {
|
||||
// valid Spanish and Italian bip39 mnemonics
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"humo odio oriente colina taco fingir salto geranio glaciar academia suave vigor",
|
||||
),
|
||||
).toThrowError(/contains invalid word/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"yema folleto tos llave obtener natural fruta deseo laico sopa novato lazo imponer afinar vena hoja zarza cama",
|
||||
),
|
||||
).toThrowError(/contains invalid word/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"burla plaza arroz ronda pregunta vacuna veloz boina retiro exento prensa tortuga cabeza pilar anual molino molde fiesta masivo jefe leve fatiga clase plomo",
|
||||
),
|
||||
).toThrowError(/contains invalid word/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"braccio trincea armonia emiro svedese lepre stridulo metallo baldo rasente potassio rilassato",
|
||||
),
|
||||
).toThrowError(/contains invalid word/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"riparato arrosto globulo singolo bozzolo roba pirolisi ultimato padrone munto leggero avanzato monetario guanto lorenzo latino inoltrare modulo",
|
||||
),
|
||||
).toThrowError(/contains invalid word/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"promessa mercurio spessore snodo trave risata mecenate vichingo ceto orecchino vissuto risultato canino scarso futile fune epilogo uovo inedito apatico folata egoismo rifugio coma",
|
||||
),
|
||||
).toThrowError(/contains invalid word/i);
|
||||
});
|
||||
|
||||
describe("toString", () => {
|
||||
it("works", () => {
|
||||
const original =
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
|
||||
const mnemonic = new EnglishMnemonic(original);
|
||||
expect(mnemonic.toString()).toEqual(original);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+2184
-12
File diff suppressed because it is too large
Load Diff
@@ -1,242 +0,0 @@
|
||||
import { fromAscii, fromBase64, fromHex } from "@cosmjs/encoding";
|
||||
|
||||
import { EnglishMnemonic } from "./englishmnemonic";
|
||||
import { sha256 } from "./sha";
|
||||
import wordlists from "./testdata/bip39_wordlists.json";
|
||||
|
||||
describe("EnglishMnemonic", () => {
|
||||
describe("wordlist", () => {
|
||||
it("matches the words from the bitcoin/bips/bip-0039 spec", () => {
|
||||
const lineFeed = 0x0a;
|
||||
const bip39EnglishTxt = fromBase64(wordlists.english);
|
||||
|
||||
// Ensure we loaded the correct english.txt from https://github.com/bitcoin/bips/tree/master/bip-0039
|
||||
const checksum = sha256(bip39EnglishTxt);
|
||||
expect(checksum).toEqual(fromHex("2f5eed53a4727b4bf8880d8f3f199efc90e58503646d9ff8eff3a2ed3b24dbda"));
|
||||
|
||||
const wordsFromSpec: string[] = [];
|
||||
|
||||
let start = 0; // the start cursor marks the first byte of the word
|
||||
let end = 0; // the end cursor marks the line feed byte
|
||||
while (end < bip39EnglishTxt.length - 1) {
|
||||
end = start;
|
||||
while (bip39EnglishTxt[end] !== lineFeed) end++;
|
||||
const slice = bip39EnglishTxt.slice(start, end);
|
||||
wordsFromSpec.push(fromAscii(slice));
|
||||
start = end + 1;
|
||||
}
|
||||
|
||||
expect(EnglishMnemonic.wordlist).toEqual(wordsFromSpec);
|
||||
});
|
||||
});
|
||||
|
||||
it("works for valid inputs", () => {
|
||||
expect(() => {
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
);
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon address",
|
||||
);
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent",
|
||||
);
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon admit",
|
||||
);
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art",
|
||||
);
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it("rejects invalid whitespacing", () => {
|
||||
// extra space (leading, middle, trailing)
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
" abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about ",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
|
||||
// newline, tab
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon\nabandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon\tabandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
});
|
||||
|
||||
it("rejects disallowed letters", () => {
|
||||
// Disallowed letters in words (capital, number, special char)
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"Abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon Abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"route66 abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon route66 abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"lötkolben abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon lötkolben abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic format/i);
|
||||
});
|
||||
|
||||
it("word counts other than 12, 15, 18, 21, 24", () => {
|
||||
// too few and too many words (11, 13, 17, 19, 23, 25)
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid word count(.*)got: 11/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
),
|
||||
).toThrowError(/invalid word count(.*)got: 13/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent",
|
||||
),
|
||||
).toThrowError(/invalid word count(.*)got: 17/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent",
|
||||
),
|
||||
).toThrowError(/invalid word count(.*)got: 19/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art",
|
||||
),
|
||||
).toThrowError(/invalid word count(.*)got: 23/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art",
|
||||
),
|
||||
).toThrowError(/invalid word count(.*)got: 25/i);
|
||||
});
|
||||
|
||||
it("rejects invalid checksums", () => {
|
||||
// 12x, 15x, 18x, 21x, 24x "zoo"
|
||||
expect(() => new EnglishMnemonic("zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo")).toThrowError(
|
||||
/invalid mnemonic checksum/i,
|
||||
);
|
||||
expect(
|
||||
() => new EnglishMnemonic("zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo"),
|
||||
).toThrowError(/invalid mnemonic checksum/i);
|
||||
expect(
|
||||
() => new EnglishMnemonic("zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo"),
|
||||
).toThrowError(/invalid mnemonic checksum/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic checksum/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo",
|
||||
),
|
||||
).toThrowError(/invalid mnemonic checksum/i);
|
||||
});
|
||||
|
||||
it("rejects valid mnemonics of other languages", () => {
|
||||
// valid Spanish and Italian bip39 mnemonics
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"humo odio oriente colina taco fingir salto geranio glaciar academia suave vigor",
|
||||
),
|
||||
).toThrowError(/contains invalid word/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"yema folleto tos llave obtener natural fruta deseo laico sopa novato lazo imponer afinar vena hoja zarza cama",
|
||||
),
|
||||
).toThrowError(/contains invalid word/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"burla plaza arroz ronda pregunta vacuna veloz boina retiro exento prensa tortuga cabeza pilar anual molino molde fiesta masivo jefe leve fatiga clase plomo",
|
||||
),
|
||||
).toThrowError(/contains invalid word/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"braccio trincea armonia emiro svedese lepre stridulo metallo baldo rasente potassio rilassato",
|
||||
),
|
||||
).toThrowError(/contains invalid word/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"riparato arrosto globulo singolo bozzolo roba pirolisi ultimato padrone munto leggero avanzato monetario guanto lorenzo latino inoltrare modulo",
|
||||
),
|
||||
).toThrowError(/contains invalid word/i);
|
||||
expect(
|
||||
() =>
|
||||
new EnglishMnemonic(
|
||||
"promessa mercurio spessore snodo trave risata mecenate vichingo ceto orecchino vissuto risultato canino scarso futile fune epilogo uovo inedito apatico folata egoismo rifugio coma",
|
||||
),
|
||||
).toThrowError(/contains invalid word/i);
|
||||
});
|
||||
|
||||
describe("toString", () => {
|
||||
it("works", () => {
|
||||
const original =
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
|
||||
const mnemonic = new EnglishMnemonic(original);
|
||||
expect(mnemonic.toString()).toEqual(original);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,39 +0,0 @@
|
||||
import * as bip39 from "bip39";
|
||||
|
||||
export class EnglishMnemonic {
|
||||
public static readonly wordlist: readonly string[] = bip39.wordlists.english;
|
||||
|
||||
// list of space separated lower case words (1 or more)
|
||||
private static readonly mnemonicMatcher = /^[a-z]+( [a-z]+)*$/;
|
||||
|
||||
private readonly data: string;
|
||||
|
||||
public constructor(mnemonic: string) {
|
||||
if (!EnglishMnemonic.mnemonicMatcher.test(mnemonic)) {
|
||||
throw new Error("Invalid mnemonic format");
|
||||
}
|
||||
|
||||
const words = mnemonic.split(" ");
|
||||
const allowedWordsLengths: readonly number[] = [12, 15, 18, 21, 24];
|
||||
if (allowedWordsLengths.indexOf(words.length) === -1) {
|
||||
throw new Error(
|
||||
`Invalid word count in mnemonic (allowed: ${allowedWordsLengths} got: ${words.length})`,
|
||||
);
|
||||
}
|
||||
|
||||
for (const word of words) {
|
||||
if (EnglishMnemonic.wordlist.indexOf(word) === -1) {
|
||||
throw new Error("Mnemonic contains invalid word");
|
||||
}
|
||||
}
|
||||
|
||||
// Throws with informative error message if mnemonic is not valid
|
||||
bip39.mnemonicToEntropy(mnemonic);
|
||||
|
||||
this.data = mnemonic;
|
||||
}
|
||||
|
||||
public toString(): string {
|
||||
return this.data;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
export { Bip39 } from "./bip39";
|
||||
export { EnglishMnemonic } from "./englishmnemonic";
|
||||
export { Bip39, EnglishMnemonic } from "./bip39";
|
||||
export { HashFunction } from "./hash";
|
||||
export { Hmac } from "./hmac";
|
||||
export { Keccak256, keccak256 } from "./keccak";
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
import { fromHex, toAscii, toUtf8 } from "@cosmjs/encoding";
|
||||
|
||||
import {
|
||||
getCryptoModule,
|
||||
getSubtle,
|
||||
pbkdf2Sha512,
|
||||
pbkdf2Sha512Crypto,
|
||||
pbkdf2Sha512Noble,
|
||||
pbkdf2Sha512Subtle,
|
||||
} from "./pbkdf2";
|
||||
|
||||
interface TestVector {
|
||||
secret: Uint8Array;
|
||||
salt: Uint8Array;
|
||||
iterations: number;
|
||||
keylen: number;
|
||||
expected: Uint8Array;
|
||||
}
|
||||
|
||||
describe("pbkdf2", () => {
|
||||
// https://github.com/randombit/botan/blob/master/src/tests/data/pbkdf/pbkdf2.vec#L70-L74
|
||||
const botanTest: TestVector = {
|
||||
secret: toAscii("xyz"),
|
||||
salt: fromHex("0001020304050607"),
|
||||
iterations: 10000,
|
||||
keylen: 48,
|
||||
expected: fromHex(
|
||||
"DAF8A734327745EB63D19054DBD4018A682CEF11086A1BFB63FDBC16158C2F8B0742802F36AEF1B1DF92ACCBEA5D31A5",
|
||||
),
|
||||
};
|
||||
|
||||
// https://github.com/brycx/Test-Vector-Generation/blob/f88d152db/PBKDF2/pbkdf2-hmac-sha2-test-vectors.md
|
||||
const brycxTests: TestVector[] = [
|
||||
// Test Case 1
|
||||
{
|
||||
secret: toUtf8("password"),
|
||||
salt: toUtf8("salt"),
|
||||
iterations: 1,
|
||||
keylen: 20,
|
||||
expected: fromHex("867f70cf1ade02cff3752599a3a53dc4af34c7a6"),
|
||||
},
|
||||
// Test Case 2
|
||||
{
|
||||
secret: toUtf8("password"),
|
||||
salt: toUtf8("salt"),
|
||||
iterations: 2,
|
||||
keylen: 20,
|
||||
expected: fromHex("e1d9c16aa681708a45f5c7c4e215ceb66e011a2e"),
|
||||
},
|
||||
// Test Case 3
|
||||
{
|
||||
secret: toUtf8("password"),
|
||||
salt: toUtf8("salt"),
|
||||
iterations: 4096,
|
||||
keylen: 20,
|
||||
expected: fromHex("d197b1b33db0143e018b12f3d1d1479e6cdebdcc"),
|
||||
},
|
||||
// Test Case 4 (disabled by default because long running)
|
||||
// {
|
||||
// secret: toUtf8("password"),
|
||||
// salt: toUtf8("salt"),
|
||||
// iterations: 16777216,
|
||||
// keylen: 20,
|
||||
// expected: fromHex("6180a3ceabab45cc3964112c811e0131bca93a35"),
|
||||
// },
|
||||
// Test Case 5
|
||||
{
|
||||
secret: toUtf8("passwordPASSWORDpassword"),
|
||||
salt: toUtf8("saltSALTsaltSALTsaltSALTsaltSALTsalt"),
|
||||
iterations: 4096,
|
||||
keylen: 25,
|
||||
expected: fromHex("8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868"),
|
||||
},
|
||||
// Test Case 6
|
||||
{
|
||||
secret: toUtf8("pass\0word"),
|
||||
salt: toUtf8("sa\0lt"),
|
||||
iterations: 4096,
|
||||
keylen: 16,
|
||||
expected: fromHex("9d9e9c4cd21fe4be24d5b8244c759665"),
|
||||
},
|
||||
// Test Case 7
|
||||
{
|
||||
secret: toUtf8("passwd"),
|
||||
salt: toUtf8("salt"),
|
||||
iterations: 1,
|
||||
keylen: 128,
|
||||
expected: fromHex(
|
||||
"c74319d99499fc3e9013acff597c23c5baf0a0bec5634c46b8352b793e324723d55caa76b2b25c43402dcfdc06cdcf66f95b7d0429420b39520006749c51a04ef3eb99e576617395a178ba33214793e48045132928a9e9bf2661769fdc668f31798597aaf6da70dd996a81019726084d70f152baed8aafe2227c07636c6ddece",
|
||||
),
|
||||
},
|
||||
// Test Case 8
|
||||
{
|
||||
secret: toUtf8("Password"),
|
||||
salt: toUtf8("NaCl"),
|
||||
iterations: 80000,
|
||||
keylen: 128,
|
||||
expected: fromHex(
|
||||
"e6337d6fbeb645c794d4a9b5b75b7b30dac9ac50376a91df1f4460f6060d5addb2c1fd1f84409abacc67de7eb4056e6bb06c2d82c3ef4ccd1bded0f675ed97c65c33d39f81248454327aa6d03fd049fc5cbb2b5e6dac08e8ace996cdc960b1bd4530b7e754773d75f67a733fdb99baf6470e42ffcb753c15c352d4800fb6f9d6",
|
||||
),
|
||||
},
|
||||
// Test Case 9
|
||||
{
|
||||
secret: toUtf8("Password"),
|
||||
salt: toUtf8("sa\0lt"),
|
||||
iterations: 4096,
|
||||
keylen: 256,
|
||||
expected: fromHex(
|
||||
"10176fb32cb98cd7bb31e2bb5c8f6e425c103333a2e496058e3fd2bd88f657485c89ef92daa0668316bc23ebd1ef88f6dd14157b2320b5d54b5f26377c5dc279b1dcdec044bd6f91b166917c80e1e99ef861b1d2c7bce1b961178125fb86867f6db489a2eae0022e7bc9cf421f044319fac765d70cb89b45c214590e2ffb2c2b565ab3b9d07571fde0027b1dc57f8fd25afa842c1056dd459af4074d7510a0c020b914a5e202445d4d3f151070589dd6a2554fc506018c4f001df6239643dc86771286ae4910769d8385531bba57544d63c3640b90c98f1445ebdd129475e02086b600f0beb5b05cc6ca9b3633b452b7dad634e9336f56ec4c3ac0b4fe54ced8",
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
describe("pbkdf2Sha512", () => {
|
||||
it("works", async () => {
|
||||
{
|
||||
const { secret, salt, iterations, keylen, expected } = botanTest;
|
||||
const hash = await pbkdf2Sha512(secret, salt, iterations, keylen);
|
||||
expect(hash).toEqual(expected);
|
||||
}
|
||||
|
||||
for (const [index, test] of brycxTests.entries()) {
|
||||
const { secret, salt, iterations, keylen, expected } = test;
|
||||
const hash = await pbkdf2Sha512(secret, salt, iterations, keylen);
|
||||
expect(hash).withContext(`brycx tests index ${index}`).toEqual(expected);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("pbkdf2Sha512Subtle", () => {
|
||||
it("works", async () => {
|
||||
const subtle = await getSubtle();
|
||||
if (!subtle) pending("Subtle is not available in this environment");
|
||||
|
||||
{
|
||||
const { secret, salt, iterations, keylen, expected } = botanTest;
|
||||
const hash = await pbkdf2Sha512Subtle(subtle, secret, salt, iterations, keylen);
|
||||
expect(hash).toEqual(expected);
|
||||
}
|
||||
|
||||
for (const [index, test] of brycxTests.entries()) {
|
||||
const { secret, salt, iterations, keylen, expected } = test;
|
||||
const hash = await pbkdf2Sha512Subtle(subtle, secret, salt, iterations, keylen);
|
||||
expect(hash).withContext(`brycx tests index ${index}`).toEqual(expected);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("pbkdf2Sha512Crypto", () => {
|
||||
it("works", async () => {
|
||||
const crypto = await getCryptoModule();
|
||||
if (!crypto) pending("The crypto module is not available in this environment");
|
||||
|
||||
{
|
||||
const { secret, salt, iterations, keylen, expected } = botanTest;
|
||||
const hash = await pbkdf2Sha512Crypto(crypto, secret, salt, iterations, keylen);
|
||||
expect(hash).toEqual(expected);
|
||||
}
|
||||
|
||||
for (const [index, test] of brycxTests.entries()) {
|
||||
const { secret, salt, iterations, keylen, expected } = test;
|
||||
const hash = await pbkdf2Sha512Crypto(crypto, secret, salt, iterations, keylen);
|
||||
expect(hash).withContext(`brycx tests index ${index}`).toEqual(expected);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("pbkdf2Sha512Noble", () => {
|
||||
it("works", async () => {
|
||||
{
|
||||
const { secret, salt, iterations, keylen, expected } = botanTest;
|
||||
const hash = await pbkdf2Sha512Noble(secret, salt, iterations, keylen);
|
||||
expect(hash).toEqual(expected);
|
||||
}
|
||||
|
||||
for (const [index, test] of brycxTests.entries()) {
|
||||
const { secret, salt, iterations, keylen, expected } = test;
|
||||
const hash = await pbkdf2Sha512Noble(secret, salt, iterations, keylen);
|
||||
expect(hash).withContext(`brycx tests index ${index}`).toEqual(expected);
|
||||
}
|
||||
}, 120_000);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,119 @@
|
||||
import { assert } from "@cosmjs/utils";
|
||||
import { pbkdf2Async as noblePbkdf2Async } from "@noble/hashes/pbkdf2";
|
||||
import { sha512 as nobleSha512 } from "@noble/hashes/sha512";
|
||||
|
||||
/**
|
||||
* Returns the Node.js crypto module when available and `undefined`
|
||||
* otherwise.
|
||||
*
|
||||
* Detects an unimplemented fallback module from Webpack 5 and returns
|
||||
* `undefined` in that case.
|
||||
*/
|
||||
export async function getCryptoModule(): Promise<any | undefined> {
|
||||
try {
|
||||
const crypto = await import("crypto");
|
||||
// We get `Object{default: Object{}}` as a fallback when using
|
||||
// `crypto: false` in Webpack 5, which we interprete as unavailable.
|
||||
if (typeof crypto === "object" && Object.keys(crypto).length <= 1) {
|
||||
return undefined;
|
||||
}
|
||||
return crypto;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getSubtle(): Promise<any | undefined> {
|
||||
const g: any = globalThis;
|
||||
let subtle = g.crypto && g.crypto.subtle;
|
||||
if (!subtle) {
|
||||
const crypto = await getCryptoModule();
|
||||
if (crypto && crypto.webcrypto && crypto.webcrypto.subtle) {
|
||||
subtle = crypto.webcrypto.subtle;
|
||||
}
|
||||
}
|
||||
return subtle;
|
||||
}
|
||||
|
||||
export async function pbkdf2Sha512Subtle(
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
subtle: any,
|
||||
secret: Uint8Array,
|
||||
salt: Uint8Array,
|
||||
iterations: number,
|
||||
keylen: number,
|
||||
): Promise<Uint8Array> {
|
||||
assert(subtle, "Argument subtle is falsy");
|
||||
assert(typeof subtle === "object", "Argument subtle is not of type object");
|
||||
assert(typeof subtle.importKey === "function", "subtle.importKey is not a function");
|
||||
assert(typeof subtle.deriveBits === "function", "subtle.deriveBits is not a function");
|
||||
|
||||
return subtle.importKey("raw", secret, { name: "PBKDF2" }, false, ["deriveBits"]).then((key: Uint8Array) =>
|
||||
subtle
|
||||
.deriveBits(
|
||||
{
|
||||
name: "PBKDF2",
|
||||
salt: salt,
|
||||
iterations: iterations,
|
||||
hash: { name: "SHA-512" },
|
||||
},
|
||||
key,
|
||||
keylen * 8,
|
||||
)
|
||||
.then((buffer: ArrayBuffer) => new Uint8Array(buffer)),
|
||||
);
|
||||
}
|
||||
|
||||
export async function pbkdf2Sha512Crypto(
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
crypto: any,
|
||||
secret: Uint8Array,
|
||||
salt: Uint8Array,
|
||||
iterations: number,
|
||||
keylen: number,
|
||||
): Promise<Uint8Array> {
|
||||
assert(crypto, "Argument crypto is falsy");
|
||||
assert(typeof crypto === "object", "Argument crypto is not of type object");
|
||||
assert(typeof crypto.pbkdf2 === "function", "crypto.pbkdf2 is not a function");
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
crypto.pbkdf2(secret, salt, iterations, keylen, "sha512", (error: any, result: any) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(Uint8Array.from(result));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function pbkdf2Sha512Noble(
|
||||
secret: Uint8Array,
|
||||
salt: Uint8Array,
|
||||
iterations: number,
|
||||
keylen: number,
|
||||
): Promise<Uint8Array> {
|
||||
return noblePbkdf2Async(nobleSha512, secret, salt, { c: iterations, dkLen: keylen });
|
||||
}
|
||||
|
||||
/**
|
||||
* A pbkdf2 implementation for BIP39. This is not exported at package level and thus a private API.
|
||||
*/
|
||||
export async function pbkdf2Sha512(
|
||||
secret: Uint8Array,
|
||||
salt: Uint8Array,
|
||||
iterations: number,
|
||||
keylen: number,
|
||||
): Promise<Uint8Array> {
|
||||
const subtle = await getSubtle();
|
||||
if (subtle) {
|
||||
return pbkdf2Sha512Subtle(subtle, secret, salt, iterations, keylen);
|
||||
} else {
|
||||
const crypto = await getCryptoModule();
|
||||
if (crypto) {
|
||||
return pbkdf2Sha512Crypto(crypto, secret, salt, iterations, keylen);
|
||||
} else {
|
||||
return pbkdf2Sha512Noble(secret, salt, iterations, keylen);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ module.exports = [
|
||||
crypto: false,
|
||||
events: false,
|
||||
path: false,
|
||||
stream: require.resolve("stream-browserify"),
|
||||
stream: false,
|
||||
string_decoder: false,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -79,7 +79,6 @@
|
||||
"prettier": "^2.4.1",
|
||||
"ses": "^0.11.0",
|
||||
"source-map-support": "^0.5.19",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"ts-node": "^8",
|
||||
"typedoc": "^0.22",
|
||||
"typescript": "~4.4",
|
||||
|
||||
@@ -26,7 +26,7 @@ module.exports = [
|
||||
crypto: false,
|
||||
events: false,
|
||||
path: false,
|
||||
stream: require.resolve("stream-browserify"),
|
||||
stream: false,
|
||||
string_decoder: false,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -84,7 +84,6 @@
|
||||
"readonly-date": "^1.0.0",
|
||||
"ses": "^0.11.0",
|
||||
"source-map-support": "^0.5.19",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"ts-node": "^8",
|
||||
"typedoc": "^0.22",
|
||||
"typescript": "~4.4",
|
||||
|
||||
@@ -32,7 +32,7 @@ module.exports = [
|
||||
crypto: false,
|
||||
events: false,
|
||||
path: false,
|
||||
stream: require.resolve("stream-browserify"),
|
||||
stream: false,
|
||||
string_decoder: false,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -329,7 +329,6 @@ __metadata:
|
||||
prettier: ^2.4.1
|
||||
ses: ^0.11.0
|
||||
source-map-support: ^0.5.19
|
||||
stream-browserify: ^3.0.0
|
||||
ts-node: ^8
|
||||
typedoc: ^0.22
|
||||
typescript: ~4.4
|
||||
@@ -435,7 +434,6 @@ __metadata:
|
||||
readonly-date: ^1.0.0
|
||||
ses: ^0.11.0
|
||||
source-map-support: ^0.5.19
|
||||
stream-browserify: ^3.0.0
|
||||
ts-node: ^8
|
||||
typedoc: ^0.22
|
||||
typescript: ~4.4
|
||||
@@ -464,7 +462,6 @@ __metadata:
|
||||
"@types/node": ^15.0.1
|
||||
"@typescript-eslint/eslint-plugin": ^4.28
|
||||
"@typescript-eslint/parser": ^4.28
|
||||
bip39: ^3.0.2
|
||||
bn.js: ^5.2.0
|
||||
buffer: ^6.0.3
|
||||
elliptic: ^6.5.3
|
||||
@@ -489,7 +486,6 @@ __metadata:
|
||||
prettier: ^2.4.1
|
||||
ses: ^0.11.0
|
||||
source-map-support: ^0.5.19
|
||||
stream-browserify: ^3.0.0
|
||||
ts-node: ^8
|
||||
typedoc: ^0.22
|
||||
typescript: ~4.4
|
||||
@@ -799,7 +795,6 @@ __metadata:
|
||||
protobufjs: ~6.10.2
|
||||
ses: ^0.11.0
|
||||
source-map-support: ^0.5.19
|
||||
stream-browserify: ^3.0.0
|
||||
ts-node: ^8
|
||||
typedoc: ^0.22
|
||||
typescript: ~4.4
|
||||
@@ -900,7 +895,6 @@ __metadata:
|
||||
readonly-date: ^1.0.0
|
||||
ses: ^0.11.0
|
||||
source-map-support: ^0.5.19
|
||||
stream-browserify: ^3.0.0
|
||||
ts-node: ^8
|
||||
typedoc: ^0.22
|
||||
typescript: ~4.4
|
||||
@@ -1692,13 +1686,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:11.11.6":
|
||||
version: 11.11.6
|
||||
resolution: "@types/node@npm:11.11.6"
|
||||
checksum: 075f1c011cf568e49701419acbcb55c24906b3bb5a34d9412a3b88f228a7a78401a5ad4d3e1cd6855c99aaea5ef96e37fc86ca097e50f06da92cf822befc1fff
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:>=13.7.0":
|
||||
version: 15.9.0
|
||||
resolution: "@types/node@npm:15.9.0"
|
||||
@@ -2401,18 +2388,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"bip39@npm:^3.0.2":
|
||||
version: 3.0.4
|
||||
resolution: "bip39@npm:3.0.4"
|
||||
dependencies:
|
||||
"@types/node": 11.11.6
|
||||
create-hash: ^1.1.0
|
||||
pbkdf2: ^3.0.9
|
||||
randombytes: ^2.0.1
|
||||
checksum: 79ce1600a03d1ba5053bdd4e6323f9463ec340764c7e52918b6c6b9dca81221940f2d9a65656447f108f9bc2c8d9ae8df319cca83bbd1dad63f53ef2768d9bae
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"bl@npm:^4.0.3":
|
||||
version: 4.1.0
|
||||
resolution: "bl@npm:4.1.0"
|
||||
@@ -2670,16 +2645,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3":
|
||||
version: 1.0.4
|
||||
resolution: "cipher-base@npm:1.0.4"
|
||||
dependencies:
|
||||
inherits: ^2.0.1
|
||||
safe-buffer: ^5.0.1
|
||||
checksum: 47d3568dbc17431a339bad1fe7dff83ac0891be8206911ace3d3b818fc695f376df809bea406e759cdea07fff4b454fa25f1013e648851bec790c1d75763032e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"clean-stack@npm:^2.0.0":
|
||||
version: 2.2.0
|
||||
resolution: "clean-stack@npm:2.2.0"
|
||||
@@ -2948,33 +2913,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"create-hash@npm:^1.1.0, create-hash@npm:^1.1.2":
|
||||
version: 1.2.0
|
||||
resolution: "create-hash@npm:1.2.0"
|
||||
dependencies:
|
||||
cipher-base: ^1.0.1
|
||||
inherits: ^2.0.1
|
||||
md5.js: ^1.3.4
|
||||
ripemd160: ^2.0.1
|
||||
sha.js: ^2.4.0
|
||||
checksum: 02a6ae3bb9cd4afee3fabd846c1d8426a0e6b495560a977ba46120c473cb283be6aa1cace76b5f927cf4e499c6146fb798253e48e83d522feba807d6b722eaa9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"create-hmac@npm:^1.1.4":
|
||||
version: 1.1.7
|
||||
resolution: "create-hmac@npm:1.1.7"
|
||||
dependencies:
|
||||
cipher-base: ^1.0.3
|
||||
create-hash: ^1.1.0
|
||||
inherits: ^2.0.1
|
||||
ripemd160: ^2.0.0
|
||||
safe-buffer: ^5.0.1
|
||||
sha.js: ^2.4.8
|
||||
checksum: ba12bb2257b585a0396108c72830e85f882ab659c3320c83584b1037f8ab72415095167ced80dc4ce8e446a8ecc4b2acf36d87befe0707d73b26cf9dc77440ed
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3":
|
||||
version: 7.0.3
|
||||
resolution: "cross-spawn@npm:7.0.3"
|
||||
@@ -4394,7 +4332,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4":
|
||||
"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3":
|
||||
version: 2.0.4
|
||||
resolution: "inherits@npm:2.0.4"
|
||||
checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1
|
||||
@@ -5227,17 +5165,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"md5.js@npm:^1.3.4":
|
||||
version: 1.3.5
|
||||
resolution: "md5.js@npm:1.3.5"
|
||||
dependencies:
|
||||
hash-base: ^3.0.0
|
||||
inherits: ^2.0.1
|
||||
safe-buffer: ^5.1.2
|
||||
checksum: 098494d885684bcc4f92294b18ba61b7bd353c23147fbc4688c75b45cb8590f5a95fd4584d742415dcc52487f7a1ef6ea611cfa1543b0dc4492fe026357f3f0c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"media-typer@npm:0.3.0":
|
||||
version: 0.3.0
|
||||
resolution: "media-typer@npm:0.3.0"
|
||||
@@ -5947,19 +5874,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pbkdf2@npm:^3.0.9":
|
||||
version: 3.1.2
|
||||
resolution: "pbkdf2@npm:3.1.2"
|
||||
dependencies:
|
||||
create-hash: ^1.1.2
|
||||
create-hmac: ^1.1.4
|
||||
ripemd160: ^2.0.1
|
||||
safe-buffer: ^5.0.1
|
||||
sha.js: ^2.4.8
|
||||
checksum: 2c950a100b1da72123449208e231afc188d980177d021d7121e96a2de7f2abbc96ead2b87d03d8fe5c318face097f203270d7e27908af9f471c165a4e8e69c92
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.2.3":
|
||||
version: 2.2.3
|
||||
resolution: "picomatch@npm:2.2.3"
|
||||
@@ -6210,7 +6124,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"randombytes@npm:^2.0.1, randombytes@npm:^2.1.0":
|
||||
"randombytes@npm:^2.1.0":
|
||||
version: 2.1.0
|
||||
resolution: "randombytes@npm:2.1.0"
|
||||
dependencies:
|
||||
@@ -6300,7 +6214,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0":
|
||||
"readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0":
|
||||
version: 3.6.0
|
||||
resolution: "readable-stream@npm:3.6.0"
|
||||
dependencies:
|
||||
@@ -6481,7 +6395,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ripemd160@npm:^2.0.0, ripemd160@npm:^2.0.1, ripemd160@npm:^2.0.2":
|
||||
"ripemd160@npm:^2.0.2":
|
||||
version: 2.0.2
|
||||
resolution: "ripemd160@npm:2.0.2"
|
||||
dependencies:
|
||||
@@ -6516,7 +6430,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.0, safe-buffer@npm:~5.2.0":
|
||||
"safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.2.0, safe-buffer@npm:~5.2.0":
|
||||
version: 5.2.1
|
||||
resolution: "safe-buffer@npm:5.2.1"
|
||||
checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491
|
||||
@@ -6611,18 +6525,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"sha.js@npm:^2.4.0, sha.js@npm:^2.4.8":
|
||||
version: 2.4.11
|
||||
resolution: "sha.js@npm:2.4.11"
|
||||
dependencies:
|
||||
inherits: ^2.0.1
|
||||
safe-buffer: ^5.0.1
|
||||
bin:
|
||||
sha.js: ./bin.js
|
||||
checksum: ebd3f59d4b799000699097dadb831c8e3da3eb579144fd7eb7a19484cbcbb7aca3c68ba2bb362242eb09e33217de3b4ea56e4678184c334323eca24a58e3ad07
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"shallow-clone@npm:^3.0.0":
|
||||
version: 3.0.1
|
||||
resolution: "shallow-clone@npm:3.0.1"
|
||||
@@ -6882,16 +6784,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"stream-browserify@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "stream-browserify@npm:3.0.0"
|
||||
dependencies:
|
||||
inherits: ~2.0.4
|
||||
readable-stream: ^3.5.0
|
||||
checksum: 4c47ef64d6f03815a9ca3874e2319805e8e8a85f3550776c47ce523b6f4c6cd57f40e46ec6a9ab8ad260fde61863c2718f250d3bedb3fe9052444eb9abfd9921
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"streamroller@npm:^3.0.2":
|
||||
version: 3.0.2
|
||||
resolution: "streamroller@npm:3.0.2"
|
||||
|
||||
Reference in New Issue
Block a user