From 848c27fac36b12ed1170bed4c3a63e0a09f693b6 Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Wed, 2 Jul 2025 19:46:06 -0700 Subject: [PATCH] Merge branch 'threads' into main --- .gitignore | 3 + benchmarks.md | 199 ++ esbuild-browser.mjs | 16 + esbuild-node.mjs | 16 + favicon.ico | Bin 0 -> 176148 bytes favicon.ico.license | 2 + index.html | 112 +- package-lock.json | 1901 ++++++++++- package.json | 42 +- perf/account.perf.js | 66 - perf/block.perf.js | 56 - performance.html | 11 - src/global.ts | 5 - src/lib/account.ts | 78 +- src/lib/bip39-mnemonic.ts | 32 +- src/lib/blake2b.ts | 455 ++- src/lib/block.ts | 149 +- src/lib/constants.ts | 4 +- src/lib/convert.ts | 59 +- src/lib/entropy.ts | 13 +- src/lib/ledger.ts | 89 +- src/lib/pool.ts | 16 +- src/lib/rolodex.ts | 2 +- src/lib/safe.ts | 95 +- src/lib/tools.ts | 30 +- src/lib/wallet.ts | 156 +- src/lib/workers.ts | 7 - src/lib/workers/bip44-ckd.ts | 2 +- src/lib/workers/index.ts | 11 + src/lib/workers/nano-nacl.ts | 587 +--- src/lib/workers/powgl.ts | 404 --- src/main.ts | 19 +- test.html | 11 - GLOBALS.mjs => test/GLOBALS.mjs | 119 +- test/QUEUE.mjs | 38 + test/TEST_VECTORS.js | 211 -- test/VECTORS.js | 2841 +++++++++++++++++ test/main.mjs | 14 - test/perf.account.js | 64 + test/perf.block.js | 32 + perf/main.mjs => test/perf.main.mjs | 6 +- perf/wallet.perf.js => test/perf.wallet.js | 20 +- test/performance.html | 16 + test/test.blake2b.mjs | 91 + ...te-pow.test.mjs => test.calculate-pow.mjs} | 6 +- ...wallet.test.mjs => test.create-wallet.mjs} | 31 +- ...unts.test.mjs => test.derive-accounts.mjs} | 45 +- ...wallet.test.mjs => test.import-wallet.mjs} | 34 +- ...wallet.mjs => test.lock-unlock-wallet.mjs} | 43 +- test/test.main.mjs | 15 + ...ge-rolodex.mjs => test.manage-rolodex.mjs} | 9 +- ...nts.test.mjs => test.refresh-accounts.mjs} | 41 +- ...n-blocks.test.mjs => test.sign-blocks.mjs} | 20 +- test/{tools.test.mjs => test.tools.mjs} | 17 +- tsconfig.json | 8 +- 55 files changed, 6273 insertions(+), 2096 deletions(-) create mode 100644 benchmarks.md create mode 100644 esbuild-browser.mjs create mode 100644 esbuild-node.mjs create mode 100644 favicon.ico create mode 100644 favicon.ico.license delete mode 100644 perf/account.perf.js delete mode 100644 perf/block.perf.js delete mode 100644 performance.html delete mode 100644 src/global.ts delete mode 100644 src/lib/workers.ts create mode 100644 src/lib/workers/index.ts delete mode 100644 src/lib/workers/powgl.ts delete mode 100644 test.html rename GLOBALS.mjs => test/GLOBALS.mjs (68%) create mode 100644 test/QUEUE.mjs delete mode 100644 test/TEST_VECTORS.js create mode 100644 test/VECTORS.js delete mode 100644 test/main.mjs create mode 100644 test/perf.account.js create mode 100644 test/perf.block.js rename perf/main.mjs => test/perf.main.mjs (67%) rename perf/wallet.perf.js => test/perf.wallet.js (54%) create mode 100644 test/performance.html create mode 100644 test/test.blake2b.mjs rename test/{calculate-pow.test.mjs => test.calculate-pow.mjs} (85%) rename test/{create-wallet.test.mjs => test.create-wallet.mjs} (70%) rename test/{derive-accounts.test.mjs => test.derive-accounts.mjs} (68%) rename test/{import-wallet.test.mjs => test.import-wallet.mjs} (94%) rename test/{lock-unlock-wallet.mjs => test.lock-unlock-wallet.mjs} (93%) create mode 100644 test/test.main.mjs rename test/{manage-rolodex.mjs => test.manage-rolodex.mjs} (97%) rename test/{refresh-accounts.test.mjs => test.refresh-accounts.mjs} (91%) rename test/{sign-blocks.test.mjs => test.sign-blocks.mjs} (88%) rename test/{tools.test.mjs => test.tools.mjs} (92%) diff --git a/.gitignore b/.gitignore index 50492de..eb95a92 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,6 @@ typings/ # esbuild build/ dist/ + +# IDE +.vscode diff --git a/benchmarks.md b/benchmarks.md new file mode 100644 index 0000000..fc2f5a9 --- /dev/null +++ b/benchmarks.md @@ -0,0 +1,199 @@ + + +PASS Original PoW module: Time to calculate proof-of-work for a send block 16 times +Total: 89756 ms +Average: 5609.75 ms +Harmonic: 2092.567565254879 ms +Geometric: 3612.112662613675 ms + +PASS Customized PoW: Time to calculate proof-of-work for a send block 16 times +Total: 33240 ms +Average: 2077.5 ms +Harmonic: 1328.5635414262717 ms +Geometric: 1663.110986923899 ms + +How much faster? +Total: 56156 ms +Average: 3532 ms +Harmonic: 764 ms +Geometric: 1949 ms + +Another PowGl test: +Total: 22831.300000041723 ms +Average: 3805.2166666736207 ms +Harmonic: 928.6432328540742 ms +Geometric: 2500.810238375608 ms +Minimum: 193 ms +Maximum: 8361 ms + +The proof-of-work equation for Nano cryptocurrency is defined as `blake2b(nonce||blockhash)>=threshold` where blake2b is the hash function configured for an 8-byte output, nonce is a random 8-byte value, || is concatenation, blockhash is a 32-byte value, and threshold is 0xfffffff800000000. + +My code currently finds valid nonces on a gaming GPU without issue but only because the initial search space is so large due to using a workgroup size of 256 and a dispatch of (256, 256, 256), so the probability of finding a nonce in the first pass is extremely high. However, this does not perform well on less powerful hardware like smartphones. Please alter my code to perform the nonce search in `main()` in a loop until a valid nonce is found with the idea that a smaller workgroup size and/or smaller dispatch dimensions can allow weak hardware to nonetheless iterate through nonces to search for a valid one and return it. + + +Total: 680948 ms +Average: 1329.9765625 ms +Harmonic: 749.6552658409396 ms +PASS Customized PoW: Time to calculate proof-of-work for a send block 512 times + + + +CHROMIUM with more accurate timings + +PowGpu: Time to calculate proof-of-work for a send block 8192 times +Total: 2934170.3000008166 ms +Average: 358.17508544931843 ms +Harmonic: 218.11823673331645 ms +Minimum: 76.2000000178814 ms +Maximum: 2999.9000000059605 ms + + + +PowGpu: Time to calculate proof-of-work for a send block 512 times +Total: 187428.40000000596 ms +Average: 366.07109375001164 ms +Harmonic: 220.70399520519166 ms + +PowGpu: Time to calculate proof-of-work for a send block 512 times +Total: 187827.7999998629 ms +Average: 366.85117187473224 ms +Harmonic: 223.9897252426498 ms + +libnemo: Time to calculate proof-of-work for a send block 512 times +(after inlining entire first G round) +Total: 156981.3999993205 ms +Average: 306.60429687367287 ms +Harmonic: 128.74904701127866 ms +Minimum: 21.700000047683716 ms +Maximum: 1981.199999988079 ms + +libnemo: Time to calculate proof-of-work for a send block 512 times +(after inlining entire first G round) +Total: 162225.30000036955 ms +Average: 316.8462890632218 ms +Harmonic: 130.50451885939313 ms +Geometric: 211.25671228925867 ms +Minimum: 21.600000023841858 ms +Maximum: 2267.600000023842 ms + +libnemo: Time to calculate proof-of-work for a send block 512 times +(after inlining 3 rounds of G mixing) +Total: 155547.09999996424 ms +Average: 303.80292968743015 ms +Harmonic: 118.19131857240315 ms +Geometric: 196.77234360098842 ms +Minimum: 19.5 ms +Maximum: 2140.2000000476837 ms + +libnemo: Time to calculate proof-of-work for a send block 512 times +(after inlining 5 rounds of G mixing) +Total: 165145.19999998808 ms +Average: 322.5492187499767 ms +Harmonic: 126.40822610460997 ms +Geometric: 205.28427810986508 ms +Minimum: 20.099999964237213 ms +Maximum: 1850.5 ms + +libnemo: Time to calculate proof-of-work for a send block 512 times +(after inlining 5 rounds of G mixing and replacing if with select in original G function) +Total: 135665.40000021458 ms +Average: 264.9714843754191 ms +Harmonic: 118.80915172412905 ms +Geometric: 181.19191881133972 ms +Minimum: 19.599999964237213 ms +Maximum: 1908.5 ms + +libnemo: Time to calculate proof-of-work for a send block 512 times +(after inlining 9 rounds of G mixing and replacing if with select in original G function) +Total: 147481.09999907017 ms +Average: 288.0490234356839 ms +Harmonic: 122.25335314983455 ms +Geometric: 192.75325397221323 ms +Minimum: 22.19999998807907 ms +Maximum: 1762.800000011921 ms + +libnemo: Time to calculate proof-of-work for a send block 512 times +(after inlining all rounds of G mixing) +Total: 165041.20000058413 ms +Average: 322.34609375114087 ms +Harmonic: 121.30652845909019 ms +Geometric: 202.80092012876665 ms +Minimum: 21.69999998807907 ms +Maximum: 2303 ms + +libnemo: Time to calculate proof-of-work for a send block 512 times +(after inlining all rounds of G mixing and all if statements replaced with select function) +Total: 134865.20000064373 ms +Average: 263.4085937512573 ms +Harmonic: 108.28019222737286 ms +Geometric: 171.8797089689105 ms +Minimum: 20.80000001192093 ms +Maximum: 2093.199999988079 ms + +libnemo: Time to calculate proof-of-work for a send block 512 times +(after increasing workgroup_size to 256 from 64 and decreasing dispatch size) +Total: 149857.0999999717 ms +Average: 292.6896484374447 ms +Harmonic: 73.49751645489904 ms +Geometric: 174.9560632035056 ms +Minimum: 2.600000001490116 ms +Maximum: 2364.5999999940395 ms + +GLOBALS.mjs:46 PASS libnemo: Time to calculate proof-of-work for a send block 512 times +(after increasing workgroup_size to 256 from 64 and decreasing dispatch size) +Total: 145201.70000004023 ms +Average: 283.5970703125786 ms +Harmonic: 54.2894989554052 ms +Geometric: 155.58659283933008 ms +Minimum: 2.5 ms +Maximum: 1812.3999999985099 ms + + + +PowGpu: Time to calculate proof-of-work for a send block 32 times +Total: 8909.500000029802 ms +Average: 278.4218750009313 ms +Harmonic: 191.49100480215873 ms +Geometric: 232.13670548729021 ms +Minimum: 76.69999998807907 ms +Maximum: 641.5 ms + +PowGpu: Time to calculate proof-of-work for a send block 32 times +Total: 11805.200000077486 ms +Average: 368.91250000242144 ms +Harmonic: 131.36379466491744 ms +Geometric: 228.69384924435158 ms +Minimum: 21.900000005960464 ms +Maximum: 1479.5 ms + +libnemo: Time to calculate proof-of-work for a send block 32 times +(after inlining three G calls) +Total: 11208.399999916553 ms +Average: 350.2624999973923 ms +Harmonic: 115.78621253028925 ms +Geometric: 210.41080264689026 ms +Minimum: 25 ms +Maximum: 1249.199999988079 ms + +libnemo: Time to calculate proof-of-work for a send block 32 times +(after inlining entire first G round) +Total: 9778.899999797344 ms +Average: 305.590624993667 ms +Harmonic: 120.65186396913916 ms +Geometric: 193.85674573632113 ms +Minimum: 23.69999998807907 ms +Maximum: 1752.199999988079 ms + +libnemo: Time to calculate proof-of-work for a send block 32 times +(after inlining 3 rounds of G mixing) +Total: 10425.399999856949 ms +Average: 325.79374999552965 ms +Harmonic: 150.5729403997282 ms +Geometric: 231.43806657572657 ms +Minimum: 31.900000035762787 ms +Maximum: 954.9000000357628 ms + +In the following code, look at the fourth argument. Prepend it with `v&` and remove its `u` suffix. Then insert a parameter right after it with the same name except the digit is incremented by 1. For example, `G(&v, &v0, &v1, 8u, 16u, 24u, m0, m1, m2, m3);` becomes `G(&v, &v0, &v1, &v8, &v9, 16u, 24u, m0, m1, m2, m3);`. Make sure the ampersand is present and the digits are correct as described. Do not make any other modifications. diff --git a/esbuild-browser.mjs b/esbuild-browser.mjs new file mode 100644 index 0000000..df0bb54 --- /dev/null +++ b/esbuild-browser.mjs @@ -0,0 +1,16 @@ +//! SPDX-FileCopyrightText: 2025 Chris Duncan +//! SPDX-License-Identifier: GPL-3.0-or-later + +import { build } from 'esbuild' + +await build({ + bundle: true, + platform: 'browser', + entryPoints: [ + { in: './src/main.ts', out: 'main.min' } + ], + format: 'esm', + legalComments: 'inline', + outdir: 'dist', + target: 'esnext' +}) diff --git a/esbuild-node.mjs b/esbuild-node.mjs new file mode 100644 index 0000000..dcbfd2f --- /dev/null +++ b/esbuild-node.mjs @@ -0,0 +1,16 @@ +//! SPDX-FileCopyrightText: 2025 Chris Duncan +//! SPDX-License-Identifier: GPL-3.0-or-later + +import { build } from 'esbuild' + +await build({ + bundle: true, + platform: 'node', + entryPoints: [ + { in: './src/main.ts', out: 'main.min' } + ], + format: 'esm', + legalComments: 'inline', + outdir: 'dist', + target: 'esnext' +}) diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..024ed21b4c597e4cbb816f020d7c4db61a24bb7c GIT binary patch literal 176148 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 +SPDX-License-Identifier: GPL-3.0-or-later +--> + - - - + -

-

+

libnemo

+

diff --git a/package-lock.json b/package-lock.json index 75e959c..92eeac0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,210 +7,1540 @@ "": { "name": "libnemo", "version": "0.0.21", + "license": "(GPL-3.0-or-later AND MIT AND ISC)", + "dependencies": { + "nano-pow": "^5.1.4", + "nano-webgl-pow": "^1.1.1" + }, + "devDependencies": { + "@types/node": "^24.0.4", + "@types/w3c-web-hid": "^1.0.6", + "@types/w3c-web-usb": "^1.0.10", + "@types/web-bluetooth": "^0.0.21", + "esbuild": "^0.25.5", + "typescript": "^5.8.3" + }, + "funding": { + "type": "nano", + "url": "nano:nano_1zosoqs47yt47bnfg7sdf46kj7asn58b7uzm9ek95jw7ccatq37898u1zoso" + }, + "optionalDependencies": { + "@ledgerhq/hw-transport-web-ble": "^6.29.7", + "@ledgerhq/hw-transport-webhid": "^6.30.3", + "@ledgerhq/hw-transport-webusb": "^6.29.7" + } + }, + "../nano-pow": { + "version": "1.2.3", + "extraneous": true, + "license": "(GPL-3.0-or-later AND MIT)", + "devDependencies": { + "@types/node": "^22.10.5", + "@webgpu/types": "^0.1.52", + "esbuild": "^0.24.2", + "esbuild-plugin-glsl": "^1.2.2", + "nano-webgl-pow": "^1.1.1", + "typescript": "^5.7.3" + }, + "funding": { + "type": "nano", + "url": "nano:nano_1zosoqs47yt47bnfg7sdf46kj7asn58b7uzm9ek95jw7ccatq37898u1zoso" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", + "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", + "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", + "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", + "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", + "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", + "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", + "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", + "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", + "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", + "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", + "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", + "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", + "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", + "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", + "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", + "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", + "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", + "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", + "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", + "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", + "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", + "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", + "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", + "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", + "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@ledgerhq/devices": { + "version": "8.4.7", + "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-8.4.7.tgz", + "integrity": "sha512-CljHIaPmtv93H2If1Zs1xW0pgg+M37bAoJkm6+V6Yw5S0MgFWFpLnTTNgCvHXyD8pG0+uq8TuOXUiG1oAV5AyA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@ledgerhq/errors": "^6.22.0", + "@ledgerhq/logs": "^6.13.0", + "rxjs": "^7.8.1", + "semver": "^7.3.5" + } + }, + "node_modules/@ledgerhq/errors": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-6.22.0.tgz", + "integrity": "sha512-rXtpIOfHL62jWB7o77PNFD4EDYdcqyMeVgt7TZcmTkWT78cK+YYSUTMrNuGLhnZZZTMLWH023Wgt65OfKIdGBQ==", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/@ledgerhq/hw-transport": { + "version": "6.31.7", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.31.7.tgz", + "integrity": "sha512-R+QMlqoLJDPeCiqwWv85PbZ3m0hel5PwQzWwSIbyEwialqjXnG7LFQgytkgXlgMcayT0chvvLeYjuY5ZfMPY7w==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@ledgerhq/devices": "8.4.7", + "@ledgerhq/errors": "^6.22.0", + "@ledgerhq/logs": "^6.13.0", + "events": "^3.3.0" + } + }, + "node_modules/@ledgerhq/hw-transport-web-ble": { + "version": "6.29.7", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-web-ble/-/hw-transport-web-ble-6.29.7.tgz", + "integrity": "sha512-oDDPubEtKWNo5SusJOBWGQwpXlk8+8rsVoY7cqKwnEEK4hcXtbAe0y3EE/KsK+NSJtE0RfciAjfmPebybYXXPQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@ledgerhq/devices": "8.4.7", + "@ledgerhq/errors": "^6.22.0", + "@ledgerhq/hw-transport": "^6.31.7", + "@ledgerhq/logs": "^6.13.0", + "rxjs": "^7.8.1" + } + }, + "node_modules/@ledgerhq/hw-transport-webhid": { + "version": "6.30.3", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webhid/-/hw-transport-webhid-6.30.3.tgz", + "integrity": "sha512-DV2QL4gZ3XvB5i271np5DHROu3Ry6Pjvhd65mu6JLpasAQr0VeW0L8KZ+JK9VryARC1soU1ZEPkL2uVw8MRmvg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@ledgerhq/devices": "8.4.7", + "@ledgerhq/errors": "^6.22.0", + "@ledgerhq/hw-transport": "^6.31.7", + "@ledgerhq/logs": "^6.13.0" + } + }, + "node_modules/@ledgerhq/hw-transport-webusb": { + "version": "6.29.7", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-6.29.7.tgz", + "integrity": "sha512-6BJkgvC+8yXssD6JN5QgSKxTSLucb2Cf+dg0EJAoqNXqz84Yse3W9Z+AJVSLH6XwxH69tWtHP5VtQgltWZJA6g==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@ledgerhq/devices": "8.4.7", + "@ledgerhq/errors": "^6.22.0", + "@ledgerhq/hw-transport": "^6.31.7", + "@ledgerhq/logs": "^6.13.0" + } + }, + "node_modules/@ledgerhq/logs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-6.13.0.tgz", + "integrity": "sha512-4+qRW2Pc8V+btL0QEmdB2X+uyx0kOWMWE1/LWsq5sZy3Q5tpi4eItJS6mB0XL3wGW59RQ+8bchNQQ1OW/va8Og==", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/@puppeteer/browsers": { + "version": "2.10.5", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.5.tgz", + "integrity": "sha512-eifa0o+i8dERnngJwKrfp3dEq7ia5XFyoqB17S4gK8GhsQE4/P8nxOfQSE0zQHxzzLo/cmF+7+ywEQ7wK7Fb+w==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "debug": "^4.4.1", + "extract-zip": "^2.0.1", + "progress": "^2.0.3", + "proxy-agent": "^6.5.0", + "semver": "^7.7.2", + "tar-fs": "^3.0.8", + "yargs": "^17.7.2" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/node": { + "version": "24.0.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.4.tgz", + "integrity": "sha512-ulyqAkrhnuNq9pB76DRBTkcS6YsmDALy6Ua63V8OhrOBgbcYt6IOdzpw5P1+dyRIyMerzLkeYWBeOXPpA9GMAA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.8.0" + } + }, + "node_modules/@types/w3c-web-hid": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/w3c-web-hid/-/w3c-web-hid-1.0.6.tgz", + "integrity": "sha512-IWyssXmRDo6K7s31dxf+U+x/XUWuVsl9qUIYbJmpUHPcTv/COfBCKw/F0smI45+gPV34brjyP30BFcIsHgYWLA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/w3c-web-usb": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@types/w3c-web-usb/-/w3c-web-usb-1.0.10.tgz", + "integrity": "sha512-CHgUI5kTc/QLMP8hODUHhge0D4vx+9UiAwIGiT0sTy/B2XpdX1U5rJt6JSISgr6ikRT7vxV9EVAFeYZqUnl1gQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0", + "optional": true + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/b4a": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/bare-events": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", + "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/bare-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.1.5.tgz", + "integrity": "sha512-1zccWBMypln0jEE05LzZt+V/8y8AQsQQqxtklqaIyg5nu6OAYFhZxPXinJTSG+kU5qyNmeLgcn9AW7eHiCHVLA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-events": "^2.5.4", + "bare-path": "^3.0.0", + "bare-stream": "^2.6.4" + }, + "engines": { + "bare": ">=1.16.0" + }, + "peerDependencies": { + "bare-buffer": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + } + } + }, + "node_modules/bare-os": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.1.tgz", + "integrity": "sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "bare": ">=1.14.0" + } + }, + "node_modules/bare-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", + "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-os": "^3.0.1" + } + }, + "node_modules/bare-stream": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.6.5.tgz", + "integrity": "sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "streamx": "^2.21.0" + }, + "peerDependencies": { + "bare-buffer": "*", + "bare-events": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + }, + "bare-events": { + "optional": true + } + } + }, + "node_modules/basic-ftp": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/chromium-bidi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-5.1.0.tgz", + "integrity": "sha512-9MSRhWRVoRPDG0TgzkHrshFSJJNZzfY5UFqUMuksg7zL1yoZIZ3jLB0YAgHclbiAxPI86pBnwDX1tbzoiV8aFw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "mitt": "^3.0.1", + "zod": "^3.24.1" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT", + "optional": true + }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "license": "MIT", + "optional": true, + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/devtools-protocol": { + "version": "0.0.1464554", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1464554.tgz", + "integrity": "sha512-CAoP3lYfwAGQTaAXYvA6JZR0fjGUb7qec1qf4mToyoH2TZgUFeIqYcjh6f9jNuhHfuZiEdH+PONHYrLhRQX6aw==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT", + "optional": true + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "optional": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/esbuild": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", + "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.5", + "@esbuild/android-arm": "0.25.5", + "@esbuild/android-arm64": "0.25.5", + "@esbuild/android-x64": "0.25.5", + "@esbuild/darwin-arm64": "0.25.5", + "@esbuild/darwin-x64": "0.25.5", + "@esbuild/freebsd-arm64": "0.25.5", + "@esbuild/freebsd-x64": "0.25.5", + "@esbuild/linux-arm": "0.25.5", + "@esbuild/linux-arm64": "0.25.5", + "@esbuild/linux-ia32": "0.25.5", + "@esbuild/linux-loong64": "0.25.5", + "@esbuild/linux-mips64el": "0.25.5", + "@esbuild/linux-ppc64": "0.25.5", + "@esbuild/linux-riscv64": "0.25.5", + "@esbuild/linux-s390x": "0.25.5", + "@esbuild/linux-x64": "0.25.5", + "@esbuild/netbsd-arm64": "0.25.5", + "@esbuild/netbsd-x64": "0.25.5", + "@esbuild/openbsd-arm64": "0.25.5", + "@esbuild/openbsd-x64": "0.25.5", + "@esbuild/sunos-x64": "0.25.5", + "@esbuild/win32-arm64": "0.25.5", + "@esbuild/win32-ia32": "0.25.5", + "@esbuild/win32-x64": "0.25.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "license": "BSD-2-Clause", + "optional": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", + "optional": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "license": "BSD-2-Clause", + "optional": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "license": "MIT", + "optional": true + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "license": "MIT", + "optional": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "optional": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", + "optional": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-uri": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", + "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "license": "MIT", + "optional": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT", + "optional": true + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT", + "optional": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "optional": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "license": "MIT", + "optional": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT", + "optional": true + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT", + "optional": true + }, + "node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT", + "optional": true + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "optional": true + }, + "node_modules/nano-pow": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/nano-pow/-/nano-pow-5.1.4.tgz", + "integrity": "sha512-pYK2JF2rW43pal0iWNFIlKDpSXA/IEe1CN59stOe0qFm4iu0/s+VvPWq6HgwZd7dEcGBJ1Rol1ZqqfcVaAieRA==", "license": "(GPL-3.0-or-later AND MIT)", - "devDependencies": { - "@types/node": "^22.10.1", - "@types/w3c-web-hid": "^1.0.6", - "@types/w3c-web-usb": "^1.0.10", - "@types/web-bluetooth": "^0.0.20", - "esbuild": "^0.24.0", - "nano-webgl-pow": "^1.1.1", - "typescript": "^5.6.3" + "bin": { + "nano-pow": "dist/bin/nano-pow.sh" }, "funding": { "type": "nano", "url": "nano:nano_1zosoqs47yt47bnfg7sdf46kj7asn58b7uzm9ek95jw7ccatq37898u1zoso" }, "optionalDependencies": { - "@ledgerhq/hw-transport-web-ble": "^6.29.4", - "@ledgerhq/hw-transport-webhid": "^6.29.4", - "@ledgerhq/hw-transport-webusb": "^6.29.4" + "puppeteer": "^24.10.1" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", - "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/nano-webgl-pow": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nano-webgl-pow/-/nano-webgl-pow-1.1.1.tgz", + "integrity": "sha512-IKAg7qx2y4n9dnT7tYYypOun/aV+35SfRxJCVnc63GboWQ5/woVIVAZcdX5VfXM1mLYBzADvXxoWZ39G3iPOFA==", + "license": "MIT" + }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", "license": "MIT", "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">= 0.4.0" } }, - "node_modules/@ledgerhq/devices": { - "version": "8.4.4", - "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-8.4.4.tgz", - "integrity": "sha512-sz/ryhe/R687RHtevIE9RlKaV8kkKykUV4k29e7GAVwzHX1gqG+O75cu1NCJUHLbp3eABV5FdvZejqRUlLis9A==", - "license": "Apache-2.0", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", "optional": true, "dependencies": { - "@ledgerhq/errors": "^6.19.1", - "@ledgerhq/logs": "^6.12.0", - "rxjs": "^7.8.1", - "semver": "^7.3.5" + "wrappy": "1" } }, - "node_modules/@ledgerhq/errors": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-6.19.1.tgz", - "integrity": "sha512-75yK7Nnit/Gp7gdrJAz0ipp31CCgncRp+evWt6QawQEtQKYEDfGo10QywgrrBBixeRxwnMy1DP6g2oCWRf1bjw==", - "license": "Apache-2.0", - "optional": true - }, - "node_modules/@ledgerhq/hw-transport": { - "version": "6.31.4", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.31.4.tgz", - "integrity": "sha512-6c1ir/cXWJm5dCWdq55NPgCJ3UuKuuxRvf//Xs36Bq9BwkV2YaRQhZITAkads83l07NAdR16hkTWqqpwFMaI6A==", - "license": "Apache-2.0", + "node_modules/pac-proxy-agent": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", + "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", + "license": "MIT", "optional": true, "dependencies": { - "@ledgerhq/devices": "^8.4.4", - "@ledgerhq/errors": "^6.19.1", - "@ledgerhq/logs": "^6.12.0", - "events": "^3.3.0" + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.6", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" } }, - "node_modules/@ledgerhq/hw-transport-web-ble": { - "version": "6.29.4", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-web-ble/-/hw-transport-web-ble-6.29.4.tgz", - "integrity": "sha512-OJyp6CryvyFlg1L9uifo5hYYdDt+WPw8/0ijBixYhYmGvlRz2W6/F2c5rG/zBQWcNnNydPOLjLJM0vR070RfCw==", - "license": "Apache-2.0", + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "license": "MIT", "optional": true, "dependencies": { - "@ledgerhq/devices": "^8.4.4", - "@ledgerhq/errors": "^6.19.1", - "@ledgerhq/hw-transport": "^6.31.4", - "@ledgerhq/logs": "^6.12.0", - "rxjs": "^7.8.1" + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" } }, - "node_modules/@ledgerhq/hw-transport-webhid": { - "version": "6.29.4", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webhid/-/hw-transport-webhid-6.29.4.tgz", - "integrity": "sha512-XkF37lcuyg9zVExMyfDQathWly8rRcGac13wgZATBa3nZ+hUzzWr5QVKg1pKCw10izVHGErW/9a4tbb72rUEmQ==", - "license": "Apache-2.0", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", "optional": true, "dependencies": { - "@ledgerhq/devices": "^8.4.4", - "@ledgerhq/errors": "^6.19.1", - "@ledgerhq/hw-transport": "^6.31.4", - "@ledgerhq/logs": "^6.12.0" + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/@ledgerhq/hw-transport-webusb": { - "version": "6.29.4", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-6.29.4.tgz", - "integrity": "sha512-HoGF1LlBT9HEGBQy2XeCHrFdv/FEOZU0+J+yfKcgAQIAiASr2MLvdzwoJbUS8h6Gn+vc+/BjzBSO3JNn7Loqbg==", - "license": "Apache-2.0", + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", "optional": true, "dependencies": { - "@ledgerhq/devices": "^8.4.4", - "@ledgerhq/errors": "^6.19.1", - "@ledgerhq/hw-transport": "^6.31.4", - "@ledgerhq/logs": "^6.12.0" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@ledgerhq/logs": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-6.12.0.tgz", - "integrity": "sha512-ExDoj1QV5eC6TEbMdLUMMk9cfvNKhhv5gXol4SmULRVCx/3iyCPhJ74nsb3S0Vb+/f+XujBEj3vQn5+cwS0fNA==", - "license": "Apache-2.0", + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "license": "MIT", "optional": true }, - "node_modules/@types/node": { - "version": "22.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz", - "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==", - "dev": true, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC", + "optional": true + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "optional": true, + "engines": { + "node": ">=0.4.0" } }, - "node_modules/@types/w3c-web-hid": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/w3c-web-hid/-/w3c-web-hid-1.0.6.tgz", - "integrity": "sha512-IWyssXmRDo6K7s31dxf+U+x/XUWuVsl9qUIYbJmpUHPcTv/COfBCKw/F0smI45+gPV34brjyP30BFcIsHgYWLA==", - "dev": true, - "license": "MIT" + "node_modules/proxy-agent": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", + "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.6", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.1.0", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } }, - "node_modules/@types/w3c-web-usb": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@types/w3c-web-usb/-/w3c-web-usb-1.0.10.tgz", - "integrity": "sha512-CHgUI5kTc/QLMP8hODUHhge0D4vx+9UiAwIGiT0sTy/B2XpdX1U5rJt6JSISgr6ikRT7vxV9EVAFeYZqUnl1gQ==", - "dev": true, - "license": "MIT" + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT", + "optional": true }, - "node_modules/@types/web-bluetooth": { - "version": "0.0.20", - "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", - "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==", - "dev": true, - "license": "MIT" + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "license": "MIT", + "optional": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } }, - "node_modules/esbuild": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz", - "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", - "dev": true, + "node_modules/puppeteer": { + "version": "24.11.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.11.1.tgz", + "integrity": "sha512-QbccB/LgxX4tSZRzr9KQ1Jajdvu3n35Dlf/Otjz0QfR+6mDoZdMWLcWF94uQoC3OJerCyYm5hlU2Ru4nBoId2A==", "hasInstallScript": true, - "license": "MIT", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@puppeteer/browsers": "2.10.5", + "chromium-bidi": "5.1.0", + "cosmiconfig": "^9.0.0", + "devtools-protocol": "0.0.1464554", + "puppeteer-core": "24.11.1", + "typed-query-selector": "^2.12.0" + }, "bin": { - "esbuild": "bin/esbuild" + "puppeteer": "lib/cjs/puppeteer/node/cli.js" }, "engines": { "node": ">=18" + } + }, + "node_modules/puppeteer-core": { + "version": "24.11.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.11.1.tgz", + "integrity": "sha512-I0Gv3jWBRY9E3NTBElp7br7Gaid5RbFTxCRRMHym1kCf0ompO0Pel4REGsGDwMWkg3uwFzIH7t7qXs3T4DKRWA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@puppeteer/browsers": "2.10.5", + "chromium-bidi": "5.1.0", + "debug": "^4.4.1", + "devtools-protocol": "0.0.1464554", + "typed-query-selector": "^2.12.0", + "ws": "^8.18.2" }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.24.0", - "@esbuild/android-arm": "0.24.0", - "@esbuild/android-arm64": "0.24.0", - "@esbuild/android-x64": "0.24.0", - "@esbuild/darwin-arm64": "0.24.0", - "@esbuild/darwin-x64": "0.24.0", - "@esbuild/freebsd-arm64": "0.24.0", - "@esbuild/freebsd-x64": "0.24.0", - "@esbuild/linux-arm": "0.24.0", - "@esbuild/linux-arm64": "0.24.0", - "@esbuild/linux-ia32": "0.24.0", - "@esbuild/linux-loong64": "0.24.0", - "@esbuild/linux-mips64el": "0.24.0", - "@esbuild/linux-ppc64": "0.24.0", - "@esbuild/linux-riscv64": "0.24.0", - "@esbuild/linux-s390x": "0.24.0", - "@esbuild/linux-x64": "0.24.0", - "@esbuild/netbsd-x64": "0.24.0", - "@esbuild/openbsd-arm64": "0.24.0", - "@esbuild/openbsd-x64": "0.24.0", - "@esbuild/sunos-x64": "0.24.0", - "@esbuild/win32-arm64": "0.24.0", - "@esbuild/win32-ia32": "0.24.0", - "@esbuild/win32-x64": "0.24.0" + "engines": { + "node": ">=18" } }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "license": "MIT", "optional": true, "engines": { - "node": ">=0.8.x" + "node": ">=0.10.0" } }, - "node_modules/nano-webgl-pow": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/nano-webgl-pow/-/nano-webgl-pow-1.1.1.tgz", - "integrity": "sha512-IKAg7qx2y4n9dnT7tYYypOun/aV+35SfRxJCVnc63GboWQ5/woVIVAZcdX5VfXM1mLYBzADvXxoWZ39G3iPOFA==", - "dev": true, - "license": "MIT" + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } }, "node_modules/rxjs": { "version": "7.8.1", @@ -223,9 +1553,9 @@ } }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "license": "ISC", "optional": true, "bin": { @@ -235,6 +1565,143 @@ "node": ">=10" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.5.tgz", + "integrity": "sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==", + "license": "MIT", + "optional": true, + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/streamx": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.1.tgz", + "integrity": "sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA==", + "license": "MIT", + "optional": true, + "dependencies": { + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar-fs": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.10.tgz", + "integrity": "sha512-C1SwlQGNLe/jPNqapK8epDsXME7CAJR5RL3GcE6KWx1d9OUByzoHVcbu1VPI8tevg9H8Alae0AApHHFGzrD5zA==", + "license": "MIT", + "optional": true, + "dependencies": { + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^4.0.1", + "bare-path": "^3.0.0" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "b4a": "^1.6.4" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -242,11 +1709,18 @@ "license": "0BSD", "optional": true }, + "node_modules/typed-query-selector": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", + "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==", + "license": "MIT", + "optional": true + }, "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", - "dev": true, + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -257,11 +1731,118 @@ } }, "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "dev": true, + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", + "devOptional": true, "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC", + "optional": true + }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "optional": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "license": "MIT", + "optional": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/zod": { + "version": "3.25.67", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", + "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==", + "license": "MIT", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index 93ae843..f11318a 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ ], "homepage": "https://zoso.dev", "bugs": "bug-libnemo@zoso.dev", - "license": "(GPL-3.0-or-later AND MIT)", + "license": "(GPL-3.0-or-later AND MIT AND ISC)", "author": "Chris Duncan ", "funding": { "type": "nano", @@ -42,32 +42,40 @@ "url": "git+https://zoso.dev/libnemo.git" }, "scripts": { - "build": "rm -rf dist && tsc && esbuild main.min=dist/main.js global.min=dist/global.js --outdir=dist --target=esnext --format=esm --platform=browser --bundle --sourcemap", - "test": "npm run build && esbuild test.min=test/main.mjs --outdir=dist --target=esnext --format=esm --platform=browser --bundle --sourcemap", - "test:node": "npm run build -- --platform=node && node --test --test-force-exit --env-file .env", + "build": "rm -rf {dist,types} && mkdir -p dist && tsc && mv types dist/types", + "build:browser": "npm run build && node esbuild-browser.mjs", + "build:node": "npm run build && node esbuild-node.mjs", + "publish": "npm test", + "test": "npm run build:browser", + "test:node": "npm run build:node && node --test --test-force-exit --env-file .env", "test:coverage": "npm run test:node -- --experimental-test-coverage", - "test:coverage:report": "npm run test:coverage -- --test-reporter=lcov --test-reporter-destination=coverage.info && genhtml coverage.info --output-directory test/coverage && rm coverage.info && xdg-open test/coverage/index.html", - "test:performance": "npm run build && esbuild perf.min=perf/main.mjs --outdir=dist --target=esnext --format=esm --platform=browser --bundle --sourcemap" + "test:coverage:report": "npm run test:coverage -- --test-reporter=lcov --test-reporter-destination=coverage.info && genhtml coverage.info --output-directory test/coverage && rm coverage.info && xdg-open test/coverage/index.html" }, "imports": { - "#*": "./*" + "#dist/*": "./dist/*", + "#src/*": "./src/*", + "#workers": "./src/lib/workers/index.js", + "#workers/*": "./src/lib/workers/*" }, "optionalDependencies": { - "@ledgerhq/hw-transport-web-ble": "^6.29.4", - "@ledgerhq/hw-transport-webhid": "^6.29.4", - "@ledgerhq/hw-transport-webusb": "^6.29.4" + "@ledgerhq/hw-transport-web-ble": "^6.29.7", + "@ledgerhq/hw-transport-webhid": "^6.30.3", + "@ledgerhq/hw-transport-webusb": "^6.29.7" }, "devDependencies": { - "@types/node": "^22.10.1", + "@types/node": "^24.0.4", "@types/w3c-web-hid": "^1.0.6", "@types/w3c-web-usb": "^1.0.10", - "@types/web-bluetooth": "^0.0.20", - "esbuild": "^0.24.0", - "nano-webgl-pow": "^1.1.1", - "typescript": "^5.6.3" + "@types/web-bluetooth": "^0.0.21", + "esbuild": "^0.25.5", + "typescript": "^5.8.3" }, "type": "module", "exports": "./dist/main.js", - "types": "dist/main.d.ts", - "unpkg": "dist/main.min.js" + "types": "dist/types/main.d.ts", + "unpkg": "dist/main.min.js", + "dependencies": { + "nano-pow": "^5.1.4", + "nano-webgl-pow": "^1.1.1" + } } diff --git a/perf/account.perf.js b/perf/account.perf.js deleted file mode 100644 index 0d7deef..0000000 --- a/perf/account.perf.js +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Chris Duncan -// SPDX-License-Identifier: GPL-3.0-or-later - -'use strict' - -import { assert, average, skip, suite, test } from '#GLOBALS.mjs' -import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js' -import { Bip44Wallet, Blake2bWallet } from '#dist/main.js' - -await suite('Account performance', async () => { - await test('Time to create 0x200 BIP-44 accounts', async () => { - const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const start = performance.now() - const accounts = await wallet.accounts(0, 0x1fff) - const end = performance.now() - console.log(`Total: ${end - start} ms`) - console.log(`Average: ${(end - start) / 0x2000} ms`) - assert.equals(accounts.length, 0x2000) - }) - - await test('Time to create 0x200 BLAKE2b accounts', async () => { - const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const start = performance.now() - const accounts = await wallet.accounts(0, 0x1fff) - const end = performance.now() - console.log(`Total: ${end - start} ms`) - console.log(`Average: ${(end - start) / 0x2000} ms`) - assert.equals(accounts.length, 0x2000) - }) - - await test('Time to create 1 BIP-44 account 0x20 times', async () => { - const times = [] - const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - for (let i = 0; i < 0x20; i++) { - const start = performance.now() - await wallet.accounts(i) - const end = performance.now() - times.push(end - start) - } - const { total, arithmetic, harmonic, geometric } = average(times) - console.log(`Total: ${total} ms`) - console.log(`Average: ${arithmetic} ms`) - console.log(`Harmonic: ${harmonic} ms`) - console.log(`Geometric: ${geometric} ms`) - }) - - await test('Average time to create 1 BLAKE2b account 0x20 times', async () => { - const times = [] - const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - for (let i = 0; i < 0x20; i++) { - const start = performance.now() - await wallet.accounts(i) - const end = performance.now() - times.push(end - start) - } - const { total, arithmetic, harmonic, geometric } = average(times) - console.log(`Total: ${total} ms`) - console.log(`Average: ${arithmetic} ms`) - console.log(`Harmonic: ${harmonic} ms`) - console.log(`Geometric: ${geometric} ms`) - }) -}) diff --git a/perf/block.perf.js b/perf/block.perf.js deleted file mode 100644 index 0fa1337..0000000 --- a/perf/block.perf.js +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Chris Duncan -// SPDX-License-Identifier: GPL-3.0-or-later - -'use strict' - -import { assert, average, skip, suite, test } from '#GLOBALS.mjs' -import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js' -import { SendBlock } from '#dist/main.js' -import 'nano-webgl-pow' - -await suite('Block performance', async () => { - const COUNT = 0x10 - - await test(`Customized PoW: Time to calculate proof-of-work for a send block ${COUNT} times`, async () => { - const times = [] - const block = new SendBlock( - NANO_TEST_VECTORS.SEND_BLOCK.account, - NANO_TEST_VECTORS.SEND_BLOCK.balance, - NANO_TEST_VECTORS.SEND_BLOCK.link, - '0', - NANO_TEST_VECTORS.SEND_BLOCK.representative, - NANO_TEST_VECTORS.SEND_BLOCK.previous - ) - for (let i = 0; i < COUNT; i++) { - const start = performance.now() - await block.pow() - const end = performance.now() - times.push(end - start) - console.log(`${block.work} (${end - start} ms)`) - } - const { total, arithmetic, harmonic, geometric } = average(times) - console.log(`Total: ${total} ms`) - console.log(`Average: ${arithmetic} ms`) - console.log(`Harmonic: ${harmonic} ms`) - console.log(`Geometric: ${geometric} ms`) - }) - - await test(`Original PoW module: Time to calculate proof-of-work for a send block ${COUNT} times`, async () => { - const times = [] - for (let i = 0; i < COUNT; i++) { - const start = performance.now() - const work = await new Promise(resolve => { - //@ts-expect-error - window.NanoWebglPow(NANO_TEST_VECTORS.SEND_BLOCK.previous, resolve, undefined, '0xFFFFFFF8') - }) - const end = performance.now() - times.push(end - start) - console.log(`${work} (${end - start} ms)`) - } - const { total, arithmetic, harmonic, geometric } = average(times) - console.log(`Total: ${total} ms`) - console.log(`Average: ${arithmetic} ms`) - console.log(`Harmonic: ${harmonic} ms`) - console.log(`Geometric: ${geometric} ms`) - }) -}) diff --git a/performance.html b/performance.html deleted file mode 100644 index 106863b..0000000 --- a/performance.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/src/global.ts b/src/global.ts deleted file mode 100644 index f7b61d6..0000000 --- a/src/global.ts +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Chris Duncan -// SPDX-License-Identifier: GPL-3.0-or-later - -import * as main from './main.js' -(globalThis as any).libnemo ??= main diff --git a/src/lib/account.ts b/src/lib/account.ts index 001208c..47fc69a 100644 --- a/src/lib/account.ts +++ b/src/lib/account.ts @@ -1,12 +1,12 @@ // SPDX-FileCopyrightText: 2024 Chris Duncan // SPDX-License-Identifier: GPL-3.0-or-later -import { Blake2b } from './blake2b.js' -import { ACCOUNT_KEY_LENGTH, ALPHABET, PREFIX, PREFIX_LEGACY } from './constants.js' -import { base32, bytes, hex } from './convert.js' -import { Rpc } from './rpc.js' -import { Safe } from './safe.js' -import { NanoNaCl } from './workers/nano-nacl.js' +import { Blake2b } from './blake2b' +import { ACCOUNT_KEY_LENGTH, ALPHABET, PREFIX, PREFIX_LEGACY } from './constants' +import { base32, bytes, hex } from './convert' +import { Rpc } from './rpc' +import { Safe } from './safe' +import { NanoNaCl } from '#workers' /** * Represents a single Nano address and the associated public key. To include the @@ -68,6 +68,21 @@ export class Account { Account.#isInternal = false } + /** + * Removes encrypted secrets in storage and releases variable references to + * allow garbage collection. + */ + destroy (): void { + this.#s.destroy(this.#pub) + this.#prv = null + this.#i = undefined + this.#f = undefined + this.#b = undefined + this.#r = undefined + this.#rep = undefined + this.#w = undefined + } + /** * Instantiates an Account object from its Nano address. * @@ -115,27 +130,6 @@ export class Account { return account } - /** - * Instantiates an Account object from its public and private - * keys. - * - * WARNING: The validity of the keys is checked, but they are assumed to have - * been precalculated. Whether they are an actual matching pair is NOT checked! - * If unsure, use `Account.fromPrivateKey(key)` instead. - * - * @param {string} publicKey - Public key of the account - * @param {string} privateKey - Private key of the account - * @param {number} [index] - Account number used when deriving the key - * @returns {Account} The instantiated Account object - */ - static fromKeypair (privateKey: string, publicKey: string, index?: number): Account { - Account.#isInternal = true - Account.#validateKey(privateKey) - const account = Account.fromPublicKey(publicKey, index) - account.#prv = privateKey.toUpperCase() - return account - } - async lock (password: string): Promise async lock (key: CryptoKey): Promise async lock (passkey: string | CryptoKey): Promise { @@ -211,10 +205,10 @@ export class Account { throw new TypeError('RPC must be a valid node') } const data = { - "account": this.address, - "receivable": "true", - "representative": "true", - "weight": "true" + account: this.address, + receivable: true, + representative: true, + weight: true } const { balance, frontier, receivable, representative, weight } = await rpc.call('account_info', data) if (frontier == null) { @@ -260,3 +254,25 @@ export class Account { } } } + +export class AccountList extends Object { + [index: number]: Account + + get length (): number { + return Object.keys(this).length + } + + *[Symbol.iterator] (): Iterator { + const indexes = Object.keys(this) + .map(key => parseInt(key)) + .filter(index => Number.isFinite(index)) + .sort((a, b) => a - b) + for (const i of indexes) { + yield this[i] + } + } + + static { + Object.defineProperty(this, 'length', { enumerable: false }) + } +} diff --git a/src/lib/bip39-mnemonic.ts b/src/lib/bip39-mnemonic.ts index 1d9fe2d..b9d9463 100644 --- a/src/lib/bip39-mnemonic.ts +++ b/src/lib/bip39-mnemonic.ts @@ -1,10 +1,10 @@ // SPDX-FileCopyrightText: 2024 Chris Duncan // SPDX-License-Identifier: GPL-3.0-or-later -import { Bip39Words } from './bip39-wordlist.js' -import { bin, bytes, dec, utf8 } from './convert.js' -import { BIP39_ITERATIONS } from './constants.js' -import { Entropy } from './entropy.js' +import { Bip39Words } from './bip39-wordlist' +import { BIP39_ITERATIONS } from './constants' +import { bin, bytes, dec, utf8 } from './convert' +import { Entropy } from './entropy' const { subtle } = globalThis.crypto @@ -20,7 +20,7 @@ export class Bip39Mnemonic { constructor () { if (!Bip39Mnemonic.#isInternal) { - throw new Error(`Bip39Mnemonic cannot be instantiated directly. Use 'await Bip39Mnemonic.fromPhrase()' or 'await Bip39Mnemonic.fromEntropy() instead.`) + throw new Error(`Bip39Mnemonic must be created with async methods 'fromPhrase()' or 'fromEntropy().`) } Bip39Mnemonic.#isInternal = false } @@ -143,24 +143,22 @@ export class Bip39Mnemonic { if (passphrase == null || typeof passphrase !== 'string') { passphrase = '' } - passphrase = `mnemonic${passphrase.normalize('NFKD')}` - - const derivationAlgorithm: Pbkdf2Params = { - name: 'PBKDF2', - hash: 'SHA-512', - salt: utf8.toBytes(passphrase), - iterations: BIP39_ITERATIONS - } - const phraseKey = await subtle.importKey('raw', utf8.toBytes(this.phrase), 'PBKDF2', false, ['deriveBits', 'deriveKey']) + const keyData = utf8.toBytes(this.phrase) + const phraseKey = await subtle.importKey('raw', keyData, 'PBKDF2', false, ['deriveBits', 'deriveKey']) const derivedKeyType: HmacImportParams = { name: 'HMAC', hash: 'SHA-512', length: 512 } - const isSeedKeyExtractable: boolean = true - const seedKeyUsages: KeyUsage[] = ['sign'] - const seedKey = await subtle.deriveKey(derivationAlgorithm, phraseKey, derivedKeyType, isSeedKeyExtractable, seedKeyUsages) + passphrase = `mnemonic${passphrase.normalize('NFKD')}` + const algorithm: Pbkdf2Params = { + name: 'PBKDF2', + hash: 'SHA-512', + salt: utf8.toBytes(passphrase), + iterations: BIP39_ITERATIONS + } + const seedKey = await subtle.deriveKey(algorithm, phraseKey, derivedKeyType, true, ['sign']) const seedBuffer = await subtle.exportKey('raw', seedKey) const seedBytes = new Uint8Array(seedBuffer) const seed = bytes.toHex(seedBytes) diff --git a/src/lib/blake2b.ts b/src/lib/blake2b.ts index d80ef22..4631980 100644 --- a/src/lib/blake2b.ts +++ b/src/lib/blake2b.ts @@ -1,322 +1,266 @@ -// SPDX-FileCopyrightText: 2024 Chris Duncan -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: 2025 Chris Duncan +// SPDX-License-Identifier: GPL-3.0-or-later AND ISC /** * Implementation derived from blake2b@2.1.4. Copyright 2017 Emil Bay * (https://github.com/emilbayes/blake2b). See LICENSES/ISC.txt * -* Modified to eliminate dependencies, port to TypeScript, and embed in web -* workers. +* Modified to use BigUint64 values, eliminate dependencies, port to TypeScript, +* and embed in web workers. * * Original source commit: https://github.com/emilbayes/blake2b/blob/1f63e02e3f226642959506cdaa67c8819ff145cd/index.js */ +type UnknownNumber = number | unknown +type UnknownUint8Array = Uint8Array | unknown export class Blake2b { - static BYTES_MIN: number = 1 - static BYTES_MAX: number = 64 - static KEYBYTES_MIN: number = 16 - static KEYBYTES_MAX: number = 64 - static SALTBYTES: number = 16 - static PERSONALBYTES: number = 16 - - // Initialization Vector - static BLAKE2B_IV32: Uint32Array = new Uint32Array([ - 0xF3BCC908, 0x6A09E667, 0x84CAA73B, 0xBB67AE85, - 0xFE94F82B, 0x3C6EF372, 0x5F1D36F1, 0xA54FF53A, - 0xADE682D1, 0x510E527F, 0x2B3E6C1F, 0x9B05688C, - 0xFB41BD6B, 0x1F83D9AB, 0x137E2179, 0x5BE0CD19 - ]) - - static SIGMA8: number[] = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3, - 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4, - 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8, - 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13, - 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9, - 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11, - 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10, - 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5, - 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 - ] - - /** - * These are offsets into a uint64 buffer. - * Multiply them all by 2 to make them offsets into a uint32 buffer, - * because this is Javascript and we don't have uint64s - */ - static SIGMA82: Uint8Array = new Uint8Array(this.SIGMA8.map(x => x * 2)) - - // reusable parameter_block - static parameter_block: Uint8Array = new Uint8Array([ - 0, 0, 0, 0, // 0: outlen, keylen, fanout, depth - 0, 0, 0, 0, // 4: leaf length, sequential mode - 0, 0, 0, 0, // 8: node offset - 0, 0, 0, 0, // 12: node offset - 0, 0, 0, 0, // 16: node depth, inner length, rfu - 0, 0, 0, 0, // 20: rfu - 0, 0, 0, 0, // 24: rfu - 0, 0, 0, 0, // 28: rfu - 0, 0, 0, 0, // 32: salt - 0, 0, 0, 0, // 36: salt - 0, 0, 0, 0, // 40: salt - 0, 0, 0, 0, // 44: salt - 0, 0, 0, 0, // 48: personal - 0, 0, 0, 0, // 52: personal - 0, 0, 0, 0, // 56: personal - 0, 0, 0, 0 // 60: personal - ]) - - - static v: Uint32Array = new Uint32Array(32) - static m: Uint32Array = new Uint32Array(32) - - /** - * 64-bit unsigned addition - * Sets v[a,a+1] += v[b,b+1] - * v should be a Uint32Array - */ - static ADD64AA (v: Uint32Array, a: number, b: number): void { - var o0 = v[a] + v[b] - var o1 = v[a + 1] + v[b + 1] - if (o0 >= 0x100000000) { - o1++ - } - v[a] = o0 - v[a + 1] = o1 + static get OUTBYTES_MIN (): 1 { return 1 } + static get OUTBYTES_MAX (): 64 { return 64 } + static get KEYBYTES_MIN (): 1 { return 1 } + static get KEYBYTES_MAX (): 64 { return 64 } + static get SALTBYTES (): 16 { return 16 } + static get PERSONALBYTES (): 16 { return 16 } + static get IV (): bigint[] { + return [ + 0x6a09e667f3bcc908n, + 0xbb67ae8584caa73bn, + 0x3c6ef372fe94f82bn, + 0xa54ff53a5f1d36f1n, + 0x510e527fade682d1n, + 0x9b05688c2b3e6c1fn, + 0x1f83d9abfb41bd6bn, + 0x5be0cd19137e2179n + ] + } + static get SIGMA (): number[][] { + return [ + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], + [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3], + [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4], + [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8], + [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13], + [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9], + [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11], + [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10], + [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5], + [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0], + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], + [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3] + ] } - /** - * 64-bit unsigned addition - * Sets v[a,a+1] += b - * b0 is the low 32 bits of b, b1 represents the high 32 bits - */ - static ADD64AC (v: Uint32Array, a: number, b0: number, b1: number): void { - var o0 = v[a] + b0 - if (b0 < 0) { - o0 += 0x100000000 - } - var o1 = v[a + 1] + b1 - if (o0 >= 0x100000000) { - o1++ + static #toHex (buf: Uint8Array): string { + let str = '' + for (let i = 0; i < buf.length; i++) { + str += buf[i].toString(16).padStart(2, '0') } - v[a] = o0 - v[a + 1] = o1 + return str } - // Little-endian byte access - static B2B_GET32 (arr: Uint8Array, i: number): number { - return (arr[i] ^ - (arr[i + 1] << 8) ^ - (arr[i + 2] << 16) ^ - (arr[i + 3] << 24)) + #G (r: number, i: number, a: number, b: number, c: number, d: number): void { + this.#v[a] += this.#v[b] + this.#m[Blake2b.SIGMA[r][2 * i + 0]] + this.#v[d] ^= this.#v[a] + this.#v[d] = (this.#v[d] >> 32n) | (this.#v[d] << 32n) + this.#v[c] += this.#v[d] + this.#v[b] ^= this.#v[c] + this.#v[b] = (this.#v[b] >> 24n) | (this.#v[b] << 40n) + this.#v[a] += this.#v[b] + this.#m[Blake2b.SIGMA[r][2 * i + 1]] + this.#v[d] ^= this.#v[a] + this.#v[d] = (this.#v[d] >> 16n) | (this.#v[d] << 48n) + this.#v[c] += this.#v[d] + this.#v[b] ^= this.#v[c] + this.#v[b] = (this.#v[b] >> 63n) | (this.#v[b] << 1n) } - /** - * G Mixing function - * The ROTRs are inlined for speed - */ - static B2B_G (a: number, b: number, c: number, d: number, ix: number, iy: number): void { - var x0 = Blake2b.m[ix] - var x1 = Blake2b.m[ix + 1] - var y0 = Blake2b.m[iy] - var y1 = Blake2b.m[iy + 1] - - Blake2b.ADD64AA(Blake2b.v, a, b) // v[a,a+1] += v[b,b+1] ... in JS we must store a uint64 as two uint32s - Blake2b.ADD64AC(Blake2b.v, a, x0, x1) // v[a, a+1] += x ... x0 is the low 32 bits of x, x1 is the high 32 bits - - // v[d,d+1] = (v[d,d+1] xor v[a,a+1]) rotated to the right by 32 bits - var xor0 = Blake2b.v[d] ^ Blake2b.v[a] - var xor1 = Blake2b.v[d + 1] ^ Blake2b.v[a + 1] - Blake2b.v[d] = xor1 - Blake2b.v[d + 1] = xor0 - - Blake2b.ADD64AA(Blake2b.v, c, d) - - // v[b,b+1] = (v[b,b+1] xor v[c,c+1]) rotated right by 24 bits - xor0 = Blake2b.v[b] ^ Blake2b.v[c] - xor1 = Blake2b.v[b + 1] ^ Blake2b.v[c + 1] - Blake2b.v[b] = (xor0 >>> 24) ^ (xor1 << 8) - Blake2b.v[b + 1] = (xor1 >>> 24) ^ (xor0 << 8) - - Blake2b.ADD64AA(Blake2b.v, a, b) - Blake2b.ADD64AC(Blake2b.v, a, y0, y1) - - // v[d,d+1] = (v[d,d+1] xor v[a,a+1]) rotated right by 16 bits - xor0 = Blake2b.v[d] ^ Blake2b.v[a] - xor1 = Blake2b.v[d + 1] ^ Blake2b.v[a + 1] - Blake2b.v[d] = (xor0 >>> 16) ^ (xor1 << 16) - Blake2b.v[d + 1] = (xor1 >>> 16) ^ (xor0 << 16) - - Blake2b.ADD64AA(Blake2b.v, c, d) - - // v[b,b+1] = (v[b,b+1] xor v[c,c+1]) rotated right by 63 bits - xor0 = Blake2b.v[b] ^ Blake2b.v[c] - xor1 = Blake2b.v[b + 1] ^ Blake2b.v[c + 1] - Blake2b.v[b] = (xor1 >>> 31) ^ (xor0 << 1) - Blake2b.v[b + 1] = (xor0 >>> 31) ^ (xor1 << 1) + #ROUND (r: number): void { + this.#G(r, 0, 0, 4, 8, 12) + this.#G(r, 1, 1, 5, 9, 13) + this.#G(r, 2, 2, 6, 10, 14) + this.#G(r, 3, 3, 7, 11, 15) + this.#G(r, 4, 0, 5, 10, 15) + this.#G(r, 5, 1, 6, 11, 12) + this.#G(r, 6, 2, 7, 8, 13) + this.#G(r, 7, 3, 4, 9, 14) } /** - * Compression function. 'last' flag indicates last block. - * Note we're representing 16 uint64s as 32 uint32s + * Compression function called during three phases: on keying (if applicable), + * each time the input buffer is filled, and when finalizing message block. + * + * @param {boolean} final - If true, invert bits of v[14] */ - static blake2bCompress (ctx: any, last: boolean): void { - let i = 0 + #blake2bCompress (final: boolean): void { // init work variables - for (i = 0; i < 16; i++) { - Blake2b.v[i] = ctx.h[i] - Blake2b.v[i + 16] = Blake2b.BLAKE2B_IV32[i] + for (let i = 0; i < 8; i++) { + this.#v[i] = this.#h[i] + this.#v[i + 8] = Blake2b.IV[i] } - // low 64 bits of offset - Blake2b.v[24] = Blake2b.v[24] ^ ctx.t - Blake2b.v[25] = Blake2b.v[25] ^ (ctx.t / 0x100000000) - // high 64 bits not supported, offset may not be higher than 2**53-1 + // lo 64 bits of counter + this.#v[12] ^= this.#t & ((1n << 64n) - 1n) + + // hi 64 bits of counter + this.#v[13] ^= this.#t & ((1n << 128n) - (1n << 64n)) - // last block flag set ? - if (last) { - Blake2b.v[28] = ~Blake2b.v[28] - Blake2b.v[29] = ~Blake2b.v[29] + // is last block flag set? + if (final) { + this.#v[14] = ~this.#v[14] } - // get little-endian words - for (i = 0; i < 32; i++) { - Blake2b.m[i] = Blake2b.B2B_GET32(ctx.b, 4 * i) + // copy input buffer to message block + const buf = new DataView(this.#b.buffer) + for (let i = 0; i < 16; i++) { + this.#m[i] = buf.getBigUint64(i * 8, true) } // twelve rounds of mixing - for (i = 0; i < 12; i++) { - Blake2b.B2B_G(0, 8, 16, 24, Blake2b.SIGMA82[i * 16 + 0], Blake2b.SIGMA82[i * 16 + 1]) - Blake2b.B2B_G(2, 10, 18, 26, Blake2b.SIGMA82[i * 16 + 2], Blake2b.SIGMA82[i * 16 + 3]) - Blake2b.B2B_G(4, 12, 20, 28, Blake2b.SIGMA82[i * 16 + 4], Blake2b.SIGMA82[i * 16 + 5]) - Blake2b.B2B_G(6, 14, 22, 30, Blake2b.SIGMA82[i * 16 + 6], Blake2b.SIGMA82[i * 16 + 7]) - Blake2b.B2B_G(0, 10, 20, 30, Blake2b.SIGMA82[i * 16 + 8], Blake2b.SIGMA82[i * 16 + 9]) - Blake2b.B2B_G(2, 12, 22, 24, Blake2b.SIGMA82[i * 16 + 10], Blake2b.SIGMA82[i * 16 + 11]) - Blake2b.B2B_G(4, 14, 16, 26, Blake2b.SIGMA82[i * 16 + 12], Blake2b.SIGMA82[i * 16 + 13]) - Blake2b.B2B_G(6, 8, 18, 28, Blake2b.SIGMA82[i * 16 + 14], Blake2b.SIGMA82[i * 16 + 15]) + for (let i = 0; i < 12; i++) { + this.#ROUND(i) } - for (i = 0; i < 16; i++) { - ctx.h[i] = ctx.h[i] ^ Blake2b.v[i] ^ Blake2b.v[i + 16] + // set new chain value + for (let i = 0; i < 8; i++) { + this.#h[i] ^= this.#v[i] ^ this.#v[i + 8] } } /** - * Updates a BLAKE2b streaming hash - * Requires hash context and Uint8Array (byte array) + * Update the BLAKE2b streaming hash with additional input. When the 128-byte + * input buffer is full, compress and start refilling. */ - static blake2bUpdate (ctx: any, input: Uint8Array): void { - for (var i = 0; i < input.length; i++) { - if (ctx.c === 128) { // buffer full ? - ctx.t += ctx.c // add counters - Blake2b.blake2bCompress(ctx, false) // compress (not last) - ctx.c = 0 // counter to zero + #blake2bUpdate (input: Uint8Array): void { + for (let i = 0; i < input.length; i++) { + if (this.#c === this.#b.byteLength) { // is buffer full? + this.#t += BigInt(this.#b.byteLength) // increment total byte counter + this.#c = 0 // reset buffer counter to zero + this.#blake2bCompress(false) // compress (not final) } - ctx.b[ctx.c++] = input[i] + this.#b[this.#c++] = input[i] } } /** - * Completes a BLAKE2b streaming hash - * Returns a Uint8Array containing the message digest + * Completes a BLAKE2b streaming hash. + * + * @param {Uint8Array} out - Buffer to store the final output */ - static blake2bFinal (ctx: any, out: Uint8Array): Uint8Array { - ctx.t += ctx.c // mark last block offset - - while (ctx.c < 128) { // fill up with zeros - ctx.b[ctx.c++] = 0 - } - Blake2b.blake2bCompress(ctx, true) // final block flag = 1 - - for (var i = 0; i < ctx.outlen; i++) { - out[i] = ctx.h[i >> 2] >> (8 * (i & 3)) + #blake2bFinal (out: Uint8Array): void { + this.#t += BigInt(this.#c) // add final message block size to total bytes + this.#b.fill(0, this.#c) // pad final block with zeros + this.#blake2bCompress(true) // set final block flag and compress + const data = new DataView(this.#h.buffer) + for (let i = 0; i < this.#outlen; i++) { + out[i] = data.getUint8(i) } - return out - } - - static hexSlice (buf: Uint8Array): string { - let str = '' - for (let i = 0; i < buf.length; i++) str += Blake2b.toHex(buf[i]) - return str } - static toHex (n: number): string { - if (typeof n !== 'number') - throw new TypeError(`expected number to convert to hex; received ${typeof n}`) - if (n < 0 || n > 255) - throw new RangeError(`expected byte value 0-255; received ${n}`) - return n.toString(16).padStart(2, '0') - } - - b: Uint8Array - h: Uint32Array - t: number - c: number - outlen: number + #parameter_block: Uint8Array = new Uint8Array([ + 0, 0, 0, 0, // 0: outlen, keylen, fanout, depth + 0, 0, 0, 0, // 4: leaf length (0 for sequential mode) + 0, 0, 0, 0, // 8: node offset + 0, 0, 0, 0, // 12: node offset + 0, 0, 0, 0, // 16: node depth, inner length, rfu + 0, 0, 0, 0, // 20: rfu + 0, 0, 0, 0, // 24: rfu + 0, 0, 0, 0, // 28: rfu + 0, 0, 0, 0, // 32: salt + 0, 0, 0, 0, // 36: salt + 0, 0, 0, 0, // 40: salt + 0, 0, 0, 0, // 44: salt + 0, 0, 0, 0, // 48: personal + 0, 0, 0, 0, // 52: personal + 0, 0, 0, 0, // 56: personal + 0, 0, 0, 0 // 60: personal + ]) + #parameter_view: DataView = new DataView(this.#parameter_block.buffer) + /** Byte buffer which is compressed when full */ + #b: Uint8Array = new Uint8Array(128) + /** Hash chain value */ + #h: BigUint64Array = new BigUint64Array(8) + /** Total input byte count (BLAKE2b supports 2¹²⁸-1) */ + #t: bigint = 0n + /** Pointer to current element within input buffer */ + #c: number = 0 + /** State vector */ + #v: BigUint64Array = new BigUint64Array(16) + /** Message block */ + #m: BigUint64Array = new BigUint64Array(16) + /** User-requested output length */ + #outlen: number /** - * Creates a BLAKE2b hashing context - * Requires an output length between 1 and 64 bytes - * Takes an optional Uint8Array key + * Creates a BLAKE2b hashing context. + * + * @param {number} length - Output length between 1-64 bytes + * @param {Uint8Array} [key] - (_optional_) Used for keyed hashing (MAC and PRF) + * @param {Uint8Array} [salt] - (_optional_) Used to simplify randomized hashing for digital signatures + * @param {Uint8Array} [personal] - (_optional_) Arbitrary user-specified value */ - constructor (outlen: number, key?: Uint8Array, salt?: Uint8Array, personal?: Uint8Array, noAssert?: boolean) { - if (noAssert !== true) { - if (outlen < Blake2b.BYTES_MIN) throw new RangeError(`expected outlen >= ${Blake2b.BYTES_MIN}; actual ${outlen}`) - if (outlen > Blake2b.BYTES_MAX) throw new RangeError(`expectd outlen <= ${Blake2b.BYTES_MAX}; actual ${outlen}`) - if (key != null) { - if (!(key instanceof Uint8Array)) throw new TypeError(`key must be Uint8Array or Buffer`) - if (key.length < Blake2b.KEYBYTES_MIN) throw new RangeError(`expected key >= ${Blake2b.KEYBYTES_MIN}; actual ${key.length}`) - if (key.length > Blake2b.KEYBYTES_MAX) throw new RangeError(`expected key <= ${Blake2b.KEYBYTES_MAX}; actual ${key.length}`) + constructor (length: UnknownNumber, key?: UnknownUint8Array, salt?: UnknownUint8Array, personal?: UnknownUint8Array) { + if (length == null) { + throw new TypeError(`length is required`) + } + if (typeof length !== 'number') { + throw new TypeError(`length must be number`) + } + if (length < Blake2b.OUTBYTES_MIN || length > Blake2b.OUTBYTES_MAX) { + throw new RangeError(`length must be ${Blake2b.OUTBYTES_MIN}-${Blake2b.OUTBYTES_MAX} bytes`) + } + if (key != null) { + if (!(key instanceof Uint8Array)) { + throw new TypeError(`key must be Uint8Array or Buffer`) + } + if (key.length < Blake2b.KEYBYTES_MIN || key.length > Blake2b.KEYBYTES_MAX) { + throw new RangeError(`key must be ${Blake2b.KEYBYTES_MIN}-${Blake2b.KEYBYTES_MAX} bytes`) + } + } + if (salt != null) { + if (!(salt instanceof Uint8Array)) { + throw new TypeError(`salt must be Uint8Array or Buffer`) + } + if (salt.length !== Blake2b.SALTBYTES) { + throw new RangeError(`salt must be ${Blake2b.SALTBYTES} bytes`) } - if (salt != null) { - if (!(salt instanceof Uint8Array)) throw new TypeError(`salt must be Uint8Array or Buffer`) - if (salt.length !== Blake2b.SALTBYTES) throw new RangeError(`expected salt ${Blake2b.SALTBYTES} bytes; actual ${salt.length} bytes`) + } + if (personal != null) { + if (!(personal instanceof Uint8Array)) { + throw new TypeError(`personal must be Uint8Array or Buffer`) } - if (personal != null) { - if (!(personal instanceof Uint8Array)) throw new TypeError(`personal must be Uint8Array or Buffer`) - if (personal.length !== Blake2b.PERSONALBYTES) throw new RangeError(`expected personal ${Blake2b.PERSONALBYTES} bytes; actual ${personal.length} bytes`) + if (personal.length !== Blake2b.PERSONALBYTES) { + throw new RangeError(`personal must be ${Blake2b.PERSONALBYTES} bytes`) } } - this.b = new Uint8Array(128) - this.h = new Uint32Array(16) - this.t = 0 // input count - this.c = 0 // pointer within buffer - this.outlen = outlen // output length in bytes + this.#outlen = length // output length in bytes - // zero out parameter_block before usage - Blake2b.parameter_block.fill(0) // state, 'param block' + this.#parameter_block[0] = length + this.#parameter_block[1] = key?.length ?? 0 + this.#parameter_block[2] = 1 // fanout + this.#parameter_block[3] = 1 // depth - Blake2b.parameter_block[0] = outlen - if (key) Blake2b.parameter_block[1] = key.length - Blake2b.parameter_block[2] = 1 // fanout - Blake2b.parameter_block[3] = 1 // depth - - if (salt) Blake2b.parameter_block.set(salt, 32) - if (personal) Blake2b.parameter_block.set(personal, 48) + if (salt) this.#parameter_block.set(salt, 32) + if (personal) this.#parameter_block.set(personal, 48) // initialize hash state - for (var i = 0; i < 16; i++) { - this.h[i] = Blake2b.BLAKE2B_IV32[i] ^ Blake2b.B2B_GET32(Blake2b.parameter_block, i * 4) + for (let i = 0; i < 8; i++) { + this.#h[i] = Blake2b.IV[i] ^ this.#parameter_view.getBigUint64(i * 8, true) } // key the hash, if applicable if (key) { - Blake2b.blake2bUpdate(this, key) - // at the end - this.c = 128 + this.#blake2bUpdate(key) + // force input buffer to reset for first block of actual message + this.#c = 128 } } update (input: Uint8Array): Blake2b { - if (!(input instanceof Uint8Array)) + if (!(input instanceof Uint8Array)) { throw new TypeError(`input must be Uint8Array or Buffer`) - Blake2b.blake2bUpdate(this, input) + } + this.#blake2bUpdate(input) return this } @@ -324,12 +268,13 @@ export class Blake2b { digest (out: 'hex'): string digest (out: 'binary' | Uint8Array): Uint8Array digest (out?: 'binary' | 'hex' | Uint8Array): string | Uint8Array { - const buf = (!out || out === 'binary' || out === 'hex') ? new Uint8Array(this.outlen) : out + const buf = (!out || out === 'binary' || out === 'hex') ? new Uint8Array(this.#outlen) : out if (!(buf instanceof Uint8Array)) throw new TypeError(`out must be "binary", "hex", Uint8Array, or Buffer`) - if (buf.length < this.outlen) throw new RangeError(`out must have at least outlen bytes of space`) - Blake2b.blake2bFinal(this, buf) - if (out === 'hex') return Blake2b.hexSlice(buf) as string - return buf + if (buf.length < this.#outlen) throw new RangeError(`out must have at least outlen bytes of space`) + this.#blake2bFinal(buf) + return (out === 'hex') + ? Blake2b.#toHex(buf) + : buf } } diff --git a/src/lib/block.ts b/src/lib/block.ts index da23d56..4976f82 100644 --- a/src/lib/block.ts +++ b/src/lib/block.ts @@ -1,14 +1,14 @@ // SPDX-FileCopyrightText: 2024 Chris Duncan // SPDX-License-Identifier: GPL-3.0-or-later -import { BURN_ADDRESS, PREAMBLE, THRESHOLD_RECEIVE, THRESHOLD_SEND } from './constants.js' -import { Account } from './account.js' -import { Blake2b } from './blake2b.js' -import { dec, hex } from './convert.js' -import { NanoNaCl } from './workers/nano-nacl.js' -import { Pool } from './pool.js' -import { Rpc } from './rpc.js' -import { Pow } from './workers.js' +import { NanoPow } from 'nano-pow' +import { Account } from './account' +import { Blake2b } from './blake2b' +import { BURN_ADDRESS, PREAMBLE, DIFFICULTY_RECEIVE, DIFFICULTY_SEND } from './constants' +import { dec, hex } from './convert' +import { Pool } from './pool' +import { Rpc } from './rpc' +import { NanoNaCl, NanoNaClWorker } from '#workers' /** * Represents a block as defined by the Nano cryptocurrency protocol. The Block @@ -16,7 +16,7 @@ import { Pow } from './workers.js' * of three derived classes: SendBlock, ReceiveBlock, ChangeBlock. */ abstract class Block { - static #pool: Pool = new Pool(Pow) + static #pool: Pool account: Account type: string = 'state' abstract subtype: 'send' | 'receive' | 'change' @@ -38,32 +38,15 @@ abstract class Block { } else { throw new TypeError('Invalid account') } + Block.#pool ??= new Pool(NanoNaClWorker) } /** - * Converts the block to JSON format as expected by the `process` RPC. - * - * @returns {string} JSON representation of the block - */ - json (): { [key: string]: string } { - return { - "type": this.type, - "account": this.account.address, - "previous": this.previous, - "representative": this.representative.address, - "balance": this.balance.toString(), - "link": this.link, - "signature": this.signature ?? '', - "work": this.work ?? '' - } - } - - /** - * Hashes the block using Blake2b. + * Calculates the block hash using Blake2b. * * @returns {Promise} Block data hashed to a byte array */ - async hash (): Promise { + get hash (): string { const data = [ PREAMBLE, this.account.publicKey, @@ -78,19 +61,37 @@ abstract class Block { } /** - * Calculates proof-of-work using a pool of WebGL workers. + * Converts the block to JSON format as expected by the `process` RPC. + * + * @returns {string} JSON representation of the block + */ + toJSON (): { [key: string]: string } { + return { + "type": this.type, + "account": this.account.address, + "previous": this.previous, + "representative": this.representative.address, + "balance": this.balance.toString(), + "link": this.link, + "signature": this.signature ?? '', + "work": this.work ?? '' + } + } + + /** + * Calculates proof-of-work using a pool of Web Workers. * * A successful response sets the `work` property. */ async pow (): Promise { - const data = { - "hash": this.previous, - "threshold": (this instanceof SendBlock || this instanceof ChangeBlock) - ? THRESHOLD_SEND - : THRESHOLD_RECEIVE + const difficulty: bigint = (this instanceof SendBlock || this instanceof ChangeBlock) + ? DIFFICULTY_SEND + : DIFFICULTY_RECEIVE + const result = await NanoPow.work_generate(this.previous, { difficulty }) + if ('error' in result) { + throw new Error('Failed to generate work', { cause: result.error }) } - const [{ work }] = await Block.#pool.assign([data]) - this.work = work + this.work = result.work } /** @@ -118,7 +119,7 @@ abstract class Block { async sign (input?: number | string, block?: { [key: string]: string }): Promise { if (typeof input === 'number') { const index = input - const { Ledger } = await import('./ledger.js') + const { Ledger } = await import('./ledger') const ledger = await Ledger.init() await ledger.open() if (block) { @@ -129,7 +130,7 @@ abstract class Block { } } const result = await ledger.sign(index, this as SendBlock | ReceiveBlock | ChangeBlock) - if (result.status !== 'OK') { + if (result.status !== 'OK' || result.signature == null) { throw new Error(result.status) } this.signature = result.signature @@ -140,13 +141,14 @@ abstract class Block { } const account = await Account.fromPrivateKey(key) try { - const signature = NanoNaCl.detached( - hex.toBytes(await this.hash()), - hex.toBytes(`${account.privateKey}`) - ) - this.signature = signature + const result = (await Block.#pool.assign({ + method: 'detached', + msg: hex.toArray(this.hash), + secretKey: hex.toArray(`${account.privateKey}`) + }))[0] + this.signature = result.signature } catch (err) { - throw new Error(`Failed to sign block with key ${key}: ${err}`) + throw new Error(`Failed to sign block`, { cause: err }) } } } @@ -170,7 +172,7 @@ abstract class Block { const data = { "subtype": this.subtype, "json_block": "true", - "block": this.json() + "block": this.toJSON() } const res = await rpc.call('process', data) if (res.hash == null) { @@ -191,19 +193,8 @@ abstract class Block { if (!key) { throw new Error('Provide a key for block signature verification.') } - const data = [ - PREAMBLE, - this.account.publicKey, - this.previous, - this.representative.publicKey, - dec.toHex(this.balance, 32), - this.link - ] - const hash = new Blake2b(32) - data.forEach(str => hash.update(hex.toBytes(str))) - const blockHash = hash.digest('hex').toUpperCase() return NanoNaCl.verify( - hex.toBytes(blockHash), + hex.toBytes(this.hash), hex.toBytes(this.signature ?? ''), hex.toBytes(key) ) @@ -224,10 +215,20 @@ export class SendBlock extends Block { signature?: string work?: string - constructor (sender: Account | string, balance: string, recipient: string, amount: string, representative: string, frontier: string, work?: string) { + constructor ( + sender: Account | string, + balance: string, + recipient: string, + amount: string, + representative: Account | string, + frontier: string, + work?: string + ) { + if (typeof sender === 'string') sender = Account.fromAddress(sender) + if (typeof representative === 'string') representative = Account.fromAddress(representative) super(sender) this.previous = frontier - this.representative = Account.fromAddress(representative) + this.representative = representative this.link = Account.fromAddress(recipient).publicKey this.work = work ?? '' @@ -253,10 +254,20 @@ export class ReceiveBlock extends Block { signature?: string work?: string - constructor (recipient: string, balance: string, origin: string, amount: string, representative: string, frontier?: string, work?: string) { + constructor ( + recipient: Account | string, + balance: string, + origin: string, + amount: string, + representative: Account | string, + frontier?: string, + work?: string + ) { + if (typeof recipient === 'string') recipient = Account.fromAddress(recipient) + if (typeof representative === 'string') representative = Account.fromAddress(representative) super(recipient) - this.previous = frontier ?? Account.fromAddress(recipient).publicKey - this.representative = Account.fromAddress(representative) + this.previous = frontier ?? recipient.publicKey + this.representative = representative this.link = origin this.work = work ?? '' @@ -283,10 +294,18 @@ export class ChangeBlock extends Block { signature?: string work?: string - constructor (account: string, balance: string, representative: string, frontier: string, work?: string) { + constructor ( + account: Account | string, + balance: string, + representative: Account | string, + frontier: string, + work?: string + ) { + if (typeof account === 'string') account = Account.fromAddress(account) + if (typeof representative === 'string') representative = Account.fromAddress(representative) super(account) this.previous = frontier - this.representative = Account.fromAddress(representative) + this.representative = representative this.balance = BigInt(balance) this.work = work ?? '' diff --git a/src/lib/constants.ts b/src/lib/constants.ts index a888c88..b19fbea 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -16,8 +16,8 @@ export const PREFIX_LEGACY = 'xrb_' export const SEED_LENGTH_BIP44 = 128 export const SEED_LENGTH_BLAKE2B = 64 export const SLIP10_ED25519 = 'ed25519 seed' -export const THRESHOLD_RECEIVE = 0xfffffe00 -export const THRESHOLD_SEND = 0xfffffff8 +export const DIFFICULTY_RECEIVE = 0xfffffe0000000000n +export const DIFFICULTY_SEND = 0xfffffff800000000n export const XNO = 'Ӿ' export const LEDGER_STATUS_CODES: { [key: number]: string } = Object.freeze({ diff --git a/src/lib/convert.ts b/src/lib/convert.ts index 08fe685..d5801c9 100644 --- a/src/lib/convert.ts +++ b/src/lib/convert.ts @@ -1,7 +1,10 @@ // SPDX-FileCopyrightText: 2024 Chris Duncan // SPDX-License-Identifier: GPL-3.0-or-later -import { ALPHABET } from "./constants.js" +import { ALPHABET } from './constants' + +const encoder = new TextEncoder() +const decoder = new TextDecoder() export const base32 = { /** @@ -53,7 +56,7 @@ export const bin = { * @param {string} bin - String to convert * @returns {Uint8Array} Byte array representation of the input string */ - toBytes (bin: string): Uint8Array { + toBytes (bin: string): Uint8Array { const bytes: number[] = [] while (bin.length > 0) { const bits = bin.substring(0, 8) @@ -196,7 +199,7 @@ export const bytes = { * @returns {string} UTF-8 encoded text string */ toUtf8 (bytes: Uint8Array): string { - return new TextDecoder().decode(bytes) + return decoder.decode(bytes) } } @@ -205,7 +208,7 @@ export const dec = { * Convert a decimal integer to a binary string. * * @param {bigint|number|string} decimal - Integer to convert - * @param {number} [padding=0] - Minimum length of the resulting string which will be padded as necessary with starting zeroes + * @param {number} [padding=0] - Minimum length of the resulting string padded as necessary with starting zeroes * @returns {string} Binary string representation of the input decimal */ toBin (decimal: bigint | number | string, padding: number = 0): string { @@ -224,7 +227,7 @@ export const dec = { * Convert a decimal integer to a Uint8Array of bytes. Fractional part is truncated. * * @param {bigint|number|string} decimal - Integer to convert - * @param {number} [padding=0] - Minimum length of the resulting array which will be padded as necessary with starting 0x00 bytes + * @param {number} [padding=0] - Minimum length of the resulting array padded as necessary with starting 0x00 bytes * @returns {Uint8Array} Byte array representation of the input decimal */ toBytes (decimal: bigint | number | string, padding: number = 0): Uint8Array { @@ -246,7 +249,7 @@ export const dec = { * Convert a decimal integer to a hexadecimal string. * * @param {(bigint|number|string)} decimal - Integer to convert - * @param {number} [padding=0] - Minimum length of the resulting string which will be padded as necessary with starting zeroes + * @param {number} [padding=0] - Minimum length of the resulting string padded as necessary with starting zeroes * @returns {string} Hexadecimal string representation of the input decimal */ toHex (decimal: bigint | number | string, padding: number = 0): string { @@ -265,6 +268,30 @@ export const dec = { } export const hex = { + /** + * Convert a hexadecimal string to an array of decimal byte values. + * + * @param {string} hex - Hexadecimal number string to convert + * @param {number}[padding=0] - Minimum length of the resulting array padded as necessary with starting 0 values + * @returns {number[]} Decimal array representation of the input value + */ + toArray (hex: string, padding: number = 0): number[] { + if (typeof hex !== 'string' || !/^[A-Fa-f0-9]+$/i.test(hex)) { + throw new TypeError('Invalid string when converting hex to array') + } + if (typeof padding !== 'number') { + throw new TypeError('Invalid padding when converting hex to array') + } + if (hex.length % 2 === 1) hex = `0${hex}` + const hexArray = hex.match(/.{2}/g) + if (hexArray == null) { + throw new RangeError('Invalid hex string when converting to array') + } + for (let i = hexArray.length; i < padding; i++) { + hexArray.unshift('0') + } + return hexArray.map(v => parseInt(v, 16)) + }, /** * Convert a hexadecimal string to a binary string. * @@ -278,23 +305,11 @@ export const hex = { * Convert a hexadecimal string to a Uint8Array of bytes. * * @param {string} hex - Hexadecimal number string to convert - * @param {number} [padding=0] - Minimum length of the resulting array which will be padded as necessary with starting 0x00 bytes + * @param {number} [padding=0] - Minimum length of the resulting array padded as necessary with starting 0x00 bytes * @returns {Uint8Array} Byte array representation of the input value */ - toBytes (hex: string, padding: number = 0): Uint8Array { - if (typeof padding !== 'number') { - throw new TypeError('Invalid padding when converting hex to bytes') - } - const hexArray = hex.match(/.{1,2}/g) - if (!/^[0-9a-f]+$/i.test(hex) || hexArray == null) { - console.warn('Invalid hex string when converting to bytes') - return new Uint8Array() - } else { - const bytes = Uint8Array.from(hexArray.map(byte => parseInt(byte, 16))) - const result = new Uint8Array(Math.max(padding, bytes.length)) - result.set(bytes.reverse()) - return result.reverse() - } + toBytes (hex: string, padding: number = 0): Uint8Array { + return new Uint8Array(this.toArray(hex, padding)) } } @@ -306,7 +321,7 @@ export const utf8 = { * @returns {Uint8Array} Byte array representation of the input string */ toBytes (utf8: string): Uint8Array { - return new TextEncoder().encode(utf8) + return encoder.encode(utf8) }, /** * Convert a string to a hexadecimal representation diff --git a/src/lib/entropy.ts b/src/lib/entropy.ts index 3fb5cba..39d0eff 100644 --- a/src/lib/entropy.ts +++ b/src/lib/entropy.ts @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2024 Chris Duncan // SPDX-License-Identifier: GPL-3.0-or-later -import { bytes, hex } from './convert.js' +import { bytes, hex } from './convert' const { crypto } = globalThis const MIN = 16 @@ -19,14 +19,14 @@ const MOD = 4 */ export class Entropy { static #isInternal: boolean = false - #bytes: Uint8Array + #bytes: Uint8Array get bits (): string { return bytes.toBin(this.#bytes) } get buffer (): ArrayBuffer { return this.#bytes.buffer } get bytes (): Uint8Array { return this.#bytes } get hex (): string { return bytes.toHex(this.#bytes) } - constructor (bytes: Uint8Array) { + constructor (bytes: Uint8Array) { if (!Entropy.#isInternal) { throw new Error(`Entropy cannot be instantiated directly. Use 'await Entropy.create()' instead.`) } @@ -75,8 +75,8 @@ export class Entropy { * Import existing entropy and validate it. * @param {Uint8Array} bytes - Byte array */ - static async import (bytes: Uint8Array): Promise - static async import (input: string | ArrayBuffer | Uint8Array): Promise { + static async import (bytes: Uint8Array): Promise + static async import (input: string | ArrayBuffer | Uint8Array): Promise { return new Promise((resolve, reject) => { if (typeof input === 'string') { if (input.length < MIN * 2 || input.length > MAX * 2) { @@ -104,6 +104,9 @@ export class Entropy { } if (input instanceof Uint8Array) { + if (!(input.buffer instanceof ArrayBuffer)) { + throw new TypeError(`Entropy imported bytes must be backed by an ArrayBuffer.`) + } if (input.length < MIN || input.length > MAX) { throw new Error(`Entropy must be ${MIN}-${MAX} bytes`) } diff --git a/src/lib/ledger.ts b/src/lib/ledger.ts index 43fadd1..06b2503 100644 --- a/src/lib/ledger.ts +++ b/src/lib/ledger.ts @@ -1,21 +1,48 @@ // SPDX-FileCopyrightText: 2024 Chris Duncan // SPDX-License-Identifier: GPL-3.0-or-later -/** -* Ledger ADPU commands: https://github.com/roosmaa/ledger-app-nano/blob/master/doc/nano.md -*/ +// Ledger ADPU commands: https://github.com/roosmaa/ledger-app-nano/blob/master/doc/nano.md import Transport from '@ledgerhq/hw-transport' import { default as TransportBLE } from '@ledgerhq/hw-transport-web-ble' import { default as TransportUSB } from '@ledgerhq/hw-transport-webusb' import { default as TransportHID } from '@ledgerhq/hw-transport-webhid' -import { BIP44_COIN_NANO, BIP44_PURPOSE, HARDENED_OFFSET, LEDGER_STATUS_CODES } from './constants.js' -import { bytes, dec, hex, utf8 } from './convert.js' -import { Rpc } from './rpc.js' -import { ChangeBlock, ReceiveBlock, SendBlock } from './block.js' +import { ChangeBlock, ReceiveBlock, SendBlock } from './block' +import { BIP44_COIN_NANO, BIP44_PURPOSE, HARDENED_OFFSET, LEDGER_STATUS_CODES } from './constants' +import { bytes, dec, hex, utf8 } from './convert' +import { Rpc } from './rpc' + +interface LedgerResponse { + status: string +} + +interface LedgerVersionResponse extends LedgerResponse { + name: string | null, + version: string | null +} + +interface LedgerAccountResponse extends LedgerResponse { + publicKey: string | null, + address: string | null +} + +interface LedgerSignResponse extends LedgerResponse { + signature: string | null, + hash?: string +} export class Ledger { static #isInternal: boolean = false + static #adpu = { + class: 0xa1, + bip32DerivationLevel: 0x03, + version: 0x01, + account: 0x02, + cacheBlock: 0x03, + signBlock: 0x04, + signNonce: 0x05, + paramUnused: 0x00 + } #status: 'DISCONNECTED' | 'LOCKED' | 'BUSY' | 'CONNECTED' = 'DISCONNECTED' get status () { return this.#status } openTimeout = 3000 @@ -100,7 +127,7 @@ export class Ledger { return this.status } - async onDisconnectUsb (e: USBConnectionEvent) { + async onDisconnectUsb (e: USBConnectionEvent): Promise { if (e.device?.manufacturerName === 'Ledger') { const { usb } = globalThis.navigator usb.removeEventListener('disconnect', this.onDisconnectUsb) @@ -121,10 +148,10 @@ export class Ledger { * * @returns Status of command */ - async open (): Promise<{ status: string }> { + async open (): Promise { const name = new TextEncoder().encode('Nano') const transport = await this.DynamicTransport.create(this.openTimeout, this.listenTimeout) - const response = await transport.send(0xe0, 0xd8, 0x00, 0x00, name as Buffer) + const response = await transport.send(0xe0, 0xd8, Ledger.#adpu.paramUnused, Ledger.#adpu.paramUnused, name as Buffer) .then(res => bytes.toDec(res)) .catch(err => err.statusCode) as number return new Promise(resolve => setTimeout(resolve, 1000, { status: LEDGER_STATUS_CODES[response] })) @@ -143,9 +170,9 @@ export class Ledger { * * @returns Status of command */ - async close (): Promise { + async close (): Promise { const transport = await this.DynamicTransport.create(this.openTimeout, this.listenTimeout) - const response = await transport.send(0xb0, 0xa7, 0x00, 0x00) + const response = await transport.send(0xb0, 0xa7, Ledger.#adpu.paramUnused, Ledger.#adpu.paramUnused) .then(res => bytes.toDec(res)) .catch(err => err.statusCode) as number return new Promise(resolve => setTimeout(resolve, 1000, { status: LEDGER_STATUS_CODES[response] })) @@ -159,9 +186,9 @@ export class Ledger { * * @returns Status, process name, and version */ - async version (): Promise<{ status: string, name: string | null, version: string | null }> { + async version (): Promise { const transport = await this.DynamicTransport.create(this.openTimeout, this.listenTimeout) - const response = await transport.send(0xb0, 0x01, 0x00, 0x00) + const response = await transport.send(0xb0, Ledger.#adpu.version, Ledger.#adpu.paramUnused, Ledger.#adpu.paramUnused) .catch(err => dec.toBytes(err.statusCode)) as Uint8Array await transport.close() @@ -186,17 +213,17 @@ export class Ledger { * * @returns Response object containing command status, public key, and address */ - async account (index: number = 0, show: boolean = false): Promise<{ status: string, publicKey: string | null, address: string | null }> { + async account (index: number = 0, show: boolean = false): Promise { if (typeof index !== 'number' || index < 0 || index >= HARDENED_OFFSET) { throw new TypeError('Invalid account index') } const purpose = dec.toBytes(BIP44_PURPOSE + HARDENED_OFFSET, 4) const coin = dec.toBytes(BIP44_COIN_NANO + HARDENED_OFFSET, 4) const account = dec.toBytes(index + HARDENED_OFFSET, 4) - const data = new Uint8Array([0x03, ...purpose, ...coin, ...account]) + const data = new Uint8Array([Ledger.#adpu.bip32DerivationLevel, ...purpose, ...coin, ...account]) const transport = await this.DynamicTransport.create(this.openTimeout, this.listenTimeout) - const response = await transport.send(0xa1, 0x02, show ? 0x01 : 0x00, 0x00, data as Buffer) + const response = await transport.send(Ledger.#adpu.class, Ledger.#adpu.account, show ? 0x01 : 0x00, Ledger.#adpu.paramUnused, data as Buffer) .catch(err => dec.toBytes(err.statusCode)) as Uint8Array await transport.close() @@ -225,7 +252,7 @@ export class Ledger { * @param {any} block - Block data to cache * @returns Status of command */ - async cacheBlock (index: number = 0, block: SendBlock | ReceiveBlock | ChangeBlock): Promise<{ status: string }> { + async cacheBlock (index: number = 0, block: SendBlock | ReceiveBlock | ChangeBlock): Promise { if (typeof index !== 'number' || index < 0 || index >= HARDENED_OFFSET) { throw new TypeError('Invalid account index') } @@ -244,10 +271,10 @@ export class Ledger { const representative = hex.toBytes(block.representative.publicKey) const balance = hex.toBytes(BigInt(block.balance).toString(16), 16) const signature = hex.toBytes(block.signature) - const data = new Uint8Array([0x03, ...purpose, ...coin, ...account, ...previous, ...link, ...representative, ...balance, ...signature]) + const data = new Uint8Array([Ledger.#adpu.bip32DerivationLevel, ...purpose, ...coin, ...account, ...previous, ...link, ...representative, ...balance, ...signature]) const transport = await this.DynamicTransport.create(this.openTimeout, this.listenTimeout) - const response = await transport.send(0xa1, 0x03, 0x00, 0x00, data as Buffer) + const response = await transport.send(Ledger.#adpu.class, Ledger.#adpu.cacheBlock, Ledger.#adpu.paramUnused, Ledger.#adpu.paramUnused, data as Buffer) .then(res => bytes.toDec(res)) .catch(err => err.statusCode) as number await transport.close() @@ -262,7 +289,7 @@ export class Ledger { * @param {object} block - Block data to sign * @returns {Promise} Status, signature, and block hash */ - async sign (index: number, block: SendBlock | ReceiveBlock | ChangeBlock): Promise<{ status: string, signature: string, hash: string }> + async sign (index: number, block: SendBlock | ReceiveBlock | ChangeBlock): Promise /** * Sign a nonce with the Ledger device. * @@ -270,8 +297,8 @@ export class Ledger { * @param {string} nonce - 128-bit string to sign * @returns {Promise} Status and signature */ - async sign (index: number, nonce: string): Promise<{ status: string, signature: string }> - async sign (index: number = 0, input: string | SendBlock | ReceiveBlock | ChangeBlock): Promise<{ status: string, signature: string | null, hash?: string | null }> { + async sign (index: number, nonce: string): Promise + async sign (index: number = 0, input: string | SendBlock | ReceiveBlock | ChangeBlock): Promise { if (typeof index !== 'number' || index < 0 || index >= HARDENED_OFFSET) { throw new TypeError('Invalid account index') } @@ -286,8 +313,8 @@ export class Ledger { if (nonce.length !== 16) { throw new RangeError('Nonce must be 16-byte string') } - const data = new Uint8Array([0x03, ...purpose, ...coin, ...account, ...nonce]) - const response = await transport.send(0xa1, 0x05, 0x00, 0x00, data as Buffer) + const data = new Uint8Array([Ledger.#adpu.bip32DerivationLevel, ...purpose, ...coin, ...account, ...nonce]) + const response = await transport.send(Ledger.#adpu.class, Ledger.#adpu.signNonce, Ledger.#adpu.paramUnused, Ledger.#adpu.paramUnused, data as Buffer) .catch(err => dec.toBytes(err.statusCode)) as Uint8Array await transport.close() @@ -307,15 +334,15 @@ export class Ledger { const link = hex.toBytes(input.link) const representative = hex.toBytes(input.representative.publicKey) const balance = hex.toBytes(BigInt(input.balance).toString(16), 16) - const data = new Uint8Array([0x03, ...purpose, ...coin, ...account, ...previous, ...link, ...representative, ...balance]) - const response = await transport.send(0xa1, 0x04, 0x00, 0x00, data as Buffer) + const data = new Uint8Array([Ledger.#adpu.bip32DerivationLevel, ...purpose, ...coin, ...account, ...previous, ...link, ...representative, ...balance]) + const response = await transport.send(Ledger.#adpu.class, Ledger.#adpu.signBlock, Ledger.#adpu.paramUnused, Ledger.#adpu.paramUnused, data as Buffer) .catch(err => dec.toBytes(err.statusCode)) as Uint8Array await transport.close() if (response.length === 2) { const statusCode = bytes.toDec(response) as number const status = LEDGER_STATUS_CODES[statusCode] ?? 'UNKNOWN_ERROR' - return { status, signature: null, hash: null } + return { status, signature: null } } const hash = bytes.toHex(response.slice(0, 32)) @@ -332,7 +359,7 @@ export class Ledger { * @param {number} index - Account number * @param {object} block - JSON-formatted block data */ - async updateCache (index: number, block: { [key: string]: string }): Promise<{ status: string }> + async updateCache (index: number, block: { [key: string]: string }): Promise /** * Update cache from a block hash by calling out to a node. Suitable for online * use only. @@ -341,8 +368,8 @@ export class Ledger { * @param {string} hash - Hexadecimal block hash * @param {Rpc} rpc - Rpc class object with a node URL */ - async updateCache (index: number, hash: string, rpc: Rpc): Promise<{ status: string }> - async updateCache (index: number, input: any, node?: Rpc): Promise<{ status: string }> { + async updateCache (index: number, hash: string, rpc: Rpc): Promise + async updateCache (index: number, input: any, node?: Rpc): Promise { if (typeof input === 'string' && node?.constructor === Rpc) { const data = { 'json_block': 'true', diff --git a/src/lib/pool.ts b/src/lib/pool.ts index d763dff..f569543 100644 --- a/src/lib/pool.ts +++ b/src/lib/pool.ts @@ -51,14 +51,24 @@ export class Pool { if (this.#queue.length > 0) { this.#queue.push(job) } else { - for (const thread of this.#threads) this.#assign(thread, job) + for (const thread of this.#threads) { + this.#assign(thread, job) + } } }) } + terminate (): void { + for (const thread of this.#threads) { + thread.job = null + thread.worker.terminate() + } + } + /** + * Creates a Web Worker from a stringified script. * - * @param {string} worker - Stringified worker class + * @param {string} worker - Stringified worker class body * @param {number} [count=1] - Integer between 1 and CPU thread count shared among all Pools */ constructor (worker: string, count: number = 1) { @@ -70,7 +80,7 @@ export class Pool { job: null } thread.worker.addEventListener('message', message => { - let result = JSON.parse(new TextDecoder().decode(message.data) || "[]") + let result = JSON.parse(new TextDecoder().decode(message.data) || '[]') if (!Array.isArray(result)) result = [result] this.#report(thread, result) }) diff --git a/src/lib/rolodex.ts b/src/lib/rolodex.ts index 211f841..2800107 100644 --- a/src/lib/rolodex.ts +++ b/src/lib/rolodex.ts @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2024 Chris Duncan // SPDX-License-Identifier: GPL-3.0-or-later -import { Account } from './account.js' +import { Account } from './account' type RolodexEntry = { name: string diff --git a/src/lib/safe.ts b/src/lib/safe.ts index 457dc93..6eaed3c 100644 --- a/src/lib/safe.ts +++ b/src/lib/safe.ts @@ -1,8 +1,9 @@ // SPDX-FileCopyrightText: 2024 Chris Duncan // SPDX-License-Identifier: GPL-3.0-or-later -import { buffer, hex, utf8 } from './convert.js' -import { Entropy } from './entropy.js' +import { buffer, hex, utf8 } from './convert' +import { Entropy } from './entropy' + const { subtle } = globalThis.crypto const ERR_MSG = 'Failed to store item in Safe' @@ -13,6 +14,17 @@ export class Safe { this.#storage = globalThis.sessionStorage } + /** + * Removes data from the Safe without decrypting. + */ + destroy (name: string): void { + try { + this.#storage.removeItem(name) + } catch (err) { + console.log(err) + } + } + /** * Encrypts data with a password and stores it in the Safe. */ @@ -22,10 +34,17 @@ export class Safe { */ async put (name: string, key: CryptoKey, data: any): Promise async put (name: string, passkey: string | CryptoKey, data: any): Promise { + if (typeof passkey === 'string') { + try { + passkey = await subtle.importKey('raw', utf8.toBytes(passkey), 'PBKDF2', false, ['deriveBits', 'deriveKey']) + } catch { + throw new Error(ERR_MSG) + } + } if (this.#storage.getItem(name)) { throw new Error(ERR_MSG) } - return this.overwrite(name, passkey as string, data) + return this.overwrite(name, passkey, data) } /** @@ -37,16 +56,32 @@ export class Safe { */ async overwrite (name: string, key: CryptoKey, data: any): Promise async overwrite (name: string, passkey: string | CryptoKey, data: any): Promise { - if (this.#isNotValid(name, passkey, data)) { + if (typeof passkey === 'string') { + try { + passkey = await subtle.importKey('raw', utf8.toBytes(passkey), 'PBKDF2', false, ['deriveBits', 'deriveKey']) + } catch { + throw new Error(ERR_MSG) + } + } + if (this.#isInvalid(name, passkey, data)) { throw new Error(ERR_MSG) } const iv = await Entropy.create() - if (typeof passkey === 'string') { + if (passkey.usages.includes('deriveKey')) { try { - passkey = await subtle.importKey('raw', utf8.toBytes(passkey), 'PBKDF2', false, ['deriveBits', 'deriveKey']) - passkey = await subtle.deriveKey({ name: 'PBKDF2', hash: 'SHA-512', salt: iv.bytes, iterations: 210000 }, passkey, { name: 'AES-GCM', length: 256 }, false, ['encrypt']) - } catch (err) { + const derivationAlgorithm: Pbkdf2Params = { + name: 'PBKDF2', + hash: 'SHA-512', + salt: iv.bytes, + iterations: 210000 + } + const derivedKeyType: AesKeyGenParams = { + name: 'AES-GCM', + length: 256 + } + passkey = await subtle.deriveKey(derivationAlgorithm, passkey, derivedKeyType, false, ['encrypt']) + } catch { throw new Error(ERR_MSG) } } @@ -56,21 +91,12 @@ export class Safe { data = data.toString() } data = JSON.stringify(data) - const encoded = utf8.toBytes(data) - const encrypted = await subtle.encrypt({ name: 'AES-GCM', iv: iv.buffer }, passkey, encoded) + const encrypted = await subtle.encrypt({ name: 'AES-GCM', iv: iv.buffer }, passkey, utf8.toBytes(data)) const record = { encrypted: buffer.toHex(encrypted), iv: iv.hex } - await new Promise((resolve, reject) => { - try { - this.#storage.setItem(name, JSON.stringify(record)) - resolve() - } catch (err) { - reject(err) - } - }) - passkey = '' + this.#storage.setItem(name, JSON.stringify(record)) } catch (err) { throw new Error(ERR_MSG) } @@ -86,13 +112,18 @@ export class Safe { */ async get (name: string, key: CryptoKey): Promise async get (name: string, passkey: string | CryptoKey): Promise { - if (this.#isNotValid(name, passkey)) { + if (typeof passkey === 'string') { + try { + passkey = await subtle.importKey('raw', utf8.toBytes(passkey), 'PBKDF2', false, ['deriveBits', 'deriveKey']) + } catch { + return null + } + } + if (this.#isInvalid(name, passkey)) { return null } - const item = await new Promise(resolve => { - resolve(this.#storage.getItem(name)) - }) + const item = this.#storage.getItem(name) if (item == null) { return null } @@ -101,9 +132,18 @@ export class Safe { const iv = await Entropy.import(record.iv) try { - if (typeof passkey === 'string') { - passkey = await subtle.importKey('raw', utf8.toBytes(passkey), 'PBKDF2', false, ['deriveBits', 'deriveKey']) - passkey = await subtle.deriveKey({ name: 'PBKDF2', hash: 'SHA-512', salt: iv.bytes, iterations: 210000 }, passkey, { name: 'AES-GCM', length: 256 }, false, ['decrypt']) + if (passkey.usages.includes('deriveKey')) { + const derivationAlgorithm: Pbkdf2Params = { + name: 'PBKDF2', + hash: 'SHA-512', + salt: iv.bytes, + iterations: 210000 + } + const derivedKeyType: AesKeyGenParams = { + name: 'AES-GCM', + length: 256 + } + passkey = await subtle.deriveKey(derivationAlgorithm, passkey, derivedKeyType, false, ['decrypt']) } } catch (err) { return null @@ -113,7 +153,6 @@ export class Safe { const decrypted = await subtle.decrypt({ name: 'AES-GCM', iv: iv.buffer }, passkey, encrypted) const decoded = buffer.toUtf8(decrypted) const data = JSON.parse(decoded) - passkey = '' this.#storage.removeItem(name) return data } catch (err) { @@ -121,7 +160,7 @@ export class Safe { } } - #isNotValid (name: string, passkey: string | CryptoKey, data?: any): boolean { + #isInvalid (name: string, passkey: string | CryptoKey, data?: any): boolean { if (typeof name !== 'string' || name === '') { return true } diff --git a/src/lib/tools.ts b/src/lib/tools.ts index fe934fe..d1f0ce4 100644 --- a/src/lib/tools.ts +++ b/src/lib/tools.ts @@ -1,14 +1,20 @@ // SPDX-FileCopyrightText: 2024 Chris Duncan // SPDX-License-Identifier: GPL-3.0-or-later -import { Account } from './account.js' -import { Blake2b } from './blake2b.js' -import { UNITS } from './constants.js' -import { hex } from './convert.js' -import { Rpc } from './rpc.js' -import { Bip44Wallet, Blake2bWallet, LedgerWallet } from './wallet.js' -import { SendBlock } from './block.js' -import { NanoNaCl } from './workers/nano-nacl.js' +import { Account } from './account' +import { Blake2b } from './blake2b' +import { SendBlock } from './block' +import { UNITS } from './constants' +import { hex } from './convert' +import { Rpc } from './rpc' +import { Bip44Wallet, Blake2bWallet, LedgerWallet } from './wallet' +import { NanoNaCl } from '#workers' + +type SweepResult = { + status: "success" | "error" + address: string + message: string +} function hash (data: string | string[], encoding?: 'hex'): string { if (!Array.isArray(data)) data = [data] @@ -99,7 +105,13 @@ export async function sign (key: string, ...input: string[]): Promise { * @param {number} to - Ending account index to sweep * @returns An array of results including both successes and failures */ -export async function sweep (rpc: Rpc | string | URL, wallet: Blake2bWallet | Bip44Wallet | LedgerWallet, recipient: string, from: number = 0, to: number = from) { +export async function sweep ( + rpc: Rpc | string | URL, + wallet: Blake2bWallet | Bip44Wallet | LedgerWallet, + recipient: string, + from: number = 0, + to: number = from +): Promise { if (rpc == null || wallet == null || recipient == null) { throw new ReferenceError('Missing required sweep arguments') } diff --git a/src/lib/wallet.ts b/src/lib/wallet.ts index 33ca4c3..1e1852b 100644 --- a/src/lib/wallet.ts +++ b/src/lib/wallet.ts @@ -1,22 +1,24 @@ // SPDX-FileCopyrightText: 2024 Chris Duncan // SPDX-License-Identifier: GPL-3.0-or-later -import { Account } from './account.js' -import { Blake2b } from './blake2b.js' -import { Bip39Mnemonic } from './bip39-mnemonic.js' -import { ADDRESS_GAP, SEED_LENGTH_BIP44, SEED_LENGTH_BLAKE2B } from './constants.js' -import { Entropy } from './entropy.js' -import { Pool } from './pool.js' -import { Rpc } from './rpc.js' -import { Safe } from './safe.js' -import { Bip44Ckd, NanoNaCl } from './workers.js' -import type { Ledger } from './ledger.js' +import { Account, AccountList } from './account' +import { Bip39Mnemonic } from './bip39-mnemonic' +import { Blake2b } from './blake2b' +import { ADDRESS_GAP, SEED_LENGTH_BIP44, SEED_LENGTH_BLAKE2B } from './constants' +import { hex } from './convert' +import { Entropy } from './entropy' +import { Ledger } from './ledger' +import { Pool } from './pool' +import { Rpc } from './rpc' +import { Safe } from './safe' +import { Bip44CkdWorker, NanoNaClWorker } from '#workers' type KeyPair = { publicKey?: string, privateKey?: string, index?: number } + /** * Represents a wallet containing numerous Nano accounts derived from a single * source, the form of which can vary based on the type of wallet. The Wallet @@ -25,7 +27,7 @@ type KeyPair = { * Blake2bWallet, LedgerWallet. */ abstract class Wallet { - #accounts: Account[] + #accounts: AccountList #id: Entropy #locked: boolean = true #mnemonic: Bip39Mnemonic | null @@ -54,57 +56,108 @@ abstract class Wallet { if (this.constructor === Wallet) { throw new Error('Wallet is an abstract class and cannot be instantiated directly.') } - this.#accounts = [] + this.#accounts = new AccountList() this.#id = id this.#mnemonic = mnemonic ?? null - this.#poolNanoNacl = new Pool(NanoNaCl) + this.#poolNanoNacl = new Pool(NanoNaClWorker) this.#safe = new Safe() this.#seed = seed ?? null } /** - * Retrieves accounts from a wallet using its child key derivation function. + * Removes encrypted secrets in storage and releases variable references to + * allow garbage collection. + */ + destroy (): void { + let i = 0 + for (const a in this.#accounts) { + this.#accounts[a].destroy() + delete this.#accounts[a] + i++ + } + this.#safe.destroy(this.id) + this.#mnemonic = null + this.#seed = null + this.#poolNanoNacl.terminate() + } + + /** + * Retrieves an account from a wallet using its child key derivation function. * Defaults to the first account at index 0. * - * Note: The wallet index of a given requested account might not correlate with - * its index in the returned array. - * - * For example, calling `await wallet.accounts(5)` will return the sixth - * account of the wallet in the first array element position at index 0. + * ``` + * console.log(await wallet.account(5)) + * // outputs sixth account of the wallet + * // { + * // privateKey: <...>, + * // index: 5 + * // } + * ``` + * + * @param {number} index - Wallet index of secret key. Default: 0 + * @returns {Account} Account derived at the specified wallet index + */ + async account (index: number = 0): Promise { + return (await this.accounts(index))[index] + } + + /** + * Retrieves accounts from a wallet using its child key derivation function. + * Defaults to the first account at index 0. * - * A shorthand way of getting one specific account could be - * `const account = (await wallet.accounts(N))[0]` where N is the wallet index - * of the desired account. + * The returned object will have keys corresponding with the requested range + * of account indexes. The value of each key will be the Account derived for + * that index in the wallet. + * + * ``` + * console.log(await wallet.accounts(5)) + * // outputs sixth account of the wallet + * // { + * // 5: { + * // privateKey: <...>, + * // index: 5 + * // } + * // } + * ``` * * @param {number} from - Start index of secret keys. Default: 0 * @param {number} to - End index of secret keys. Default: `from` + * @returns {AccountList} Object with keys of account indexes and values of the corresponding Accounts */ - async accounts (from: number = 0, to: number = from): Promise { + async accounts (from: number = 0, to: number = from): Promise { if (from > to) { const swap = from from = to to = swap } + const output = new AccountList() const indexes: number[] = [] for (let i = from; i <= to; i++) { if (this.#accounts[i] == null) { indexes.push(i) + } else { + output[i] = this.#accounts[i] } } if (indexes.length > 0) { let results = await this.ckd(indexes) const data: any = [] - results.forEach(r => data.push({ privateKey: r.privateKey, index: r.index })) + results.forEach(r => data.push({ + method: 'convert', + privateKey: r.privateKey, + index: r.index + })) const keypairs: KeyPair[] = await this.#poolNanoNacl.assign(data) for (const keypair of keypairs) { if (keypair.privateKey == null) throw new RangeError('Account private key missing') if (keypair.publicKey == null) throw new RangeError('Account public key missing') if (keypair.index == null) throw new RangeError('Account keys derived but index missing') - const { privateKey, publicKey, index } = keypair - this.#accounts[keypair.index] = Account.fromKeypair(privateKey, publicKey, index) + const { privateKey, index } = keypair + output[keypair.index] = Account.fromPrivateKey(privateKey, index) + this.#accounts[keypair.index] = output[keypair.index] } } - return this.#accounts.slice(from, to + 1) + return output } /** @@ -116,13 +169,15 @@ abstract class Wallet { * @param {number} from - Account index from which to start the search * @returns {Promise} The lowest-indexed unopened account belonging to the wallet */ - async getNextNewAccount (rpc: Rpc, batchSize: number = ADDRESS_GAP, from: number = 0): Promise { if (!Number.isSafeInteger(batchSize) || batchSize < 1) { throw new RangeError(`Invalid batch size ${batchSize}`) } const accounts = await this.accounts(from, from + batchSize - 1) - const addresses = accounts.map(({ address }) => address) + const addresses = [] + for (const a in accounts) { + addresses.push(accounts[a].address) + } const data = { "accounts": addresses } @@ -145,7 +200,7 @@ abstract class Wallet { * @param {Rpc|string|URL} rpc - RPC node information required to refresh accounts, calculate PoW, and process blocks * @returns {Promise} Accounts with updated balances, frontiers, and representatives */ - async refresh (rpc: Rpc | string | URL, from: number = 0, to: number = from): Promise { + async refresh (rpc: Rpc | string | URL, from: number = 0, to: number = from): Promise { if (typeof rpc === 'string' || rpc.constructor === URL) { rpc = new Rpc(rpc) } @@ -153,11 +208,11 @@ abstract class Wallet { throw new TypeError('RPC must be a valid node') } const accounts = await this.accounts(from, to) - for (let i = 0; i < accounts.length; i++) { + for (const a in accounts) { try { - await accounts[i].refresh(rpc) + await accounts[a].refresh(rpc) } catch (err) { - accounts.splice(i--, 1) + delete accounts[a] } } return accounts @@ -192,7 +247,11 @@ abstract class Wallet { data.seed = this.#seed } success &&= await this.#safe.put(this.id, passkey as string, data) - await Promise.all(this.#accounts.map((a) => a.lock(passkey as string))) + const promises = [] + for (const account of this.#accounts) { + promises.push(account.lock(passkey as string)) + } + await Promise.all(promises) if (!success) { throw null } @@ -225,7 +284,11 @@ abstract class Wallet { if (id !== this.id) { throw null } - await Promise.all(this.#accounts.map((a) => a.unlock(passkey as string))) + const promises = [] + for (const account of this.#accounts) { + promises.push(account.unlock(passkey as string)) + } + await Promise.all(promises) if (mnemonic != null) { this.#mnemonic = await Bip39Mnemonic.fromPhrase(mnemonic) } @@ -264,7 +327,7 @@ abstract class Wallet { */ export class Bip44Wallet extends Wallet { static #isInternal: boolean = false - static #poolBip44Ckd: Pool = new Pool(Bip44Ckd) + #poolBip44Ckd: Pool constructor (id: Entropy, seed: string, mnemonic?: Bip39Mnemonic) { if (!Bip44Wallet.#isInternal) { @@ -272,6 +335,16 @@ export class Bip44Wallet extends Wallet { } Bip44Wallet.#isInternal = false super(id, seed, mnemonic) + this.#poolBip44Ckd = new Pool(Bip44CkdWorker) + } + + /** + * Removes encrypted secrets in storage and releases variable references to + * allow garbage collection. + */ + destroy () { + super.destroy() + this.#poolBip44Ckd.terminate() } /** @@ -425,7 +498,7 @@ export class Bip44Wallet extends Wallet { async ckd (indexes: number[]): Promise { const data: any = [] indexes.forEach(i => data.push({ seed: this.seed, index: i })) - const privateKeys: KeyPair[] = await Bip44Wallet.#poolBip44Ckd.assign(data) + const privateKeys: KeyPair[] = await this.#poolBip44Ckd.assign(data) return privateKeys } } @@ -570,8 +643,7 @@ export class Blake2bWallet extends Wallet { const results = indexes.map(index => { const indexHex = index.toString(16).padStart(8, '0').toUpperCase() const inputHex = `${this.seed}${indexHex}`.padStart(72, '0') - const inputArray = (inputHex.match(/.{1,2}/g) ?? []).map(h => parseInt(h, 16)) - const inputBytes = Uint8Array.from(inputArray) + const inputBytes = hex.toBytes(inputHex) const privateKey: string = new Blake2b(32).update(inputBytes).digest('hex') return { privateKey, index } }) @@ -612,7 +684,7 @@ export class LedgerWallet extends Wallet { * @returns {LedgerWallet} A wallet containing accounts and a Ledger device communication object */ static async create (): Promise { - const { Ledger } = await import('./ledger.js') + const { Ledger } = await import('./ledger') const l = await Ledger.init() const id = await Entropy.create(16) LedgerWallet.#isInternal = true @@ -629,7 +701,7 @@ export class LedgerWallet extends Wallet { if (typeof id !== 'string' || id === '') { throw new TypeError('Wallet ID is required to restore') } - const { Ledger } = await import('./ledger.js') + const { Ledger } = await import('./ledger') const l = await Ledger.init() LedgerWallet.#isInternal = true return new this(await Entropy.import(id), l) @@ -667,7 +739,7 @@ export class LedgerWallet extends Wallet { return false } const result = await this.ledger.close() - return result === 'OK' + return result.status === 'OK' } /** diff --git a/src/lib/workers.ts b/src/lib/workers.ts deleted file mode 100644 index 017025f..0000000 --- a/src/lib/workers.ts +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Chris Duncan -// SPDX-License-Identifier: GPL-3.0-or-later -import { default as Bip44Ckd } from './workers/bip44-ckd.js' -import { default as NanoNaCl } from './workers/nano-nacl.js' -import { default as Pow } from './workers/powgl.js' - -export { Bip44Ckd, NanoNaCl, Pow } diff --git a/src/lib/workers/bip44-ckd.ts b/src/lib/workers/bip44-ckd.ts index 7764399..59a9149 100644 --- a/src/lib/workers/bip44-ckd.ts +++ b/src/lib/workers/bip44-ckd.ts @@ -1,6 +1,6 @@ // SPDX-FileCopyrightText: 2024 Chris Duncan // SPDX-License-Identifier: GPL-3.0-or-later -import { WorkerInterface } from '../pool.js' +import { WorkerInterface } from '#src/lib/pool.js' type ExtendedKey = { privateKey: DataView diff --git a/src/lib/workers/index.ts b/src/lib/workers/index.ts new file mode 100644 index 0000000..9613bc9 --- /dev/null +++ b/src/lib/workers/index.ts @@ -0,0 +1,11 @@ +// SPDX-FileCopyrightText: 2024 Chris Duncan +// SPDX-License-Identifier: GPL-3.0-or-later +import { default as Bip44CkdWorker, Bip44Ckd } from './bip44-ckd' +import { default as NanoNaClWorker, NanoNaCl } from './nano-nacl' + +export { + Bip44Ckd, + Bip44CkdWorker, + NanoNaCl, + NanoNaClWorker +} diff --git a/src/lib/workers/nano-nacl.ts b/src/lib/workers/nano-nacl.ts index 3bbaf69..b1fedea 100644 --- a/src/lib/workers/nano-nacl.ts +++ b/src/lib/workers/nano-nacl.ts @@ -3,8 +3,8 @@ 'use strict' -import { Blake2b } from '../blake2b.js' -import { WorkerInterface } from '../pool.js' +import { Blake2b } from '#src/lib/blake2b.js' +import { WorkerInterface } from '#src/lib/pool.js' // Ported in 2014 by Dmitry Chestnykh and Devi Mandiri. // Public domain. @@ -27,7 +27,19 @@ export class NanoNaCl extends WorkerInterface { return new Promise(async (resolve, reject): Promise => { for (let d of data) { try { - d.publicKey = await this.convert(d.privateKey) + switch (d.method) { + case 'detached': { + d.signature = await this.detached(Uint8Array.from(d.msg), Uint8Array.from(d.secretKey)) + break + } + case 'convert': { + d.publicKey = await this.convert(d.privateKey) + break + } + default: { + throw new TypeError(`unknown NanoNaCl method ${d.method}`) + } + } } catch (err) { reject(err) } @@ -38,7 +50,9 @@ export class NanoNaCl extends WorkerInterface { static gf = function (init?: number[]): Float64Array { const r = new Float64Array(16) - if (init) for (let i = 0; i < init.length; i++) r[i] = init[i] + if (init) for (let i = 0; i < init.length; i++) { + r[i] = init[i] + } return r } @@ -52,7 +66,9 @@ export class NanoNaCl extends WorkerInterface { static vn (x: Uint8Array, xi: number, y: Uint8Array, yi: number, n: number): number { let d = 0 - for (let i = 0; i < n; i++) d |= x[xi + i] ^ y[yi + i] + for (let i = 0; i < n; i++) { + d |= x[xi + i] ^ y[yi + i] + } return (1 & ((d - 1) >>> 8)) - 1 } @@ -61,7 +77,9 @@ export class NanoNaCl extends WorkerInterface { } static set25519 (r: Float64Array, a: Float64Array): void { - for (let i = 0; i < 16; i++) r[i] = a[i] | 0 + for (let i = 0; i < 16; i++) { + r[i] = a[i] | 0 + } } static car25519 (o: Float64Array): void { @@ -71,7 +89,7 @@ export class NanoNaCl extends WorkerInterface { c = Math.floor(v / 65536) o[i] = v - c * 65536 } - o[0] += c - 1 + 37 * (c - 1) + o[0] += 38 * (c - 1) } static sel25519 (p: Float64Array, q: Float64Array, b: number): void { @@ -88,7 +106,9 @@ export class NanoNaCl extends WorkerInterface { let b: number const m: Float64Array = this.gf() const t: Float64Array = this.gf() - for (let i = 0; i < 16; i++) t[i] = n[i] + for (let i = 0; i < 16; i++) { + t[i] = n[i] + } this.car25519(t) this.car25519(t) this.car25519(t) @@ -118,393 +138,68 @@ export class NanoNaCl extends WorkerInterface { } static par25519 (a: Float64Array): number { - var d = new Uint8Array(32) + const d = new Uint8Array(32) this.pack25519(d, a) return d[0] & 1 } static unpack25519 (o: Float64Array, n: Uint8Array): void { - for (let i = 0; i < 16; i++) o[i] = n[2 * i] + (n[2 * i + 1] << 8) - o[15] &= 0x7fff + for (let i = 0; i < 16; i++) { + o[i] = n[2 * i] + (n[2 * i + 1] << 8) + } + o[15] &= (1 << 15) - 1 } static A (o: Float64Array, a: Float64Array, b: Float64Array): void { - for (let i = 0; i < 16; i++) o[i] = a[i] + b[i] + for (let i = 0; i < 16; i++) { + o[i] = a[i] + b[i] + } } static Z (o: Float64Array, a: Float64Array, b: Float64Array): void { - for (let i = 0; i < 16; i++) o[i] = a[i] - b[i] + for (let i = 0; i < 16; i++) { + o[i] = a[i] - b[i] + } } static M (o: Float64Array, a: Float64Array, b: Float64Array): void { - let v, c, - t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, - t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0, - t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0, - t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0, - b0 = b[0], - b1 = b[1], - b2 = b[2], - b3 = b[3], - b4 = b[4], - b5 = b[5], - b6 = b[6], - b7 = b[7], - b8 = b[8], - b9 = b[9], - b10 = b[10], - b11 = b[11], - b12 = b[12], - b13 = b[13], - b14 = b[14], - b15 = b[15] - - v = a[0] - t0 += v * b0 - t1 += v * b1 - t2 += v * b2 - t3 += v * b3 - t4 += v * b4 - t5 += v * b5 - t6 += v * b6 - t7 += v * b7 - t8 += v * b8 - t9 += v * b9 - t10 += v * b10 - t11 += v * b11 - t12 += v * b12 - t13 += v * b13 - t14 += v * b14 - t15 += v * b15 - v = a[1] - t1 += v * b0 - t2 += v * b1 - t3 += v * b2 - t4 += v * b3 - t5 += v * b4 - t6 += v * b5 - t7 += v * b6 - t8 += v * b7 - t9 += v * b8 - t10 += v * b9 - t11 += v * b10 - t12 += v * b11 - t13 += v * b12 - t14 += v * b13 - t15 += v * b14 - t16 += v * b15 - v = a[2] - t2 += v * b0 - t3 += v * b1 - t4 += v * b2 - t5 += v * b3 - t6 += v * b4 - t7 += v * b5 - t8 += v * b6 - t9 += v * b7 - t10 += v * b8 - t11 += v * b9 - t12 += v * b10 - t13 += v * b11 - t14 += v * b12 - t15 += v * b13 - t16 += v * b14 - t17 += v * b15 - v = a[3] - t3 += v * b0 - t4 += v * b1 - t5 += v * b2 - t6 += v * b3 - t7 += v * b4 - t8 += v * b5 - t9 += v * b6 - t10 += v * b7 - t11 += v * b8 - t12 += v * b9 - t13 += v * b10 - t14 += v * b11 - t15 += v * b12 - t16 += v * b13 - t17 += v * b14 - t18 += v * b15 - v = a[4] - t4 += v * b0 - t5 += v * b1 - t6 += v * b2 - t7 += v * b3 - t8 += v * b4 - t9 += v * b5 - t10 += v * b6 - t11 += v * b7 - t12 += v * b8 - t13 += v * b9 - t14 += v * b10 - t15 += v * b11 - t16 += v * b12 - t17 += v * b13 - t18 += v * b14 - t19 += v * b15 - v = a[5] - t5 += v * b0 - t6 += v * b1 - t7 += v * b2 - t8 += v * b3 - t9 += v * b4 - t10 += v * b5 - t11 += v * b6 - t12 += v * b7 - t13 += v * b8 - t14 += v * b9 - t15 += v * b10 - t16 += v * b11 - t17 += v * b12 - t18 += v * b13 - t19 += v * b14 - t20 += v * b15 - v = a[6] - t6 += v * b0 - t7 += v * b1 - t8 += v * b2 - t9 += v * b3 - t10 += v * b4 - t11 += v * b5 - t12 += v * b6 - t13 += v * b7 - t14 += v * b8 - t15 += v * b9 - t16 += v * b10 - t17 += v * b11 - t18 += v * b12 - t19 += v * b13 - t20 += v * b14 - t21 += v * b15 - v = a[7] - t7 += v * b0 - t8 += v * b1 - t9 += v * b2 - t10 += v * b3 - t11 += v * b4 - t12 += v * b5 - t13 += v * b6 - t14 += v * b7 - t15 += v * b8 - t16 += v * b9 - t17 += v * b10 - t18 += v * b11 - t19 += v * b12 - t20 += v * b13 - t21 += v * b14 - t22 += v * b15 - v = a[8] - t8 += v * b0 - t9 += v * b1 - t10 += v * b2 - t11 += v * b3 - t12 += v * b4 - t13 += v * b5 - t14 += v * b6 - t15 += v * b7 - t16 += v * b8 - t17 += v * b9 - t18 += v * b10 - t19 += v * b11 - t20 += v * b12 - t21 += v * b13 - t22 += v * b14 - t23 += v * b15 - v = a[9] - t9 += v * b0 - t10 += v * b1 - t11 += v * b2 - t12 += v * b3 - t13 += v * b4 - t14 += v * b5 - t15 += v * b6 - t16 += v * b7 - t17 += v * b8 - t18 += v * b9 - t19 += v * b10 - t20 += v * b11 - t21 += v * b12 - t22 += v * b13 - t23 += v * b14 - t24 += v * b15 - v = a[10] - t10 += v * b0 - t11 += v * b1 - t12 += v * b2 - t13 += v * b3 - t14 += v * b4 - t15 += v * b5 - t16 += v * b6 - t17 += v * b7 - t18 += v * b8 - t19 += v * b9 - t20 += v * b10 - t21 += v * b11 - t22 += v * b12 - t23 += v * b13 - t24 += v * b14 - t25 += v * b15 - v = a[11] - t11 += v * b0 - t12 += v * b1 - t13 += v * b2 - t14 += v * b3 - t15 += v * b4 - t16 += v * b5 - t17 += v * b6 - t18 += v * b7 - t19 += v * b8 - t20 += v * b9 - t21 += v * b10 - t22 += v * b11 - t23 += v * b12 - t24 += v * b13 - t25 += v * b14 - t26 += v * b15 - v = a[12] - t12 += v * b0 - t13 += v * b1 - t14 += v * b2 - t15 += v * b3 - t16 += v * b4 - t17 += v * b5 - t18 += v * b6 - t19 += v * b7 - t20 += v * b8 - t21 += v * b9 - t22 += v * b10 - t23 += v * b11 - t24 += v * b12 - t25 += v * b13 - t26 += v * b14 - t27 += v * b15 - v = a[13] - t13 += v * b0 - t14 += v * b1 - t15 += v * b2 - t16 += v * b3 - t17 += v * b4 - t18 += v * b5 - t19 += v * b6 - t20 += v * b7 - t21 += v * b8 - t22 += v * b9 - t23 += v * b10 - t24 += v * b11 - t25 += v * b12 - t26 += v * b13 - t27 += v * b14 - t28 += v * b15 - v = a[14] - t14 += v * b0 - t15 += v * b1 - t16 += v * b2 - t17 += v * b3 - t18 += v * b4 - t19 += v * b5 - t20 += v * b6 - t21 += v * b7 - t22 += v * b8 - t23 += v * b9 - t24 += v * b10 - t25 += v * b11 - t26 += v * b12 - t27 += v * b13 - t28 += v * b14 - t29 += v * b15 - v = a[15] - t15 += v * b0 - t16 += v * b1 - t17 += v * b2 - t18 += v * b3 - t19 += v * b4 - t20 += v * b5 - t21 += v * b6 - t22 += v * b7 - t23 += v * b8 - t24 += v * b9 - t25 += v * b10 - t26 += v * b11 - t27 += v * b12 - t28 += v * b13 - t29 += v * b14 - t30 += v * b15 - - t0 += 38 * t16 - t1 += 38 * t17 - t2 += 38 * t18 - t3 += 38 * t19 - t4 += 38 * t20 - t5 += 38 * t21 - t6 += 38 * t22 - t7 += 38 * t23 - t8 += 38 * t24 - t9 += 38 * t25 - t10 += 38 * t26 - t11 += 38 * t27 - t12 += 38 * t28 - t13 += 38 * t29 - t14 += 38 * t30 + let v, c, s = 1 << 16, t = new Array(31) + t.fill(0) + + // init t values + for (let i = 0; i < 16; i++) { + for (let j = 0; j < 16; j++) { + t[i + j] += a[i] * b[j] + } + } + + for (let i = 0; i < 15; i++) { + t[i] += 38 * t[i + 16] + } // t15 left as is - // first car + // first carry c = 1 - v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536 - v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536 - v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536 - v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536 - v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536 - v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536 - v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536 - v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536 - v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536 - v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536 - v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536 - v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536 - v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536 - v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536 - v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536 - v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536 - t0 += c - 1 + 37 * (c - 1) - - // second car + for (let i = 0; i < 16; i++) { + v = t[i] + c + s - 1 + c = Math.floor(v / s) + t[i] = v - c * s + } + t[0] += 38 * (c - 1) + + // second carry c = 1 - v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536 - v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536 - v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536 - v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536 - v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536 - v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536 - v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536 - v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536 - v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536 - v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536 - v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536 - v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536 - v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536 - v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536 - v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536 - v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536 - t0 += c - 1 + 37 * (c - 1) - - o[0] = t0 - o[1] = t1 - o[2] = t2 - o[3] = t3 - o[4] = t4 - o[5] = t5 - o[6] = t6 - o[7] = t7 - o[8] = t8 - o[9] = t9 - o[10] = t10 - o[11] = t11 - o[12] = t12 - o[13] = t13 - o[14] = t14 - o[15] = t15 + for (let i = 0; i < 16; i++) { + v = t[i] + c + s - 1 + c = Math.floor(v / s) + t[i] = v - c * s + } + t[0] += 38 * (c - 1) + + // assign result to output + for (let i = 0; i < 16; i++) { + o[i] = t[i] + } } static S (o: Float64Array, a: Float64Array): void { @@ -512,31 +207,43 @@ export class NanoNaCl extends WorkerInterface { } static inv25519 (o: Float64Array, i: Float64Array): void { - const c: Float64Array = this.gf() - for (let a = 0; a < 16; a++) c[a] = i[a] + const c: Float64Array = new Float64Array(16) + for (let a = 0; a < 16; a++) { + c[a] = i[a] + } for (let a = 253; a >= 0; a--) { this.S(c, c) if (a !== 2 && a !== 4) this.M(c, c, i) } - for (let a = 0; a < 16; a++) o[a] = c[a] + for (let a = 0; a < 16; a++) { + o[a] = c[a] + } } static pow2523 (o: Float64Array, i: Float64Array): void { const c: Float64Array = this.gf() - for (let a = 0; a < 16; a++) c[a] = i[a] + for (let a = 0; a < 16; a++) { + c[a] = i[a] + } for (let a = 250; a >= 0; a--) { this.S(c, c) if (a !== 1) this.M(c, c, i) } - for (let a = 0; a < 16; a++) o[a] = c[a] + for (let a = 0; a < 16; a++) { + o[a] = c[a] + } } // Note: difference from TweetNaCl - BLAKE2b used to hash instead of SHA-512. static crypto_hash (out: Uint8Array, m: Uint8Array, n: number): number { const input = new Uint8Array(n) - for (let i = 0; i < n; ++i) input[i] = m[i] + for (let i = 0; i < n; ++i) { + input[i] = m[i] + } const hash = new Blake2b(64).update(m).digest() - for (let i = 0; i < 64; ++i) out[i] = hash[i] + for (let i = 0; i < 64; ++i) { + out[i] = hash[i] + } return 0 } @@ -637,7 +344,9 @@ export class NanoNaCl extends WorkerInterface { carry = x[j] >> 8 x[j] &= 255 } - for (j = 0; j < 32; j++) x[j] -= carry * this.L[j] + for (j = 0; j < 32; j++) { + x[j] -= carry * this.L[j] + } for (i = 0; i < 32; i++) { x[i + 1] += x[i] >> 8 r[i] = x[i] & 255 @@ -646,8 +355,12 @@ export class NanoNaCl extends WorkerInterface { static reduce (r: Uint8Array): void { let x = new Float64Array(64) - for (let i = 0; i < 64; i++) x[i] = r[i] - for (let i = 0; i < 64; i++) r[i] = 0 + for (let i = 0; i < 64; i++) { + x[i] = r[i] + } + for (let i = 0; i < 64; i++) { + r[i] = 0 + } this.modL(r, x) } @@ -665,20 +378,30 @@ export class NanoNaCl extends WorkerInterface { d[31] |= 64 const smlen = n + 64 - for (let i = 0; i < n; i++) sm[64 + i] = m[i] - for (let i = 0; i < 32; i++) sm[32 + i] = d[32 + i] + for (let i = 0; i < n; i++) { + sm[64 + i] = m[i] + } + for (let i = 0; i < 32; i++) { + sm[32 + i] = d[32 + i] + } this.crypto_hash(r, sm.subarray(32), n + 32) this.reduce(r) this.scalarbase(p, r) this.pack(sm, p) - for (let i = 0; i < 32; i++) sm[i + 32] = pk[i] + for (let i = 0; i < 32; i++) { + sm[i + 32] = pk[i] + } this.crypto_hash(h, sm, n + 64) this.reduce(h) - for (let i = 0; i < 64; i++) x[i] = 0 - for (let i = 0; i < 32; i++) x[i] = r[i] + for (let i = 0; i < 64; i++) { + x[i] = 0 + } + for (let i = 0; i < 32; i++) { + x[i] = r[i] + } for (let i = 0; i < 32; i++) { for (let j = 0; j < 32; j++) { x[i + j] += h[i] * d[j] @@ -741,8 +464,12 @@ export class NanoNaCl extends WorkerInterface { if (this.unpackneg(q, pk)) return -1 - for (let i = 0; i < n; i++) m[i] = sm[i] - for (let i = 0; i < 32; i++) m[i + 32] = pk[i] + for (let i = 0; i < n; i++) { + m[i] = sm[i] + } + for (let i = 0; i < 32; i++) { + m[i + 32] = pk[i] + } this.crypto_hash(h, m, n) this.reduce(h) this.scalarmult(p, q, h) @@ -753,25 +480,29 @@ export class NanoNaCl extends WorkerInterface { n -= 64 if (this.crypto_verify_32(sm, 0, t, 0)) { - for (let i = 0; i < n; i++) m[i] = 0 + for (let i = 0; i < n; i++) { + m[i] = 0 + } return -1 } - for (let i = 0; i < n; i++) m[i] = sm[i + 64] + for (let i = 0; i < n; i++) { + m[i] = sm[i + 64] + } return n } - static crypto_sign_BYTES = 64 - static crypto_sign_PUBLICKEYBYTES = 32 - static crypto_sign_SECRETKEYBYTES = 32 - static crypto_sign_SEEDBYTES = 32 + static crypto_sign_BYTES: 64 = 64 + static crypto_sign_PUBLICKEYBYTES: 32 = 32 + static crypto_sign_SECRETKEYBYTES: 32 = 32 + static crypto_sign_SEEDBYTES: 32 = 32 /* High-level API */ - static checkArrayTypes (...args: Uint8Array[]): void { for (let i = 0; i < args.length; i++) { - if (!(args[i] instanceof Uint8Array)) - throw new TypeError(`expected Uint8Array; received ${args[i].constructor?.name ?? typeof args[i]}`) + if (!(args[i] instanceof Uint8Array)) { + throw new TypeError(`expected Uint8Array; actual ${args[i].constructor?.name ?? typeof args[i]}`) + } } } @@ -784,10 +515,12 @@ export class NanoNaCl extends WorkerInterface { static hexify (buf: Uint8Array): string { let str = '' for (let i = 0; i < buf.length; i++) { - if (typeof buf[i] !== 'number') + if (typeof buf[i] !== 'number') { throw new TypeError(`expected number to convert to hex; received ${typeof buf[i]}`) - if (buf[i] < 0 || buf[i] > 255) + } + if (buf[i] < 0 || buf[i] > 255) { throw new RangeError(`expected byte value 0-255; received ${buf[i]}`) + } str += buf[i].toString(16).padStart(2, '0') } return str @@ -795,9 +528,10 @@ export class NanoNaCl extends WorkerInterface { static sign (msg: Uint8Array, secretKey: Uint8Array): Uint8Array { this.checkArrayTypes(msg, secretKey) - if (secretKey.length !== this.crypto_sign_SECRETKEYBYTES) - throw new Error('bad secret key size') - var signedMsg = new Uint8Array(this.crypto_sign_BYTES + msg.length) + if (secretKey.byteLength !== this.crypto_sign_SECRETKEYBYTES) { + throw new Error(`expected key size ${this.crypto_sign_SECRETKEYBYTES} bytes; actual key size ${secretKey.byteLength} bytes`) + } + const signedMsg = new Uint8Array(this.crypto_sign_BYTES + msg.length) const publicKey = this.parseHex(this.convert(secretKey)) this.crypto_sign(signedMsg, msg, msg.length, secretKey, publicKey) return signedMsg @@ -805,44 +539,55 @@ export class NanoNaCl extends WorkerInterface { static open (signedMsg: Uint8Array, publicKey: Uint8Array): Uint8Array { this.checkArrayTypes(signedMsg, publicKey) - if (publicKey.length !== this.crypto_sign_PUBLICKEYBYTES) + if (publicKey.length !== this.crypto_sign_PUBLICKEYBYTES) { throw new Error('bad public key size') + } const tmp = new Uint8Array(signedMsg.length) - var mlen = this.crypto_sign_open(tmp, signedMsg, signedMsg.length, publicKey) + const mlen = this.crypto_sign_open(tmp, signedMsg, signedMsg.length, publicKey) if (mlen < 0) return new Uint8Array(0) - var m = new Uint8Array(mlen) - for (var i = 0; i < m.length; i++) m[i] = tmp[i] + const m = new Uint8Array(mlen) + for (let i = 0; i < m.length; i++) { + m[i] = tmp[i] + } return m } static detached (msg: Uint8Array, secretKey: Uint8Array): string { - var signedMsg = this.sign(msg, secretKey) - var sig = new Uint8Array(this.crypto_sign_BYTES) - for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i] + const signedMsg = this.sign(msg, secretKey) + const sig = new Uint8Array(this.crypto_sign_BYTES) + for (let i = 0; i < sig.length; i++) { + sig[i] = signedMsg[i] + } return this.hexify(sig).toUpperCase() } static verify (msg: Uint8Array, sig: Uint8Array, publicKey: Uint8Array): boolean { this.checkArrayTypes(msg, sig, publicKey) - if (sig.length !== this.crypto_sign_BYTES) + if (sig.length !== this.crypto_sign_BYTES) { throw new Error('bad signature size') - if (publicKey.length !== this.crypto_sign_PUBLICKEYBYTES) + } + if (publicKey.length !== this.crypto_sign_PUBLICKEYBYTES) { throw new Error('bad public key size') + } const sm = new Uint8Array(this.crypto_sign_BYTES + msg.length) const m = new Uint8Array(this.crypto_sign_BYTES + msg.length) - for (let i = 0; i < this.crypto_sign_BYTES; i++) sm[i] = sig[i] - for (let i = 0; i < msg.length; i++) sm[i + this.crypto_sign_BYTES] = msg[i] + for (let i = 0; i < this.crypto_sign_BYTES; i++) { + sm[i] = sig[i] + } + for (let i = 0; i < msg.length; i++) { + sm[i + this.crypto_sign_BYTES] = msg[i] + } return (this.crypto_sign_open(m, sm, sm.length, publicKey) >= 0) } static convert (seed: string | Uint8Array): string { if (typeof seed === 'string') seed = this.parseHex(seed) this.checkArrayTypes(seed) - if (seed.length !== this.crypto_sign_SEEDBYTES) + if (seed.length !== this.crypto_sign_SEEDBYTES) { throw new Error('bad seed size') - + } const pk = new Uint8Array(this.crypto_sign_PUBLICKEYBYTES) const p: Float64Array[] = [this.gf(), this.gf(), this.gf(), this.gf()] diff --git a/src/lib/workers/powgl.ts b/src/lib/workers/powgl.ts deleted file mode 100644 index 5f7733a..0000000 --- a/src/lib/workers/powgl.ts +++ /dev/null @@ -1,404 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Chris Duncan -// SPDX-License-Identifier: GPL-3.0-or-later -// Based on nano-webgl-pow by Ben Green (numtel) -// https://github.com/numtel/nano-webgl-pow -import { WorkerInterface } from '../pool.js' - -export class Pow extends WorkerInterface { - static { - Pow.listen() - } - /** - * Calculates proof-of-work as described by the Nano cryptocurrency protocol. - * - * @param {any[]} data - Array of hashes and minimum thresholds - * @returns Promise for proof-of-work attached to original array objects - */ - static async work (data: any[]): Promise { - return new Promise(async (resolve, reject): Promise => { - for (const d of data) { - try { - d.work = await this.find(d.hash, d.threshold) - } catch (err) { - reject(err) - } - } - resolve(data) - }) - } - - /** - * Finds a nonce that satisfies the Nano proof-of-work requirements. - * - * @param {string} hashHex - Hexadecimal hash of previous block, or public key for new accounts - * @param {number} [threshold=0xfffffff8] - Difficulty of proof-of-work calculation - */ - static async find (hash: string, threshold: number = 0xfffffff8): Promise { - return new Promise(resolve => { - this.#calculate(hash, resolve, threshold) - }) - } - - // Vertex Shader - static #vsSource = `#version 300 es -#pragma vscode_glsllint_stage: vert -precision highp float; -layout (location=0) in vec4 position; -layout (location=1) in vec2 uv; - -out vec2 uv_pos; - -void main() { - uv_pos = uv; - gl_Position = position; -}` - - // Fragment shader - static #fsSource = `#version 300 es -#pragma vscode_glsllint_stage: frag -precision highp float; -precision highp int; - -in vec2 uv_pos; -out vec4 fragColor; - -// blockhash - array of precalculated block hash components -// threshold - 0xfffffff8 for send/change blocks, 0xfffffe00 for all else -// workload - Defines canvas size -layout(std140) uniform UBO { - uint blockhash[8]; - uint threshold; - float workload; -}; - -// Random work values -// First 2 bytes will be overwritten by texture pixel position -// Second 2 bytes will be modified if the canvas size is greater than 256x256 -// Last 4 bytes remain as generated externally -layout(std140) uniform WORK { - uvec4 work[2]; -}; - -// Defined separately from uint v[32] below as the original value is required -// to calculate the second uint32 of the digest for threshold comparison -#define BLAKE2B_IV32_1 0x6A09E667u - -// Both buffers represent 16 uint64s as 32 uint32s -// because that's what GLSL offers, just like Javascript - -// Compression buffer, intialized to 2 instances of the initialization vector -// The following values have been modified from the BLAKE2B_IV: -// OUTLEN is constant 8 bytes -// v[0] ^= 0x01010000u ^ uint(OUTLEN); -// INLEN is constant 40 bytes: work value (8) + block hash (32) -// v[24] ^= uint(INLEN); -// It's always the "last" compression at this INLEN -// v[28] = ~v[28]; -// v[29] = ~v[29]; -uint v[32] = uint[32]( - 0xF2BDC900u, 0x6A09E667u, 0x84CAA73Bu, 0xBB67AE85u, - 0xFE94F82Bu, 0x3C6EF372u, 0x5F1D36F1u, 0xA54FF53Au, - 0xADE682D1u, 0x510E527Fu, 0x2B3E6C1Fu, 0x9B05688Cu, - 0xFB41BD6Bu, 0x1F83D9ABu, 0x137E2179u, 0x5BE0CD19u, - 0xF3BCC908u, 0x6A09E667u, 0x84CAA73Bu, 0xBB67AE85u, - 0xFE94F82Bu, 0x3C6EF372u, 0x5F1D36F1u, 0xA54FF53Au, - 0xADE682F9u, 0x510E527Fu, 0x2B3E6C1Fu, 0x9B05688Cu, - 0x04BE4294u, 0xE07C2654u, 0x137E2179u, 0x5BE0CD19u -); -// Input data buffer -uint m[32]; - -// These are offsets into the input data buffer for each mixing step. -// They are multiplied by 2 from the original SIGMA values in -// the C reference implementation, which refered to uint64s. -const int SIGMA82[192] = int[192]( - 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30, - 28,20,8,16,18,30,26,12,2,24,0,4,22,14,10,6, - 22,16,24,0,10,4,30,26,20,28,6,12,14,2,18,8, - 14,18,6,2,26,24,22,28,4,12,10,20,8,0,30,16, - 18,0,10,14,4,8,20,30,28,2,22,24,12,16,6,26, - 4,24,12,20,0,22,16,6,8,26,14,10,30,28,2,18, - 24,10,2,30,28,26,8,20,0,14,12,6,18,4,16,22, - 26,22,14,28,24,2,6,18,10,0,30,8,16,12,4,20, - 12,30,28,18,22,6,0,16,24,4,26,14,2,8,20,10, - 20,4,16,8,14,12,2,10,30,22,18,28,6,24,26,0, - 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30, - 28,20,8,16,18,30,26,12,2,24,0,4,22,14,10,6 -); - -// 64-bit unsigned addition within the compression buffer -// Sets v[a,a+1] += b -// b0 is the low 32 bits of b, b1 represents the high 32 bits -void add_uint64 (int a, uint b0, uint b1) { - uint o0 = v[a] + b0; - uint o1 = v[a + 1] + b1; - if (v[a] > 0xFFFFFFFFu - b0) { // did low 32 bits overflow? - o1++; - } - v[a] = o0; - v[a + 1] = o1; -} - -// G Mixing function -void B2B_G (int a, int b, int c, int d, int ix, int iy) { - add_uint64(a, v[b], v[b+1]); - add_uint64(a, m[ix], m[ix + 1]); - - // v[d,d+1] = (v[d,d+1] xor v[a,a+1]) rotated to the right by 32 bits - uint xor0 = v[d] ^ v[a]; - uint xor1 = v[d + 1] ^ v[a + 1]; - v[d] = xor1; - v[d + 1] = xor0; - - add_uint64(c, v[d], v[d+1]); - - // v[b,b+1] = (v[b,b+1] xor v[c,c+1]) rotated right by 24 bits - xor0 = v[b] ^ v[c]; - xor1 = v[b + 1] ^ v[c + 1]; - v[b] = (xor0 >> 24) ^ (xor1 << 8); - v[b + 1] = (xor1 >> 24) ^ (xor0 << 8); - - add_uint64(a, v[b], v[b+1]); - add_uint64(a, m[iy], m[iy + 1]); - - // v[d,d+1] = (v[d,d+1] xor v[a,a+1]) rotated right by 16 bits - xor0 = v[d] ^ v[a]; - xor1 = v[d + 1] ^ v[a + 1]; - v[d] = (xor0 >> 16) ^ (xor1 << 16); - v[d + 1] = (xor1 >> 16) ^ (xor0 << 16); - - add_uint64(c, v[d], v[d+1]); - - // v[b,b+1] = (v[b,b+1] xor v[c,c+1]) rotated right by 63 bits - xor0 = v[b] ^ v[c]; - xor1 = v[b + 1] ^ v[c + 1]; - v[b] = (xor1 >> 31) ^ (xor0 << 1); - v[b + 1] = (xor0 >> 31) ^ (xor1 << 1); -} - -void main() { - int i; - uvec4 u_work0 = work[0]; - uvec4 u_work1 = work[1]; - uint uv_x = uint(uv_pos.x * workload); - uint uv_y = uint(uv_pos.y * workload); - uint x_pos = uv_x % 256u; - uint y_pos = uv_y % 256u; - uint x_index = (uv_x - x_pos) / 256u; - uint y_index = (uv_y - y_pos) / 256u; - - // First 2 work bytes are the x,y pos within the 256x256 area, the next - // two bytes are modified from the random generated value, XOR'd with - // the x,y area index of where this pixel is located - m[0] = (x_pos ^ (y_pos << 8) ^ ((u_work0.b ^ x_index) << 16) ^ ((u_work0.a ^ y_index) << 24)); - - // Remaining bytes are un-modified from the random generated value - m[1] = (u_work1.r ^ (u_work1.g << 8) ^ (u_work1.b << 16) ^ (u_work1.a << 24)); - - // Block hash - for (i=0;i<8;i++) { - m[i+2] = blockhash[i]; - } - - // twelve rounds of mixing - for(i=0;i<12;i++) { - B2B_G(0, 8, 16, 24, SIGMA82[i * 16 + 0], SIGMA82[i * 16 + 1]); - B2B_G(2, 10, 18, 26, SIGMA82[i * 16 + 2], SIGMA82[i * 16 + 3]); - B2B_G(4, 12, 20, 28, SIGMA82[i * 16 + 4], SIGMA82[i * 16 + 5]); - B2B_G(6, 14, 22, 30, SIGMA82[i * 16 + 6], SIGMA82[i * 16 + 7]); - B2B_G(0, 10, 20, 30, SIGMA82[i * 16 + 8], SIGMA82[i * 16 + 9]); - B2B_G(2, 12, 22, 24, SIGMA82[i * 16 + 10], SIGMA82[i * 16 + 11]); - B2B_G(4, 14, 16, 26, SIGMA82[i * 16 + 12], SIGMA82[i * 16 + 13]); - B2B_G(6, 8, 18, 28, SIGMA82[i * 16 + 14], SIGMA82[i * 16 + 15]); - } - - // Pixel data is multipled by threshold test result (0 or 1) - // First 4 bytes insignificant, only calculate digest of second 4 bytes - if ((BLAKE2B_IV32_1 ^ v[1] ^ v[17]) > threshold) { - fragColor = vec4( - float(x_index + 1u)/255., // +1 to distinguish from 0 (unsuccessful) pixels - float(y_index + 1u)/255., // Same as previous - float(x_pos)/255., // Return the 2 custom bytes used in work value - float(y_pos)/255. // Second custom byte - ); - } else { - discard; - } -}` - - /** Used to set canvas size. Must be a multiple of 256. */ - static #WORKLOAD: number = 256 * Math.max(1, Math.floor(navigator.hardwareConcurrency)) - - static #hexify (arr: number[] | Uint8Array): string { - let out = '' - for (let i = arr.length - 1; i >= 0; i--) { - out += arr[i].toString(16).padStart(2, '0') - } - return out - } - - static #gl: WebGL2RenderingContext | null - static #program: WebGLProgram | null - static #vertexShader: WebGLShader | null - static #fragmentShader: WebGLShader | null - static #positionBuffer: WebGLBuffer | null - static #uvBuffer: WebGLBuffer | null - static #uboBuffer: WebGLBuffer | null - static #workBuffer: WebGLBuffer | null - static #query: WebGLQuery | null - static #pixels: Uint8Array - // Vertex Positions, 2 triangles - static #positions = new Float32Array([ - -1, -1, 0, -1, 1, 0, 1, 1, 0, - 1, -1, 0, 1, 1, 0, -1, -1, 0 - ]) - // Texture Positions - static #uvPosArray = new Float32Array([ - 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1 - ]) - - // Compile - static { - this.#gl = new OffscreenCanvas(this.#WORKLOAD, this.#WORKLOAD).getContext('webgl2') - if (this.#gl == null) throw new Error('WebGL 2 is required') - this.#gl.clearColor(0, 0, 0, 1) - - this.#program = this.#gl.createProgram() - if (this.#program == null) throw new Error('Failed to create shader program') - - this.#vertexShader = this.#gl.createShader(this.#gl.VERTEX_SHADER) - if (this.#vertexShader == null) throw new Error('Failed to create vertex shader') - this.#gl.shaderSource(this.#vertexShader, this.#vsSource) - this.#gl.compileShader(this.#vertexShader) - if (!this.#gl.getShaderParameter(this.#vertexShader, this.#gl.COMPILE_STATUS)) - throw new Error(this.#gl.getShaderInfoLog(this.#vertexShader) ?? `Failed to compile vertex shader`) - - this.#fragmentShader = this.#gl.createShader(this.#gl.FRAGMENT_SHADER) - if (this.#fragmentShader == null) throw new Error('Failed to create fragment shader') - this.#gl.shaderSource(this.#fragmentShader, this.#fsSource) - this.#gl.compileShader(this.#fragmentShader) - if (!this.#gl.getShaderParameter(this.#fragmentShader, this.#gl.COMPILE_STATUS)) - throw new Error(this.#gl.getShaderInfoLog(this.#fragmentShader) ?? `Failed to compile fragment shader`) - - this.#gl.attachShader(this.#program, this.#vertexShader) - this.#gl.attachShader(this.#program, this.#fragmentShader) - this.#gl.linkProgram(this.#program) - if (!this.#gl.getProgramParameter(this.#program, this.#gl.LINK_STATUS)) - throw new Error(this.#gl.getProgramInfoLog(this.#program) ?? `Failed to link program`) - - // Construct simple 2D geometry - this.#gl.useProgram(this.#program) - const triangleArray = this.#gl.createVertexArray() - this.#gl.bindVertexArray(triangleArray) - - this.#positionBuffer = this.#gl.createBuffer() - this.#gl.bindBuffer(this.#gl.ARRAY_BUFFER, this.#positionBuffer) - this.#gl.bufferData(this.#gl.ARRAY_BUFFER, this.#positions, this.#gl.STATIC_DRAW) - this.#gl.vertexAttribPointer(0, 3, this.#gl.FLOAT, false, 0, 0) - this.#gl.enableVertexAttribArray(0) - - this.#uvBuffer = this.#gl.createBuffer() - this.#gl.bindBuffer(this.#gl.ARRAY_BUFFER, this.#uvBuffer) - this.#gl.bufferData(this.#gl.ARRAY_BUFFER, this.#uvPosArray, this.#gl.STATIC_DRAW) - this.#gl.vertexAttribPointer(1, 2, this.#gl.FLOAT, false, 0, 0) - this.#gl.enableVertexAttribArray(1) - - this.#uboBuffer = this.#gl.createBuffer() - this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, this.#uboBuffer) - this.#gl.bufferData(this.#gl.UNIFORM_BUFFER, 144, this.#gl.DYNAMIC_DRAW) - this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, null) - this.#gl.bindBufferBase(this.#gl.UNIFORM_BUFFER, 0, this.#uboBuffer) - this.#gl.uniformBlockBinding(this.#program, this.#gl.getUniformBlockIndex(this.#program, 'UBO'), 0) - - this.#workBuffer = this.#gl.createBuffer() - this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, this.#workBuffer) - this.#gl.bufferData(this.#gl.UNIFORM_BUFFER, 32, this.#gl.STREAM_DRAW) - this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, null) - this.#gl.bindBufferBase(this.#gl.UNIFORM_BUFFER, 1, this.#workBuffer) - this.#gl.uniformBlockBinding(this.#program, this.#gl.getUniformBlockIndex(this.#program, 'WORK'), 1) - - this.#pixels = new Uint8Array(this.#gl.drawingBufferWidth * this.#gl.drawingBufferHeight * 4) - this.#query = this.#gl.createQuery() - } - - static #calculate (hashHex: string, callback: (nonce: string | PromiseLike) => any, threshold: number): void { - if (Pow.#gl == null) throw new Error('WebGL 2 is required') - if (!/^[A-F-a-f0-9]{64}$/.test(hashHex)) throw new Error(`invalid_hash ${hashHex}`) - if (typeof threshold !== 'number') throw new TypeError(`Invalid threshold ${threshold}`) - if (this.#gl == null) throw new Error('WebGL 2 is required') - - // Set up uniform buffer object - const uboView = new DataView(new ArrayBuffer(144)) - for (let i = 0; i < 64; i += 8) { - const uint32 = hashHex.slice(i, i + 8) - uboView.setUint32(i * 2, parseInt(uint32, 16)) - } - uboView.setUint32(128, threshold, true) - uboView.setFloat32(132, Pow.#WORKLOAD - 1, true) - Pow.#gl.bindBuffer(Pow.#gl.UNIFORM_BUFFER, Pow.#uboBuffer) - Pow.#gl.bufferSubData(Pow.#gl.UNIFORM_BUFFER, 0, uboView) - Pow.#gl.bindBuffer(Pow.#gl.UNIFORM_BUFFER, null) - - // Draw output until success or progressCallback says to stop - const work = new Uint8Array(8) - const draw = (): void => { - if (Pow.#gl == null) throw new Error('WebGL 2 is required') - if (Pow.#query == null) throw new Error('WebGL 2 is required to run queries') - Pow.#gl.clear(Pow.#gl.COLOR_BUFFER_BIT) - - // Upload work buffer - crypto.getRandomValues(work) - Pow.#gl.bindBuffer(Pow.#gl.UNIFORM_BUFFER, Pow.#workBuffer) - Pow.#gl.bufferSubData(Pow.#gl.UNIFORM_BUFFER, 0, Uint32Array.from(work)) - Pow.#gl.bindBuffer(Pow.#gl.UNIFORM_BUFFER, null) - - Pow.#gl.beginQuery(Pow.#gl.ANY_SAMPLES_PASSED_CONSERVATIVE, Pow.#query) - Pow.#gl.drawArrays(Pow.#gl.TRIANGLES, 0, 6) - Pow.#gl.endQuery(Pow.#gl.ANY_SAMPLES_PASSED_CONSERVATIVE) - - requestAnimationFrame(checkQueryResult) - } - - function checkQueryResult () { - if (Pow.#gl == null) throw new Error('WebGL 2 is required to check query results') - if (Pow.#query == null) throw new Error('Query not found') - if (Pow.#gl.getQueryParameter(Pow.#query, Pow.#gl.QUERY_RESULT_AVAILABLE)) { - const anySamplesPassed = Pow.#gl.getQueryParameter(Pow.#query, Pow.#gl.QUERY_RESULT) - if (anySamplesPassed) { - // A valid nonce was found - readBackResult() - } else { - // No valid nonce found, start the next draw call - requestAnimationFrame(draw) - } - } else { - // Query result not yet available, check again in the next frame - requestAnimationFrame(checkQueryResult) - } - } - function readBackResult () { - if (Pow.#gl == null) throw new Error('WebGL 2 is required to check read results') - Pow.#gl.readPixels(0, 0, Pow.#gl.drawingBufferWidth, Pow.#gl.drawingBufferHeight, Pow.#gl.RGBA, Pow.#gl.UNSIGNED_BYTE, Pow.#pixels) - // Check the pixels for any success - for (let i = 0; i < Pow.#pixels.length; i += 4) { - if (Pow.#pixels[i] !== 0) { - const hex = Pow.#hexify(work.subarray(4, 8)) + Pow.#hexify([ - Pow.#pixels[i + 2], - Pow.#pixels[i + 3], - work[2] ^ (Pow.#pixels[i] - 1), - work[3] ^ (Pow.#pixels[i + 1] - 1) - ]) - // Return the work value with the custom bits - typeof callback === 'function' && callback(hex) - return - } - } - } - draw() - } -} - -export default ` - const WorkerInterface = ${WorkerInterface} - const Pow = ${Pow} -` diff --git a/src/main.ts b/src/main.ts index 8f12d11..0db2b25 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,14 +1,13 @@ // SPDX-FileCopyrightText: 2024 Chris Duncan // SPDX-License-Identifier: GPL-3.0-or-later -import { Account } from './lib/account.js' -import { Blake2b } from './lib/blake2b.js' -import { SendBlock, ReceiveBlock, ChangeBlock } from './lib/block.js' -import { Pow } from './lib/workers/powgl.js' -import { Rpc } from './lib/rpc.js' -import { Rolodex } from './lib/rolodex.js' -import { Safe } from './lib/safe.js' -import { Tools } from './lib/tools.js' -import { Bip44Wallet, Blake2bWallet, LedgerWallet } from './lib/wallet.js' +import { Account } from './lib/account' +import { Blake2b } from './lib/blake2b' +import { SendBlock, ReceiveBlock, ChangeBlock } from './lib/block' +import { Rolodex } from './lib/rolodex' +import { Rpc } from './lib/rpc' +import { Safe } from './lib/safe' +import { Tools } from './lib/tools' +import { Bip44Wallet, Blake2bWallet, LedgerWallet } from './lib/wallet' -export { Account, Blake2b, SendBlock, ReceiveBlock, ChangeBlock, Pow, Rpc, Rolodex, Safe, Tools, Bip44Wallet, Blake2bWallet, LedgerWallet } +export { Account, Blake2b, SendBlock, ReceiveBlock, ChangeBlock, Rpc, Rolodex, Safe, Tools, Bip44Wallet, Blake2bWallet, LedgerWallet } diff --git a/test.html b/test.html deleted file mode 100644 index 39ee1f9..0000000 --- a/test.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/GLOBALS.mjs b/test/GLOBALS.mjs similarity index 68% rename from GLOBALS.mjs rename to test/GLOBALS.mjs index 475d8de..e4b0050 100644 --- a/GLOBALS.mjs +++ b/test/GLOBALS.mjs @@ -1,6 +1,10 @@ // SPDX-FileCopyrightText: 2024 Chris Duncan // SPDX-License-Identifier: GPL-3.0-or-later +import { Queue } from './QUEUE.mjs' + +const queue = new Queue() + if (globalThis.sessionStorage == null) { let _sessionStorage = {} Object.defineProperty(globalThis, 'sessionStorage', { @@ -16,18 +20,58 @@ if (globalThis.sessionStorage == null) { }) } -export function average (times) { - let sum = 0, reciprocals = 0, product = 1, count = times.length +export function stats (times) { + if (times == null || times.length === 0) return null + + const count = times.length + const truncatedStart = Math.floor(count * 0.1) + const truncatedEnd = count - truncatedStart + const truncatedCount = truncatedEnd - truncatedStart + let min = Number.MAX_SAFE_INTEGER + let logarithms, max, median, reciprocals, total + logarithms = max = median = reciprocals = total = 0 + + let truncatedMin = Number.MAX_SAFE_INTEGER + let truncatedLogarithms, truncatedMax, truncatedReciprocals, truncatedTotal + truncatedLogarithms = truncatedMax = truncatedReciprocals = truncatedTotal = 0 + + times.sort((a, b) => a - b) for (let i = 0; i < count; i++) { - sum += times[i] - reciprocals += 1 / times[i] - product *= times[i] + const time = times[i] + total += time + logarithms += Math.log(time) + reciprocals += 1 / time + min = Math.min(min, time) + max = Math.max(max, time) + if (i === Math.floor((count - 1) / 2)) median = time + if (i === Math.floor(count / 2) && count % 2 === 0) median = (median + time) / 2 + } + for (let i = truncatedStart; i < truncatedEnd; i++) { + const time = times[i] + truncatedTotal += time + truncatedLogarithms += Math.log(time) + truncatedReciprocals += 1 / time + truncatedMin = Math.min(truncatedMin, time) + truncatedMax = Math.max(truncatedMax, time) } return { - total: sum, - arithmetic: sum / count, + count, + total, + rate: 1000 * count / total, + min, + max, + median, + arithmetic: total / count, + geometric: Math.exp(logarithms / count), harmonic: count / reciprocals, - geometric: Math.pow(product, 1 / count) + truncatedCount, + truncatedTotal, + truncatedRate: 1000 * truncatedCount / truncatedTotal, + truncatedMin, + truncatedMax, + truncatedArithmetic: truncatedTotal / truncatedCount, + truncatedGeometric: Math.exp(truncatedLogarithms / truncatedCount), + truncatedHarmonic: truncatedCount / truncatedReciprocals, } } @@ -42,11 +86,8 @@ function pass (...args) { console.log(`%cPASS `, 'color:green', ...args) } - -/** -* Who watches the watchers? -*/ await suite('TEST RUNNER CHECK', async () => { + console.assert(failures.length === 0) console.assert(passes.length === 0) @@ -77,25 +118,25 @@ await suite('TEST RUNNER CHECK', async () => { console.log(`%cTEST RUNNER CHECK DONE`, 'font-weight:bold') }) -export function skip (name, fn) { - return new Promise(resolve => { - console.log(`%cSKIP `, 'color:blue', name) - resolve(null) - }) -} - -export function suite (name, fn) { - if (fn.constructor.name === 'AsyncFunction') fn = fn() - if (typeof fn === 'function') fn = new Promise(resolve => resolve(fn())) - return new Promise(async (resolve) => { +export function suite (name, opts, fn) { + if (fn === undefined) fn = opts + return queue.add(async () => { + if (opts?.skip) { + console.group(`%cSKIP `, 'color:CornflowerBlue', name) + console.groupEnd() + return + } + if (fn.constructor.name === 'AsyncFunction') fn = fn() + if (typeof fn === 'function') fn = new Promise(resolve => resolve(fn())) console.group(`%c${name}`, 'font-weight:bold') await fn console.groupEnd() - resolve(null) }) } -export function test (name, fn) { +export function test (name, opts, fn) { + if (opts?.skip) return console.log(`%cSKIP `, 'color:CornflowerBlue', name) + if (fn === undefined) fn = opts if (fn instanceof Promise) { try { return fn @@ -163,17 +204,13 @@ export const assert = { return a !== b }, rejects: async (fn, msg) => { + if (fn.constructor.name === 'AsyncFunction') { + fn = fn() + } if (fn instanceof Promise) { try { - fn.then(() => { throw new Error(msg ?? 'expected async function to reject') }) - .catch((err) => { return true }) - } catch (err) { - return true - } - } else if (fn.constructor.name === 'AsyncFunction') { - try { - fn.then(() => { throw new Error(msg ?? 'expected async function to reject') }) - .catch((err) => { return true }) + await fn + throw new Error(msg ?? 'expected async function to reject') } catch (err) { return true } @@ -182,18 +219,12 @@ export const assert = { } }, resolves: async (fn, msg) => { + if (fn.constructor.name === 'AsyncFunction') { + fn = fn() + } if (fn instanceof Promise) { try { - fn.then(() => { return true }) - .catch((err) => { throw new Error(msg ?? 'expected async function to resolve') }) - return true - } catch (err) { - throw new Error(msg ?? 'expected async function to resolve') - } - } else if (fn.constructor.name === 'AsyncFunction') { - try { - fn().then(() => { return true }) - .catch((err) => { throw new Error(msg ?? 'expected async function to resolve') }) + await fn return true } catch (err) { throw new Error(msg ?? 'expected async function to resolve') diff --git a/test/QUEUE.mjs b/test/QUEUE.mjs new file mode 100644 index 0000000..68c6cf4 --- /dev/null +++ b/test/QUEUE.mjs @@ -0,0 +1,38 @@ +//! SPDX-FileCopyrightText: 2025 Chris Duncan +//! SPDX-License-Identifier: GPL-3.0-or-later + +/** + * Serially executes asynchronous functions. + */ +export class Queue { + #isIdle + #queue + + constructor () { + this.#isIdle = true + this.#queue = [] + } + + #process = () => { + const { task, resolve, reject, args } = this.#queue.shift() ?? {} + this.#isIdle = !task + task?.(...args).then(resolve).catch(reject).finally(this.#process) + } + + async add (task, ...args) { + if (typeof task !== 'function') throw new TypeError('task is not a function') + return new Promise((resolve, reject) => { + this.#queue.push({ task, resolve, reject, args }) + if (this.#isIdle) this.#process() + }) + } + + async prioritize (task, ...args) { + if (typeof task !== 'function') throw new TypeError('task is not a function') + return new Promise((resolve, reject) => { + if (typeof task !== 'function') reject('task is not a function') + this.#queue.unshift({ task, resolve, reject, args }) + if (this.#isIdle) this.#process() + }) + } +} diff --git a/test/TEST_VECTORS.js b/test/TEST_VECTORS.js deleted file mode 100644 index 33633aa..0000000 --- a/test/TEST_VECTORS.js +++ /dev/null @@ -1,211 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Chris Duncan -// SPDX-License-Identifier: GPL-3.0-or-later - -/** -* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING -* -* Do not send any funds to the test vectors below! -* -* Sources: -* https://docs.nano.org/integration-guides/key-management/#test-vectors -* https://docs.nano.org/integration-guides/key-management/#creating-transactions -* https://github.com/trezor/python-mnemonic/blob/master/vectors.json -* https://tools.nanos.cc/?tool=seed -*/ -export const GENESIS_ADDRESS = 'nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3' -export const RAW_MAX = '340282366920938463463374607431768211455' -export const SUPPLY_MAX = '133248297920938463463374607431768211455' - -export const NANO_TEST_VECTORS = Object.freeze({ - MNEMONIC: 'edge defense waste choose enrich upon flee junk siren film clown finish luggage leader kid quick brick print evidence swap drill paddle truly occur', - PASSWORD: 'some password', - BIP39_SEED: '0DC285FDE768F7FF29B66CE7252D56ED92FE003B605907F7A4F683C3DC8586D34A914D3C71FC099BB38EE4A59E5B081A3497B7A323E90CC68F67B5837690310C', - - PRIVATE_0: '3BE4FC2EF3F3B7374E6FC4FB6E7BB153F8A2998B3B3DAB50853EABE128024143', - PUBLIC_0: '5B65B0E8173EE0802C2C3E6C9080D1A16B06DE1176C938A924F58670904E82C4', - ADDRESS_0: 'nano_1pu7p5n3ghq1i1p4rhmek41f5add1uh34xpb94nkbxe8g4a6x1p69emk8y1d', - - PRIVATE_1: 'CE7E429E683D652446261C17A96DA9ED1897AEA96C8046F2B8036F6B05CB1A83', - PUBLIC_1: 'D9F7762E9CD4E7ED632481308CDB8F54ABF0241332C0A8641F61E92E2FB03C12', - ADDRESS_1: 'nano_3phqgrqbso99xojkb1bijmfryo7dy1k38ep1o3k3yrhb7rqu1h1k47yu78gz', - - PRIVATE_2: '1257DF74609B9C6461A3F4E7FD6E3278F2DDCF2562694F2C3AA0515AF4F09E38', - PUBLIC_2: 'A46DA51986E25A14D82E32D765DCEE69B9EECCD4405411430D91DDB61B717566', - ADDRESS_2: 'nano_3b5fnnerfrkt4me4wepqeqggwtfsxu8fai4n473iu6gxprfq4xd8pk9gh1dg', - - SEND_BLOCK: { - account: "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx", - previous: "92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D", - representative: "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", - balance: "11618869000000000000000000000000", - link: "nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p", - hash: "BB569136FA05F8CBF65CEF2EDE368475B289C4477342976556BA4C0DDF216E45", - key: "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3", - signature: "74BCC59DBA39A1E34A5F75F96D6DE9154E3477AAD7DE30EA563DFCFE501A804228008F98DDF4A15FD35705102785C50EF76732C3A74B0FEC5B0DD67B574A5900", - work: "fbffed7c73b61367" - }, - RECEIVE_BLOCK: { - account: "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx", - previous: "92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D", - representative: "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", - balance: "11618869000000000000000000000000", - link: "CBC911F57B6827649423C92C88C0C56637A4274FF019E77E24D61D12B5338783", - hash: "350D145570578A36D3D5ADE58DC7465F4CAAF257DD55BD93055FF826057E2CDD", - key: "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3", - signature: "EEFFE1EFCCC8F2F6F2F1B79B80ABE855939DD9D6341323186494ADEE775DAADB3B6A6A07A85511F2185F6E739C4A54F1454436E22255A542ED879FD04FEED001", - work: "c5cf86de24b24419" - }, - OPEN_BLOCK: { - account: "nano_1rawdji18mmcu9psd6h87qath4ta7iqfy8i4rqi89sfdwtbcxn57jm9k3q11", - previous: "0000000000000000000000000000000000000000000000000000000000000000", - representative: "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", - balance: "100", - link: "5B2DA492506339C0459867AA1DA1E7EDAAC4344342FAB0848F43B46D248C8E99", - hash: "ED3BE5340CC9D62964B5A5F84375A06078CBEDC45FB5FA2926985D6E27D803BB", - key: "0ED82E6990A16E7AD2375AB5D54BEAABF6C676D09BEC74D9295FCAE35439F694", - signature: "C4C1D0E25E9E1118F0E139704E9001FF54BDABAB4C3A59DE24510E5B48F269ACBC2F3393DFA46B390CA9C6831074829D91E694B81E8C0C2C9C4FA49A757ECB03", - work: "08d09dc3405d9441" - } -}) - -export const TREZOR_TEST_VECTORS = Object.freeze({ - PASSWORD: 'TREZOR', - - ENTROPY_0: "0000000000000000000000000000000000000000000000000000000000000000", - MNEMONIC_0: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art", - SEED_0: "bda85446c68413707090a52022edd26a1c9462295029f2e60cd7c4f2bbd3097170af7a4d73245cafa9c3cca8d561a7c3de6f5d4a10be8ed2a5e608d68f92fcc8", - BIP32_KEY_0: "xprv9s21ZrQH143K32qBagUJAMU2LsHg3ka7jqMcV98Y7gVeVyNStwYS3U7yVVoDZ4btbRNf4h6ibWpY22iRmXq35qgLs79f312g2kj5539ebPM", - BLAKE2B_PRIVATE_0: "9F0E444C69F77A49BD0BE89DB92C38FE713E0963165CCA12FAF5712D7657120F", - BLAKE2B_PUBLIC_0: "C008B814A7D269A1FA3C6528B19201A24D797912DB9996FF02A1FF356E45552B", - BLAKE2B_ADDRESS_0: "nano_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7", - - ENTROPY_1: "7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F", - MNEMONIC_1: "legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth title", - SEED_1: "bc09fca1804f7e69da93c2f2028eb238c227f2e9dda30cd63699232578480a4021b146ad717fbb7e451ce9eb835f43620bf5c514db0f8add49f5d121449d3e87", - BIP32_KEY_1: "xprv9s21ZrQH143K3Y1sd2XVu9wtqxJRvybCfAetjUrMMco6r3v9qZTBeXiBZkS8JxWbcGJZyio8TrZtm6pkbzG8SYt1sxwNLh3Wx7to5pgiVFU", - BLAKE2B_1_PRIVATE_0: "C54F9F69B088B554FF494D4CE7D23EB1B13E89D338F219F83BC91F415C3F7F2D", - BLAKE2B_1_PUBLIC_0: "1573BD1B96ECF80571BF544854026E6A967F065028FBC514B548471DC60B3229", - BLAKE2B_1_ADDRESS_0: "nano_17dmqnfsfu9r1oruyo4aci38wtnphw571c9urncdck495q51pejbp3c648yo", - BLAKE2B_1_PRIVATE_1: "1B704560A0A04EAFD81E8D13481370DA458E2BB00C57F3AA00120D80F6A2BB6F", - BLAKE2B_1_PUBLIC_1: "353288BD57F98A2FC940B4D5A5CE9194EF1598611B00C629E96189320AC7409F", - BLAKE2B_1_ADDRESS_1: "nano_1fbkj4yohyec7z6n3f8onq9b579h4pe848r1rrnykreb8a7egi6z14nozo43", - - ENTROPY_2: "8080808080808080808080808080808080808080808080808080808080808080", - MNEMONIC_2: "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic bless", - SEED_2: "c0c519bd0e91a2ed54357d9d1ebef6f5af218a153624cf4f2da911a0ed8f7a09e2ef61af0aca007096df430022f7a2b6fb91661a9589097069720d015e4e982f", - BIP32_KEY_2: "xprv9s21ZrQH143K3CSnQNYC3MqAAqHwxeTLhDbhF43A4ss4ciWNmCY9zQGvAKUSqVUf2vPHBTSE1rB2pg4avopqSiLVzXEU8KziNnVPauTqLRo", - BLAKE2B_2_PRIVATE_0: "554BE953D1E2DAAD0F8CBC2002967FC158E57032A6C4FD107FFEB2ACA518B613", - BLAKE2B_2_PUBLIC_0: "D85DECD78A303A18CC0D7B65FB384B9C49A7E2EF3666250CBD4F6EC4791513F8", - BLAKE2B_2_ADDRESS_0: "nano_3p4xxmdrne3t5581tyu7zew6q94bnzjgyfm86n8dtmugrjwjc6zrrci4g1rc", - - ENTROPY_3: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", - MNEMONIC_3: "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote", - SEED_3: "dd48c104698c30cfe2b6142103248622fb7bb0ff692eebb00089b32d22484e1613912f0a5b694407be899ffd31ed3992c456cdf60f5d4564b8ba3f05a69890ad", - BIP32_KEY_3: "xprv9s21ZrQH143K2WFF16X85T2QCpndrGwx6GueB72Zf3AHwHJaknRXNF37ZmDrtHrrLSHvbuRejXcnYxoZKvRquTPyp2JiNG3XcjQyzSEgqCB", - BLAKE2B_3_PRIVATE_0: "F1FD8CBD15A54FABDED17C65C4DD44E1F93AAD122FCC1840B1EDEFAAA5BA2B22", - BLAKE2B_3_PUBLIC_0: "6DDE6DDEDE04254B9BC75D04017D4F4406AC7A5F7374550C1EECC8594BFB1E70", - BLAKE2B_3_ADDRESS_0: "nano_1ugyfqhfw337bgfwgqa617ynyj18ojx7ywuncn83xu8ad77zp9mip188iakf" -}) - -export const BIP32_TEST_VECTORS = Object.freeze({ - SEED_0: '000102030405060708090a0b0c0d0e0f', - m_PUB_0: 'xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8', - m_PRV_0: 'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi', - m_0H_PUB_0: 'xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw', - m_0H_PRV_0: 'xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7', - m_0H_1_PUB_0: 'xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ', - m_0H_1_PRV_0: 'xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs', - m_0H_1_2H_PUB_0: 'xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5', - m_0H_1_2H_PRV_0: 'xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM', - m_0H_1_2H_2_PUB_0: 'xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV', - m_0H_1_2H_2_PRV_0: 'xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334', - m_0H_1_2H_2_1000000000_PUB_0: 'xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy', - m_0H_1_2H_2_1000000000_PRV_0: 'xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76', - - SEED_1: 'fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542', - m_PUB_1: 'xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB', - m_PRV_1: 'xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U', - m_0_PUB_1: 'xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH', - m_0_PRV_1: 'xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt', - m_0_2147483647H_PUB_1: 'xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a', - m_0_2147483647H_PRV_1: 'xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9', - m_0_2147483647H_1_PUB_1: 'xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon', - m_0_2147483647H_1_PRV_1: 'xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef', - m_0_2147483647H_1_2147483646H_PUB_1: 'xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL', - m_0_2147483647H_1_2147483646H_PRV_1: 'xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc', - m_0_2147483647H_1_2147483646H_2_PUB_1: 'xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt', - m_0_2147483647H_1_2147483646H_2_PRV_1: 'xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j', - - /** - * These vectors test for the retention of leading zeros. - * See bitpay / bitcore - lib#47 and iancoleman / bip39#58 for more information. - */ - SEED_2: '4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be', - m_PUB_2: 'xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13', - m_PRV_2: 'xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6', - m_0H_PUB_2: 'xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y', - m_0H_PRV_2: 'xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L', - - /** - * These vectors test for the retention of leading zeros. - * See btcsuite / btcutil#172 for more information. - */ - - SEED_3: '3ddd5602285899a946114506157c7997e5444528f3003f6134712147db19b678', - m_PUB_3: 'xpub661MyMwAqRbcGczjuMoRm6dXaLDEhW1u34gKenbeYqAix21mdUKJyuyu5F1rzYGVxyL6tmgBUAEPrEz92mBXjByMRiJdba9wpnN37RLLAXa', - m_PRV_3: 'xprv9s21ZrQH143K48vGoLGRPxgo2JNkJ3J3fqkirQC2zVdk5Dgd5w14S7fRDyHH4dWNHUgkvsvNDCkvAwcSHNAQwhwgNMgZhLtQC63zxwhQmRv', - m_0H_PUB_3: 'xpub69AUMk3qDBi3uW1sXgjCmVjJ2G6WQoYSnNHyzkmdCHEhSZ4tBok37xfFEqHd2AddP56Tqp4o56AePAgCjYdvpW2PU2jbUPFKsav5ut6Ch1m', - m_0H_PRV_3: 'xprv9vB7xEWwNp9kh1wQRfCCQMnZUEG21LpbR9NPCNN1dwhiZkjjeGRnaALmPXCX7SgjFTiCTT6bXes17boXtjq3xLpcDjzEuGLQBM5ohqkao9G', - m_0H_1H_PUB_3: 'xpub6BJA1jSqiukeaesWfxe6sNK9CCGaujFFSJLomWHprUL9DePQ4JDkM5d88n49sMGJxrhpjazuXYWdMf17C9T5XnxkopaeS7jGk1GyyVziaMt', - m_0H_1H_PRV_3: 'xprv9xJocDuwtYCMNAo3Zw76WENQeAS6WGXQ55RCy7tDJ8oALr4FWkuVoHJeHVAcAqiZLE7Je3vZJHxspZdFHfnBEjHqU5hG1Jaj32dVoS6XLT1', - - /** - * These vectors test that invalid extended keys are recognized as invalid. - */ - INVALID_0: 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6LBpB85b3D2yc8sfvZU521AAwdZafEz7mnzBBsz4wKY5fTtTQBm', // (pubkey version / prvkey mismatch) - INVALID_1: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGTQQD3dC4H2D5GBj7vWvSQaaBv5cxi9gafk7NF3pnBju6dwKvH', // (prvkey version / pubkey mismatch) - INVALID_2: 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Txnt3siSujt9RCVYsx4qHZGc62TG4McvMGcAUjeuwZdduYEvFn', // (invalid pubkey prefix 04) - INVALID_3: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGpWnsj83BHtEy5Zt8CcDr1UiRXuWCmTQLxEK9vbz5gPstX92JQ', // (invalid prvkey prefix 04) - INVALID_4: 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6N8ZMMXctdiCjxTNq964yKkwrkBJJwpzZS4HS2fxvyYUA4q2Xe4', // (invalid pubkey prefix 01) - INVALID_5: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD9y5gkZ6Eq3Rjuahrv17fEQ3Qen6J', // (invalid prvkey prefix 01) - INVALID_6: 'xprv9s2SPatNQ9Vc6GTbVMFPFo7jsaZySyzk7L8n2uqKXJen3KUmvQNTuLh3fhZMBoG3G4ZW1N2kZuHEPY53qmbZzCHshoQnNf4GvELZfqTUrcv', // (zero depth with non - zero parent fingerprint) - INVALID_7: 'xpub661no6RGEX3uJkY4bNnPcw4URcQTrSibUZ4NqJEw5eBkv7ovTwgiT91XX27VbEXGENhYRCf7hyEbWrR3FewATdCEebj6znwMfQkhRYHRLpJ', // (zero depth with non - zero parent fingerprint) - INVALID_8: 'xprv9s21ZrQH4r4TsiLvyLXqM9P7k1K3EYhA1kkD6xuquB5i39AU8KF42acDyL3qsDbU9NmZn6MsGSUYZEsuoePmjzsB3eFKSUEh3Gu1N3cqVUN', // (zero depth with non - zero index) - INVALID_9: 'xpub661MyMwAuDcm6CRQ5N4qiHKrJ39Xe1R1NyfouMKTTWcguwVcfrZJaNvhpebzGerh7gucBvzEQWRugZDuDXjNDRmXzSZe4c7mnTK97pTvGS8', // (zero depth with non - zero index) - INVALID_10: 'DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHGMQzT7ayAmfo4z3gY5KfbrZWZ6St24UVf2Qgo6oujFktLHdHY4', // (unknown extended key version) - INVALID_11: 'DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHPmHJiEDXkTiJTVV9rHEBUem2mwVbbNfvT2MTcAqj3nesx8uBf9', // (unknown extended key version) - INVALID_12: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzF93Y5wvzdUayhgkkFoicQZcP3y52uPPxFnfoLZB21Teqt1VvEHx', // (private key 0 not in 1..n - 1) - INVALID_13: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD5SDKr24z3aiUvKr9bJpdrcLg1y3G', // (private key n not in 1..n - 1) - INVALID_14: 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Q5JXayek4PRsn35jii4veMimro1xefsM58PgBMrvdYre8QyULY', // (invalid pubkey 020000000000000000000000000000000000000000000000000000000000000007) - INVALID_15: 'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHL' // (invalid checksum) -}) - -export const CUSTOM_TEST_VECTORS = Object.freeze({ - ENTROPY_0: "00000000000000000000000000000000", - MNEMONIC_0: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about", - SEED_0: "5EB00BBDDCF069084889A8AB9155568165F5C453CCB85E70811AAED6F6DA5FC19A5AC40B389CD370D086206DEC8AA6C43DAEA6690F20AD3D8D48B2D2CE9E38E4", - PRIVATE_0: "7F72C7D17BEAC5CDC249D3AEBA8BF76D640129F69DB17E584A4A98E635855D7C", - PUBLIC_0: "588FAABCE802DF8C1700BDF50F2861DE1C0FA48B38B27ECE910D7C696759BAF5", - ADDRESS_0: "nano_1p6hocygi1pzjidi3hho3wn85qiw3ykapg7khu9b45dwf7momgqoytn1c1jz", - - ENTROPY_1: "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", - MNEMONIC_1: "legal winner thank year wave sausage worth useful legal winner thank year wave sausage wise", - SEED_1: "D95F1FAA0F8AEA406101A81510690D781DA04C86678FC5A13A09C251B7505BB6D17EC0BB408F9D2D6BC9434ADBD79491F09F91186B1E445A392D682D8DB586AD", - PRIVATE_1: "8971838804CE4D715A9250D673EACCAEA7AF26349B6E43B50CCC5554DF0BD342", - PUBLIC_1: "D1DBB524EF0A1A56C91E2EDCE4D7E1A5814CCC45C1B18EDF657E2859BB96A1E9", - ADDRESS_1: "nano_3ngupnkgy4itcu6jwdpwwmdy5be3bm86difjjuhpczjad8xsfahbg61c7ipy", - - ENTROPY_2: "808080808080808080808080808080808080808080808080", - MNEMONIC_2: "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter always", - SEED_2: "04D5F77103510C41D610F7F5FB3F0BADC77C377090815CEE808EA5D2F264FDFABF7C7DED4BE6D4C6D7CDB021BA4C777B0B7E57CA8AA6DE15AEB9905DBA674D66", - PRIVATE_2: "50F76F0211E8F18D3554C6C0DD8131E75BDBB2AC392BF6FBE23698E900EFCA13", - PUBLIC_2: "9C93BD3C0796381F7562E3E14D2E3CF0F4056226149D7CAC891B241434B4285A", - ADDRESS_2: "nano_396mqny1h7jr5xtp7rz3bnq5sw9n1oj4e76xhkpak8s64itdac4t95ux7xn4", - - ENTROPY_3: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - MNEMONIC_3: "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo veteran", - SEED_3: "DB4BFE5911205C0B2E048CEEF790D0433A902A070D0744AF9B5E88ED5E0AEF548246102DD6BA2313E418FD799360E2DBD8EB93EE40FE0942517555B66E89D488", - PRIVATE_3: "133F351F1EDF5B4FE86EA7849AEC2C7E4D3F5F16C0CBAB4A236ADF17ACCB98B0", - PUBLIC_3: "2D6E50265036DE634FC71A2F9BE8A336AB991B8751C15D883ACCD90BFD3BEDB6", - ADDRESS_3: "nano_1ddgc1m71fpyef9wg8jhmhnc8fodm6frgng3dp65om8s3hymqufp8jefijxu", -}) diff --git a/test/VECTORS.js b/test/VECTORS.js new file mode 100644 index 0000000..36a1ac5 --- /dev/null +++ b/test/VECTORS.js @@ -0,0 +1,2841 @@ +// SPDX-FileCopyrightText: 2024 Chris Duncan +// SPDX-License-Identifier: GPL-3.0-or-later + +/** +* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING +* +* Do not send any funds to the test vectors below! +* +* Sources: +* https://docs.nano.org/integration-guides/key-management/#test-vectors +* https://docs.nano.org/integration-guides/key-management/#creating-transactions +* https://github.com/trezor/python-mnemonic/blob/master/vectors.json +* https://tools.nanos.cc/?tool=seed +*/ +export const GENESIS_ADDRESS = 'nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3' +export const RAW_MAX = '340282366920938463463374607431768211455' +export const SUPPLY_MAX = '133248297920938463463374607431768211455' + +export const NANO_TEST_VECTORS = Object.freeze({ + MNEMONIC: 'edge defense waste choose enrich upon flee junk siren film clown finish luggage leader kid quick brick print evidence swap drill paddle truly occur', + PASSWORD: 'some password', + BIP39_SEED: '0DC285FDE768F7FF29B66CE7252D56ED92FE003B605907F7A4F683C3DC8586D34A914D3C71FC099BB38EE4A59E5B081A3497B7A323E90CC68F67B5837690310C', + + PRIVATE_0: '3BE4FC2EF3F3B7374E6FC4FB6E7BB153F8A2998B3B3DAB50853EABE128024143', + PUBLIC_0: '5B65B0E8173EE0802C2C3E6C9080D1A16B06DE1176C938A924F58670904E82C4', + ADDRESS_0: 'nano_1pu7p5n3ghq1i1p4rhmek41f5add1uh34xpb94nkbxe8g4a6x1p69emk8y1d', + + PRIVATE_1: 'CE7E429E683D652446261C17A96DA9ED1897AEA96C8046F2B8036F6B05CB1A83', + PUBLIC_1: 'D9F7762E9CD4E7ED632481308CDB8F54ABF0241332C0A8641F61E92E2FB03C12', + ADDRESS_1: 'nano_3phqgrqbso99xojkb1bijmfryo7dy1k38ep1o3k3yrhb7rqu1h1k47yu78gz', + + PRIVATE_2: '1257DF74609B9C6461A3F4E7FD6E3278F2DDCF2562694F2C3AA0515AF4F09E38', + PUBLIC_2: 'A46DA51986E25A14D82E32D765DCEE69B9EECCD4405411430D91DDB61B717566', + ADDRESS_2: 'nano_3b5fnnerfrkt4me4wepqeqggwtfsxu8fai4n473iu6gxprfq4xd8pk9gh1dg', + + SEND_BLOCK: { + account: "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx", + previous: "92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D", + representative: "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", + balance: "11618869000000000000000000000000", + link: "nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p", + hash: "BB569136FA05F8CBF65CEF2EDE368475B289C4477342976556BA4C0DDF216E45", + key: "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3", + signature: "74BCC59DBA39A1E34A5F75F96D6DE9154E3477AAD7DE30EA563DFCFE501A804228008F98DDF4A15FD35705102785C50EF76732C3A74B0FEC5B0DD67B574A5900", + work: "fbffed7c73b61367" + }, + RECEIVE_BLOCK: { + account: "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx", + previous: "92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D", + representative: "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", + balance: "11618869000000000000000000000000", + link: "CBC911F57B6827649423C92C88C0C56637A4274FF019E77E24D61D12B5338783", + hash: "350D145570578A36D3D5ADE58DC7465F4CAAF257DD55BD93055FF826057E2CDD", + key: "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3", + signature: "EEFFE1EFCCC8F2F6F2F1B79B80ABE855939DD9D6341323186494ADEE775DAADB3B6A6A07A85511F2185F6E739C4A54F1454436E22255A542ED879FD04FEED001", + work: "c5cf86de24b24419" + }, + OPEN_BLOCK: { + account: "nano_1rawdji18mmcu9psd6h87qath4ta7iqfy8i4rqi89sfdwtbcxn57jm9k3q11", + previous: "0000000000000000000000000000000000000000000000000000000000000000", + representative: "nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou", + balance: "100", + link: "5B2DA492506339C0459867AA1DA1E7EDAAC4344342FAB0848F43B46D248C8E99", + hash: "ED3BE5340CC9D62964B5A5F84375A06078CBEDC45FB5FA2926985D6E27D803BB", + key: "0ED82E6990A16E7AD2375AB5D54BEAABF6C676D09BEC74D9295FCAE35439F694", + signature: "C4C1D0E25E9E1118F0E139704E9001FF54BDABAB4C3A59DE24510E5B48F269ACBC2F3393DFA46B390CA9C6831074829D91E694B81E8C0C2C9C4FA49A757ECB03", + work: "08d09dc3405d9441" + } +}) + +export const TREZOR_TEST_VECTORS = Object.freeze({ + PASSWORD: 'TREZOR', + + ENTROPY_0: "0000000000000000000000000000000000000000000000000000000000000000", + MNEMONIC_0: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art", + SEED_0: "bda85446c68413707090a52022edd26a1c9462295029f2e60cd7c4f2bbd3097170af7a4d73245cafa9c3cca8d561a7c3de6f5d4a10be8ed2a5e608d68f92fcc8", + BIP32_KEY_0: "xprv9s21ZrQH143K32qBagUJAMU2LsHg3ka7jqMcV98Y7gVeVyNStwYS3U7yVVoDZ4btbRNf4h6ibWpY22iRmXq35qgLs79f312g2kj5539ebPM", + BLAKE2B_PRIVATE_0: "9F0E444C69F77A49BD0BE89DB92C38FE713E0963165CCA12FAF5712D7657120F", + BLAKE2B_PUBLIC_0: "C008B814A7D269A1FA3C6528B19201A24D797912DB9996FF02A1FF356E45552B", + BLAKE2B_ADDRESS_0: "nano_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7", + + ENTROPY_1: "7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F", + MNEMONIC_1: "legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth title", + SEED_1: "bc09fca1804f7e69da93c2f2028eb238c227f2e9dda30cd63699232578480a4021b146ad717fbb7e451ce9eb835f43620bf5c514db0f8add49f5d121449d3e87", + BIP32_KEY_1: "xprv9s21ZrQH143K3Y1sd2XVu9wtqxJRvybCfAetjUrMMco6r3v9qZTBeXiBZkS8JxWbcGJZyio8TrZtm6pkbzG8SYt1sxwNLh3Wx7to5pgiVFU", + BLAKE2B_1_PRIVATE_0: "C54F9F69B088B554FF494D4CE7D23EB1B13E89D338F219F83BC91F415C3F7F2D", + BLAKE2B_1_PUBLIC_0: "1573BD1B96ECF80571BF544854026E6A967F065028FBC514B548471DC60B3229", + BLAKE2B_1_ADDRESS_0: "nano_17dmqnfsfu9r1oruyo4aci38wtnphw571c9urncdck495q51pejbp3c648yo", + BLAKE2B_1_PRIVATE_1: "1B704560A0A04EAFD81E8D13481370DA458E2BB00C57F3AA00120D80F6A2BB6F", + BLAKE2B_1_PUBLIC_1: "353288BD57F98A2FC940B4D5A5CE9194EF1598611B00C629E96189320AC7409F", + BLAKE2B_1_ADDRESS_1: "nano_1fbkj4yohyec7z6n3f8onq9b579h4pe848r1rrnykreb8a7egi6z14nozo43", + + ENTROPY_2: "8080808080808080808080808080808080808080808080808080808080808080", + MNEMONIC_2: "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic bless", + SEED_2: "c0c519bd0e91a2ed54357d9d1ebef6f5af218a153624cf4f2da911a0ed8f7a09e2ef61af0aca007096df430022f7a2b6fb91661a9589097069720d015e4e982f", + BIP32_KEY_2: "xprv9s21ZrQH143K3CSnQNYC3MqAAqHwxeTLhDbhF43A4ss4ciWNmCY9zQGvAKUSqVUf2vPHBTSE1rB2pg4avopqSiLVzXEU8KziNnVPauTqLRo", + BLAKE2B_2_PRIVATE_0: "554BE953D1E2DAAD0F8CBC2002967FC158E57032A6C4FD107FFEB2ACA518B613", + BLAKE2B_2_PUBLIC_0: "D85DECD78A303A18CC0D7B65FB384B9C49A7E2EF3666250CBD4F6EC4791513F8", + BLAKE2B_2_ADDRESS_0: "nano_3p4xxmdrne3t5581tyu7zew6q94bnzjgyfm86n8dtmugrjwjc6zrrci4g1rc", + + ENTROPY_3: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + MNEMONIC_3: "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote", + SEED_3: "dd48c104698c30cfe2b6142103248622fb7bb0ff692eebb00089b32d22484e1613912f0a5b694407be899ffd31ed3992c456cdf60f5d4564b8ba3f05a69890ad", + BIP32_KEY_3: "xprv9s21ZrQH143K2WFF16X85T2QCpndrGwx6GueB72Zf3AHwHJaknRXNF37ZmDrtHrrLSHvbuRejXcnYxoZKvRquTPyp2JiNG3XcjQyzSEgqCB", + BLAKE2B_3_PRIVATE_0: "F1FD8CBD15A54FABDED17C65C4DD44E1F93AAD122FCC1840B1EDEFAAA5BA2B22", + BLAKE2B_3_PUBLIC_0: "6DDE6DDEDE04254B9BC75D04017D4F4406AC7A5F7374550C1EECC8594BFB1E70", + BLAKE2B_3_ADDRESS_0: "nano_1ugyfqhfw337bgfwgqa617ynyj18ojx7ywuncn83xu8ad77zp9mip188iakf" +}) + +export const BIP32_TEST_VECTORS = Object.freeze({ + SEED_0: '000102030405060708090a0b0c0d0e0f', + m_PUB_0: 'xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8', + m_PRV_0: 'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi', + m_0H_PUB_0: 'xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw', + m_0H_PRV_0: 'xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7', + m_0H_1_PUB_0: 'xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ', + m_0H_1_PRV_0: 'xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs', + m_0H_1_2H_PUB_0: 'xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5', + m_0H_1_2H_PRV_0: 'xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM', + m_0H_1_2H_2_PUB_0: 'xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV', + m_0H_1_2H_2_PRV_0: 'xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334', + m_0H_1_2H_2_1000000000_PUB_0: 'xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy', + m_0H_1_2H_2_1000000000_PRV_0: 'xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76', + + SEED_1: 'fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542', + m_PUB_1: 'xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB', + m_PRV_1: 'xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U', + m_0_PUB_1: 'xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH', + m_0_PRV_1: 'xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt', + m_0_2147483647H_PUB_1: 'xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a', + m_0_2147483647H_PRV_1: 'xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9', + m_0_2147483647H_1_PUB_1: 'xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon', + m_0_2147483647H_1_PRV_1: 'xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef', + m_0_2147483647H_1_2147483646H_PUB_1: 'xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL', + m_0_2147483647H_1_2147483646H_PRV_1: 'xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc', + m_0_2147483647H_1_2147483646H_2_PUB_1: 'xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt', + m_0_2147483647H_1_2147483646H_2_PRV_1: 'xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j', + + /** + * These vectors test for the retention of leading zeros. + * See bitpay / bitcore - lib#47 and iancoleman / bip39#58 for more information. + */ + SEED_2: '4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be', + m_PUB_2: 'xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13', + m_PRV_2: 'xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6', + m_0H_PUB_2: 'xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y', + m_0H_PRV_2: 'xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L', + + /** + * These vectors test for the retention of leading zeros. + * See btcsuite / btcutil#172 for more information. + */ + SEED_3: '3ddd5602285899a946114506157c7997e5444528f3003f6134712147db19b678', + m_PUB_3: 'xpub661MyMwAqRbcGczjuMoRm6dXaLDEhW1u34gKenbeYqAix21mdUKJyuyu5F1rzYGVxyL6tmgBUAEPrEz92mBXjByMRiJdba9wpnN37RLLAXa', + m_PRV_3: 'xprv9s21ZrQH143K48vGoLGRPxgo2JNkJ3J3fqkirQC2zVdk5Dgd5w14S7fRDyHH4dWNHUgkvsvNDCkvAwcSHNAQwhwgNMgZhLtQC63zxwhQmRv', + m_0H_PUB_3: 'xpub69AUMk3qDBi3uW1sXgjCmVjJ2G6WQoYSnNHyzkmdCHEhSZ4tBok37xfFEqHd2AddP56Tqp4o56AePAgCjYdvpW2PU2jbUPFKsav5ut6Ch1m', + m_0H_PRV_3: 'xprv9vB7xEWwNp9kh1wQRfCCQMnZUEG21LpbR9NPCNN1dwhiZkjjeGRnaALmPXCX7SgjFTiCTT6bXes17boXtjq3xLpcDjzEuGLQBM5ohqkao9G', + m_0H_1H_PUB_3: 'xpub6BJA1jSqiukeaesWfxe6sNK9CCGaujFFSJLomWHprUL9DePQ4JDkM5d88n49sMGJxrhpjazuXYWdMf17C9T5XnxkopaeS7jGk1GyyVziaMt', + m_0H_1H_PRV_3: 'xprv9xJocDuwtYCMNAo3Zw76WENQeAS6WGXQ55RCy7tDJ8oALr4FWkuVoHJeHVAcAqiZLE7Je3vZJHxspZdFHfnBEjHqU5hG1Jaj32dVoS6XLT1', + + /** + * These vectors test that invalid extended keys are recognized as invalid. + */ + INVALID_0: 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6LBpB85b3D2yc8sfvZU521AAwdZafEz7mnzBBsz4wKY5fTtTQBm', // (pubkey version / prvkey mismatch) + INVALID_1: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGTQQD3dC4H2D5GBj7vWvSQaaBv5cxi9gafk7NF3pnBju6dwKvH', // (prvkey version / pubkey mismatch) + INVALID_2: 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Txnt3siSujt9RCVYsx4qHZGc62TG4McvMGcAUjeuwZdduYEvFn', // (invalid pubkey prefix 04) + INVALID_3: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGpWnsj83BHtEy5Zt8CcDr1UiRXuWCmTQLxEK9vbz5gPstX92JQ', // (invalid prvkey prefix 04) + INVALID_4: 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6N8ZMMXctdiCjxTNq964yKkwrkBJJwpzZS4HS2fxvyYUA4q2Xe4', // (invalid pubkey prefix 01) + INVALID_5: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD9y5gkZ6Eq3Rjuahrv17fEQ3Qen6J', // (invalid prvkey prefix 01) + INVALID_6: 'xprv9s2SPatNQ9Vc6GTbVMFPFo7jsaZySyzk7L8n2uqKXJen3KUmvQNTuLh3fhZMBoG3G4ZW1N2kZuHEPY53qmbZzCHshoQnNf4GvELZfqTUrcv', // (zero depth with non - zero parent fingerprint) + INVALID_7: 'xpub661no6RGEX3uJkY4bNnPcw4URcQTrSibUZ4NqJEw5eBkv7ovTwgiT91XX27VbEXGENhYRCf7hyEbWrR3FewATdCEebj6znwMfQkhRYHRLpJ', // (zero depth with non - zero parent fingerprint) + INVALID_8: 'xprv9s21ZrQH4r4TsiLvyLXqM9P7k1K3EYhA1kkD6xuquB5i39AU8KF42acDyL3qsDbU9NmZn6MsGSUYZEsuoePmjzsB3eFKSUEh3Gu1N3cqVUN', // (zero depth with non - zero index) + INVALID_9: 'xpub661MyMwAuDcm6CRQ5N4qiHKrJ39Xe1R1NyfouMKTTWcguwVcfrZJaNvhpebzGerh7gucBvzEQWRugZDuDXjNDRmXzSZe4c7mnTK97pTvGS8', // (zero depth with non - zero index) + INVALID_10: 'DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHGMQzT7ayAmfo4z3gY5KfbrZWZ6St24UVf2Qgo6oujFktLHdHY4', // (unknown extended key version) + INVALID_11: 'DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHPmHJiEDXkTiJTVV9rHEBUem2mwVbbNfvT2MTcAqj3nesx8uBf9', // (unknown extended key version) + INVALID_12: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzF93Y5wvzdUayhgkkFoicQZcP3y52uPPxFnfoLZB21Teqt1VvEHx', // (private key 0 not in 1..n - 1) + INVALID_13: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD5SDKr24z3aiUvKr9bJpdrcLg1y3G', // (private key n not in 1..n - 1) + INVALID_14: 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Q5JXayek4PRsn35jii4veMimro1xefsM58PgBMrvdYre8QyULY', // (invalid pubkey 020000000000000000000000000000000000000000000000000000000000000007) + INVALID_15: 'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHL' // (invalid checksum) +}) + +export const CUSTOM_TEST_VECTORS = Object.freeze({ + ENTROPY_0: "00000000000000000000000000000000", + MNEMONIC_0: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about", + SEED_0: "5EB00BBDDCF069084889A8AB9155568165F5C453CCB85E70811AAED6F6DA5FC19A5AC40B389CD370D086206DEC8AA6C43DAEA6690F20AD3D8D48B2D2CE9E38E4", + PRIVATE_0: "7F72C7D17BEAC5CDC249D3AEBA8BF76D640129F69DB17E584A4A98E635855D7C", + PUBLIC_0: "588FAABCE802DF8C1700BDF50F2861DE1C0FA48B38B27ECE910D7C696759BAF5", + ADDRESS_0: "nano_1p6hocygi1pzjidi3hho3wn85qiw3ykapg7khu9b45dwf7momgqoytn1c1jz", + + ENTROPY_1: "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", + MNEMONIC_1: "legal winner thank year wave sausage worth useful legal winner thank year wave sausage wise", + SEED_1: "D95F1FAA0F8AEA406101A81510690D781DA04C86678FC5A13A09C251B7505BB6D17EC0BB408F9D2D6BC9434ADBD79491F09F91186B1E445A392D682D8DB586AD", + PRIVATE_1: "8971838804CE4D715A9250D673EACCAEA7AF26349B6E43B50CCC5554DF0BD342", + PUBLIC_1: "D1DBB524EF0A1A56C91E2EDCE4D7E1A5814CCC45C1B18EDF657E2859BB96A1E9", + ADDRESS_1: "nano_3ngupnkgy4itcu6jwdpwwmdy5be3bm86difjjuhpczjad8xsfahbg61c7ipy", + + ENTROPY_2: "808080808080808080808080808080808080808080808080", + MNEMONIC_2: "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter always", + SEED_2: "04D5F77103510C41D610F7F5FB3F0BADC77C377090815CEE808EA5D2F264FDFABF7C7DED4BE6D4C6D7CDB021BA4C777B0B7E57CA8AA6DE15AEB9905DBA674D66", + PRIVATE_2: "50F76F0211E8F18D3554C6C0DD8131E75BDBB2AC392BF6FBE23698E900EFCA13", + PUBLIC_2: "9C93BD3C0796381F7562E3E14D2E3CF0F4056226149D7CAC891B241434B4285A", + ADDRESS_2: "nano_396mqny1h7jr5xtp7rz3bnq5sw9n1oj4e76xhkpak8s64itdac4t95ux7xn4", + + ENTROPY_3: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + MNEMONIC_3: "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo veteran", + SEED_3: "DB4BFE5911205C0B2E048CEEF790D0433A902A070D0744AF9B5E88ED5E0AEF548246102DD6BA2313E418FD799360E2DBD8EB93EE40FE0942517555B66E89D488", + PRIVATE_3: "133F351F1EDF5B4FE86EA7849AEC2C7E4D3F5F16C0CBAB4A236ADF17ACCB98B0", + PUBLIC_3: "2D6E50265036DE634FC71A2F9BE8A336AB991B8751C15D883ACCD90BFD3BEDB6", + ADDRESS_3: "nano_1ddgc1m71fpyef9wg8jhmhnc8fodm6frgng3dp65om8s3hymqufp8jefijxu", +}) + +export const BLAKE2B_TEST_VECTORS = Object.freeze({ + LIBSODIUM: [ + { "outlen": 1, "out": "ba", "in": "", "key": "00", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 2, "out": "6139", "in": "00", "key": "0001", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 3, "out": "3a1666", "in": "0001", "key": "000102", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 4, "out": "5797e9d0", "in": "000102", "key": "00010203", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 5, "out": "834a26efe6", "in": "00010203", "key": "0001020304", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 6, "out": "d7e9e862bbce", "in": "0001020304", "key": "000102030405", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 7, "out": "40d8b84c374750", "in": "000102030405", "key": "00010203040506", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 8, "out": "276789189244cf04", "in": "00010203040506", "key": "0001020304050607", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 9, "out": "16f73ffe0673cc9992", "in": "0001020304050607", "key": "000102030405060708", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 10, "out": "b3835bfaf6eb71d94078", "in": "000102030405060708", "key": "00010203040506070809", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 11, "out": "8c624e844d34f4a59f34cc", "in": "00010203040506070809", "key": "000102030405060708090a", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 12, "out": "e0a394962413ad09975df3cf", "in": "000102030405060708090a", "key": "000102030405060708090a0b", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 13, "out": "47f043c3aacb501f97e0458ae3", "in": "000102030405060708090a0b", "key": "000102030405060708090a0b0c", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 14, "out": "b4a11f2fb72a7e6f96fdacf98d49", "in": "000102030405060708090a0b0c", "key": "000102030405060708090a0b0c0d", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 15, "out": "f434079e9adeb244047cb6855f9854", "in": "000102030405060708090a0b0c0d", "key": "000102030405060708090a0b0c0d0e", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 16, "out": "5fbe885c4b2d4e0d78dc5905622a277a", "in": "000102030405060708090a0b0c0d0e", "key": "000102030405060708090a0b0c0d0e0f", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 17, "out": "e262ba3e2ab76efdf83513108e3b987d1b", "in": "000102030405060708090a0b0c0d0e0f", "key": "000102030405060708090a0b0c0d0e0f10", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 18, "out": "add93dde78d32e77bc039c34a49043f19d26", "in": "000102030405060708090a0b0c0d0e0f10", "key": "000102030405060708090a0b0c0d0e0f1011", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 19, "out": "093842ac10e2eb1237ddc9ca9e7990cf397772", "in": "000102030405060708090a0b0c0d0e0f1011", "key": "000102030405060708090a0b0c0d0e0f101112", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 20, "out": "09e7f6a0e2ea4888f1dbf6562effd1561c65029c", "in": "000102030405060708090a0b0c0d0e0f101112", "key": "000102030405060708090a0b0c0d0e0f10111213", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 21, "out": "bd33a9ec914f5b81864a49184338e4062d6c6b2b2e", "in": "000102030405060708090a0b0c0d0e0f10111213", "key": "000102030405060708090a0b0c0d0e0f1011121314", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 22, "out": "8dc46295235d94f5881d429a5ad47f9db9e35cf8c6b3", "in": "000102030405060708090a0b0c0d0e0f1011121314", "key": "000102030405060708090a0b0c0d0e0f101112131415", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 23, "out": "ba5df554dca7ac1cba4889fa88adf3070fbf4ab5d187b5", "in": "000102030405060708090a0b0c0d0e0f101112131415", "key": "000102030405060708090a0b0c0d0e0f10111213141516", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 24, "out": "1ff84715e71c66214d271d421395fb6166db97b1d47ed697", "in": "000102030405060708090a0b0c0d0e0f10111213141516", "key": "000102030405060708090a0b0c0d0e0f1011121314151617", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 25, "out": "75a0d227c70549f5b0c933b7b21f151355bd47e04b6085c91f", "in": "000102030405060708090a0b0c0d0e0f1011121314151617", "key": "000102030405060708090a0b0c0d0e0f101112131415161718", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 26, "out": "a32a5c9439a0fa771dcbe7f338b5dcef62a754edc4952614d6f0", "in": "000102030405060708090a0b0c0d0e0f101112131415161718", "key": "000102030405060708090a0b0c0d0e0f10111213141516171819", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 27, "out": "53a87de519cdcc7f64730d58bce6baaf7b44c5c428a4611a208ad4", "in": "000102030405060708090a0b0c0d0e0f10111213141516171819", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 28, "out": "5e5ad8f0c4f083f9b7a5154d9c0dfd0f3d2fce94cf54fc215450314a", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 29, "out": "9c76b9e63c77e6564b1e5111c2fb140046e1e5a4f900a7cfc2bac3fcfa", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 30, "out": "bb919251ca310eb9b994e5d7883bc9fa2144b59b8d5d940677b7130ac777", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 31, "out": "faa492a66f08ef0c7adb868fcb7b523aedd35b8ff1414bd1d554794f144474", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 32, "out": "9b273ebe335540b87be899abe169389ed61ed262c3a0a16e4998bbf752f0bee3", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 33, "out": "1e0070b92429c151b33bdd1bb4430a0e650a3dfc94d404054e93c8568330ecc505", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 34, "out": "e3b64149f1b76231686d592d1d4af984ce2826ba03c2224a92f95f9526130ce4eb40", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 35, "out": "5f8e378120b73db9eefa65ddcdcdcb4acd8046c31a5e47f298caa400937d5623f1394b", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 36, "out": "74c757a4165a1782c933e587353a9fd8f6d7bf26b7f51b52c542747030bfb3d560c2e5c2", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 37, "out": "2d5ee85cc238b923806dd98db18919d1924f2340ec88917d4ce1799cbfd5f2cb9df99db2e1", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 38, "out": "c93ff727e6f9822efec0a77eed0025c0eff19127bf8746b7c71c2a098f57cef02febb86a1e6c", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 39, "out": "adfb6d7ba13779a5dd1bbf268e400f4156f0f5c9d5b670ff539e1d9c1a63373416f3001f338407", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 40, "out": "3a6900e58a448887d77c5911e4bdde620e64f25b2d71723fa60f7cb3efa7c320b6153bdbc3287949", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 41, "out": "413eb0fd379b32dd88e82242a87cc58ce3e64c72352387a4c70f92ee5c8d23fa7ecd86f6df170a32d2", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 42, "out": "92d0d3cacc3e25628caf6f2c4cd50d25d154ac45098f531d690230b859f37cfe089eb169f76bba72a3ff", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526272829", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 43, "out": "92f6ccc11a9a3bee520b17e0cddc4550c0e9cf47ddd9a6161284259ffb161c1d0675b505cb1066872768e8", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526272829", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 44, "out": "a3cd675804e6be7f120138a9eaadcd56bb7763d1c046e87fe0d358c8276b0d24621f46c60b46e397933b75b4", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 45, "out": "304a1af53cbdd6486b8419d1ebd5e9528c540d8dc46a10be49067f46a0617229577015d776783f702b2954df43", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 46, "out": "d8a6358970446453ac0c82c758644ab68989b5b4f06f9768807ce0c5f2a0dbac1e8450f4e3a02deecf7b54b6a45d", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 47, "out": "1264b8dee9ac4aa8de69a43ada95cc95f20230f33836d4a1db8c2466ab38361686e5ac282025ccc2e0f6a1cd98a4dd", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 48, "out": "7eed787abaa7f4e8b8aa3090f0676201cfbaaf350899661cdd5216ac0b5cd874443f5c0688ffd7ca1ccbfe1ca7e1a3f5", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 49, "out": "8907f0218585167962a8e8213559a643dd03c2bf1a7a5ad3e3bc5f88c0ff1532ee8cd29880e7e0e68da22a5798aef27cc5", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 50, "out": "12dea17b0733e5060751b1115e10c3d4b2f4583bcd009d9f1f42ec23d4a6a0df1185d3abbdbe86de08569e70583d6de1c1fe", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 51, "out": "8ff75e91f1de547dc3a25472db2f51f5910a290c449603da54207b5e39bd735d240ec913b52df90709b5d29357971d6c341452", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 52, "out": "4a3b16b12400f38e74778efc3a4caa52ec6fdf6b0180a5bfac9189e52e162c10e8911a54ab33e2b389ee1949e58edaa119e2b2b9", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 53, "out": "c9943e7186fdc9bbfa1d7087fa7086babe6fcf95a6196d1772187854071304e2f1fff39e6e6f48f76addb16d5c00249e0523aac91f", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 54, "out": "0297f16fdd34add9cc87b4adf816525b590ba08ac733c43f8d225d194df4f9c83b4dce617be51e25b5f6c80dff249f27c707de20e422", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 55, "out": "576bb891eab9930998e2e73b5d0498e3c5f040f8dec9397a8c7a622c17de01fee7cc936e3bd4de1f7fd8b31dea9e70c65462bbb5dc7b50", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 56, "out": "9416a57ae7c8c51c6e008f940fe06d8ebc02c350c19a2f71583a6d260b085670d73a95248fef0f4cae5292ba7db1189a7cd9c51122ba7913", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 57, "out": "ea644b9051cca5eee8868a553e3f0f4e14739e1555474151156e10578256b288a233870dd43a380765400ea446df7f452c1e03a9e5b6731256", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 58, "out": "f99cc1603de221abc1ecb1a7eb4bbf06e99561d1cc5541d8d601bae2b1dd3cbe448ac276667f26de5e269183a09f7deaf35d33174b3cc8ad4aa2", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536373839", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 59, "out": "ee2be1ec57fdac23f89402a534177eca0f4b982a4ed2c2e900b6a79e1f47a2d023eff2e647baf4f4c0da3a28d08a44bc780516974074e2523e6651", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536373839", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 60, "out": "9cda001868949a2bad96c5b3950a8315e6e5214d0b54dcd596280565d351806ef22cf3053f63623da72fcad9afa3896641658632334c9ec4f644c984", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 61, "out": "c6d6722a916651a8671383d8260873347d9c248696b4cb3dac4dea9ba57ed971127cb18e44211d7e14177ace248b3c6e0785356ee261ebdc6ef0faf143", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 62, "out": "5dd258a3e7505bc6b9776b0df25676a1c19e2c8258c7b5f2e361423523d96299eb6827bc7c27e7bca2d2b59d717c2ebcb05e6dcaa32289d96fae9a4077ef", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 63, "out": "19c14de35fe19c92cc0e624280e4136355d4cfa9a0a98b090c4b06f5665021920725852ff1f566b0c8c37157b25fb9f947a2e70b40577a17860a0732c170ac", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" }, + { "outlen": 64, "out": "5fcdcc02be7714a0dbc77df498bf999ea9225d564adca1c121c9af03af92cac8177b9b4a86bcc47c79aa32aac58a3fef967b2132e9352d4613fe890beed2571b", "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e", "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "salt": "35623662343165643962333433666530", "personal": "35313236666232613337343030643261" } + ], + REFERENCE: [ + { + "in": "", + "key": "", + "out": "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce" + }, + { + "in": "00", + "key": "", + "out": "2fa3f686df876995167e7c2e5d74c4c7b6e48f8068fe0e44208344d480f7904c36963e44115fe3eb2a3ac8694c28bcb4f5a0f3276f2e79487d8219057a506e4b" + }, + { + "in": "0001", + "key": "", + "out": "1c08798dc641aba9dee435e22519a4729a09b2bfe0ff00ef2dcd8ed6f8a07d15eaf4aee52bbf18ab5608a6190f70b90486c8a7d4873710b1115d3debbb4327b5" + }, + { + "in": "000102", + "key": "", + "out": "40a374727302d9a4769c17b5f409ff32f58aa24ff122d7603e4fda1509e919d4107a52c57570a6d94e50967aea573b11f86f473f537565c66f7039830a85d186" + }, + { + "in": "00010203", + "key": "", + "out": "77ddf4b14425eb3d053c1e84e3469d92c4cd910ed20f92035e0c99d8a7a86cecaf69f9663c20a7aa230bc82f60d22fb4a00b09d3eb8fc65ef547fe63c8d3ddce" + }, + { + "in": "0001020304", + "key": "", + "out": "cbaa0ba7d482b1f301109ae41051991a3289bc1198005af226c5e4f103b66579f461361044c8ba3439ff12c515fb29c52161b7eb9c2837b76a5dc33f7cb2e2e8" + }, + { + "in": "000102030405", + "key": "", + "out": "f95d45cf69af5c2023bdb505821e62e85d7caedf7beda12c0248775b0c88205eeb35af3a90816f6608ce7dd44ec28db1140614e1ddebf3aa9cd1843e0fad2c36" + }, + { + "in": "00010203040506", + "key": "", + "out": "8f945ba700f2530e5c2a7df7d5dce0f83f9efc78c073fe71ae1f88204a4fd1cf70a073f5d1f942ed623aa16e90a871246c90c45b621b3401a5ddbd9df6264165" + }, + { + "in": "0001020304050607", + "key": "", + "out": "e998e0dc03ec30eb99bb6bfaaf6618acc620320d7220b3af2b23d112d8e9cb1262f3c0d60d183b1ee7f096d12dae42c958418600214d04f5ed6f5e718be35566" + }, + { + "in": "000102030405060708", + "key": "", + "out": "6a9a090c61b3410aede7ec9138146ceb2c69662f460c3da53c6515c1eb31f41ca3d280e567882f95cf664a94147d78f42cfc714a40d22ef19470e053493508a2" + }, + { + "in": "00010203040506070809", + "key": "", + "out": "29102511d749db3cc9b4e335fa1f5e8faca8421d558f6a3f3321d50d044a248ba595cfc3efd3d2adc97334da732413f5cbf4751c362ba1d53862ac1e8dabeee8" + }, + { + "in": "000102030405060708090a", + "key": "", + "out": "c97a4779d47e6f77729b5917d0138abb35980ab641bd73a8859eb1ac98c05362ed7d608f2e9587d6ba9e271d343125d40d933a8ed04ec1fe75ec407c7a53c34e" + }, + { + "in": "000102030405060708090a0b", + "key": "", + "out": "10f0dc91b9f845fb95fad6860e6ce1adfa002c7fc327116d44d047cd7d5870d772bb12b5fac00e02b08ac2a0174d0446c36ab35f14ca31894cd61c78c849b48a" + }, + { + "in": "000102030405060708090a0b0c", + "key": "", + "out": "dea9101cac62b8f6a3c650f90eea5bfae2653a4eafd63a6d1f0f132db9e4f2b1b662432ec85b17bcac41e775637881f6aab38dd66dcbd080f0990a7a6e9854fe" + }, + { + "in": "000102030405060708090a0b0c0d", + "key": "", + "out": "441ffaa08cd79dff4afc9b9e5b5620eec086730c25f661b1d6fbfbd1cec3148dd72258c65641f2fca5eb155fadbcabb13c6e21dc11faf72c2a281b7d56145f19" + }, + { + "in": "000102030405060708090a0b0c0d0e", + "key": "", + "out": "444b240fe3ed86d0e2ef4ce7d851edde22155582aa0914797b726cd058b6f45932e0e129516876527b1dd88fc66d7119f4ab3bed93a61a0e2d2d2aeac336d958" + }, + { + "in": "000102030405060708090a0b0c0d0e0f", + "key": "", + "out": "bfbabbef45554ccfa0dc83752a19cc35d5920956b301d558d772282bc867009168e9e98606bb5ba73a385de5749228c925a85019b71f72fe29b3cd37ca52efe6" + }, + { + "in": "000102030405060708090a0b0c0d0e0f10", + "key": "", + "out": "9c4d0c3e1cdbbf485bec86f41cec7c98373f0e09f392849aaa229ebfbf397b22085529cb7ef39f9c7c2222a514182b1effaa178cc3687b1b2b6cbcb6fdeb96f8" + }, + { + "in": "000102030405060708090a0b0c0d0e0f1011", + "key": "", + "out": "477176b3bfcbadd7657c23c24625e4d0d674d1868f006006398af97aa41877c8e70d3d14c3bbc9bbcdcea801bd0e1599af1f3eec67405170f4e26c964a57a8b7" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112", + "key": "", + "out": "a78c490eda3173bb3f10dee52f110fb1c08e0302230b85ddd7c11257d92de148785ef00c039c0bb8eb9808a35b2d8c080f572859714c9d4069c5bcaf090e898e" + }, + { + "in": "000102030405060708090a0b0c0d0e0f10111213", + "key": "", + "out": "58d023397beb5b4145cb2255b07d74290b36d9fd1e594afbd8eea47c205b2efbfe6f46190faf95af504ab072e36f6c85d767a321bfd7f22687a4abbf494a689c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f1011121314", + "key": "", + "out": "4001ec74d5a46fd29c2c3cdbe5d1b9f20e51a941be98d2a4e1e2fbf866a672121db6f81a514cfd10e7358d571bdba48e4ce708b9d124894bc0b5ed554935f73a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415", + "key": "", + "out": "ccd1b22dab6511225d2401ea2d8625d206a12473cc732b615e5640cefff0a4adf971b0e827a619e0a80f5db9ccd0962329010d07e34a2064e731c520817b2183" + }, + { + "in": "000102030405060708090a0b0c0d0e0f10111213141516", + "key": "", + "out": "b4a0a9e3574edb9e1e72aa31e39cc5f30dbf943f8cabc408449654a39131e66d718a18819143e3ea96b4a1895988a1c0056cf2b6e04f9ac19d657383c2910c44" + }, + { + "in": "000102030405060708090a0b0c0d0e0f1011121314151617", + "key": "", + "out": "447becab16630608d39f4f058b16f7af95b85a76aa0fa7cea2b80755fb76e9c804f2ca78f02643c915fbf2fce5e19de86000de03b18861815a83126071f8a37b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718", + "key": "", + "out": "54e6dab9977380a5665822db93374eda528d9beb626f9b94027071cb26675e112b4a7fec941ee60a81e4d2ea3ff7bc52cfc45dfbfe735a1c646b2cf6d6a49b62" + }, + { + "in": "000102030405060708090a0b0c0d0e0f10111213141516171819", + "key": "", + "out": "3ea62625949e3646704d7e3c906f82f6c028f540f5f72a794b0c57bf97b7649bfeb90b01d3ca3e829de21b3826e6f87014d3c77350cb5a15ff5d468a81bec160" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a", + "key": "", + "out": "213cfe145c54a33691569980e5938c8883a46d84d149c8ff1a67cd287b4d49c6da69d3a035443db085983d0efe63706bd5b6f15a7da459e8d50a19093db55e80" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b", + "key": "", + "out": "5716c4a38f38db104e494a0a27cbe89a26a6bb6f499ec01c8c01aa7cb88497e75148cd6eee12a7168b6f78ab74e4be749251a1a74c38c86d6129177e2889e0b6" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c", + "key": "", + "out": "030460a98bdf9ff17cd96404f28fc304f2b7c04eaade53677fd28f788ca22186b8bc80dd21d17f8549c711aff0e514e19d4e15f5990252a03e082f28dc2052f6" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d", + "key": "", + "out": "19e7f1ccee88a10672333e390cf22013a8c734c6cb9eab41f17c3c8032a2e4aca0569ea36f0860c7a1af28fa476840d66011168859334a9e4ef9cc2e61a0e29e" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e", + "key": "", + "out": "29f8b8c78c80f2fcb4bdf7825ed90a70d625ff785d262677e250c04f3720c888d03f8045e4edf3f5285bd39d928a10a7d0a5df00b8484ac2868142a1e8bea351" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "key": "", + "out": "5c52920a7263e39d57920ca0cb752ac6d79a04fef8a7a216a1ecb7115ce06d89fd7d735bd6f4272555dba22c2d1c96e6352322c62c5630fde0f4777a76c3de2c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "key": "", + "out": "83b098f262251bf660064a9d3511ce7687a09e6dfbb878299c30e93dfb43a9314db9a600337db26ebeedaf2256a96dabe9b29e7573ad11c3523d874dde5be7ed" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021", + "key": "", + "out": "9447d98aa5c9331352f43d3e56d0a9a9f9581865998e2885cc56dd0a0bd5a7b50595bd10f7529bcd31f37dc16a1465d594079667da2a3fcb70401498837cedeb" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122", + "key": "", + "out": "867732f2feeb23893097561ac710a4bff453be9cfbedba8ba324f9d312a82d732e1b83b829fdcd177b882ca0c1bf544b223be529924a246a63cf059bfdc50a1b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223", + "key": "", + "out": "f15ab26d4cdfcf56e196bb6ba170a8fccc414de9285afd98a3d3cf2fb88fcbc0f19832ac433a5b2cc2392a4ce34332987d8d2c2bef6c3466138db0c6e42fa47b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324", + "key": "", + "out": "2813516d68ed4a08b39d648aa6aacd81e9d655ecd5f0c13556c60fdf0d333ea38464b36c02baccd746e9575e96c63014f074ae34a0a25b320f0fbedd6acf7665" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425", + "key": "", + "out": "d3259afca8a48962fa892e145acf547f26923ae8d4924c8a531581526b04b44c7af83c643ef5a0bc282d36f3fb04c84e28b351f40c74b69dc7840bc717b6f15f" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526", + "key": "", + "out": "f14b061ae359fa31b989e30332bfe8de8cc8cdb568e14be214a2223b84caab7419549ecfcc96ce2acec119485d87d157d3a8734fc426597d64f36570ceaf224d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627", + "key": "", + "out": "55e70b01d1fbf8b23b57fb62e26c2ce54f13f8fa2464e6eb98d16a6117026d8b90819012496d4071ebe2e59557ece3519a7aa45802f9615374877332b73490b3" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728", + "key": "", + "out": "25261eb296971d6e4a71b2928e64839c67d422872bf9f3c31993615222de9f8f0b2c4be8548559b4b354e736416e3218d4e8a1e219a4a6d43e1a9a521d0e75fc" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526272829", + "key": "", + "out": "08307f347c41294e34bb54cb42b1522d22f824f7b6e5db50fda096798e181a8f026fa27b4ae45d52a62caf9d5198e24a4913c6671775b2d723c1239bfbf016d7" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a", + "key": "", + "out": "1e5c62e7e9bfa1b118747a2de08b3ca10112af96a46e4b22c3fc06f9bfee4eb5c49e057a4a4886234324572576bb9b5ecfde0d99b0de4f98ec16e4d1b85fa947" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b", + "key": "", + "out": "c74a77395fb8bc126447454838e561e962853dc7eb49a1e3cb67c3d0851f3e39517be8c350ac910903d49cd2bfdf545c99316d0346170b739f0add5d533c2cfc" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c", + "key": "", + "out": "0dd57b423cc01eb2861391eb886a0d17079b933fc76eb3fc08a19f8a74952cb68f6bcdc644f77370966e4d13e80560bcf082ef0479d48fbbab4df03b53a4e178" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d", + "key": "", + "out": "4d8dc3923edccdfce70072398b8a3da5c31fcb3ee3b645c85f717cbaeb4b673a19394425a585bfb464d92f1597d0b754d163f97ced343b25db5a70ef48ebb34f" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e", + "key": "", + "out": "f0a50553e4dfb0c4e3e3d3ba82034857e3b1e50918f5b8a7d698e10d242b0fb544af6c92d0c3aaf9932220416117b4e78ecb8a8f430e13b82a5915290a5819c5" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", + "key": "", + "out": "b15543f3f736086627cc5365e7e8988c2ef155c0fd4f428961b00d1526f04d6d6a658b4b8ed32c5d8621e7f4f8e8a933d9ecc9dd1b8333cbe28cfc37d9719e1c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30", + "key": "", + "out": "7b4fa158e415fef023247264cbbe15d16d91a44424a8db707eb1e2033c30e9e1e7c8c0864595d2cb8c580eb47e9d16abbd7e44e824f7cedb7def57130e52cfe9" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031", + "key": "", + "out": "60424ff23234c34dc9687ad502869372cc31a59380186bc2361c835d972f49666eb1ac69629de646f03f9b4db9e2ace093fbfdf8f20ab5f98541978be8ef549f" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132", + "key": "", + "out": "7406018ce704d84f5eb9c79fea97da345699468a350ee0b2d0f3a4bf2070304ea862d72a51c57d3064947286f531e0eaf7563702262e6c724abf5ed8c8398d17" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233", + "key": "", + "out": "14ef5c6d647b3bd1e6e32006c231199810de5c4dc88e70240273b0ea18e651a3eb4f5ca3114b8a56716969c7cda27e0c8db832ad5e89a2dc6cb0adbe7d93abd1" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334", + "key": "", + "out": "38cf6c24e3e08bcf1f6cf3d1b1f65b905239a3118033249e448113ec632ea6dc346feeb2571c38bd9a7398b2221280328002b23e1a45adaffe66d93f6564eaa2" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435", + "key": "", + "out": "6cd7208a4bc7e7e56201bbba02a0f489cd384abe40afd4222f158b3d986ee72a54c50fb64fd4ed2530eda2c8af2928a0da6d4f830ae1c9db469dfd970f12a56f" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536", + "key": "", + "out": "659858f0b5c9edab5b94fd732f6e6b17c51cc096104f09beb3afc3aa467c2ecf885c4c6541effa9023d3b5738ae5a14d867e15db06fe1f9d1127b77e1aabb516" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637", + "key": "", + "out": "26cca0126f5d1a813c62e5c71001c046f9c92095704550be5873a495a999ad010a4f79491f24f286500adce1a137bc2084e4949f5b7294cefe51ecaff8e95cba" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738", + "key": "", + "out": "4147c1f55172788c5567c561feef876f621fff1ce87786b8467637e70dfbcd0dbdb6415cb600954ab9c04c0e457e625b407222c0fe1ae21b2143688ada94dc58" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536373839", + "key": "", + "out": "5b1bf154c62a8af6e93d35f18f7f90abb16a6ef0e8d1aecd118bf70167bab2af08935c6fdc0663ce74482d17a8e54b546d1c296631c65f3b522a515839d43d71" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a", + "key": "", + "out": "9f600419a4e8f4fb834c24b0f7fc13bf4e279d98e8a3c765ee934917403e3a66097182ea21453cb63ebbe8b73a9c2167596446438c57627f330badd4f569f7d6" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b", + "key": "", + "out": "457ef6466a8924fd8011a34471a5a1ac8ccd9bd0d07a97414ac943021ce4b9e4b9c8db0a28f016ed43b1542481990022147b313e194671131e708dd43a3ed7dc" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c", + "key": "", + "out": "9997b2194d9af6dfcb9143f41c0ed83d3a3f4388361103d38c2a49b280a581212715fd908d41c651f5c715ca38c0ce2830a37e00e508ced1bcdc320e5e4d1e2e" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d", + "key": "", + "out": "5c6bbf16baa180f986bd40a1287ed4c549770e7284858fc47bc21ab95ebbf3374b4ee3fd9f2af60f3395221b2acc76f2d34c132954049f8a3a996f1e32ec84e5" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e", + "key": "", + "out": "d10bf9a15b1c9fc8d41f89bb140bf0be08d2f3666176d13baac4d381358ad074c9d4748c300520eb026daeaea7c5b158892fde4e8ec17dc998dcd507df26eb63" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "key": "", + "out": "2fc6e69fa26a89a5ed269092cb9b2a449a4409a7a44011eecad13d7c4b0456602d402fa5844f1a7a758136ce3d5d8d0e8b86921ffff4f692dd95bdc8e5ff0052" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40", + "key": "", + "out": "fcbe8be7dcb49a32dbdf239459e26308b84dff1ea480df8d104eeff34b46fae98627b450c2267d48c0946a697c5b59531452ac0484f1c84e3a33d0c339bb2e28" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f4041", + "key": "", + "out": "a19093a6e3bcf5952f850f2030f69b9606f147f90b8baee3362da71d9f35b44ef9d8f0a7712ba1877fddcd2d8ea8f1e5a773d0b745d4725605983a2de901f803" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142", + "key": "", + "out": "3c2006423f73e268fa59d2920377eb29a4f9a8b462be15983ee3b85ae8a78e992633581a9099893b63db30241c34f643027dc878279af5850d7e2d4a2653073a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243", + "key": "", + "out": "d0f2f2e3787653f77cce2fa24835785bbd0c433fc779465a115149905a9dd1cb827a628506d457fcf124a0c2aef9ce2d2a0a0f63545570d8667ff9e2eba07334" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f4041424344", + "key": "", + "out": "78a9fc048e25c6dcb5de45667de8ffdd3a93711141d594e9fa62a959475da6075ea8f0916e84e45ad911b75467077ee52d2c9aebf4d58f20ce4a3a00458b05d4" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445", + "key": "", + "out": "45813f441769ab6ed37d349ff6e72267d76ae6bb3e3c612ec05c6e02a12af5a37c918b52bf74267c3f6a3f183a8064ff84c07b193d08066789a01accdb6f9340" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243444546", + "key": "", + "out": "956da1c68d83a7b881e01b9a966c3c0bf27f68606a8b71d457bd016d4c41dd8a380c709a296cb4c6544792920fd788835771a07d4a16fb52ed48050331dc4c8b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f4041424344454647", + "key": "", + "out": "df186c2dc09caa48e14e942f75de5ac1b7a21e4f9f072a5b371e09e07345b0740c76177b01278808fec025eded9822c122afd1c63e6f0ce2e32631041063145c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748", + "key": "", + "out": "87475640966a9fdcd6d3a3b5a2cca5c08f0d882b10243c0ec1bf3c6b1c37f2cd3212f19a057864477d5eaf8faed73f2937c768a0af415e84bbce6bd7de23b660" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243444546474849", + "key": "", + "out": "c3b573bbe10949a0fbd4ff884c446f2229b76902f9dfdbb8a0353da5c83ca14e8151bbaac82fd1576a009adc6f1935cf26edd4f1fb8da483e6c5cd9d8923adc3" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a", + "key": "", + "out": "b09d8d0bba8a7286e43568f7907550e42036d674e3c8fc34d8ca46f771d6466b70fb605875f6a863c877d12f07063fdc2e90ccd459b1910dcd52d8f10b2b0a15" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b", + "key": "", + "out": "af3a22bf75b21abfb0acd54422ba1b7300a952eff02ebeb65b5c234471a98df32f4f9643ce1904108a168767924280bd76c83f8c82d9a79d9259b195362a2a04" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c", + "key": "", + "out": "bf4ff2221b7e6957a724cd964aa3d5d0d9941f540413752f4699d8101b3e537508bf09f8508b317736ffd265f2847aa7d84bd2d97569c49d632aed9945e5fa5e" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d", + "key": "", + "out": "9c6b6b78199b1bdacb4300e31479fa622a6b5bc80d4678a6078f88a8268cd7206a2799e8d4621a464ef6b43dd8adffe97caf221b22b6b8778b149a822aefbb09" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e", + "key": "", + "out": "890656f09c99d280b5ecb381f56427b813751bc652c7828078b23a4af83b4e3a61fdbac61f89bee84ea6bee760c047f25c6b0a201c69a38fd6fd971af18588bb" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f", + "key": "", + "out": "31a046f7882ffe6f83ce472e9a0701832ec7b3f76fbcfd1df60fe3ea48fde1651254247c3fd95e100f9172731e17fd5297c11f4bb328363ca361624a81af797c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50", + "key": "", + "out": "27a60b2d00e7a671d47d0aec2a686a0ac04b52f40ab6629028eb7d13f4baa99ac0fe46ee6c814944f2f4b4d20e9378e4847ea44c13178091e277b87ea7a55711" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f5051", + "key": "", + "out": "8b5ccef194162c1f19d68f91e0b0928f289ec5283720840c2f73d253111238dcfe94af2b59c2c1ca2591901a7bc060e7459b6c47df0f71701a35cc0aa831b5b6" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152", + "key": "", + "out": "57ab6c4b2229aeb3b70476d803cd63812f107ce6da17fed9b17875e8f86c724f49e024cbf3a1b8b119c50357652b81879d2ade2d588b9e4f7cedba0e4644c9ee" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253", + "key": "", + "out": "0190a8dac320a739f322e15731aa140ddaf5bed294d5c82e54fef29f214e18aafaa84f8be99af62950266b8f901f15dd4c5d35516fc35b4cab2e96e4695bbe1c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f5051525354", + "key": "", + "out": "d14d7c4c415eeb0e10b159224bea127ebd84f9591c702a330f5bb7bb7aa44ea39de6ed01f18da7adf40cfb97c5d152c27528824b21e239526af8f36b214e0cfb" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455", + "key": "", + "out": "be28c4be706970488fac7d29c3bd5c4e986085c4c3332f1f3fd30973db614164ba2f31a78875ffdc150325c88327a9443ed04fdfe5be93876d1628560c764a80" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556", + "key": "", + "out": "031da1069e3a2e9c3382e436ffd79df74b1ca6a8adb2deabe676ab45994cbc054f037d2f0eace858d32c14e2d1c8b46077308e3bdc2c1b53172ecf7a8c14e349" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f5051525354555657", + "key": "", + "out": "4665cef8ba4db4d0acb118f2987f0bb09f8f86aa445aa3d5fc9a8b346864787489e8fcecc125d17e9b56e12988eac5ecc7286883db0661b8ff05da2afff30fe4" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758", + "key": "", + "out": "63b7032e5f930cc9939517f9e986816cfbec2be59b9568b13f2ead05bae7777cab620c6659404f7409e4199a3be5f7865aa7cbdf8c4253f7e8219b1bd5f46fea" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556575859", + "key": "", + "out": "9f09bf093a2b0ff8c2634b49e37f1b2135b447aa9144c9787dbfd92129316c99e88aab8a21fdef2372d1189aec500f95775f1f92bfb45545e4259fb9b7b02d14" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a", + "key": "", + "out": "f9f8493c68088807df7f6a2693d64ea59f03e9e05a223e68524ca32195a4734b654fcea4d2734c866cf95c889fb10c49159be2f5043dc98bb55e02ef7bdcb082" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b", + "key": "", + "out": "3c9a7359ab4febce07b20ac447b06a240b7fe1dae5439c49b60b5819f7812e4c172406c1aac316713cf0dded1038077258e2eff5b33913d9d95caeb4e6c6b970" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c", + "key": "", + "out": "ad6aab8084510e822cfce8625d62cf4de655f4763884c71e80bab9ac9d5318dba4a6033ed29084e65216c031606ca17615dcfe3ba11d26851ae0999ca6e232cf" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d", + "key": "", + "out": "156e9e6261374c9dc884f36e70f0fe1ab9297997b836fa7d170a9c9ebf575b881e7bcea44d6c0248d35597907154828955be19135852f9228815eca024a8adfb" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e", + "key": "", + "out": "4215407633f4cca9b6788be93e6aa3d963c7d6ce4b147247099f46a3acb500a30038cb3e788c3d29f132ad844e80e9e99251f6db96acd8a091cfc770af53847b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f", + "key": "", + "out": "1c077e279de6548523502b6df800ffdab5e2c3e9442eb838f58c295f3b147cef9d701c41c321283f00c71affa0619310399126295b78dd4d1a74572ef9ed5135" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60", + "key": "", + "out": "f07a555f49fe481cf4cd0a87b71b82e4a95064d06677fdd90a0eb598877ba1c83d4677b393c3a3b6661c421f5b12cb99d20376ba7275c2f3a8f5a9b7821720da" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6061", + "key": "", + "out": "b5911b380d20c7b04323e4026b38e200f534259233b581e02c1e3e2d8438d6c66d5a4eb201d5a8b75072c4ec29106334da70bc79521b0ced2cfd533f5ff84f95" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162", + "key": "", + "out": "01f070a09bae911296361f91aa0e8e0d09a7725478536d9d48c5fe1e5e7c3c5b9b9d6eb07796f6da57ae562a7d70e882e37adfde83f0c433c2cd363536bb22c8" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60616263", + "key": "", + "out": "6f793eb4374a48b0775acaf9adcf8e45e54270c9475f004ad8d5973e2aca52747ff4ed04ae967275b9f9eb0e1ff75fb4f794fa8be9add7a41304868d103fab10" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6061626364", + "key": "", + "out": "965f20f139765fcc4ce4ba3794675863cac24db472cd2b799d035bce3dbea502da7b524865f6b811d8c5828d3a889646fe64a380da1aa7c7044e9f245dced128" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465", + "key": "", + "out": "ec295b5783601244c30e4641e3b45be222c4dce77a58700f53bc8ec52a941690b4d0b087fb6fcb3f39832b9de8f75ec20bd43079811749cdc907edb94157d180" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60616263646566", + "key": "", + "out": "61c72f8ccc91dbb54ca6750bc489672de09faedb8fdd4f94ff2320909a303f5d5a98481c0bc1a625419fb4debfbf7f8a53bb07ec3d985e8ea11e72d559940780" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6061626364656667", + "key": "", + "out": "afd8145b259eefc8d12620c3c5b03e1ed8fd2ccefe0365078c80fd42c1770e28b44948f27e65a1886690110db814397b68e43d80d1ba16dfa358e739c898cfa3" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768", + "key": "", + "out": "552fc7893cf1ce933ada35c0da98844e41545e244c3157a1428d7b4c21f9cd7e4071aed77b7ca9f1c38fba32237412ef21a342742ec8324378f21e507fafdd88" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60616263646566676869", + "key": "", + "out": "467a33fbadf5ebc52596ef86aaaefc6faba8ee651b1ce04de368a03a5a9040ef2835e00adb09abb3fbd2bce818a2413d0b0253b5bda4fc5b2f6f85f3fd5b55f2" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a", + "key": "", + "out": "22eff8e6dd5236f5f57d94ede874d6c9428e8f5d566f17cd6d1848cd752fe13c655cb10fbaaff76872f2bf2da99e15dc624075e1ec2f58a3f64072121838569e" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b", + "key": "", + "out": "9cec6bbf62c4bce4138abae1cbec8dad31950444e90321b1347196834c114b864af3f3cc3508f83751ffb4eda7c84d140734bb4263c3625c00f04f4c8068981b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c", + "key": "", + "out": "a8b60fa4fc2442f6f1514ad7402626920cc7c2c9f72124b8cba8ee2cb7c4586f658a4410cffcc0ab88343955e094c6af0d20d0c714fb0a988f543f300f58d389" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d", + "key": "", + "out": "8271cc45dfa5e4170e847e8630b952cf9c2aa777d06f26a7585b8381f188dacc7337391cfcc94b053dc4ec29cc17f077870428f1ac23fddda165ef5a3f155f39" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e", + "key": "", + "out": "bf23c0c25c8060e4f6995f1623a3bebecaa96e308680000a8aa3cd56bb1a6da099e10d9231b37f4519b2efd2c24de72f31a5f19535241b4a59fa3c03ceb790e7" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f", + "key": "", + "out": "877fd652c05281009c0a5250e7a3a671f8b18c108817fe4a874de22da8e45db11958a600c5f62e67d36cbf84474cf244a9c2b03a9fb9dc711cd1a2cab6f3fae0" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f70", + "key": "", + "out": "29df4d87ea444baf5bcdf5f4e41579e28a67de84149f06c03f110ea84f572a9f676addd04c4878f49c5c00accda441b1a387caceb2e993bb7a10cd8c2d6717e1" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f7071", + "key": "", + "out": "710dacb166844639cd7b637c274209424e2449dc35d790bbfa4f76177054a36b3b76fac0ca6e61df1e687000678ac0746df75d0a3954897681fd393a155a1bb4" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172", + "key": "", + "out": "c1d5f93b8dea1f2571babccbc01764541a0cda87e444d673c50966ca559c33354b3acb26e5d5781ffb28847a4b4754d77008c62a835835f500dea7c3b58bdae2" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f70717273", + "key": "", + "out": "a41e41271cdab8af4d72b104bfb2ad041ac4df14677da671d85640c4b187f50c2b66513c4619fbd5d5dc4fe65dd37b9042e9848dda556a504caa2b1c6afe4730" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f7071727374", + "key": "", + "out": "e7bcbacdc379c43d81ebadcb37781552fc1d753e8cf310d968392d06c91f1d64cc9e90ce1d22c32d277fc6cda433a4d442c762e9eacf2c259f32d64cf9da3a22" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475", + "key": "", + "out": "51755b4ac5456b13218a19c5b9242f57c4a981e4d4ecdce09a3193362b808a579345d4881c2607a56534dd7f21956aff72c2f4173a6e7b6cc2212ba0e3daee1f" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f70717273747576", + "key": "", + "out": "dcc2c4beb9c1f2607b786c20c631972347034c1cc02fcc7d02ff01099cfe1c6989840ac213923629113aa8bad713ccf0fe4ce13264fb32b8b0fe372da382544a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f7071727374757677", + "key": "", + "out": "3d55176acea4a7e3a65ffa9fb10a7a1767199cf077cee9f71532d67cd7c73c9f93cfc37ccdcc1fdef50aad46a504a650d298d597a3a9fa95c6c40cb71fa5e725" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778", + "key": "", + "out": "d07713c005de96dd21d2eb8bbeca66746ea51a31ae922a3e74864889540a48db27d7e4c90311638b224bf0201b501891754848113c266108d0adb13db71909c7" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f70717273747576777879", + "key": "", + "out": "58983c21433d950caa23e4bc18543b8e601c204318532152daf5e159a0cd1480183d29285c05f129cb0cc3164687928086ffe380158df1d394c6ac0d4288bca8" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a", + "key": "", + "out": "8100a8dc528d2b682ab4250801ba33f02a3e94c54dac0ae1482aa21f51ef3a82f3807e6facb0aeb05947bf7aa2adcb034356f90fa4560ede02201a37e411ec1a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b", + "key": "", + "out": "07025f1bb6c784f3fe49de5c14b936a5acacacaab33f6ac4d0e00ab6a12483d6bec00b4fe67c7ca5cc508c2a53efb5bfa5398769d843ff0d9e8b14d36a01a77f" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c", + "key": "", + "out": "ba6aefd972b6186e027a76273a4a723321a3f580cfa894da5a9ce8e721c828552c64dacee3a7fd2d743b5c35ad0c8efa71f8ce99bf96334710e2c2346e8f3c52" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d", + "key": "", + "out": "e0721e02517aedfa4e7e9ba503e025fd46e714566dc889a84cbfe56a55dfbe2fc4938ac4120588335deac8ef3fa229adc9647f54ad2e3472234f9b34efc46543" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e", + "key": "", + "out": "b6292669ccd38d5f01caae96ba272c76a879a45743afa0725d83b9ebb26665b731f1848c52f11972b6644f554c064fa90780dbbbf3a89d4fc31f67df3e5857ef" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f", + "key": "", + "out": "2319e3789c47e2daa5fe807f61bec2a1a6537fa03f19ff32e87eecbfd64b7e0e8ccff439ac333b040f19b0c4ddd11a61e24ac1fe0f10a039806c5dcc0da3d115" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80", + "key": "", + "out": "f59711d44a031d5f97a9413c065d1e614c417ede998590325f49bad2fd444d3e4418be19aec4e11449ac1a57207898bc57d76a1bcf3566292c20c683a5c4648f" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081", + "key": "", + "out": "df0a9d0c212843a6a934e3902b2dd30d17fba5f969d2030b12a546d8a6a45e80cf5635f071f0452e9c919275da99bed51eb1173c1af0518726b75b0ec3bae2b5" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182", + "key": "", + "out": "a3eb6e6c7bf2fb8b28bfe8b15e15bb500f781ecc86f778c3a4e655fc5869bf2846a245d4e33b7b14436a17e63be79b36655c226a50ffbc7124207b0202342db5" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283", + "key": "", + "out": "56d4cbcd070563426a017069425c2cd2ae540668287a5fb9dac432eb8ab1a353a30f2fe1f40d83333afe696a267795408a92fe7da07a0c1814cf77f36e105ee8" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081828384", + "key": "", + "out": "e59b9987d428b3eda37d80abdb16cd2b0aef674c2b1dda4432ea91ee6c935c684b48b4428a8cc740e579a30deff35a803013820dd23f14ae1d8413b5c8672aec" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485", + "key": "", + "out": "cd9fcc99f99d4cc16d031900b2a736e1508db4b586814e6345857f354a70ccecb1df3b50a19adaf43c278efa423ff4bb6c523ec7fd7859b97b168a7ebff8467c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283848586", + "key": "", + "out": "0602185d8c3a78738b99164b8bc6ffb21c7debebbf806372e0da44d121545597b9c662a255dc31542cf995ecbe6a50fb5e6e0ee4ef240fe557eded1188087e86" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081828384858687", + "key": "", + "out": "c08afa5b927bf08097afc5fff9ca4e7800125c1f52f2af3553fa2b89e1e3015c4f87d5e0a48956ad31450b083dad147ffb5ec03434a26830cf37d103ab50c5da" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788", + "key": "", + "out": "36f1e1c11d6ef6bc3b536d505d544a871522c5c2a253067ec9933b6ec25464daf985525f5b9560a16d890259ac1bb5cc67c0c469cde133def000ea1d686f4f5d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283848586878889", + "key": "", + "out": "bf2ab2e2470f5438c3b689e66e7686fffa0cb1e1798ad3a86ff99075bf6138e33d9c0ce59afb24ac67a02af34428191a9a0a6041c07471b7c3b1a752d6fc0b8b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a", + "key": "", + "out": "d400601f9728ccc4c92342d9787d8d28ab323af375ca5624b4bb91d17271fbae862e413be73f1f68e615b8c5c391be0dbd9144746eb339ad541547ba9c468a17" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b", + "key": "", + "out": "79fe2fe157eb85a038abb8ebbc647731d2c83f51b0ac6ee14aa284cb6a3549a4dcceb300740a825f52f5fb30b03b8c4d8b0f4aa67a63f4a94e3303c4eda4c02b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c", + "key": "", + "out": "75351313b52a8529298d8c186b1768666dcca8595317d7a4816eb88c062020c0c8efc554bb341b64688db5ccafc35f3c3cd09d6564b36d7b04a248e146980d4b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d", + "key": "", + "out": "e3128b1d311d02179d7f25f97a5a8bee2cc8c86303644fcd664e157d1fef00f23e46f9a5e8e5c890ce565bb6abd4302ce06469d52a5bd53e1c5a54d04649dc03" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e", + "key": "", + "out": "c2382a72d2d3ace9d5933d00b60827ed380cda08d0ba5f6dd41e29ee6dbe8ecb9235f06be95d83b6816a2fb7a5ad47035e8a4b69a4884b99e4bece58cab25d44" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f", + "key": "", + "out": "6b1c69460bbd50ac2ed6f32e6e887cfed407d47dcf0aaa60387fe320d780bd03eab6d7baeb2a07d10cd552a300341354ea9a5f03183a623f92a2d4d9f00926af" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f90", + "key": "", + "out": "6cda206c80cdc9c44ba990e0328c314f819b142d00630404c48c05dc76d1b00ce4d72fc6a48e1469ddef609412c364820854214b4869af090f00d3c1ba443e1b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f9091", + "key": "", + "out": "7ffc8c26fbd6a0f7a609e6e1939f6a9edf1b0b066641fb76c4f9602ed748d11602496b35355b1aa255850a509d2f8ee18c8f3e1d7dcbc37a136598f56a59ed17" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192", + "key": "", + "out": "70de1f08dd4e09d5fc151f17fc991a23abfc05104290d50468882efaf582b6ec2f14f577c0d68c3ad06626916e3c86e6daab6c53e5163e82b6bd0ce49fc0d8df" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f90919293", + "key": "", + "out": "4f81935756ed35ee2058ee0c6a6110d6fac5cb6a4f46aa9411603f99965823b6da4838276c5c06bc7880e376d92758369ee7305bcec8d3cfd28ccabb7b4f0579" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f9091929394", + "key": "", + "out": "abcb61cb3683d18f27ad527908ed2d32a0426cb7bb4bf18061903a7dc42e7e76f982382304d18af8c80d91dd58dd47af76f8e2c36e28af2476b4bccf82e89fdf" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495", + "key": "", + "out": "02d261ad56a526331b643dd2186de9a82e72a58223cd1e723686c53d869b83b94632b7b647ab2afc0d522e29da3a5615b741d82852e0df41b66007dbcba90543" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f90919293949596", + "key": "", + "out": "c5832741fa30c5436823015383d297ff4c4a5d7276c3f902122066e04be5431b1a85faf73b918434f9300963d1dea9e8ac3924ef490226edeea5f743e410669f" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f9091929394959697", + "key": "", + "out": "cfaeab268cd075a5a6aed515023a032d54f2f2ff733ce0cbc78db51db4504d675923f82746d6594606ad5d67734b11a67cc6a468c2032e43ca1a94c6273a985e" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798", + "key": "", + "out": "860850f92eb268272b67d133609bd64e34f61bf03f4c1738645c17fec818465d7ecd2be2907641130025fda79470ab731646e7f69440e8367ea76ac4cee8a1df" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f90919293949596979899", + "key": "", + "out": "84b154ed29bbedefa648286839046f4b5aa34430e2d67f7496e4c39f2c7ea78995f69e1292200016f16ac3b37700e6c7e7861afc396b64a59a1dbf47a55c4bbc" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a", + "key": "", + "out": "aeeec260a5d8eff5ccab8b95da435a63ed7a21ea7fc7559413fd617e33609f8c290e64bbacc528f6c080262288b0f0a3219be223c991bee92e72349593e67638" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b", + "key": "", + "out": "8ad78a9f26601d127e8d2f2f976e63d19a054a17dcf59e0f013ab54a6887bbdffde7aaae117e0fbf3271016595b9d9c712c01b2c53e9655a382bc4522e616645" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c", + "key": "", + "out": "8934159dade1ac74147dfa282c75954fcef443ef25f80dfe9fb6ea633b8545111d08b34ef43fff17026c7964f5deac6d2b3c29dacf2747f022df5967dfdc1a0a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d", + "key": "", + "out": "cd36dd0b240614cf2fa2b9e959679dcdd72ec0cd58a43da3790a92f6cdeb9e1e795e478a0a47d371100d340c5cedcdbbc9e68b3f460818e5bdff7b4cda4c2744" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e", + "key": "", + "out": "00df4e099b807137a85990f49d3a94315e5a5f7f7a6076b303e96b056fb93800111f479628e2f8db59aeb6ac70c3b61f51f9b46e80ffdeae25ebddb4af6cb4ee" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "key": "", + "out": "2b9c955e6caed4b7c9e246b86f9a1726e810c59d126cee66ed71bf015b83558a4b6d84d18dc3ff4620c2ffb722359fdef85ba0d4e2d22ecbe0ed784f99afe587" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0", + "key": "", + "out": "181df0a261a2f7d29ea5a15772715105d450a4b6c236f699f462d60ca76487feedfc9f5eb92df838e8fb5dc3694e84c5e0f4a10b761f506762be052c745a6ee8" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1", + "key": "", + "out": "21fb203458bf3a7e9a80439f9a902899cd5de0139dfd56f7110c9dec8437b26bda63de2f565926d85edb1d6c6825669743dd9992653d13979544d5dc8228bfaa" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2", + "key": "", + "out": "ef021f29c5ffb830e64b9aa9058dd660fd2fcb81c497a7e698bcfbf59de5ad4a86ff93c10a4b9d1ae5774725f9072dcde9e1f199bab91f8bff921864aa502eee" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3", + "key": "", + "out": "b3cfda40526b7f1d37569bdfcdf911e5a6efe6b2ec90a0454c47b2c046bf130fc3b352b34df4813d48d33ab8e269b69b075676cb6d00a8dcf9e1f967ec191b2c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4", + "key": "", + "out": "b4c6c3b267071eefb9c8c72e0e2b941293641f8673cb70c1cc26ad1e73cf141755860ad19b34c2f34ed35bb52ec4507cc1fe59047743a5f0c6febde625e26091" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5", + "key": "", + "out": "57a34f2bcca60d4b85103b830c9d7952a416be5263ae429c9e5e53fe8590a8f78ec65a51109ea85dcdf7b6223f9f2b340539fad81923dbf8edabf95129e4dff6" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6", + "key": "", + "out": "9cf46662fcd61a232277b685663b8b5da832dfd9a3b8ccfeec993ec6ac415ad07e048adfe414df272770dba867da5c1224c6fd0aa0c2187d426ac647e9887361" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7", + "key": "", + "out": "5ce1042ab4d542c2f9ee9d17262af8164098935bef173d0e18489b04841746cd2f2df866bd7da6e5ef9024c648023ec723ab9c62fd80285739d84f15d2ab515a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8", + "key": "", + "out": "8488396bd4a8729b7a473178f232dadf3f0f8e22678ba5a43e041e72da1e2cf82194c307207a54cb8156293339eaec693ff66bfcd5efc65e95e4ecaf54530abd" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9", + "key": "", + "out": "f598da901c3835bca560779037dfde9f0c51dc61c0b760fc1522d7b470ee63f5bdc6498476e86049ad86e4e21af2854a984cc905427d2f17f66b1f41c3da6f61" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aa", + "key": "", + "out": "5f93269798cf02132107337660a8d7a177354c0212eb93e555e7c37a08aef3d8dce01217011cd965c04dd2c105f2e2b6cae5e4e6bcaf09dfbee3e0a6a6357c37" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaab", + "key": "", + "out": "0ecf581d47bac9230986faabd70c2f5b80e91066f0ec55a842937882286d2ca007bb4e973b0b091d52167ff7c4009c7ab4ad38fff1dceacdb7be81ef4a452952" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabac", + "key": "", + "out": "5aeca8abe1528582b2a307b4009585498a3d467ca6101cb0c5126f9976056e9ffc123cc20c302b2a737f492c75d21f01512c90ca0541dfa56e950a321dcb28d8" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacad", + "key": "", + "out": "732fbf8f1cb2b8329263ede27858fe46f8d3354d376bcda0548e7ce1fa9dd11f85eb661fe950b543aa635ca4d3f04ede5b32d6b656e5ce1c44d35c4a6c56cff8" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadae", + "key": "", + "out": "d5e938735d63788c80100aefd18648d18cf272f69f20ff24cfe2895c088ad08b0104da1672a4eb26fc52545cc7d7a01b266cf546c403c45bd129eb41bdd9200b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf", + "key": "", + "out": "65a245b49352ee297d91af8c8be00528ac6e046dd83ac7bd465a98816dd68f3e00e1ae8f895327a7e9a8c9326598379a29c9fc91ec0c6eef08f3e2b216c11008" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0", + "key": "", + "out": "c95654b63019130ab45dd0fb4941b98aeb3af2a123913eca2ce99b3e97410a7bf8661cc7fbaa2bc1cf2b13113b1ed40a0118b88e5fffc3542759ea007ed4c58d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1", + "key": "", + "out": "1eb262f38fa494431f017dad44c0dfb69324ac032f04b657fc91a88647bb74760f24e7c956514f0cf002990b182c1642b9b2426e96a61187e4e012f00e217d84" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2", + "key": "", + "out": "3b955aeebfa5151ac1ab8e3f5cc1e3767084c842a575d36269836e97353d41622b731dddcd5f269550a3a5b87be1e90326340b6e0e62555815d9600597ac6ef9" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3", + "key": "", + "out": "68289f6605473ba0e4f241baf7477a9885426a858f19ef2a18b0d40ef8e41282ed5526b519799e270f13881327918278755711071d8511fe963e3b5606aa3716" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4", + "key": "", + "out": "80a33787542612c38f6bcd7cd86cab460227509b1cbad5ec408a91413d51155a0476dadbf3a2518e4a6e77cc346622e347a469bf8baa5f04eb2d98705355d063" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5", + "key": "", + "out": "34629bc6d831391c4cdf8af1b4b7b6b8e8ee17cf98c70e5dd586cd99f14b11df945166236a9571e6d591bb83ee4d164d46f6b9d8ef86ff865a81bfb91b00424b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6", + "key": "", + "out": "8b7cc339163863bb4383e542b0ef0e7cf36b84ad932cdf5a80419ec9ad692e7a7e784d2c7cb3796a18b8f800035f3aa06c824100611120a7bdeb35618ccb81b7" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7", + "key": "", + "out": "4f084e4939dd5a7f5a658fad58a18a15c25c32ec1c7fd5c5c6c3e892b3971aeaac308304ef17b1c47239ea4bb398b3fd6d4528d8de8e768ae0f1a5a5c6b5c297" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8", + "key": "", + "out": "48f407a1af5b8009b2051742e8cf5cd5656669e7d722ee8e7bd202060849442168d8facc117c012bfb7bf449d99befff6a34aea203f1d8d352722be5014ec818" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9", + "key": "", + "out": "a6aa82cd1e426f9a73bfa39a29037876114655b8c22d6d3ff8b638ae7dea6b17843e09e52eb66fa1e475e4a8a3de429b7d0f4a776fcb8bdc9b9fede7d52e815f" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9ba", + "key": "", + "out": "5817027d6bdd00c5dd10ac593cd560372270775a18526d7e6f13872a2e20eab664625be7168ac4bd7c9e0ce7fc4099e0f48442e2c767191c6e1284e9b2ccea8c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babb", + "key": "", + "out": "08e41028340a45c74e4052b3a8d6389e22e043a1adab5e28d97619450d723469b620caa519b81c14523854f619fd3027e3847bd03276e60604a80ddb4de876d6" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbc", + "key": "", + "out": "130b8420537eb07d72abda07c85acbd8b9a44f16321dd0422145f809673d30f2b5321326e2bff317ef3fef983c51c4f8ab24a325d298e34afce569a82555774c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbd", + "key": "", + "out": "ac49b844afaa012e31c474ca263648844fd2f6307992c2f752aca02c3828965175794deee2d2ee95c61cd284f6b5a2d75e2ef2b29ee8149e77fb81447b2fd04b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbe", + "key": "", + "out": "b9d7ca81cc60bb9578e44024e5a0a0be80f27336a6a9f4e53df3999cb191280b090e2ac2d29c5baad9d71415bdc129e69aa2667af6a7fd5e189fccdcee817340" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf", + "key": "", + "out": "a755e113386572c75ced61d719706070b9146048e42a9f8cd35667a088b42f08808abdf77e618abd959afc757379ca2c00bcc1a48390fa2bff618b1e0078a613" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0", + "key": "", + "out": "a73c7debed326f1c0db0795ee7d6e3946894b826b1f8101c56c823ba17168312e7f53fc7dbe52c3e11e69852c40485e2ef182477862ea6a34ec136e2dfeea6f4" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1", + "key": "", + "out": "6cb8f9d52c56d82cac28f39ea1593e8bb2506293ac0d68376a1709b62a46df14a4ae64b2d8fab76733a1ced2d548e3f3c6fcb49d40c3d5808e449cd83d1c2aa2" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2", + "key": "", + "out": "683fa2b2369a10162c1c1c7b24bc970ee67da220564f32203f625696c0352a0b9ad96624362d952d84463c1106a2dba7a092599884b35a0b89c8f1b6a9b5a61e" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3", + "key": "", + "out": "aad9ad44610118b77d508aeb1bbcd1c1b7d0171397fb510a401bbc0ec34623670d86a2dc3c8f3ab5a2044df730256727545f0860ce21a1eac717dfc48f5d228e" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4", + "key": "", + "out": "c42578de23b4c987d5e1ac4d689ed5de4b0417f9704bc6bce969fa13471585d62c2cb1212a944f397fc9ca2c3747c3beb694ec4c5be68828dda53ef43faec6c0" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5", + "key": "", + "out": "470f00841ee8244e63ed2c7ea30e2e419897c197462ecccecf713b42a5065fff5914bc9b79affe8f6b657875e789ae213bd914cd35bd174d46e9d18bd843773d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6", + "key": "", + "out": "34fc4213730f47a5e9a3580f643e12945cfcb31bf206f6ad450ce528da3fa432e005d6b0ecce10dca7c5995f6aacc5150e1b009e19751e8309f8859531844374" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7", + "key": "", + "out": "fb3c1f0f56a56f8e316fdf5d853c8c872c39635d083634c3904fc3ac07d1b578e85ff0e480e92d44ade33b62e893ee32343e79ddf6ef292e89b582d312502314" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8", + "key": "", + "out": "c7c97fc65dd2b9e3d3d607d31598d3f84261e9919251e9c8e57bb5f829377d5f73eabbed55c6c381180f29ad02e5be797ffec7e57bdecbc50ad3d062f0993ab0" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9", + "key": "", + "out": "a57a49cdbe67ae7d9f797bb5cc7efc2df07f4e1b15955f85dae74b76e2ecb85afb6cd9eeed8888d5ca3ec5ab65d27a7b19e578475760a045ac3c92e13a938e77" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9ca", + "key": "", + "out": "c7143fce9614a17fd653aeb140726dc9c3dbb1de6cc581b2726897ec24b7a50359ad492243be66d9edd8c933b5b80e0b91bb61ea98056006516976fae8d99a35" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacb", + "key": "", + "out": "65bb58d07f937e2d3c7e65385f9c54730b704105ccdb691f6e146d4ee8f6c086f49511035110a9ad6031fdceb943e0f9613bcb276dd40f0624ef0f924f809783" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcc", + "key": "", + "out": "e540277f683b1186dd3b5b3f61433396581a35feb12002be8c6a6231fc40ffa70f08081bc58b2d94f7649543614a435faa2d62110e13dabc7b86629b63af9c24" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccd", + "key": "", + "out": "418500878c5fbcb584c432f4285e05e49f2e3e075399a0dbfcf874ebf8c03d02bf16bc6989d161c77ca0786b05053c6c709433712319192128835cf0b660595b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdce", + "key": "", + "out": "889090dbb1944bdc9433ee5ef1010c7a4a24a8e71ecea8e12a31318ce49dcab0aca5c3802334aab2cc84b14c6b9321fe586bf3f876f19cd406eb1127fb944801" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "key": "", + "out": "53b6a28910aa92e27e536fb549cf9b9918791060898e0b9fe183577ff43b5e9c7689c745b32e412269837c31b89e6cc12bf76e13cad366b74ece48bb85fd09e9" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0", + "key": "", + "out": "7c092080c6a80d672409d081d3d177106bcd63567785140719490950ae07ae8fcaabbaaab330cfbcf7374482c220af2eadeeb73dcbb35ed823344e144e7d4899" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1", + "key": "", + "out": "9ccde566d2400509181111f32dde4cd63209fe59a30c114546ad2776d889a41bad8fa1bb468cb2f9d42ca9928a7770fef8e8ba4d0c812d9a1e75c3d8d2ccd75a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2", + "key": "", + "out": "6e293bf5d03fe43977cfe3f57ccdb3ae282a85455dca33f37f4b74f8398cc612433d755cbec412f8f82a3bd3bc4a278f7ecd0dfa9bbdc40be7a787c8f159b2df" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3", + "key": "", + "out": "c56546fb2178456f336164c18b90deffc83ae2b5a3aca77b6884d36d2c1db39501b3e65e36c758c66e3188451fdb3515ee162c001f06c3e8cb573adf30f7a101" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4", + "key": "", + "out": "6f82f89f299ebca2fe014b59bffe1aa84e88b1915fe256afb646fd8448af2b8891a7fab37a4ea6f9a50e6c317039d8cf878f4c8e1a0dd464f0b4d6ff1c7ea853" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5", + "key": "", + "out": "2b8599ff9c3d6198637ad51e57d1998b0d75313fe2dd61a533c964a6dd9607c6f723e9452ce46e014b1c1d6de77ba5b88c914d1c597bf1eae13474b4290e89b2" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6", + "key": "", + "out": "08bf346d38e1df06c8260edb1da75579275948d5c0a0aa9ed2886f8856de5417a156998758f5b17e52f101ca957a71137473dfd18d7d209c4c10d9233c93691d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7", + "key": "", + "out": "6df2156d773114d310b63db9ee5350d77e6bcf25b05fcd910f9b31bc42bb13fe8225ebcb2a23a62280777b6bf74e2cd0917c7640b43defe468cd1e18c943c66a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8", + "key": "", + "out": "7c7038bc13a91151828a5ba82b4a96040f258a4dfb1b1373f0d359168afb0517a20b28a12d3644046be66b8d08d8ae7f6a923ea1c00187c6d11dc502bac71305" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9", + "key": "", + "out": "bcd1b30d808fb739b987cbf154bea00da9d40380b861d4c1d6377122dadd61c0e59018b71941cfb62e00dcd70aeb9abf0473e80f0a7eca6b6dea246ab229dd2b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9da", + "key": "", + "out": "7ed4468d968530fe7ab2c33540b26d8c3bd3ed44b34fbe8c2a9d7f805b5ada0ea252eeade4fce97f89728ad85bc8bb2430b1bef2cddd32c8446e59b8e8ba3c67" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadb", + "key": "", + "out": "6d30b7c6ce8a3236c0ca2f8d728b1088ca06983a8043e621d5dcf0c537d13b08791edeb01a3cf0943ec1c890ab6e29b146a236cd46bcb9d93bf516fb67c63fe5" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdc", + "key": "", + "out": "97fe03cef31438508911bded975980a66029305dc5e3fa8ad1b4fb22fcdf5a19a733320327d8f71ccf496cb3a44a77af56e3dde73d3a5f176896cc57c9a5ad99" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdd", + "key": "", + "out": "785a9d0fbd21136dbce8fa7eafd63c9dad220052978416b31d9753eaa149097847ed9b30a65c70507eff01879149ed5cf0471d37798edc05abd56ad4a2cccb1d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcddde", + "key": "", + "out": "ad408d2abddfd37b3bf34794c1a3371d928ed7fc8d966225333584c5665817832a37c07f0dc7cb5aa874cd7d20fe8fab8eabcb9b33d2e0841f6e200960899d95" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf", + "key": "", + "out": "97668f745b6032fc815d9579322769dccd9501a5080029b8ae826befb6742331bd9f76efeb3e2b8e81a9786b282f5068a3a2424697a77c41876b7e753f4c7767" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0", + "key": "", + "out": "26bb985f47e7fee0cfd252d4ef96bed42b9c370c1c6a3e8c9eb04ef7f7818b833a0d1f043ebafb911dc779e02740a02a44d3a1ea45ed4ad55e686c927cafe97e" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1", + "key": "", + "out": "5bfe2b1dcf7fe9b95088acedb575c19016c743b2e763bf5851ac407c9eda43715edfa48b4825492c5179593fff21351b76e8b7e034e4c53c79f61f29c479bd08" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2", + "key": "", + "out": "c76509ef72f4a6f9c9c40618ed52b2084f83502232e0ac8bdaf3264368e4d0180f6854c4abf4f6509c79caafc44cf3194afc57bd077bd7b3c9bda3d4b8775816" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3", + "key": "", + "out": "d66f2beab990e354ccb910e4e9c7ac618c7b63ef292a96b552341de78dc46d3ec8cfabc699b50af41fda39cf1b0173660923510ad67faedef5207cffe8641d20" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4", + "key": "", + "out": "7d8f0672992b79be3a364d8e5904f4ab713bbc8ab01b4f309ad8ccf223ce1034a860dcb0b00550612cc2fa17f2969e18f22e1427d254b4a82b3a03a3eb394adf" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5", + "key": "", + "out": "a56d6725bfb3de47c1414adf25fc8f0fc9846f6987722bc06366d5ca4e89722925ebbc881418844075397a0ca89842c7b9e9e07e1d9d183ebeb39e120b483bf7" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6", + "key": "", + "out": "af5e03d7fe60c67e10313344434e79485a03a758d6dce985574745763c1c5c77d4fb3e6fb12230368370993bf90feed0c5d1607524562d7c09c0c210ed393d7c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7", + "key": "", + "out": "7a20540cc07bf72b582421fc342e82f52134b69841ec28ed189e2ea6a29dd2f82a640352d222b52f2911dc72a7dab31caadd80c6118f13c56b2a1e4373be0ea3" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8", + "key": "", + "out": "486f02c63e5467ea1fdde7e82bfacc2c1ba5d636d9f3d08b210da3f372f706ec218cc17ff60aef703bbe0c15c38ae55d286a684f864c78211ccab4178c92adba" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9", + "key": "", + "out": "1c7a5c1dedcd04a921788f7eb23361ca1953b04b9c7aec35d65ea3e4996db26f281278ea4ae666ad81027d98af57262cdbfa4c085f4210568c7e15eec7805114" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9ea", + "key": "", + "out": "9ce3fa9a860bdbd5378fd6d7b8b671c6cb7692910ce8f9b6cb4122cbcbe6ac06ca0422cef1225935053b7d193a81b9e972eb85a1d3074f14cbb5ec9f0573892d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaeb", + "key": "", + "out": "a91187be5c371c4265c174fd4653b8ab708551f83d1fee1cc1479581bc006d6fb78fcc9a5dee1db3666f508f9780a37593ebcccf5fbed39667dc6361e921f779" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebec", + "key": "", + "out": "4625767d7b1d3d3ed2fbc674af14e0244152f2a4021fcf3311505d89bd81e2f9f9a500c3b199914db49500b3c98d03ea93286751a686a3b875daab0ccd63b44f" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebeced", + "key": "", + "out": "43dfdfe1b014fed3a2acabb7f3e9a182f2aa18019d27e3e6cdcf31a15b428e91e7b08cf5e5c376fce2d8a28ff85ab0a0a1656edb4a0a91532620096d9a5a652d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedee", + "key": "", + "out": "279e3202be3989ba3112772585177487e4fe3ee3eab49c2f7fa7fe87cfe7b80d3e0355edff6d031e6c96c795db1c6f041880ec3824defacf9263820a8e7327de" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeef", + "key": "", + "out": "ea2d066ac229d4d4b616a8bedec734325224e4b4e58f1ae6dad7e40c2da29196c3b1ea9571dacc81e87328caa0211e09027b0524aa3f4a849917b3586747ebbb" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0", + "key": "", + "out": "49f014f5c61822c899ab5cae51be4044a4495e777deb7da9b6d8490efbb87530adf293daf079f94c33b7044ef62e2e5bb3eb11e17304f8453ee6ce24f033ddb0" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1", + "key": "", + "out": "9233490344e5b0dc5912671b7ae54cee7730dbe1f4c7d92a4d3e3aab50571708db51dcf9c2944591db651db32d22935b86944969be77d5b5feae6c3840a8db26" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2", + "key": "", + "out": "b6e75e6f4c7f453b7465d25b5ac8c7196902eaa953875228c8634e16e2ae1f38bc3275304335f5989eccc1e34167d4e68d7719968fba8e2fe67947c35c48e806" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3", + "key": "", + "out": "cc14ca665af1483efbc3af80080e650d5046a3932f4f51f3fe90a0705ec25104adf07839265dc51d43401411246e474f0d5e5637af94767283d53e0617e981f4" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4", + "key": "", + "out": "230a1c857cb2e7852e41b647e90e4585d2d881e1734dc38955356e8dd7bff39053092c6b38e236e1899525647073dddf6895d64206325e7647f275567b255909" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5", + "key": "", + "out": "cbb65321ac436e2ffdab2936359ce49023f7dee7614ef28d173c3d27c5d1bffa51553d433f8ee3c9e49c05a2b883cce954c9a8093b80612a0cdd4732e041f995" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6", + "key": "", + "out": "3e7e570074337275efb51315588034c3cf0dddca20b4612e0bd5b881e7e5476d319ce4fe9f19186e4c0826f44f131eb048e65be242b1172c63badb123ab0cbe8" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7", + "key": "", + "out": "d32e9ec02d38d4e1b8249df8dcb00c5b9c68eb8922672e3505393b6a210ba56f9496e5ee0490ef387c3cdec061f06bc0382d9304cafbb8e0cd33d57029e62df2" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8", + "key": "", + "out": "8c1512466089f05b3775c262b62d22b83854a83218130b4ec91b3ccbd293d2a54302cecaab9b100c68d1e6ddc8f07cddbdfe6fdaaaf099cc09d6b725879c6369" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9", + "key": "", + "out": "91a7f61c97c2911e4c812ef71d780ad8fa788794561d08303fd1c1cb608a46a12563086ec5b39d471aed94fb0f6c678a43b8792932f9028d772a22768ea23a9b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fa", + "key": "", + "out": "4f6bb222a395e8b18f6ba155477aed3f0729ac9e83e16d31a2a8bc655422b837c891c6199e6f0d75799e3b691525c581953517f252c4b9e3a27a28fbaf49644c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafb", + "key": "", + "out": "5d06c07e7a646c413a501c3f4bb2fc38127de7509b7077c4d9b5613201c1aa02fd5f79d2745915dd57fbcb4ce08695f6efc0cb3d2d330e19b4b0e6004ea6471e" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfc", + "key": "", + "out": "b96756e57909968f14b796a5d30f4c9d671472cf82c8cfb2caca7ac7a44ca0a14c9842d00c82e337502c94d5960aca4c492ea7b0df919ddf1aada2a275bb10d4" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfd", + "key": "", + "out": "ff0a015e98db9c99f03977710aac3e658c0d896f6d71d618ba79dc6cf72ac75b7c038eb6862dede4543e145413a6368d69f5722c827ba3ef25b6ae6440d39276" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe", + "key": "", + "out": "5b21c5fd8868367612474fa2e70e9cfa2201ffeee8fafab5797ad58fefa17c9b5b107da4a3db6320baaf2c8617d5a51df914ae88da3867c2d41f0cc14fa67928" + }, + { + "in": "", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "10ebb67700b1868efb4417987acf4690ae9d972fb7a590c2f02871799aaa4786b5e996e8f0f4eb981fc214b005f42d2ff4233499391653df7aefcbc13fc51568" + }, + { + "in": "00", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "961f6dd1e4dd30f63901690c512e78e4b45e4742ed197c3c5e45c549fd25f2e4187b0bc9fe30492b16b0d0bc4ef9b0f34c7003fac09a5ef1532e69430234cebd" + }, + { + "in": "0001", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "da2cfbe2d8409a0f38026113884f84b50156371ae304c4430173d08a99d9fb1b983164a3770706d537f49e0c916d9f32b95cc37a95b99d857436f0232c88a965" + }, + { + "in": "000102", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "33d0825dddf7ada99b0e7e307104ad07ca9cfd9692214f1561356315e784f3e5a17e364ae9dbb14cb2036df932b77f4b292761365fb328de7afdc6d8998f5fc1" + }, + { + "in": "00010203", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "beaa5a3d08f3807143cf621d95cd690514d0b49efff9c91d24b59241ec0eefa5f60196d407048bba8d2146828ebcb0488d8842fd56bb4f6df8e19c4b4daab8ac" + }, + { + "in": "0001020304", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "098084b51fd13deae5f4320de94a688ee07baea2800486689a8636117b46c1f4c1f6af7f74ae7c857600456a58a3af251dc4723a64cc7c0a5ab6d9cac91c20bb" + }, + { + "in": "000102030405", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "6044540d560853eb1c57df0077dd381094781cdb9073e5b1b3d3f6c7829e12066bbaca96d989a690de72ca3133a83652ba284a6d62942b271ffa2620c9e75b1f" + }, + { + "in": "00010203040506", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "7a8cfe9b90f75f7ecb3acc053aaed6193112b6f6a4aeeb3f65d3de541942deb9e2228152a3c4bbbe72fc3b12629528cfbb09fe630f0474339f54abf453e2ed52" + }, + { + "in": "0001020304050607", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "380beaf6ea7cc9365e270ef0e6f3a64fb902acae51dd5512f84259ad2c91f4bc4108db73192a5bbfb0cbcf71e46c3e21aee1c5e860dc96e8eb0b7b8426e6abe9" + }, + { + "in": "000102030405060708", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "60fe3c4535e1b59d9a61ea8500bfac41a69dffb1ceadd9aca323e9a625b64da5763bad7226da02b9c8c4f1a5de140ac5a6c1124e4f718ce0b28ea47393aa6637" + }, + { + "in": "00010203040506070809", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "4fe181f54ad63a2983feaaf77d1e7235c2beb17fa328b6d9505bda327df19fc37f02c4b6f0368ce23147313a8e5738b5fa2a95b29de1c7f8264eb77b69f585cd" + }, + { + "in": "000102030405060708090a", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "f228773ce3f3a42b5f144d63237a72d99693adb8837d0e112a8a0f8ffff2c362857ac49c11ec740d1500749dac9b1f4548108bf3155794dcc9e4082849e2b85b" + }, + { + "in": "000102030405060708090a0b", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "962452a8455cc56c8511317e3b1f3b2c37df75f588e94325fdd77070359cf63a9ae6e930936fdf8e1e08ffca440cfb72c28f06d89a2151d1c46cd5b268ef8563" + }, + { + "in": "000102030405060708090a0b0c", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "43d44bfa18768c59896bf7ed1765cb2d14af8c260266039099b25a603e4ddc5039d6ef3a91847d1088d401c0c7e847781a8a590d33a3c6cb4df0fab1c2f22355" + }, + { + "in": "000102030405060708090a0b0c0d", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "dcffa9d58c2a4ca2cdbb0c7aa4c4c1d45165190089f4e983bb1c2cab4aaeff1fa2b5ee516fecd780540240bf37e56c8bcca7fab980e1e61c9400d8a9a5b14ac6" + }, + { + "in": "000102030405060708090a0b0c0d0e", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "6fbf31b45ab0c0b8dad1c0f5f4061379912dde5aa922099a030b725c73346c524291adef89d2f6fd8dfcda6d07dad811a9314536c2915ed45da34947e83de34e" + }, + { + "in": "000102030405060708090a0b0c0d0e0f", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "a0c65bddde8adef57282b04b11e7bc8aab105b99231b750c021f4a735cb1bcfab87553bba3abb0c3e64a0b6955285185a0bd35fb8cfde557329bebb1f629ee93" + }, + { + "in": "000102030405060708090a0b0c0d0e0f10", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "f99d815550558e81eca2f96718aed10d86f3f1cfb675cce06b0eff02f617c5a42c5aa760270f2679da2677c5aeb94f1142277f21c7f79f3c4f0cce4ed8ee62b1" + }, + { + "in": "000102030405060708090a0b0c0d0e0f1011", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "95391da8fc7b917a2044b3d6f5374e1ca072b41454d572c7356c05fd4bc1e0f40b8bb8b4a9f6bce9be2c4623c399b0dca0dab05cb7281b71a21b0ebcd9e55670" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "04b9cd3d20d221c09ac86913d3dc63041989a9a1e694f1e639a3ba7e451840f750c2fc191d56ad61f2e7936bc0ac8e094b60caeed878c18799045402d61ceaf9" + }, + { + "in": "000102030405060708090a0b0c0d0e0f10111213", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "ec0e0ef707e4ed6c0c66f9e089e4954b058030d2dd86398fe84059631f9ee591d9d77375355149178c0cf8f8e7c49ed2a5e4f95488a2247067c208510fadc44c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f1011121314", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "9a37cce273b79c09913677510eaf7688e89b3314d3532fd2764c39de022a2945b5710d13517af8ddc0316624e73bec1ce67df15228302036f330ab0cb4d218dd" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "4cf9bb8fb3d4de8b38b2f262d3c40f46dfe747e8fc0a414c193d9fcf753106ce47a18f172f12e8a2f1c26726545358e5ee28c9e2213a8787aafbc516d2343152" + }, + { + "in": "000102030405060708090a0b0c0d0e0f10111213141516", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "64e0c63af9c808fd893137129867fd91939d53f2af04be4fa268006100069b2d69daa5c5d8ed7fddcb2a70eeecdf2b105dd46a1e3b7311728f639ab489326bc9" + }, + { + "in": "000102030405060708090a0b0c0d0e0f1011121314151617", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "5e9c93158d659b2def06b0c3c7565045542662d6eee8a96a89b78ade09fe8b3dcc096d4fe48815d88d8f82620156602af541955e1f6ca30dce14e254c326b88f" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "7775dff889458dd11aef417276853e21335eb88e4dec9cfb4e9edb49820088551a2ca60339f12066101169f0dfe84b098fddb148d9da6b3d613df263889ad64b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f10111213141516171819", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "f0d2805afbb91f743951351a6d024f9353a23c7ce1fc2b051b3a8b968c233f46f50f806ecb1568ffaa0b60661e334b21dde04f8fa155ac740eeb42e20b60d764" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "86a2af316e7d7754201b942e275364ac12ea8962ab5bd8d7fb276dc5fbffc8f9a28cae4e4867df6780d9b72524160927c855da5b6078e0b554aa91e31cb9ca1d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "10bdf0caa0802705e706369baf8a3f79d72c0a03a80675a7bbb00be3a45e516424d1ee88efb56f6d5777545ae6e27765c3a8f5e493fc308915638933a1dfee55" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "b01781092b1748459e2e4ec178696627bf4ebafebba774ecf018b79a68aeb84917bf0b84bb79d17b743151144cd66b7b33a4b9e52c76c4e112050ff5385b7f0b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "c6dbc61dec6eaeac81e3d5f755203c8e220551534a0b2fd105a91889945a638550204f44093dd998c076205dffad703a0e5cd3c7f438a7e634cd59fededb539e" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "eba51acffb4cea31db4b8d87e9bf7dd48fe97b0253ae67aa580f9ac4a9d941f2bea518ee286818cc9f633f2a3b9fb68e594b48cdd6d515bf1d52ba6c85a203a7" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "86221f3ada52037b72224f105d7999231c5e5534d03da9d9c0a12acb68460cd375daf8e24386286f9668f72326dbf99ba094392437d398e95bb8161d717f8991" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "5595e05c13a7ec4dc8f41fb70cb50a71bce17c024ff6de7af618d0cc4e9c32d9570d6d3ea45b86525491030c0d8f2b1836d5778c1ce735c17707df364d054347" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "ce0f4f6aca89590a37fe034dd74dd5fa65eb1cbd0a41508aaddc09351a3cea6d18cb2189c54b700c009f4cbf0521c7ea01be61c5ae09cb54f27bc1b44d658c82" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "7ee80b06a215a3bca970c77cda8761822bc103d44fa4b33f4d07dcb997e36d55298bceae12241b3fa07fa63be5576068da387b8d5859aeab701369848b176d42" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "940a84b6a84d109aab208c024c6ce9647676ba0aaa11f86dbb7018f9fd2220a6d901a9027f9abcf935372727cbf09ebd61a2a2eeb87653e8ecad1bab85dc8327" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "2020b78264a82d9f4151141adba8d44bf20c5ec062eee9b595a11f9e84901bf148f298e0c9f8777dcdbc7cc4670aac356cc2ad8ccb1629f16f6a76bcefbee760" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "d1b897b0e075ba68ab572adf9d9c436663e43eb3d8e62d92fc49c9be214e6f27873fe215a65170e6bea902408a25b49506f47babd07cecf7113ec10c5dd31252" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "b14d0c62abfa469a357177e594c10c194243ed2025ab8aa5ad2fa41ad318e0ff48cd5e60bec07b13634a711d2326e488a985f31e31153399e73088efc86a5c55" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "4169c5cc808d2697dc2a82430dc23e3cd356dc70a94566810502b8d655b39abf9e7f902fe717e0389219859e1945df1af6ada42e4ccda55a197b7100a30c30a1" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "258a4edb113d66c839c8b1c91f15f35ade609f11cd7f8681a4045b9fef7b0b24c82cda06a5f2067b368825e3914e53d6948ede92efd6e8387fa2e537239b5bee" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526272829", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "79d2d8696d30f30fb34657761171a11e6c3f1e64cbe7bebee159cb95bfaf812b4f411e2f26d9c421dc2c284a3342d823ec293849e42d1e46b0a4ac1e3c86abaa" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "8b9436010dc5dee992ae38aea97f2cd63b946d94fedd2ec9671dcde3bd4ce9564d555c66c15bb2b900df72edb6b891ebcadfeff63c9ea4036a998be7973981e7" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "c8f68e696ed28242bf997f5b3b34959508e42d613810f1e2a435c96ed2ff560c7022f361a9234b9837feee90bf47922ee0fd5f8ddf823718d86d1e16c6090071" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "b02d3eee4860d5868b2c39ce39bfe81011290564dd678c85e8783f29302dfc1399ba95b6b53cd9ebbf400cca1db0ab67e19a325f2d115812d25d00978ad1bca4" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "7693ea73af3ac4dad21ca0d8da85b3118a7d1c6024cfaf557699868217bc0c2f44a199bc6c0edd519798ba05bd5b1b4484346a47c2cadf6bf30b785cc88b2baf" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "a0e5c1c0031c02e48b7f09a5e896ee9aef2f17fc9e18e997d7f6cac7ae316422c2b1e77984e5f3a73cb45deed5d3f84600105e6ee38f2d090c7d0442ea34c46d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "41daa6adcfdb69f1440c37b596440165c15ada596813e2e22f060fcd551f24dee8e04ba6890387886ceec4a7a0d7fc6b44506392ec3822c0d8c1acfc7d5aebe8" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "14d4d40d5984d84c5cf7523b7798b254e275a3a8cc0a1bd06ebc0bee726856acc3cbf516ff667cda2058ad5c3412254460a82c92187041363cc77a4dc215e487" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "d0e7a1e2b9a447fee83e2277e9ff8010c2f375ae12fa7aaa8ca5a6317868a26a367a0b69fbc1cf32a55d34eb370663016f3d2110230eba754028a56f54acf57c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "e771aa8db5a3e043e8178f39a0857ba04a3f18e4aa05743cf8d222b0b095825350ba422f63382a23d92e4149074e816a36c1cd28284d146267940b31f8818ea2" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "feb4fd6f9e87a56bef398b3284d2bda5b5b0e166583a66b61e538457ff0584872c21a32962b9928ffab58de4af2edd4e15d8b35570523207ff4e2a5aa7754caa" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "462f17bf005fb1c1b9e671779f665209ec2873e3e411f98dabf240a1d5ec3f95ce6796b6fc23fe171903b502023467dec7273ff74879b92967a2a43a5a183d33" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "d3338193b64553dbd38d144bea71c5915bb110e2d88180dbc5db364fd6171df317fc7268831b5aef75e4342b2fad8797ba39eddcef80e6ec08159350b1ad696d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "e1590d585a3d39f7cb599abd479070966409a6846d4377acf4471d065d5db94129cc9be92573b05ed226be1e9b7cb0cabe87918589f80dadd4ef5ef25a93d28e" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "f8f3726ac5a26cc80132493a6fedcb0e60760c09cfc84cad178175986819665e76842d7b9fedf76dddebf5d3f56faaad4477587af21606d396ae570d8e719af2" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "30186055c07949948183c850e9a756cc09937e247d9d928e869e20bafc3cd9721719d34e04a0899b92c736084550186886efba2e790d8be6ebf040b209c439a4" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536373839", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "f3c4276cb863637712c241c444c5cc1e3554e0fddb174d035819dd83eb700b4ce88df3ab3841ba02085e1a99b4e17310c5341075c0458ba376c95a6818fbb3e2" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "0aa007c4dd9d5832393040a1583c930bca7dc5e77ea53add7e2b3f7c8e231368043520d4a3ef53c969b6bbfd025946f632bd7f765d53c21003b8f983f75e2a6a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "08e9464720533b23a04ec24f7ae8c103145f765387d738777d3d343477fd1c58db052142cab754ea674378e18766c53542f71970171cc4f81694246b717d7564" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "d37ff7ad297993e7ec21e0f1b4b5ae719cdc83c5db687527f27516cbffa822888a6810ee5c1ca7bfe3321119be1ab7bfa0a502671c8329494df7ad6f522d440f" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "dd9042f6e464dcf86b1262f6accfafbd8cfd902ed3ed89abf78ffa482dbdeeb6969842394c9a1168ae3d481a017842f660002d42447c6b22f7b72f21aae021c9" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "bd965bf31e87d70327536f2a341cebc4768eca275fa05ef98f7f1b71a0351298de006fba73fe6733ed01d75801b4a928e54231b38e38c562b2e33ea1284992fa" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "65676d800617972fbd87e4b9514e1c67402b7a331096d3bfac22f1abb95374abc942f16e9ab0ead33b87c91968a6e509e119ff07787b3ef483e1dcdccf6e3022" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "939fa189699c5d2c81ddd1ffc1fa207c970b6a3685bb29ce1d3e99d42f2f7442da53e95a72907314f4588399a3ff5b0a92beb3f6be2694f9f86ecf2952d5b41c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f4041", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "c516541701863f91005f314108ceece3c643e04fc8c42fd2ff556220e616aaa6a48aeb97a84bad74782e8dff96a1a2fa949339d722edcaa32b57067041df88cc" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "987fd6e0d6857c553eaebb3d34970a2c2f6e89a3548f492521722b80a1c21a153892346d2cba6444212d56da9a26e324dccbc0dcde85d4d2ee4399eec5a64e8f" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "ae56deb1c2328d9c4017706bce6e99d41349053ba9d336d677c4c27d9fd50ae6aee17e853154e1f4fe7672346da2eaa31eea53fcf24a22804f11d03da6abfc2b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f4041424344", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "49d6a608c9bde4491870498572ac31aac3fa40938b38a7818f72383eb040ad39532bc06571e13d767e6945ab77c0bdc3b0284253343f9f6c1244ebf2ff0df866" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "da582ad8c5370b4469af862aa6467a2293b2b28bd80ae0e91f425ad3d47249fdf98825cc86f14028c3308c9804c78bfeeeee461444ce243687e1a50522456a1d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243444546", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "d5266aa3331194aef852eed86d7b5b2633a0af1c735906f2e13279f14931a9fc3b0eac5ce9245273bd1aa92905abe16278ef7efd47694789a7283b77da3c70f8" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f4041424344454647", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "2962734c28252186a9a1111c732ad4de4506d4b4480916303eb7991d659ccda07a9911914bc75c418ab7a4541757ad054796e26797feaf36e9f6ad43f14b35a4" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "e8b79ec5d06e111bdfafd71e9f5760f00ac8ac5d8bf768f9ff6f08b8f026096b1cc3a4c973333019f1e3553e77da3f98cb9f542e0a90e5f8a940cc58e59844b3" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243444546474849", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "dfb320c44f9d41d1efdcc015f08dd5539e526e39c87d509ae6812a969e5431bf4fa7d91ffd03b981e0d544cf72d7b1c0374f8801482e6dea2ef903877eba675e" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "d88675118fdb55a5fb365ac2af1d217bf526ce1ee9c94b2f0090b2c58a06ca58187d7fe57c7bed9d26fca067b4110eefcd9a0a345de872abe20de368001b0745" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "b893f2fc41f7b0dd6e2f6aa2e0370c0cff7df09e3acfcc0e920b6e6fad0ef747c40668417d342b80d2351e8c175f20897a062e9765e6c67b539b6ba8b9170545" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "6c67ec5697accd235c59b486d7b70baeedcbd4aa64ebd4eef3c7eac189561a726250aec4d48cadcafbbe2ce3c16ce2d691a8cce06e8879556d4483ed7165c063" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "f1aa2b044f8f0c638a3f362e677b5d891d6fd2ab0765f6ee1e4987de057ead357883d9b405b9d609eea1b869d97fb16d9b51017c553f3b93c0a1e0f1296fedcd" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "cbaa259572d4aebfc1917acddc582b9f8dfaa928a198ca7acd0f2aa76a134a90252e6298a65b08186a350d5b7626699f8cb721a3ea5921b753ae3a2dce24ba3a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "fa1549c9796cd4d303dcf452c1fbd5744fd9b9b47003d920b92de34839d07ef2a29ded68f6fc9e6c45e071a2e48bd50c5084e96b657dd0404045a1ddefe282ed" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "5cf2ac897ab444dcb5c8d87c495dbdb34e1838b6b629427caa51702ad0f9688525f13bec503a3c3a2c80a65e0b5715e8afab00ffa56ec455a49a1ad30aa24fcd" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f5051", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "9aaf80207bace17bb7ab145757d5696bde32406ef22b44292ef65d4519c3bb2ad41a59b62cc3e94b6fa96d32a7faadae28af7d35097219aa3fd8cda31e40c275" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "af88b163402c86745cb650c2988fb95211b94b03ef290eed9662034241fd51cf398f8073e369354c43eae1052f9b63b08191caa138aa54fea889cc7024236897" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "48fa7d64e1ceee27b9864db5ada4b53d00c9bc7626555813d3cd6730ab3cc06ff342d727905e33171bde6e8476e77fb1720861e94b73a2c538d254746285f430" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f5051525354", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "0e6fd97a85e904f87bfe85bbeb34f69e1f18105cf4ed4f87aec36c6e8b5f68bd2a6f3dc8a9ecb2b61db4eedb6b2ea10bf9cb0251fb0f8b344abf7f366b6de5ab" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "06622da5787176287fdc8fed440bad187d830099c94e6d04c8e9c954cda70c8bb9e1fc4a6d0baa831b9b78ef6648681a4867a11da93ee36e5e6a37d87fc63f6f" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "1da6772b58fabf9c61f68d412c82f182c0236d7d575ef0b58dd22458d643cd1dfc93b03871c316d8430d312995d4197f0874c99172ba004a01ee295abac24e46" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f5051525354555657", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "3cd2d9320b7b1d5fb9aab951a76023fa667be14a9124e394513918a3f44096ae4904ba0ffc150b63bc7ab1eeb9a6e257e5c8f000a70394a5afd842715de15f29" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "04cdc14f7434e0b4be70cb41db4c779a88eaef6accebcb41f2d42fffe7f32a8e281b5c103a27021d0d08362250753cdf70292195a53a48728ceb5844c2d98bab" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556575859", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "9071b7a8a075d0095b8fb3ae5113785735ab98e2b52faf91d5b89e44aac5b5d4ebbf91223b0ff4c71905da55342e64655d6ef8c89a4768c3f93a6dc0366b5bc8" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "ebb30240dd96c7bc8d0abe49aa4edcbb4afdc51ff9aaf720d3f9e7fbb0f9c6d6571350501769fc4ebd0b2141247ff400d4fd4be414edf37757bb90a32ac5c65a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "8532c58bf3c8015d9d1cbe00eef1f5082f8f3632fbe9f1ed4f9dfb1fa79e8283066d77c44c4af943d76b300364aecbd0648c8a8939bd204123f4b56260422dec" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "fe9846d64f7c7708696f840e2d76cb4408b6595c2f81ec6a28a7f2f20cb88cfe6ac0b9e9b8244f08bd7095c350c1d0842f64fb01bb7f532dfcd47371b0aeeb79" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "28f17ea6fb6c42092dc264257e29746321fb5bdaea9873c2a7fa9d8f53818e899e161bc77dfe8090afd82bf2266c5c1bc930a8d1547624439e662ef695f26f24" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "ec6b7d7f030d4850acae3cb615c21dd25206d63e84d1db8d957370737ba0e98467ea0ce274c66199901eaec18a08525715f53bfdb0aacb613d342ebdceeddc3b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "b403d3691c03b0d3418df327d5860d34bbfcc4519bfbce36bf33b208385fadb9186bc78a76c489d89fd57e7dc75412d23bcd1dae8470ce9274754bb8585b13c5" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "31fc79738b8772b3f55cd8178813b3b52d0db5a419d30ba9495c4b9da0219fac6df8e7c23a811551a62b827f256ecdb8124ac8a6792ccfecc3b3012722e94463" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6061", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "bb2039ec287091bcc9642fc90049e73732e02e577e2862b32216ae9bedcd730c4c284ef3968c368b7d37584f97bd4b4dc6ef6127acfe2e6ae2509124e66c8af4" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "f53d68d13f45edfcb9bd415e2831e938350d5380d3432278fc1c0c381fcb7c65c82dafe051d8c8b0d44e0974a0e59ec7bf7ed0459f86e96f329fc79752510fd3" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60616263", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "8d568c7984f0ecdf7640fbc483b5d8c9f86634f6f43291841b309a350ab9c1137d24066b09da9944bac54d5bb6580d836047aac74ab724b887ebf93d4b32eca9" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6061626364", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "c0b65ce5a96ff774c456cac3b5f2c4cd359b4ff53ef93a3da0778be4900d1e8da1601e769e8f1b02d2a2f8c5b9fa10b44f1c186985468feeb008730283a6657d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "4900bba6f5fb103ece8ec96ada13a5c3c85488e05551da6b6b33d988e611ec0fe2e3c2aa48ea6ae8986a3a231b223c5d27cec2eadde91ce07981ee652862d1e4" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60616263646566", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "c7f5c37c7285f927f76443414d4357ff789647d7a005a5a787e03c346b57f49f21b64fa9cf4b7e45573e23049017567121a9c3d4b2b73ec5e9413577525db45a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6061626364656667", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "ec7096330736fdb2d64b5653e7475da746c23a4613a82687a28062d3236364284ac01720ffb406cfe265c0df626a188c9e5963ace5d3d5bb363e32c38c2190a6" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "82e744c75f4649ec52b80771a77d475a3bc091989556960e276a5f9ead92a03f718742cdcfeaee5cb85c44af198adc43a4a428f5f0c2ddb0be36059f06d7df73" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60616263646566676869", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "2834b7a7170f1f5b68559ab78c1050ec21c919740b784a9072f6e5d69f828d70c919c5039fb148e39e2c8a52118378b064ca8d5001cd10a5478387b966715ed6" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "16b4ada883f72f853bb7ef253efcab0c3e2161687ad61543a0d2824f91c1f81347d86be709b16996e17f2dd486927b0288ad38d13063c4a9672c39397d3789b6" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "78d048f3a69d8b54ae0ed63a573ae350d89f7c6cf1f3688930de899afa037697629b314e5cd303aa62feea72a25bf42b304b6c6bcb27fae21c16d925e1fbdac3" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "0f746a48749287ada77a82961f05a4da4abdb7d77b1220f836d09ec814359c0ec0239b8c7b9ff9e02f569d1b301ef67c4612d1de4f730f81c12c40cc063c5caa" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "f0fc859d3bd195fbdc2d591e4cdac15179ec0f1dc821c11df1f0c1d26e6260aaa65b79fafacafd7d3ad61e600f250905f5878c87452897647a35b995bcadc3a3" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "2620f687e8625f6a412460b42e2cef67634208ce10a0cbd4dff7044a41b7880077e9f8dc3b8d1216d3376a21e015b58fb279b521d83f9388c7382c8505590b9b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "227e3aed8d2cb10b918fcb04f9de3e6d0a57e08476d93759cd7b2ed54a1cbf0239c528fb04bbf288253e601d3bc38b21794afef90b17094a182cac557745e75f" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f70", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "1a929901b09c25f27d6b35be7b2f1c4745131fdebca7f3e2451926720434e0db6e74fd693ad29b777dc3355c592a361c4873b01133a57c2e3b7075cbdb86f4fc" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f7071", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "5fd7968bc2fe34f220b5e3dc5af9571742d73b7d60819f2888b629072b96a9d8ab2d91b82d0a9aaba61bbd39958132fcc4257023d1eca591b3054e2dc81c8200" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "dfcce8cf32870cc6a503eadafc87fd6f78918b9b4d0737db6810be996b5497e7e5cc80e312f61e71ff3e9624436073156403f735f56b0b01845c18f6caf772e6" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f70717273", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "02f7ef3a9ce0fff960f67032b296efca3061f4934d690749f2d01c35c81c14f39a67fa350bc8a0359bf1724bffc3bca6d7c7bba4791fd522a3ad353c02ec5aa8" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f7071727374", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "64be5c6aba65d594844ae78bb022e5bebe127fd6b6ffa5a13703855ab63b624dcd1a363f99203f632ec386f3ea767fc992e8ed9686586aa27555a8599d5b808f" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "f78585505c4eaa54a8b5be70a61e735e0ff97af944ddb3001e35d86c4e2199d976104b6ae31750a36a726ed285064f5981b503889fef822fcdc2898dddb7889a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f70717273747576", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "e4b5566033869572edfd87479a5bb73c80e8759b91232879d96b1dda36c012076ee5a2ed7ae2de63ef8406a06aea82c188031b560beafb583fb3de9e57952a7e" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f7071727374757677", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "e1b3e7ed867f6c9484a2a97f7715f25e25294e992e41f6a7c161ffc2adc6daaeb7113102d5e6090287fe6ad94ce5d6b739c6ca240b05c76fb73f25dd024bf935" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "85fd085fdc12a080983df07bd7012b0d402a0f4043fcb2775adf0bad174f9b08d1676e476985785c0a5dcc41dbff6d95ef4d66a3fbdc4a74b82ba52da0512b74" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f70717273747576777879", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "aed8fa764b0fbff821e05233d2f7b0900ec44d826f95e93c343c1bc3ba5a24374b1d616e7e7aba453a0ada5e4fab5382409e0d42ce9c2bc7fb39a99c340c20f0" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "7ba3b2e297233522eeb343bd3ebcfd835a04007735e87f0ca300cbee6d416565162171581e4020ff4cf176450f1291ea2285cb9ebffe4c56660627685145051c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "de748bcf89ec88084721e16b85f30adb1a6134d664b5843569babc5bbd1a15ca9b61803c901a4fef32965a1749c9f3a4e243e173939dc5a8dc495c671ab52145" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "aaf4d2bdf200a919706d9842dce16c98140d34bc433df320aba9bd429e549aa7a3397652a4d768277786cf993cde2338673ed2e6b66c961fefb82cd20c93338f" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "c408218968b788bf864f0997e6bc4c3dba68b276e2125a4843296052ff93bf5767b8cdce7131f0876430c1165fec6c4f47adaa4fd8bcfacef463b5d3d0fa61a0" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "76d2d819c92bce55fa8e092ab1bf9b9eab237a25267986cacf2b8ee14d214d730dc9a5aa2d7b596e86a1fd8fa0804c77402d2fcd45083688b218b1cdfa0dcbcb" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "72065ee4dd91c2d8509fa1fc28a37c7fc9fa7d5b3f8ad3d0d7a25626b57b1b44788d4caf806290425f9890a3a2a35a905ab4b37acfd0da6e4517b2525c9651e4" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "64475dfe7600d7171bea0b394e27c9b00d8e74dd1e416a79473682ad3dfdbb706631558055cfc8a40e07bd015a4540dcdea15883cbbf31412df1de1cd4152b91" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "12cd1674a4488a5d7c2b3160d2e2c4b58371bedad793418d6f19c6ee385d70b3e06739369d4df910edb0b0a54cbff43d54544cd37ab3a06cfa0a3ddac8b66c89" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "60756966479dedc6dd4bcff8ea7d1d4ce4d4af2e7b097e32e3763518441147cc12b3c0ee6d2ecabf1198cec92e86a3616fba4f4e872f5825330adbb4c1dee444" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "a7803bcb71bc1d0f4383dde1e0612e04f872b715ad30815c2249cf34abb8b024915cb2fc9f4e7cc4c8cfd45be2d5a91eab0941c7d270e2da4ca4a9f7ac68663a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081828384", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "b84ef6a7229a34a750d9a98ee2529871816b87fbe3bc45b45fa5ae82d5141540211165c3c5d7a7476ba5a4aa06d66476f0d9dc49a3f1ee72c3acabd498967414" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "fae4b6d8efc3f8c8e64d001dabec3a21f544e82714745251b2b4b393f2f43e0da3d403c64db95a2cb6e23ebb7b9e94cdd5ddac54f07c4a61bd3cb10aa6f93b49" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283848586", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "34f7286605a122369540141ded79b8957255da2d4155abbf5a8dbb89c8eb7ede8eeef1daa46dc29d751d045dc3b1d658bb64b80ff8589eddb3824b13da235a6b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081828384858687", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "3b3b48434be27b9eababba43bf6b35f14b30f6a88dc2e750c358470d6b3aa3c18e47db4017fa55106d8252f016371a00f5f8b070b74ba5f23cffc5511c9f09f0" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "ba289ebd6562c48c3e10a8ad6ce02e73433d1e93d7c9279d4d60a7e879ee11f441a000f48ed9f7c4ed87a45136d7dccdca482109c78a51062b3ba4044ada2469" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283848586878889", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "022939e2386c5a37049856c850a2bb10a13dfea4212b4c732a8840a9ffa5faf54875c5448816b2785a007da8a8d2bc7d71a54e4e6571f10b600cbdb25d13ede3" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "e6fec19d89ce8717b1a087024670fe026f6c7cbda11caef959bb2d351bf856f8055d1c0ebdaaa9d1b17886fc2c562b5e99642fc064710c0d3488a02b5ed7f6fd" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "94c96f02a8f576aca32ba61c2b206f907285d9299b83ac175c209a8d43d53bfe683dd1d83e7549cb906c28f59ab7c46f8751366a28c39dd5fe2693c9019666c8" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "31a0cd215ebd2cb61de5b9edc91e6195e31c59a5648d5c9f737e125b2605708f2e325ab3381c8dce1a3e958886f1ecdc60318f882cfe20a24191352e617b0f21" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "91ab504a522dce78779f4c6c6ba2e6b6db5565c76d3e7e7c920caf7f757ef9db7c8fcf10e57f03379ea9bf75eb59895d96e149800b6aae01db778bb90afbc989" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "d85cabc6bd5b1a01a5afd8c6734740da9fd1c1acc6db29bfc8a2e5b668b028b6b3154bfb8703fa3180251d589ad38040ceb707c4bad1b5343cb426b61eaa49c1" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "d62efbec2ca9c1f8bd66ce8b3f6a898cb3f7566ba6568c618ad1feb2b65b76c3ce1dd20f7395372faf28427f61c9278049cf0140df434f5633048c86b81e0399" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f90", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "7c8fdc6175439e2c3db15bafa7fb06143a6a23bc90f449e79deef73c3d492a671715c193b6fea9f036050b946069856b897e08c00768f5ee5ddcf70b7cd6d0e0" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f9091", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "58602ee7468e6bc9df21bd51b23c005f72d6cb013f0a1b48cbec5eca299299f97f09f54a9a01483eaeb315a6478bad37ba47ca1347c7c8fc9e6695592c91d723" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "27f5b79ed256b050993d793496edf4807c1d85a7b0a67c9c4fa99860750b0ae66989670a8ffd7856d7ce411599e58c4d77b232a62bef64d15275be46a68235ff" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f90919293", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "3957a976b9f1887bf004a8dca942c92d2b37ea52600f25e0c9bc5707d0279c00c6e85a839b0d2d8eb59c51d94788ebe62474a791cadf52cccf20f5070b6573fc" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f9091929394", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "eaa2376d55380bf772ecca9cb0aa4668c95c707162fa86d518c8ce0ca9bf7362b9f2a0adc3ff59922df921b94567e81e452f6c1a07fc817cebe99604b3505d38" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "c1e2c78b6b2734e2480ec550434cb5d613111adcc21d475545c3b1b7e6ff12444476e5c055132e2229dc0f807044bb919b1a5662dd38a9ee65e243a3911aed1a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f90919293949596", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "8ab48713389dd0fcf9f965d3ce66b1e559a1f8c58741d67683cd971354f452e62d0207a65e436c5d5d8f8ee71c6abfe50e669004c302b31a7ea8311d4a916051" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f9091929394959697", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "24ce0addaa4c65038bd1b1c0f1452a0b128777aabc94a29df2fd6c7e2f85f8ab9ac7eff516b0e0a825c84a24cfe492eaad0a6308e46dd42fe8333ab971bb30ca" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "5154f929ee03045b6b0c0004fa778edee1d139893267cc84825ad7b36c63de32798e4a166d24686561354f63b00709a1364b3c241de3febf0754045897467cd4" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f90919293949596979899", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "e74e907920fd87bd5ad636dd11085e50ee70459c443e1ce5809af2bc2eba39f9e6d7128e0e3712c316da06f4705d78a4838e28121d4344a2c79c5e0db307a677" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "bf91a22334bac20f3fd80663b3cd06c4e8802f30e6b59f90d3035cc9798a217ed5a31abbda7fa6842827bdf2a7a1c21f6fcfccbb54c6c52926f32da816269be1" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "d9d5c74be5121b0bd742f26bffb8c89f89171f3f934913492b0903c271bbe2b3395ef259669bef43b57f7fcc3027db01823f6baee66e4f9fead4d6726c741fce" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "50c8b8cf34cd879f80e2faab3230b0c0e1cc3e9dcadeb1b9d97ab923415dd9a1fe38addd5c11756c67990b256e95ad6d8f9fedce10bf1c90679cde0ecf1be347" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "0a386e7cd5dd9b77a035e09fe6fee2c8ce61b5383c87ea43205059c5e4cd4f4408319bb0a82360f6a58e6c9ce3f487c446063bf813bc6ba535e17fc1826cfc91" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "1f1459cb6b61cbac5f0efe8fc487538f42548987fcd56221cfa7beb22504769e792c45adfb1d6b3d60d7b749c8a75b0bdf14e8ea721b95dca538ca6e25711209" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "e58b3836b7d8fedbb50ca5725c6571e74c0785e97821dab8b6298c10e4c079d4a6cdf22f0fedb55032925c16748115f01a105e77e00cee3d07924dc0d8f90659" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "b929cc6505f020158672deda56d0db081a2ee34c00c1100029bdf8ea98034fa4bf3e8655ec697fe36f40553c5bb46801644a627d3342f4fc92b61f03290fb381" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "72d353994b49d3e03153929a1e4d4f188ee58ab9e72ee8e512f29bc773913819ce057ddd7002c0433ee0a16114e3d156dd2c4a7e80ee53378b8670f23e33ef56" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "c70ef9bfd775d408176737a0736d68517ce1aaad7e81a93c8c1ed967ea214f56c8a377b1763e676615b60f3988241eae6eab9685a5124929d28188f29eab06f7" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "c230f0802679cb33822ef8b3b21bf7a9a28942092901d7dac3760300831026cf354c9232df3e084d9903130c601f63c1f4a4a4b8106e468cd443bbe5a734f45f" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "6f43094cafb5ebf1f7a4937ec50f56a4c9da303cbb55ac1f27f1f1976cd96beda9464f0e7b9c54620b8a9fba983164b8be3578425a024f5fe199c36356b88972" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "3745273f4c38225db2337381871a0c6aafd3af9b018c88aa02025850a5dc3a42a1a3e03e56cbf1b0876d63a441f1d2856a39b8801eb5af325201c415d65e97fe" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "c50c44cca3ec3edaae779a7e179450ebdda2f97067c690aa6c5a4ac7c30139bb27c0df4db3220e63cb110d64f37ffe078db72653e2daacf93ae3f0a2d1a7eb2e" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "8aef263e385cbc61e19b28914243262af5afe8726af3ce39a79c27028cf3ecd3f8d2dfd9cfc9ad91b58f6f20778fd5f02894a3d91c7d57d1e4b866a7f364b6be" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "28696141de6e2d9bcb3235578a66166c1448d3e905a1b482d423be4bc5369bc8c74dae0acc9cc123e1d8ddce9f97917e8c019c552da32d39d2219b9abf0fa8c8" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "2fb9eb2085830181903a9dafe3db428ee15be7662224efd643371fb25646aee716e531eca69b2bdc8233f1a8081fa43da1500302975a77f42fa592136710e9dc" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aa", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "66f9a7143f7a3314a669bf2e24bbb35014261d639f495b6c9c1f104fe8e320aca60d4550d69d52edbd5a3cdeb4014ae65b1d87aa770b69ae5c15f4330b0b0ad8" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaab", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "f4c4dd1d594c3565e3e25ca43dad82f62abea4835ed4cd811bcd975e46279828d44d4c62c3679f1b7f7b9dd4571d7b49557347b8c5460cbdc1bef690fb2a08c0" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabac", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "8f1dc9649c3a84551f8f6e91cac68242a43b1f8f328ee92280257387fa7559aa6db12e4aeadc2d26099178749c6864b357f3f83b2fb3efa8d2a8db056bed6bcc" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacad", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "3139c1a7f97afd1675d460ebbc07f2728aa150df849624511ee04b743ba0a833092f18c12dc91b4dd243f333402f59fe28abdbbbae301e7b659c7a26d5c0f979" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadae", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "06f94a2996158a819fe34c40de3cf0379fd9fb85b3e363ba3926a0e7d960e3f4c2e0c70c7ce0ccb2a64fc29869f6e7ab12bd4d3f14fce943279027e785fb5c29" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "c29c399ef3eee8961e87565c1ce263925fc3d0ce267d13e48dd9e732ee67b0f69fad56401b0f10fcaac119201046cca28c5b14abdea3212ae65562f7f138db3d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "4cec4c9df52eef05c3f6faaa9791bc7445937183224ecc37a1e58d0132d35617531d7e795f52af7b1eb9d147de1292d345fe341823f8e6bc1e5badca5c656108" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "898bfbae93b3e18d00697eab7d9704fa36ec339d076131cefdf30edbe8d9cc81c3a80b129659b163a323bab9793d4feed92d54dae966c77529764a09be88db45" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "ee9bd0469d3aaf4f14035be48a2c3b84d9b4b1fff1d945e1f1c1d38980a951be197b25fe22c731f20aeacc930ba9c4a1f4762227617ad350fdabb4e80273a0f4" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "3d4d3113300581cd96acbf091c3d0f3c310138cd6979e6026cde623e2dd1b24d4a8638bed1073344783ad0649cc6305ccec04beb49f31c633088a99b65130267" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "95c0591ad91f921ac7be6d9ce37e0663ed8011c1cfd6d0162a5572e94368bac02024485e6a39854aa46fe38e97d6c6b1947cd272d86b06bb5b2f78b9b68d559d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "227b79ded368153bf46c0a3ca978bfdbef31f3024a5665842468490b0ff748ae04e7832ed4c9f49de9b1706709d623e5c8c15e3caecae8d5e433430ff72f20eb" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "5d34f3952f0105eef88ae8b64c6ce95ebfade0e02c69b08762a8712d2e4911ad3f941fc4034dc9b2e479fdbcd279b902faf5d838bb2e0c6495d372b5b7029813" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "7f939bf8353abce49e77f14f3750af20b7b03902e1a1e7fb6aaf76d0259cd401a83190f15640e74f3e6c5a90e839c7821f6474757f75c7bf9002084ddc7a62dc" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "062b61a2f9a33a71d7d0a06119644c70b0716a504de7e5e1be49bd7b86e7ed6817714f9f0fc313d06129597e9a2235ec8521de36f7290a90ccfc1ffa6d0aee29" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "f29e01eeae64311eb7f1c6422f946bf7bea36379523e7b2bbaba7d1d34a22d5ea5f1c5a09d5ce1fe682cced9a4798d1a05b46cd72dff5c1b355440b2a2d476bc" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9ba", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "ec38cd3bbab3ef35d7cb6d5c914298351d8a9dc97fcee051a8a02f58e3ed6184d0b7810a5615411ab1b95209c3c810114fdeb22452084e77f3f847c6dbaafe16" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babb", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "c2aef5e0ca43e82641565b8cb943aa8ba53550caef793b6532fafad94b816082f0113a3ea2f63608ab40437ecc0f0229cb8fa224dcf1c478a67d9b64162b92d1" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbc", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "15f534efff7105cd1c254d074e27d5898b89313b7d366dc2d7d87113fa7d53aae13f6dba487ad8103d5e854c91fdb6e1e74b2ef6d1431769c30767dde067a35c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbd", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "89acbca0b169897a0a2714c2df8c95b5b79cb69390142b7d6018bb3e3076b099b79a964152a9d912b1b86412b7e372e9cecad7f25d4cbab8a317be36492a67d7" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbe", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "e3c0739190ed849c9c962fd9dbb55e207e624fcac1eb417691515499eea8d8267b7e8f1287a63633af5011fde8c4ddf55bfdf722edf88831414f2cfaed59cb9a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "8d6cf87c08380d2d1506eee46fd4222d21d8c04e585fbfd08269c98f702833a156326a0724656400ee09351d57b440175e2a5de93cc5f80db6daf83576cf75fa" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "da24bede383666d563eeed37f6319baf20d5c75d1635a6ba5ef4cfa1ac95487e96f8c08af600aab87c986ebad49fc70a58b4890b9c876e091016daf49e1d322e" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "f9d1d1b1e87ea7ae753a029750cc1cf3d0157d41805e245c5617bb934e732f0ae3180b78e05bfe76c7c3051e3e3ac78b9b50c05142657e1e03215d6ec7bfd0fc" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "11b7bc1668032048aa43343de476395e814bbbc223678db951a1b03a021efac948cfbe215f97fe9a72a2f6bc039e3956bfa417c1a9f10d6d7ba5d3d32ff323e5" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "b8d9000e4fc2b066edb91afee8e7eb0f24e3a201db8b6793c0608581e628ed0bcc4e5aa6787992a4bcc44e288093e63ee83abd0bc3ec6d0934a674a4da13838a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "ce325e294f9b6719d6b61278276ae06a2564c03bb0b783fafe785bdf89c7d5acd83e78756d301b445699024eaeb77b54d477336ec2a4f332f2b3f88765ddb0c3" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "29acc30e9603ae2fccf90bf97e6cc463ebe28c1b2f9b4b765e70537c25c702a29dcbfbf14c99c54345ba2b51f17b77b5f15db92bbad8fa95c471f5d070a137cc" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "3379cbaae562a87b4c0425550ffdd6bfe1203f0d666cc7ea095be407a5dfe61ee91441cd5154b3e53b4f5fb31ad4c7a9ad5c7af4ae679aa51a54003a54ca6b2d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "3095a349d245708c7cf550118703d7302c27b60af5d4e67fc978f8a4e60953c7a04f92fcf41aee64321ccb707a895851552b1e37b00bc5e6b72fa5bcef9e3fff" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "07262d738b09321f4dbccec4bb26f48cb0f0ed246ce0b31b9a6e7bc683049f1f3e5545f28ce932dd985c5ab0f43bd6de0770560af329065ed2e49d34624c2cbb" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "b6405eca8ee3316c87061cc6ec18dba53e6c250c63ba1f3bae9e55dd3498036af08cd272aa24d713c6020d77ab2f3919af1a32f307420618ab97e73953994fb4" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9ca", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "7ee682f63148ee45f6e5315da81e5c6e557c2c34641fc509c7a5701088c38a74756168e2cd8d351e88fd1a451f360a01f5b2580f9b5a2e8cfc138f3dd59a3ffc" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacb", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "1d263c179d6b268f6fa016f3a4f29e943891125ed8593c81256059f5a7b44af2dcb2030d175c00e62ecaf7ee96682aa07ab20a611024a28532b1c25b86657902" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcc", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "106d132cbdb4cd2597812846e2bc1bf732fec5f0a5f65dbb39ec4e6dc64ab2ce6d24630d0f15a805c3540025d84afa98e36703c3dbee713e72dde8465bc1be7e" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccd", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "0e79968226650667a8d862ea8da4891af56a4e3a8b6d1750e394f0dea76d640d85077bcec2cc86886e506751b4f6a5838f7f0b5fef765d9dc90dcdcbaf079f08" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdce", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "521156a82ab0c4e566e5844d5e31ad9aaf144bbd5a464fdca34dbd5717e8ff711d3ffebbfa085d67fe996a34f6d3e4e60b1396bf4b1610c263bdbb834d560816" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "1aba88befc55bc25efbce02db8b9933e46f57661baeabeb21cc2574d2a518a3cba5dc5a38e49713440b25f9c744e75f6b85c9d8f4681f676160f6105357b8406" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "5a9949fcb2c473cda968ac1b5d08566dc2d816d960f57e63b898fa701cf8ebd3f59b124d95bfbbedc5f1cf0e17d5eaed0c02c50b69d8a402cabcca4433b51fd4" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "b0cead09807c672af2eb2b0f06dde46cf5370e15a4096b1a7d7cbb36ec31c205fbefca00b7a4162fa89fb4fb3eb78d79770c23f44e7206664ce3cd931c291e5d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "bb6664931ec97044e45b2ae420ae1c551a8874bc937d08e969399c3964ebdba8346cdd5d09caafe4c28ba7ec788191ceca65ddd6f95f18583e040d0f30d0364d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "65bc770a5faa3792369803683e844b0be7ee96f29f6d6a35568006bd5590f9a4ef639b7a8061c7b0424b66b60ac34af3119905f33a9d8c3ae18382ca9b689900" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "ea9b4dca333336aaf839a45c6eaa48b8cb4c7ddabffea4f643d6357ea6628a480a5b45f2b052c1b07d1fedca918b6f1139d80f74c24510dcbaa4be70eacc1b06" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "e6342fb4a780ad975d0e24bce149989b91d360557e87994f6b457b895575cc02d0c15bad3ce7577f4c63927ff13f3e381ff7e72bdbe745324844a9d27e3f1c01" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "3e209c9b33e8e461178ab46b1c64b49a07fb745f1c8bc95fbfb94c6b87c69516651b264ef980937fad41238b91ddc011a5dd777c7efd4494b4b6ecd3a9c22ac0" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "fd6a3d5b1875d80486d6e69694a56dbb04a99a4d051f15db2689776ba1c4882e6d462a603b7015dc9f4b7450f05394303b8652cfb404a266962c41bae6e18a94" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "951e27517e6bad9e4195fc8671dee3e7e9be69cee1422cb9fecfce0dba875f7b310b93ee3a3d558f941f635f668ff832d2c1d033c5e2f0997e4c66f147344e02" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "8eba2f874f1ae84041903c7c4253c82292530fc8509550bfdc34c95c7e2889d5650b0ad8cb988e5c4894cb87fbfbb19612ea93ccc4c5cad17158b9763464b492" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9da", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "16f712eaa1b7c6354719a8e7dbdfaf55e4063a4d277d947550019b38dfb564830911057d50506136e2394c3b28945cc964967d54e3000c2181626cfb9b73efd2" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadb", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "c39639e7d5c7fb8cdd0fd3e6a52096039437122f21c78f1679cea9d78a734c56ecbeb28654b4f18e342c331f6f7229ec4b4bc281b2d80a6eb50043f31796c88c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdc", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "72d081af99f8a173dcc9a0ac4eb3557405639a29084b54a40172912a2f8a395129d5536f0918e902f9e8fa6000995f4168ddc5f893011be6a0dbc9b8a1a3f5bb" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdd", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "c11aa81e5efd24d5fc27ee586cfd8847fbb0e27601ccece5ecca0198e3c7765393bb74457c7e7a27eb9170350e1fb53857177506be3e762cc0f14d8c3afe9077" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcddde", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "c28f2150b452e6c0c424bcde6f8d72007f9310fed7f2f87de0dbb64f4479d6c1441ba66f44b2accee61609177ed340128b407ecec7c64bbe50d63d22d8627727" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "f63d88122877ec30b8c8b00d22e89000a966426112bd44166e2f525b769ccbe9b286d437a0129130dde1a86c43e04bedb594e671d98283afe64ce331de9828fd" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "348b0532880b88a6614a8d7408c3f913357fbb60e995c60205be9139e74998aede7f4581e42f6b52698f7fa1219708c14498067fd1e09502de83a77dd281150c" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "5133dc8bef725359dff59792d85eaf75b7e1dcd1978b01c35b1b85fcebc63388ad99a17b6346a217dc1a9622ebd122ecf6913c4d31a6b52a695b86af00d741a0" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "2753c4c0e98ecad806e88780ec27fccd0f5c1ab547f9e4bf1659d192c23aa2cc971b58b6802580baef8adc3b776ef7086b2545c2987f348ee3719cdef258c403" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "b1663573ce4b9d8caefc865012f3e39714b9898a5da6ce17c25a6a47931a9ddb9bbe98adaa553beed436e89578455416c2a52a525cf2862b8d1d49a2531b7391" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "64f58bd6bfc856f5e873b2a2956ea0eda0d6db0da39c8c7fc67c9f9feefcff3072cdf9e6ea37f69a44f0c61aa0da3693c2db5b54960c0281a088151db42b11e8" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "0764c7be28125d9065c4b98a69d60aede703547c66a12e17e1c618994132f5ef82482c1e3fe3146cc65376cc109f0138ed9a80e49f1f3c7d610d2f2432f20605" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "f748784398a2ff03ebeb07e155e66116a839741a336e32da71ec696001f0ad1b25cd48c69cfca7265eca1dd71904a0ce748ac4124f3571076dfa7116a9cf00e9" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "3f0dbc0186bceb6b785ba78d2a2a013c910be157bdaffae81bb6663b1a73722f7f1228795f3ecada87cf6ef0078474af73f31eca0cc200ed975b6893f761cb6d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "d4762cd4599876ca75b2b8fe249944dbd27ace741fdab93616cbc6e425460feb51d4e7adcc38180e7fc47c89024a7f56191adb878dfde4ead62223f5a2610efe" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "cd36b3d5b4c91b90fcbba79513cfee1907d8645a162afd0cd4cf4192d4a5f4c892183a8eacdb2b6b6a9d9aa8c11ac1b261b380dbee24ca468f1bfd043c58eefe" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9ea", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "98593452281661a53c48a9d8cd790826c1a1ce567738053d0bee4a91a3d5bd92eefdbabebe3204f2031ca5f781bda99ef5d8ae56e5b04a9e1ecd21b0eb05d3e1" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaeb", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "771f57dd2775ccdab55921d3e8e30ccf484d61fe1c1b9c2ae819d0fb2a12fab9be70c4a7a138da84e8280435daade5bbe66af0836a154f817fb17f3397e725a3" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebec", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "c60897c6f828e21f16fbb5f15b323f87b6c8955eabf1d38061f707f608abdd993fac3070633e286cf8339ce295dd352df4b4b40b2f29da1dd50b3a05d079e6bb" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebeced", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "8210cd2c2d3b135c2cf07fa0d1433cd771f325d075c6469d9c7f1ba0943cd4ab09808cabf4acb9ce5bb88b498929b4b847f681ad2c490d042db2aec94214b06b" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedee", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "1d4edfffd8fd80f7e4107840fa3aa31e32598491e4af7013c197a65b7f36dd3ac4b478456111cd4309d9243510782fa31b7c4c95fa951520d020eb7e5c36e4ef" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeef", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "af8e6e91fab46ce4873e1a50a8ef448cc29121f7f74deef34a71ef89cc00d9274bc6c2454bbb3230d8b2ec94c62b1dec85f3593bfa30ea6f7a44d7c09465a253" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "29fd384ed4906f2d13aa9fe7af905990938bed807f1832454a372ab412eea1f5625a1fcc9ac8343b7c67c5aba6e0b1cc4644654913692c6b39eb9187ceacd3ec" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "a268c7885d9874a51c44dffed8ea53e94f78456e0b2ed99ff5a3924760813826d960a15edbedbb5de5226ba4b074e71b05c55b9756bb79e55c02754c2c7b6c8a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "0cf8545488d56a86817cd7ecb10f7116b7ea530a45b6ea497b6c72c997e09e3d0da8698f46bb006fc977c2cd3d1177463ac9057fdd1662c85d0c126443c10473" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "b39614268fdd8781515e2cfebf89b4d5402bab10c226e6344e6b9ae000fb0d6c79cb2f3ec80e80eaeb1980d2f8698916bd2e9f747236655116649cd3ca23a837" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "74bef092fc6f1e5dba3663a3fb003b2a5ba257496536d99f62b9d73f8f9eb3ce9ff3eec709eb883655ec9eb896b9128f2afc89cf7d1ab58a72f4a3bf034d2b4a" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "3a988d38d75611f3ef38b8774980b33e573b6c57bee0469ba5eed9b44f29945e7347967fba2c162e1c3be7f310f2f75ee2381e7bfd6b3f0baea8d95dfb1dafb1" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "58aedfce6f67ddc85a28c992f1c0bd0969f041e66f1ee88020a125cbfcfebcd61709c9c4eba192c15e69f020d462486019fa8dea0cd7a42921a19d2fe546d43d" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "9347bd291473e6b4e368437b8e561e065f649a6d8ada479ad09b1999a8f26b91cf6120fd3bfe014e83f23acfa4c0ad7b3712b2c3c0733270663112ccd9285cd9" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "b32163e7c5dbb5f51fdc11d2eac875efbbcb7e7699090a7e7ff8a8d50795af5d74d9ff98543ef8cdf89ac13d0485278756e0ef00c817745661e1d59fe38e7537" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "1085d78307b1c4b008c57a2e7e5b234658a0a82e4ff1e4aaac72b312fda0fe27d233bc5b10e9cc17fdc7697b540c7d95eb215a19a1a0e20e1abfa126efd568c7" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fa", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "4e5c734c7dde011d83eac2b7347b373594f92d7091b9ca34cb9c6f39bdf5a8d2f134379e16d822f6522170ccf2ddd55c84b9e6c64fc927ac4cf8dfb2a17701f2" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafb", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "695d83bd990a1117b3d0ce06cc888027d12a054c2677fd82f0d4fbfc93575523e7991a5e35a3752e9b70ce62992e268a877744cdd435f5f130869c9a2074b338" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfc", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "a6213743568e3b3158b9184301f3690847554c68457cb40fc9a4b8cfd8d4a118c301a07737aeda0f929c68913c5f51c80394f53bff1c3e83b2e40ca97eba9e15" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfd", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "d444bfa2362a96df213d070e33fa841f51334e4e76866b8139e8af3bb3398be2dfaddcbc56b9146de9f68118dc5829e74b0c28d7711907b121f9161cb92b69a9" + }, + { + "in": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe", + "key": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "out": "142709d62e28fcccd0af97fad0f8465b971e82201dc51070faa0372aa43e92484be1c1e73ba10906d5d1853db6a4106e0a7bf9800d373d6dee2d46d62ef2a461" + } + ] +}) diff --git a/test/main.mjs b/test/main.mjs deleted file mode 100644 index 1737521..0000000 --- a/test/main.mjs +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Chris Duncan -// SPDX-License-Identifier: GPL-3.0-or-later - -import './calculate-pow.test.mjs' -import './create-wallet.test.mjs' -import './derive-accounts.test.mjs' -import './import-wallet.test.mjs' -import './lock-unlock-wallet.mjs' -import './manage-rolodex.mjs' -import './refresh-accounts.test.mjs' -import './sign-blocks.test.mjs' -import './tools.test.mjs' - -console.log('%cTESTING COMPLETE', 'color:orange;font-weight:bold') diff --git a/test/perf.account.js b/test/perf.account.js new file mode 100644 index 0000000..05ab058 --- /dev/null +++ b/test/perf.account.js @@ -0,0 +1,64 @@ +// SPDX-FileCopyrightText: 2024 Chris Duncan +// SPDX-License-Identifier: GPL-3.0-or-later + +'use strict' + +import { assert, stats, suite, test } from './GLOBALS.mjs' +import { NANO_TEST_VECTORS } from './VECTORS.js' +import { Bip44Wallet, Blake2bWallet } from '../dist/main.min.js' + +await suite('Account performance', async () => { + const COUNT = 0x200 + + await test(`Time to create ${COUNT} BIP-44 accounts`, async () => { + const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const start = performance.now() + const accounts = await wallet.accounts(0, COUNT - 1) + const end = performance.now() + console.log(`Total: ${end - start} ms`) + console.log(`Average: ${(end - start) / COUNT} ms`) + assert.equals(accounts.length, COUNT) + wallet.destroy() + }) + + await test(`Time to create ${COUNT} BLAKE2b accounts`, async () => { + const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const start = performance.now() + const accounts = await wallet.accounts(0, COUNT - 1) + const end = performance.now() + console.log(`Total: ${end - start} ms`) + console.log(`Average: ${(end - start) / COUNT} ms`) + assert.equals(accounts.length, COUNT) + wallet.destroy() + }) + + await test(`Time to create 1 BIP-44 account ${COUNT} times`, async () => { + const times = [] + const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + for (let i = 0; i < COUNT; i++) { + const start = performance.now() + await wallet.accounts(i) + const end = performance.now() + times.push(end - start) + } + wallet.destroy() + console.log(stats(times)) + }) + + await test(`Average time to create 1 BLAKE2b account ${COUNT} times`, async () => { + const times = [] + const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + for (let i = 0; i < COUNT; i++) { + const start = performance.now() + await wallet.accounts(i) + const end = performance.now() + times.push(end - start) + } + wallet.destroy() + console.log(stats(times)) + }) +}) diff --git a/test/perf.block.js b/test/perf.block.js new file mode 100644 index 0000000..6cc051f --- /dev/null +++ b/test/perf.block.js @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: 2024 Chris Duncan +// SPDX-License-Identifier: GPL-3.0-or-later + +'use strict' + +import { assert, stats, suite, test } from './GLOBALS.mjs' +import { NANO_TEST_VECTORS } from './VECTORS.js' +import { SendBlock } from '../dist/main.min.js' + +await suite('Block performance', async () => { + const COUNT = 0x200 + + await test(`libnemo: Time to calculate proof-of-work for a send block ${COUNT} times`, { skip: true }, async () => { + const times = [] + const block = new SendBlock( + NANO_TEST_VECTORS.SEND_BLOCK.account, + NANO_TEST_VECTORS.SEND_BLOCK.balance, + NANO_TEST_VECTORS.SEND_BLOCK.link, + '0', + NANO_TEST_VECTORS.SEND_BLOCK.representative, + NANO_TEST_VECTORS.SEND_BLOCK.previous + ) + for (let i = 0; i < COUNT; i++) { + const start = performance.now() + await block.pow() + const end = performance.now() + times.push(end - start) + console.log(`${block.work} (${end - start} ms)`) + } + console.log(stats(times)) + }) +}) diff --git a/perf/main.mjs b/test/perf.main.mjs similarity index 67% rename from perf/main.mjs rename to test/perf.main.mjs index a6b9de7..25e9b8d 100644 --- a/perf/main.mjs +++ b/test/perf.main.mjs @@ -1,8 +1,8 @@ // SPDX-FileCopyrightText: 2024 Chris Duncan // SPDX-License-Identifier: GPL-3.0-or-later -// import './wallet.perf.js' -// import './account.perf.js' -import './block.perf.js' +import './perf.wallet.js' +import './perf.account.js' +import './perf.block.js' console.log('%cTESTING COMPLETE', 'color:orange;font-weight:bold') diff --git a/perf/wallet.perf.js b/test/perf.wallet.js similarity index 54% rename from perf/wallet.perf.js rename to test/perf.wallet.js index 7ed3b14..816dde1 100644 --- a/perf/wallet.perf.js +++ b/test/perf.wallet.js @@ -3,9 +3,9 @@ 'use strict' -import { assert, average, skip, suite, test } from '#GLOBALS.mjs' -import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js' -import { Bip44Wallet, Blake2bWallet } from '#dist/main.js' +import { assert, stats, suite, test } from './GLOBALS.mjs' +import { NANO_TEST_VECTORS } from './VECTORS.js' +import { Bip44Wallet, Blake2bWallet } from '../dist/main.min.js' await suite(`Wallet performance`, async () => { const COUNT = 0x20 @@ -17,12 +17,9 @@ await suite(`Wallet performance`, async () => { const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD) const end = performance.now() times.push(end - start) + wallet.destroy() } - const { total, arithmetic, harmonic, geometric } = average(times) - console.log(`Total: ${total} ms`) - console.log(`Average: ${arithmetic} ms`) - console.log(`Harmonic: ${harmonic} ms`) - console.log(`Geometric: ${geometric} ms`) + console.log(stats(times)) }) await test(`Time to create ${COUNT} BLAKE2b wallets`, async () => { @@ -32,11 +29,8 @@ await suite(`Wallet performance`, async () => { const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD) const end = performance.now() times.push(end - start) + wallet.destroy() } - const { total, arithmetic, harmonic, geometric } = average(times) - console.log(`Total: ${total} ms`) - console.log(`Average: ${arithmetic} ms`) - console.log(`Harmonic: ${harmonic} ms`) - console.log(`Geometric: ${geometric} ms`) + console.log(stats(times)) }) }) diff --git a/test/performance.html b/test/performance.html new file mode 100644 index 0000000..b62287f --- /dev/null +++ b/test/performance.html @@ -0,0 +1,16 @@ + + + + + + + + + + + + + diff --git a/test/test.blake2b.mjs b/test/test.blake2b.mjs new file mode 100644 index 0000000..4ce2a2f --- /dev/null +++ b/test/test.blake2b.mjs @@ -0,0 +1,91 @@ +// SPDX-FileCopyrightText: 2024 Chris Duncan +// SPDX-License-Identifier: GPL-3.0-or-later + +'use strict' + +import { assert, suite, test } from './GLOBALS.mjs' +import { BLAKE2B_TEST_VECTORS } from './VECTORS.js' +import { Blake2b } from '../dist/main.min.js' + +await suite('BLAKE2b test vectors', async () => { + + await test('check 512 reference test vectors', async () => { + for (let i = 0; i < BLAKE2B_TEST_VECTORS.REFERENCE.length; i++) { + const test = BLAKE2B_TEST_VECTORS.REFERENCE[i] + if (test.in.length % 2 === 1) test.in = `0${test.in}` + const input = Uint8Array.from(test.in + .split(/(.{2})/) + .filter(v => v.length > 0) + .map(v => parseInt(v, 16)) + ) + let key + if (test.key.length > 0) { + if (test.key.length % 2 === 1) { + test.key = `0${test.key}` + } + key = Uint8Array.from(test.key + .split(/(.{2})/) + .filter(v => v.length > 0) + .map(v => parseInt(v, 16)) + ) + } + try { + const output = new Blake2b(64, key).update(input).digest('hex') + assert.equals(output, test.out) + } catch (err) { + console.error(`blake2b reference test vector ${i} failed`, { cause: err }) + } + } + }) + + await test('check 64 libsodium test vectors', async () => { + for (let i = 0; i < BLAKE2B_TEST_VECTORS.LIBSODIUM.length; i++) { + const test = BLAKE2B_TEST_VECTORS.LIBSODIUM[i] + if (test.in.length % 2 === 1) test.in = `0${test.in}` + const input = Uint8Array.from(test.in + .split(/(.{2})/) + .filter(v => v.length > 0) + .map(v => parseInt(v, 16)) + ) + let key + if (test.key.length > 0) { + if (test.key.length % 2 === 1) { + test.key = `0${test.key}` + } + key = Uint8Array.from(test.key + .split(/(.{2})/) + .filter(v => v.length > 0) + .map(v => parseInt(v, 16)) + ) + } + let salt + if (test.salt && test.salt.length > 0) { + if (test.salt.length % 2 === 1) { + test.salt = `0${test.salt}` + } + salt = Uint8Array.from(test.salt + .split(/(.{2})/) + .filter(v => v.length > 0) + .map(v => parseInt(v, 16)) + ) + } + let personal + if (test.personal && test.personal.length > 0) { + if (test.personal.length % 2 === 1) { + test.personal = `0${test.personal}` + } + personal = Uint8Array.from(test.personal + .split(/(.{2})/) + .filter(v => v.length > 0) + .map(v => parseInt(v, 16)) + ) + } + try { + const output = new Blake2b(test.outlen ?? 64, key, salt, personal).update(input).digest('hex') + assert.equals(output, test.out) + } catch (err) { + console.error(`blake2b libsodium test vector ${i} failed`, { cause: err }) + } + } + }) +}) diff --git a/test/calculate-pow.test.mjs b/test/test.calculate-pow.mjs similarity index 85% rename from test/calculate-pow.test.mjs rename to test/test.calculate-pow.mjs index e33ff6c..f17d3b9 100644 --- a/test/calculate-pow.test.mjs +++ b/test/test.calculate-pow.mjs @@ -3,9 +3,9 @@ 'use strict' -import { assert, suite, test } from '#GLOBALS.mjs' -import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js' -import { SendBlock, Blake2b } from '#dist/main.js' +import { assert, suite, test } from './GLOBALS.mjs' +import { NANO_TEST_VECTORS } from './VECTORS.js' +import { SendBlock, Blake2b } from '../dist/main.min.js' await suite('Calculate proof-of-work', async () => { diff --git a/test/create-wallet.test.mjs b/test/test.create-wallet.mjs similarity index 70% rename from test/create-wallet.test.mjs rename to test/test.create-wallet.mjs index f0feaab..61e9b96 100644 --- a/test/create-wallet.test.mjs +++ b/test/test.create-wallet.mjs @@ -3,11 +3,12 @@ 'use strict' -import { assert, skip, suite, test } from '#GLOBALS.mjs' -import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js' -import { Bip44Wallet, Blake2bWallet, LedgerWallet } from '#dist/main.js' +import { assert, suite, test } from './GLOBALS.mjs' +import { NANO_TEST_VECTORS } from './VECTORS.js' +import { Bip44Wallet, Blake2bWallet, LedgerWallet } from '../dist/main.min.js' await suite('Create wallets', async () => { + await test('BIP-44 wallet with random entropy', async () => { const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD) await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) @@ -18,6 +19,8 @@ await suite('Create wallets', async () => { assert.ok(/^(?:[a-z]{3,} ){11,23}[a-z]{3,}$/.test(wallet.mnemonic)) assert.ok('seed' in wallet) assert.ok(/[A-Fa-f0-9]{32,64}/.test(wallet.seed)) + + wallet.destroy() }) await test('BLAKE2b wallet with random entropy', async () => { @@ -30,34 +33,34 @@ await suite('Create wallets', async () => { assert.ok(/^(?:[a-z]{3,} ){11,23}[a-z]{3,}$/.test(wallet.mnemonic)) assert.ok('seed' in wallet) assert.ok(/[A-Fa-f0-9]{32,64}/.test(wallet.seed)) + + wallet.destroy() }) await test('BIP-44 replace invalid salt with empty string', async () => { - const invalidArgs = [null, true, false, 0, 1, 2, { "foo": "bar" }] + const invalidArgs = [null, true, false, 0, 1, 2, { foo: 'bar' }] for (const arg of invalidArgs) { //@ts-expect-error - await assert.resolves(Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD, arg)) + const wallet = Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD, arg) + await assert.resolves(wallet); + (await wallet).destroy() } }) await test('fail when using new', async () => { - //@ts-expect-error assert.throws(() => new Bip44Wallet()) - //@ts-expect-error assert.throws(() => new Blake2bWallet()) - //@ts-expect-error assert.throws(() => new LedgerWallet()) }) await test('fail without a password', async () => { - //@ts-expect-error await assert.rejects(Bip44Wallet.create()) - //@ts-expect-error await assert.rejects(Blake2bWallet.create()) }) -}) -await skip('connect to ledger', async () => { - const wallet = await LedgerWallet.create() - assert.ok(wallet) + await test('connect to ledger', { skip: true }, async () => { + const wallet = await LedgerWallet.create() + assert.ok(wallet) + wallet.destroy() + }) }) diff --git a/test/derive-accounts.test.mjs b/test/test.derive-accounts.mjs similarity index 68% rename from test/derive-accounts.test.mjs rename to test/test.derive-accounts.mjs index 562635a..1cea337 100644 --- a/test/derive-accounts.test.mjs +++ b/test/test.derive-accounts.mjs @@ -3,20 +3,25 @@ 'use strict' -import { assert, skip, suite, test } from '#GLOBALS.mjs' -import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js' -import { Bip44Wallet, Blake2bWallet, LedgerWallet } from '#dist/main.js' +import { assert, suite, test } from './GLOBALS.mjs' +import { NANO_TEST_VECTORS } from './VECTORS.js' +import { Bip44Wallet, Blake2bWallet, LedgerWallet } from '../dist/main.min.js' await suite('Account derivation', async () => { await test('should derive the first account from the given BIP-44 seed', async () => { const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED) await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const account = await wallet.account() + + assert.equals(account.privateKey, NANO_TEST_VECTORS.PRIVATE_0) + assert.equals(account.publicKey, NANO_TEST_VECTORS.PUBLIC_0) + assert.equals(account.address, NANO_TEST_VECTORS.ADDRESS_0) + assert.equals(account.index, 0) + const accounts = await wallet.accounts() + assert.equals(account, accounts[0]) - assert.equals(accounts.length, 1) - assert.equals(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_0) - assert.equals(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_0) - assert.equals(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_0) + wallet.destroy() }) await test('should derive low indexed accounts from the given BIP-44 seed', async () => { @@ -25,12 +30,14 @@ await suite('Account derivation', async () => { const accounts = await wallet.accounts(1, 2) assert.equals(accounts.length, 2) - assert.equals(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_1) - assert.equals(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_1) - assert.equals(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_1) - assert.equals(accounts[1].privateKey, NANO_TEST_VECTORS.PRIVATE_2) - assert.equals(accounts[1].publicKey, NANO_TEST_VECTORS.PUBLIC_2) - assert.equals(accounts[1].address, NANO_TEST_VECTORS.ADDRESS_2) + assert.equals(accounts[1].privateKey, NANO_TEST_VECTORS.PRIVATE_1) + assert.equals(accounts[1].publicKey, NANO_TEST_VECTORS.PUBLIC_1) + assert.equals(accounts[1].address, NANO_TEST_VECTORS.ADDRESS_1) + assert.equals(accounts[2].privateKey, NANO_TEST_VECTORS.PRIVATE_2) + assert.equals(accounts[2].publicKey, NANO_TEST_VECTORS.PUBLIC_2) + assert.equals(accounts[2].address, NANO_TEST_VECTORS.ADDRESS_2) + + wallet.destroy() }) await test('should derive high indexed accounts from the given seed', async () => { @@ -39,15 +46,17 @@ await suite('Account derivation', async () => { const accounts = await wallet.accounts(0x70000000, 0x700000ff) assert.equals(accounts.length, 0x100) - for (let i = 0; i < accounts.length; i++) { + for (let i = 0x70000000; i < 0x700000ff; i++) { const a = accounts[i] assert.exists(a) assert.exists(a.address) assert.exists(a.publicKey) assert.exists(a.privateKey) assert.exists(a.index) - assert.equals(a.index, i + 0x70000000) + assert.equals(a.index, i) } + + wallet.destroy() }) await test('should derive accounts for a BLAKE2b wallet', async () => { @@ -74,14 +83,18 @@ await suite('Account derivation', async () => { assert.exists(a.privateKey) assert.exists(a.index) } + + wallet.destroy() }) - await skip('fetch the first account from a Ledger device', async () => { + await test('fetch the first account from a Ledger device', { skip: true }, async () => { const wallet = await LedgerWallet.create() const accounts = await wallet.accounts() assert.equals(accounts.length, 1) assert.exists(accounts[0].publicKey) assert.exists(accounts[0].address) + + wallet.destroy() }) }) diff --git a/test/import-wallet.test.mjs b/test/test.import-wallet.mjs similarity index 94% rename from test/import-wallet.test.mjs rename to test/test.import-wallet.mjs index 5f7a6a7..18d13f5 100644 --- a/test/import-wallet.test.mjs +++ b/test/test.import-wallet.mjs @@ -3,11 +3,12 @@ 'use strict' -import { assert, suite, test } from '#GLOBALS.mjs' -import { BIP32_TEST_VECTORS, CUSTOM_TEST_VECTORS, NANO_TEST_VECTORS, TREZOR_TEST_VECTORS } from '#test/TEST_VECTORS.js' -import { Account, Bip44Wallet, Blake2bWallet } from '#dist/main.js' +import { assert, suite, test } from './GLOBALS.mjs' +import { BIP32_TEST_VECTORS, CUSTOM_TEST_VECTORS, NANO_TEST_VECTORS, TREZOR_TEST_VECTORS } from './VECTORS.js' +import { Account, Bip44Wallet, Blake2bWallet } from '../dist/main.min.js' await suite('Import wallets', async () => { + await test('nano.org BIP-44 test vector mnemonic', async () => { const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) @@ -21,6 +22,8 @@ await suite('Import wallets', async () => { assert.equals(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_0) assert.equals(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_0) assert.equals(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_0) + + wallet.destroy() }) await test('nano.org BIP-44 test vector seed with no mnemonic', async () => { @@ -36,6 +39,8 @@ await suite('Import wallets', async () => { assert.equals(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_0) assert.equals(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_0) assert.equals(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_0) + + wallet.destroy() }) await test('Trezor-derived BIP-44 entropy for 12-word mnemonic', async () => { @@ -49,6 +54,8 @@ await suite('Import wallets', async () => { assert.equals(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_0) assert.equals(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_0) assert.equals(account.address, CUSTOM_TEST_VECTORS.ADDRESS_0) + + wallet.destroy() }) await test('Trezor-derived BIP-44 entropy for 15-word mnemonic', async () => { @@ -62,6 +69,8 @@ await suite('Import wallets', async () => { assert.equals(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_1) assert.equals(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_1) assert.equals(account.address, CUSTOM_TEST_VECTORS.ADDRESS_1) + + wallet.destroy() }) await test('Trezor-derived BIP-44 entropy for 18-word mnemonic', async () => { @@ -75,6 +84,8 @@ await suite('Import wallets', async () => { assert.equals(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_2) assert.equals(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_2) assert.equals(account.address, CUSTOM_TEST_VECTORS.ADDRESS_2) + + wallet.destroy() }) await test('Trezor-derived BIP-44 entropy for 21-word mnemonic', async () => { @@ -88,6 +99,8 @@ await suite('Import wallets', async () => { assert.equals(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_3) assert.equals(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_3) assert.equals(account.address, CUSTOM_TEST_VECTORS.ADDRESS_3) + + wallet.destroy() }) await test('BIP-44 zero-string entropy', async () => { @@ -107,6 +120,8 @@ await suite('Import wallets', async () => { assert.exists(accounts[i].privateKey) assert.equals(accounts[i].index, i) } + + wallet.destroy() }) await test('BLAKE2b zero-string seed', async () => { @@ -127,6 +142,8 @@ await suite('Import wallets', async () => { assert.exists(accounts[i].privateKey) assert.equals(accounts[i].index, i) } + + wallet.destroy() }) await test('Trezor-derived BLAKE2b test vectors verified with third-party libraries', async () => { @@ -148,6 +165,8 @@ await suite('Import wallets', async () => { assert.equals(accounts[1].privateKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PRIVATE_1) assert.equals(accounts[1].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PUBLIC_1) assert.equals(accounts[1].address, TREZOR_TEST_VECTORS.BLAKE2B_1_ADDRESS_1) + + wallet.destroy() }) await test('BLAKE2b seed creates identical wallet as its derived mnemonic', async () => { @@ -170,6 +189,8 @@ await suite('Import wallets', async () => { assert.equals(imported.seed, wallet.seed) assert.equals(importedAccount.privateKey, walletAccount.privateKey) assert.equals(importedAccount.publicKey, walletAccount.publicKey) + + wallet.destroy() }) await test('BLAKE2b mnemonic for maximum seed value', async () => { @@ -186,6 +207,8 @@ await suite('Import wallets', async () => { assert.equals(accounts[0].privateKey, TREZOR_TEST_VECTORS.BLAKE2B_3_PRIVATE_0) assert.equals(accounts[0].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_3_PUBLIC_0) assert.equals(accounts[0].address, TREZOR_TEST_VECTORS.BLAKE2B_3_ADDRESS_0) + + wallet.destroy() }) await test('Reject invalid entropy', async () => { @@ -210,6 +233,7 @@ await suite('Import wallets', async () => { }) await suite('Retrieve wallets from session storage using a wallet-generated ID', async () => { + await test('Bip44Wallet', async () => { const id = (await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)).id const wallet = await Bip44Wallet.restore(id) @@ -226,6 +250,8 @@ await suite('Retrieve wallets from session storage using a wallet-generated ID', assert.ok('seed' in wallet) assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + + wallet.destroy() }) await test('Blake2bWallet', async () => { @@ -244,5 +270,7 @@ await suite('Retrieve wallets from session storage using a wallet-generated ID', assert.ok('seed' in wallet) assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0) assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0) + + wallet.destroy() }) }) diff --git a/test/lock-unlock-wallet.mjs b/test/test.lock-unlock-wallet.mjs similarity index 93% rename from test/lock-unlock-wallet.mjs rename to test/test.lock-unlock-wallet.mjs index 5ec6ec2..f2f149a 100644 --- a/test/lock-unlock-wallet.mjs +++ b/test/test.lock-unlock-wallet.mjs @@ -3,11 +3,12 @@ 'use strict' -import { assert, suite, test } from '#GLOBALS.mjs' -import { NANO_TEST_VECTORS, TREZOR_TEST_VECTORS } from '#test/TEST_VECTORS.js' -import { Bip44Wallet, Blake2bWallet } from '#dist/main.js' +import { assert, suite, test } from './GLOBALS.mjs' +import { NANO_TEST_VECTORS, TREZOR_TEST_VECTORS } from './VECTORS.js' +import { Bip44Wallet, Blake2bWallet } from '../dist/main.min.js' await suite('Lock and unlock wallets', async () => { + await test('locking and unlocking a Bip44Wallet with a password', async () => { const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) @@ -23,6 +24,8 @@ await suite('Lock and unlock wallets', async () => { assert.ok('seed' in wallet) assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + + wallet.destroy() }) await test('locking and unlocking a Bip44Wallet with a random CryptoKey', async () => { @@ -44,6 +47,8 @@ await suite('Lock and unlock wallets', async () => { assert.ok('seed' in wallet) assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + + wallet.destroy() }) await test('fail to unlock a Bip44Wallet with different passwords', async () => { @@ -57,6 +62,8 @@ await suite('Lock and unlock wallets', async () => { assert.ok('seed' in wallet) assert.notEqual(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + + wallet.destroy() }) await test('fail to unlock a Bip44Wallet with different keys', async () => { @@ -72,6 +79,8 @@ await suite('Lock and unlock wallets', async () => { assert.ok('seed' in wallet) assert.notEqual(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + + wallet.destroy() }) await test('fail to unlock a Bip44Wallet with different valid inputs', async () => { @@ -83,13 +92,14 @@ await suite('Lock and unlock wallets', async () => { assert.ok('seed' in wallet) assert.notEqual(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + + wallet.destroy() }) await test('fail to unlock a Bip44Wallet with no input', async () => { const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - //@ts-expect-error await assert.rejects(wallet.lock(), { message: 'Failed to lock wallet' }) assert.ok('mnemonic' in wallet) assert.ok('seed' in wallet) @@ -98,19 +108,19 @@ await suite('Lock and unlock wallets', async () => { await wallet.lock('password') - //@ts-expect-error await assert.rejects(wallet.unlock(), { message: 'Failed to unlock wallet' }) assert.ok('mnemonic' in wallet) assert.ok('seed' in wallet) assert.notEqual(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + + wallet.destroy() }) await test('fail to unlock a Bip44Wallet with invalid input', async () => { const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - //@ts-expect-error await assert.rejects(wallet.lock(1), { message: 'Failed to lock wallet' }) assert.ok('mnemonic' in wallet) assert.ok('seed' in wallet) @@ -119,12 +129,13 @@ await suite('Lock and unlock wallets', async () => { await wallet.lock(NANO_TEST_VECTORS.PASSWORD) - //@ts-expect-error await assert.rejects(wallet.unlock(1), { message: 'Failed to unlock wallet' }) assert.ok('mnemonic' in wallet) assert.ok('seed' in wallet) assert.notEqual(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + + wallet.destroy() }) await test('locking and unlocking a Blake2bWallet with a password', async () => { @@ -142,6 +153,8 @@ await suite('Lock and unlock wallets', async () => { assert.ok('seed' in wallet) assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0) assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0) + + wallet.destroy() }) await test('locking and unlocking a Blake2bWallet with a random CryptoKey', async () => { @@ -164,6 +177,8 @@ await suite('Lock and unlock wallets', async () => { assert.ok('seed' in wallet) assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1) assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) + + wallet.destroy() }) await test('fail to unlock a Blake2bWallet with different passwords', async () => { @@ -174,6 +189,8 @@ await suite('Lock and unlock wallets', async () => { assert.ok('seed' in wallet) assert.notEqual(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1) assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) + + wallet.destroy() }) await test('fail to unlock a Blake2bWallet with different keys', async () => { @@ -189,6 +206,8 @@ await suite('Lock and unlock wallets', async () => { assert.ok('seed' in wallet) assert.notEqual(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1) assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) + + wallet.destroy() }) await test('fail to unlock a Blake2bWallet with different valid inputs', async () => { @@ -200,13 +219,14 @@ await suite('Lock and unlock wallets', async () => { assert.ok('seed' in wallet) assert.notEqual(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1) assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) + + wallet.destroy() }) await test('fail to unlock a Blake2bWallet with no input', async () => { const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1) await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - //@ts-expect-error await assert.rejects(wallet.lock(), { message: 'Failed to lock wallet' }) assert.ok('mnemonic' in wallet) assert.ok('seed' in wallet) @@ -215,19 +235,19 @@ await suite('Lock and unlock wallets', async () => { await wallet.lock(NANO_TEST_VECTORS.PASSWORD) - //@ts-expect-error await assert.rejects(wallet.unlock(), { message: 'Failed to unlock wallet' }) assert.ok('mnemonic' in wallet) assert.ok('seed' in wallet) assert.notEqual(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1) assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) + + wallet.destroy() }) await test('fail to unlock a Blake2bWallet with invalid input', async () => { const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1) await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - //@ts-expect-error await assert.rejects(wallet.lock(1), { message: 'Failed to lock wallet' }) assert.ok('mnemonic' in wallet) assert.ok('seed' in wallet) @@ -236,11 +256,12 @@ await suite('Lock and unlock wallets', async () => { await wallet.lock(NANO_TEST_VECTORS.PASSWORD) - //@ts-expect-error await assert.rejects(wallet.unlock(1), { message: 'Failed to unlock wallet' }) assert.ok('mnemonic' in wallet) assert.ok('seed' in wallet) assert.notEqual(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1) assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) + + wallet.destroy() }) }) diff --git a/test/test.main.mjs b/test/test.main.mjs new file mode 100644 index 0000000..590b92b --- /dev/null +++ b/test/test.main.mjs @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: 2024 Chris Duncan +// SPDX-License-Identifier: GPL-3.0-or-later + +import './test.blake2b.mjs' +import './test.calculate-pow.mjs' +import './test.create-wallet.mjs' +import './test.derive-accounts.mjs' +import './test.import-wallet.mjs' +import './test.lock-unlock-wallet.mjs' +import './test.manage-rolodex.mjs' +import './test.refresh-accounts.mjs' +import './test.sign-blocks.mjs' +import './test.tools.mjs' + +console.log('%cTESTING COMPLETE', 'color:orange;font-weight:bold') diff --git a/test/manage-rolodex.mjs b/test/test.manage-rolodex.mjs similarity index 97% rename from test/manage-rolodex.mjs rename to test/test.manage-rolodex.mjs index 29c5005..a69d457 100644 --- a/test/manage-rolodex.mjs +++ b/test/test.manage-rolodex.mjs @@ -3,11 +3,12 @@ 'use strict' -import { assert, suite, test } from '#GLOBALS.mjs' -import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js' -import { Rolodex, Tools } from '#dist/main.js' +import { assert, suite, test } from './GLOBALS.mjs' +import { NANO_TEST_VECTORS } from './VECTORS.js' +import { Rolodex, Tools } from '../dist/main.min.js' await suite('Rolodex valid contact management', async () => { + await test('should create a rolodex and add two contacts', async () => { const rolodex = new Rolodex() assert.equals(rolodex.constructor, Rolodex) @@ -94,6 +95,7 @@ await suite('Rolodex valid contact management', async () => { }) await suite('Rolodex exceptions', async () => { + await test('should throw if adding no data', async () => { const rolodex = new Rolodex() //@ts-expect-error @@ -122,6 +124,7 @@ await suite('Rolodex exceptions', async () => { }) await suite('Rolodex data signature verification', async () => { + await test('should verify valid data and signature', async () => { const data = 'Test data' const signature = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, data) diff --git a/test/refresh-accounts.test.mjs b/test/test.refresh-accounts.mjs similarity index 91% rename from test/refresh-accounts.test.mjs rename to test/test.refresh-accounts.mjs index 89efbd1..1e51454 100644 --- a/test/refresh-accounts.test.mjs +++ b/test/test.refresh-accounts.mjs @@ -3,9 +3,9 @@ 'use strict' -import { assert, skip, suite, test } from '#GLOBALS.mjs' -import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js' -import { Account, Bip44Wallet, Rpc } from '#dist/main.js' +import { assert, suite, test } from './GLOBALS.mjs' +import { NANO_TEST_VECTORS } from './VECTORS.js' +import { Account, Bip44Wallet, Rpc } from '../dist/main.min.js' let rpc //@ts-ignore @@ -15,7 +15,8 @@ if (process) { rpc = new Rpc(process?.env?.NODE_URL ?? '', process?.env?.API_KEY_NAME) } -await skip('refreshing account info', async () => { +await suite('refreshing account info', { skip: true }, async () => { + await test('fetch balance, frontier, and representative', async () => { const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED) await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) @@ -42,6 +43,8 @@ await skip('refreshing account info', async () => { assert.notEqual(account.representative?.address, undefined) assert.notEqual(account.representative?.address, null) assert.notEqual(account.representative?.address, '') + + wallet.destroy() }) await test('throw when refreshing unopened account', async () => { @@ -51,6 +54,8 @@ await skip('refreshing account info', async () => { const account = accounts[0] await assert.rejects(account.refresh(rpc), { message: 'Account not found' }) + + wallet.destroy() }) await test('throw when referencing invalid account index', async () => { @@ -68,10 +73,13 @@ await skip('refreshing account info', async () => { const account = accounts[0] await assert.rejects(account.refresh(invalidNode), { message: 'Account not found' }) + + wallet.destroy() }) }) -await skip('Fetch next unopened account', async () => { +await suite('Fetch next unopened account', { skip: true }, async () => { + await test('return correct account from test vector', async () => { const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED) await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) @@ -79,6 +87,8 @@ await skip('Fetch next unopened account', async () => { assert.ok(account) assert.equals(account.address, NANO_TEST_VECTORS.ADDRESS_1) assert.equals(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1) + + wallet.destroy() }) await test('return successfully for small batch size', async () => { @@ -88,6 +98,8 @@ await skip('Fetch next unopened account', async () => { assert.ok(account) assert.equals(account.address, NANO_TEST_VECTORS.ADDRESS_1) assert.equals(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1) + + wallet.destroy() }) await test('return successfully for large batch size', async () => { @@ -97,6 +109,8 @@ await skip('Fetch next unopened account', async () => { assert.ok(account) assert.equals(account.address, NANO_TEST_VECTORS.ADDRESS_1) assert.equals(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1) + + wallet.destroy() }) await test('should throw on invalid node URL', async () => { @@ -104,14 +118,12 @@ await skip('Fetch next unopened account', async () => { await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) //@ts-expect-error await assert.rejects(wallet.getNextNewAccount()) - //@ts-expect-error await assert.rejects(wallet.getNextNewAccount(null)) - //@ts-expect-error await assert.rejects(wallet.getNextNewAccount(1)) - //@ts-expect-error await assert.rejects(wallet.getNextNewAccount('')) - //@ts-expect-error await assert.rejects(wallet.getNextNewAccount('foo')) + + wallet.destroy() }) await test('should throw on invalid batch size', async () => { @@ -126,10 +138,13 @@ await skip('Fetch next unopened account', async () => { await assert.rejects(wallet.getNextNewAccount(rpc, 'foo')) //@ts-expect-error await assert.rejects(wallet.getNextNewAccount(rpc, { 'foo': 'bar' })) + + wallet.destroy() }) }) -await skip('Refreshing wallet accounts', async () => { +await suite('Refreshing wallet accounts', { skip: true }, async () => { + await test('should get balance, frontier, and representative for one account', async () => { const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED) await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) @@ -140,6 +155,8 @@ await skip('Refreshing wallet accounts', async () => { assert.notEqual(account.frontier, undefined) assert.notEqual(account.frontier, null) assert.equals(typeof account.frontier, 'string') + + wallet.destroy() }) await test('should get balance, frontier, and representative for multiple accounts', async () => { @@ -148,11 +165,15 @@ await skip('Refreshing wallet accounts', async () => { const accounts = await wallet.refresh(rpc, 0, 2) assert.equals(accounts.length, 1) assert.ok(accounts[0] instanceof Account) + + wallet.destroy() }) await test('should handle failure gracefully', async () => { const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED) await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) await assert.doesNotReject(wallet.refresh(rpc, 0, 20)) + + wallet.destroy() }) }) diff --git a/test/sign-blocks.test.mjs b/test/test.sign-blocks.mjs similarity index 88% rename from test/sign-blocks.test.mjs rename to test/test.sign-blocks.mjs index f13abb6..65e1b08 100644 --- a/test/sign-blocks.test.mjs +++ b/test/test.sign-blocks.mjs @@ -3,14 +3,15 @@ 'use strict' -import { assert, suite, test } from '#GLOBALS.mjs' -import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js' -import { SendBlock, ReceiveBlock, ChangeBlock } from '#dist/main.js' +import { assert, suite, test } from './GLOBALS.mjs' +import { NANO_TEST_VECTORS } from './VECTORS.js' +import { SendBlock, ReceiveBlock, ChangeBlock } from '../dist/main.min.js' await suite('Valid blocks', async () => { + await test('should not allow negative balances', async () => { assert.throws(() => { - const block = new SendBlock( + new SendBlock( NANO_TEST_VECTORS.ADDRESS_0, '7000000000000000000000000000000', NANO_TEST_VECTORS.ADDRESS_1, @@ -60,6 +61,7 @@ await suite('Valid blocks', async () => { }) await suite('Block signing tests using official test vectors', async () => { + await test('should create a valid signature for an open block', async () => { const block = new ReceiveBlock( NANO_TEST_VECTORS.OPEN_BLOCK.account, @@ -71,7 +73,7 @@ await suite('Block signing tests using official test vectors', async () => { NANO_TEST_VECTORS.OPEN_BLOCK.work ) await block.sign(NANO_TEST_VECTORS.OPEN_BLOCK.key) - assert.equals(await block.hash(), NANO_TEST_VECTORS.OPEN_BLOCK.hash) + assert.equals(block.hash, NANO_TEST_VECTORS.OPEN_BLOCK.hash) assert.equals(block.signature, NANO_TEST_VECTORS.OPEN_BLOCK.signature) }) @@ -86,7 +88,7 @@ await suite('Block signing tests using official test vectors', async () => { NANO_TEST_VECTORS.RECEIVE_BLOCK.work ) await block.sign(NANO_TEST_VECTORS.RECEIVE_BLOCK.key) - assert.equals(await block.hash(), NANO_TEST_VECTORS.RECEIVE_BLOCK.hash) + assert.equals(block.hash, NANO_TEST_VECTORS.RECEIVE_BLOCK.hash) assert.equals(block.signature, NANO_TEST_VECTORS.RECEIVE_BLOCK.signature) }) @@ -100,7 +102,7 @@ await suite('Block signing tests using official test vectors', async () => { NANO_TEST_VECTORS.RECEIVE_BLOCK.previous ) await block.sign(NANO_TEST_VECTORS.RECEIVE_BLOCK.key) - assert.equals(await block.hash(), NANO_TEST_VECTORS.RECEIVE_BLOCK.hash) + assert.equals(block.hash, NANO_TEST_VECTORS.RECEIVE_BLOCK.hash) assert.equals(block.signature, NANO_TEST_VECTORS.RECEIVE_BLOCK.signature) assert.equals(block.work, '') }) @@ -116,7 +118,7 @@ await suite('Block signing tests using official test vectors', async () => { NANO_TEST_VECTORS.SEND_BLOCK.work ) await block.sign(NANO_TEST_VECTORS.SEND_BLOCK.key) - assert.equals(await block.hash(), NANO_TEST_VECTORS.SEND_BLOCK.hash) + assert.equals(block.hash, NANO_TEST_VECTORS.SEND_BLOCK.hash) assert.equals(block.signature, NANO_TEST_VECTORS.SEND_BLOCK.signature) }) @@ -130,7 +132,7 @@ await suite('Block signing tests using official test vectors', async () => { NANO_TEST_VECTORS.SEND_BLOCK.previous ) await block.sign(NANO_TEST_VECTORS.SEND_BLOCK.key) - assert.equals(await block.hash(), NANO_TEST_VECTORS.SEND_BLOCK.hash) + assert.equals(block.hash, NANO_TEST_VECTORS.SEND_BLOCK.hash) assert.equals(block.signature, NANO_TEST_VECTORS.SEND_BLOCK.signature) assert.equals(block.work, '') }) diff --git a/test/tools.test.mjs b/test/test.tools.mjs similarity index 92% rename from test/tools.test.mjs rename to test/test.tools.mjs index eabbb9f..c86392b 100644 --- a/test/tools.test.mjs +++ b/test/test.tools.mjs @@ -3,9 +3,9 @@ 'use strict' -import { assert, skip, suite, test } from '#GLOBALS.mjs' -import { RAW_MAX, NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js' -import { Bip44Wallet, Account, SendBlock, Rpc, Tools } from '#dist/main.js' +import { assert, suite, test } from './GLOBALS.mjs' +import { RAW_MAX, NANO_TEST_VECTORS } from './VECTORS.js' +import { Bip44Wallet, Account, SendBlock, Rpc, Tools } from '../dist/main.min.js' let rpc //@ts-ignore @@ -16,6 +16,7 @@ if (process) { } await suite('unit conversion tests', async () => { + await test('should convert nano to raw', async () => { const result = await Tools.convert('1', 'NANO', 'RAW') assert.equals(result, '1000000000000000000000000000000') @@ -78,6 +79,7 @@ await suite('unit conversion tests', async () => { }) await suite('signature tests', async () => { + await test('should sign data with a single parameter', async () => { const result = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, 'miro@metsanheimo.fi') assert.equals(result, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C') @@ -115,6 +117,8 @@ await suite('signature tests', async () => { await sendBlock.sign(account.privateKey ?? '') const valid = await sendBlock.verify(account.publicKey) assert.equals(valid, true) + + wallet.destroy() }) await test('should reject a block using the wrong public key', async () => { @@ -135,19 +139,22 @@ await suite('signature tests', async () => { sendBlock.account = Account.fromAddress('nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p') const valid = await sendBlock.verify(account.publicKey) assert.equals(valid, false) + + wallet.destroy() }) await test('sweeper throws without required parameters', async () => { - //@ts-expect-error await assert.rejects(Tools.sweep(), 'Missing required sweep arguments') }) - await skip('sweeper fails gracefully for ineligible accounts', async () => { + await test('sweeper fails gracefully for ineligible accounts', { skip: true }, async () => { const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED) await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) const results = await Tools.sweep(rpc, wallet, NANO_TEST_VECTORS.ADDRESS_1) assert.ok(results) assert.equals(results.length, 1) + + wallet.destroy() }) }) diff --git a/tsconfig.json b/tsconfig.json index 1dab653..a59b9b9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,15 +4,17 @@ "module": "ESNext", "moduleResolution": "Bundler", "declaration": true, - "noEmit": false, - "outDir": "./dist", + "emitDeclarationOnly": true, + "declarationDir": "./types", "alwaysStrict": true, "downlevelIteration": false, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, + "isolatedModules": true, "noErrorTruncation": true, "noFallthroughCasesInSwitch": true, - "strict": true + "strict": true, + "rootDir": "src" }, "include": [ "src/main.ts", -- 2.47.3