ox 1.0.5 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +77 -0
- package/dist/core/Base64.d.ts +10 -21
- package/dist/core/Base64.d.ts.map +1 -1
- package/dist/core/Base64.js +8 -127
- package/dist/core/Base64.js.map +1 -1
- package/dist/core/BinaryStateTree.d.ts.map +1 -1
- package/dist/core/BinaryStateTree.js +2 -2
- package/dist/core/BinaryStateTree.js.map +1 -1
- package/dist/core/Bls.d.ts.map +1 -1
- package/dist/core/Bls.js +19 -44
- package/dist/core/Bls.js.map +1 -1
- package/dist/core/Ed25519.d.ts.map +1 -1
- package/dist/core/Ed25519.js +7 -6
- package/dist/core/Ed25519.js.map +1 -1
- package/dist/core/Engine.d.ts +156 -0
- package/dist/core/Engine.d.ts.map +1 -0
- package/dist/core/Engine.js +210 -0
- package/dist/core/Engine.js.map +1 -0
- package/dist/core/Hash.d.ts +4 -4
- package/dist/core/Hash.d.ts.map +1 -1
- package/dist/core/Hash.js +9 -12
- package/dist/core/Hash.js.map +1 -1
- package/dist/core/Keystore.d.ts.map +1 -1
- package/dist/core/Keystore.js +15 -10
- package/dist/core/Keystore.js.map +1 -1
- package/dist/core/Mnemonic.d.ts.map +1 -1
- package/dist/core/Mnemonic.js +3 -2
- package/dist/core/Mnemonic.js.map +1 -1
- package/dist/core/P256.d.ts.map +1 -1
- package/dist/core/P256.js +8 -9
- package/dist/core/P256.js.map +1 -1
- package/dist/core/Secp256k1.d.ts.map +1 -1
- package/dist/core/Secp256k1.js +8 -9
- package/dist/core/Secp256k1.js.map +1 -1
- package/dist/core/WebCryptoP256.d.ts.map +1 -1
- package/dist/core/WebCryptoP256.js +2 -2
- package/dist/core/WebCryptoP256.js.map +1 -1
- package/dist/core/X25519.d.ts.map +1 -1
- package/dist/core/X25519.js +4 -3
- package/dist/core/X25519.js.map +1 -1
- package/dist/core/internal/bls.d.ts +12 -0
- package/dist/core/internal/bls.d.ts.map +1 -0
- package/dist/core/internal/bls.js +79 -0
- package/dist/core/internal/bls.js.map +1 -0
- package/dist/core/internal/codec/base64.d.ts +84 -0
- package/dist/core/internal/codec/base64.d.ts.map +1 -0
- package/dist/core/internal/codec/base64.js +177 -0
- package/dist/core/internal/codec/base64.js.map +1 -0
- package/dist/core/internal/codec/hex.d.ts +49 -4
- package/dist/core/internal/codec/hex.d.ts.map +1 -1
- package/dist/core/internal/codec/hex.js +109 -35
- package/dist/core/internal/codec/hex.js.map +1 -1
- package/dist/core/internal/curves.d.ts +17 -0
- package/dist/core/internal/curves.d.ts.map +1 -0
- package/dist/core/internal/curves.js +17 -0
- package/dist/core/internal/curves.js.map +1 -0
- package/dist/core/internal/ed25519.d.ts +14 -0
- package/dist/core/internal/ed25519.d.ts.map +1 -0
- package/dist/core/internal/ed25519.js +29 -0
- package/dist/core/internal/ed25519.js.map +1 -0
- package/dist/core/internal/engine.d.ts +278 -0
- package/dist/core/internal/engine.d.ts.map +1 -0
- package/dist/core/internal/engine.js +131 -0
- package/dist/core/internal/engine.js.map +1 -0
- package/dist/core/internal/hash.d.ts +12 -0
- package/dist/core/internal/hash.d.ts.map +1 -0
- package/dist/core/internal/hash.js +30 -0
- package/dist/core/internal/hash.js.map +1 -0
- package/dist/core/internal/keystore.d.ts +14 -0
- package/dist/core/internal/keystore.d.ts.map +1 -0
- package/dist/core/internal/keystore.js +32 -0
- package/dist/core/internal/keystore.js.map +1 -0
- package/dist/core/internal/mnemonic.d.ts +4 -0
- package/dist/core/internal/mnemonic.d.ts.map +1 -0
- package/dist/core/internal/mnemonic.js +14 -0
- package/dist/core/internal/mnemonic.js.map +1 -0
- package/dist/core/internal/p256.d.ts +14 -0
- package/dist/core/internal/p256.d.ts.map +1 -0
- package/dist/core/internal/p256.js +36 -0
- package/dist/core/internal/p256.js.map +1 -0
- package/dist/core/internal/secp256k1.d.ts +14 -0
- package/dist/core/internal/secp256k1.d.ts.map +1 -0
- package/dist/core/internal/secp256k1.js +36 -0
- package/dist/core/internal/secp256k1.js.map +1 -0
- package/dist/core/internal/x25519.d.ts +8 -0
- package/dist/core/internal/x25519.d.ts.map +1 -0
- package/dist/core/internal/x25519.js +20 -0
- package/dist/core/internal/x25519.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.docs.d.ts +2 -0
- package/dist/index.docs.d.ts.map +1 -1
- package/dist/index.docs.js +2 -0
- package/dist/index.docs.js.map +1 -1
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -1
- package/dist/node/Ed25519.d.ts +33 -0
- package/dist/node/Ed25519.d.ts.map +1 -0
- package/dist/node/Ed25519.js +67 -0
- package/dist/node/Ed25519.js.map +1 -0
- package/dist/node/Engine.d.ts +68 -0
- package/dist/node/Engine.d.ts.map +1 -0
- package/dist/node/Engine.js +75 -0
- package/dist/node/Engine.js.map +1 -0
- package/dist/node/Hash.d.ts +37 -0
- package/dist/node/Hash.d.ts.map +1 -0
- package/dist/node/Hash.js +35 -0
- package/dist/node/Hash.js.map +1 -0
- package/dist/node/Keystore.d.ts +36 -0
- package/dist/node/Keystore.d.ts.map +1 -0
- package/dist/node/Keystore.js +72 -0
- package/dist/node/Keystore.js.map +1 -0
- package/dist/node/Mnemonic.d.ts +35 -0
- package/dist/node/Mnemonic.d.ts.map +1 -0
- package/dist/node/Mnemonic.js +46 -0
- package/dist/node/Mnemonic.js.map +1 -0
- package/dist/node/P256.d.ts +32 -0
- package/dist/node/P256.d.ts.map +1 -0
- package/dist/node/P256.js +34 -0
- package/dist/node/P256.js.map +1 -0
- package/dist/node/X25519.d.ts +31 -0
- package/dist/node/X25519.d.ts.map +1 -0
- package/dist/node/X25519.js +71 -0
- package/dist/node/X25519.js.map +1 -0
- package/dist/node/index.d.ts +126 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +126 -0
- package/dist/node/index.js.map +1 -0
- package/dist/tempo/VirtualMaster.d.ts +2 -0
- package/dist/tempo/VirtualMaster.d.ts.map +1 -1
- package/dist/tempo/VirtualMaster.js +19 -5
- package/dist/tempo/VirtualMaster.js.map +1 -1
- package/dist/tempo/internal/mine.wasm.d.ts +2 -4
- package/dist/tempo/internal/mine.wasm.d.ts.map +1 -1
- package/dist/tempo/internal/mine.wasm.js +7 -12
- package/dist/tempo/internal/mine.wasm.js.map +1 -1
- package/dist/tempo/internal/virtualMasterPool.js +4 -1
- package/dist/tempo/internal/virtualMasterPool.js.map +1 -1
- package/dist/wasm/Ed25519.d.ts +35 -0
- package/dist/wasm/Ed25519.d.ts.map +1 -0
- package/dist/wasm/Ed25519.js +88 -0
- package/dist/wasm/Ed25519.js.map +1 -0
- package/dist/wasm/Engine.d.ts +71 -0
- package/dist/wasm/Engine.d.ts.map +1 -0
- package/dist/wasm/Engine.js +76 -0
- package/dist/wasm/Engine.js.map +1 -0
- package/dist/wasm/Hash.d.ts +43 -0
- package/dist/wasm/Hash.d.ts.map +1 -0
- package/dist/wasm/Hash.js +64 -0
- package/dist/wasm/Hash.js.map +1 -0
- package/dist/wasm/Keystore.d.ts +37 -0
- package/dist/wasm/Keystore.d.ts.map +1 -0
- package/dist/wasm/Keystore.js +34 -0
- package/dist/wasm/Keystore.js.map +1 -0
- package/dist/wasm/Mnemonic.d.ts +33 -0
- package/dist/wasm/Mnemonic.d.ts.map +1 -0
- package/dist/wasm/Mnemonic.js +30 -0
- package/dist/wasm/Mnemonic.js.map +1 -0
- package/dist/wasm/X25519.d.ts +33 -0
- package/dist/wasm/X25519.d.ts.map +1 -0
- package/dist/wasm/X25519.js +53 -0
- package/dist/wasm/X25519.js.map +1 -0
- package/dist/wasm/index.d.ts +115 -0
- package/dist/wasm/index.d.ts.map +1 -0
- package/dist/wasm/index.js +115 -0
- package/dist/wasm/index.js.map +1 -0
- package/dist/wasm/internal/blake3.d.ts +11 -0
- package/dist/wasm/internal/blake3.d.ts.map +1 -0
- package/dist/wasm/internal/blake3.js +31 -0
- package/dist/wasm/internal/blake3.js.map +1 -0
- package/dist/wasm/internal/blake3.wasm.d.ts +3 -0
- package/dist/wasm/internal/blake3.wasm.d.ts.map +1 -0
- package/dist/wasm/internal/blake3.wasm.js +10 -0
- package/dist/wasm/internal/blake3.wasm.js.map +1 -0
- package/dist/wasm/internal/crypto25519.d.ts +16 -0
- package/dist/wasm/internal/crypto25519.d.ts.map +1 -0
- package/dist/wasm/internal/crypto25519.js +5 -0
- package/dist/wasm/internal/crypto25519.js.map +1 -0
- package/dist/wasm/internal/crypto25519.wasm.d.ts +3 -0
- package/dist/wasm/internal/crypto25519.wasm.d.ts.map +1 -0
- package/dist/wasm/internal/crypto25519.wasm.js +10 -0
- package/dist/wasm/internal/crypto25519.wasm.js.map +1 -0
- package/dist/wasm/internal/ed25519.d.ts +4 -0
- package/dist/wasm/internal/ed25519.d.ts.map +1 -0
- package/dist/wasm/internal/ed25519.js +21 -0
- package/dist/wasm/internal/ed25519.js.map +1 -0
- package/dist/wasm/internal/hash.d.ts +9 -0
- package/dist/wasm/internal/hash.d.ts.map +1 -0
- package/dist/wasm/internal/hash.js +26 -0
- package/dist/wasm/internal/hash.js.map +1 -0
- package/dist/wasm/internal/hashes.d.ts +12 -0
- package/dist/wasm/internal/hashes.d.ts.map +1 -0
- package/dist/wasm/internal/hashes.js +8 -0
- package/dist/wasm/internal/hashes.js.map +1 -0
- package/dist/wasm/internal/hashes.wasm.d.ts +7 -0
- package/dist/wasm/internal/hashes.wasm.d.ts.map +1 -0
- package/dist/wasm/internal/hashes.wasm.js +14 -0
- package/dist/wasm/internal/hashes.wasm.js.map +1 -0
- package/dist/wasm/internal/instantiate.d.ts +56 -0
- package/dist/wasm/internal/instantiate.d.ts.map +1 -0
- package/dist/wasm/internal/instantiate.js +92 -0
- package/dist/wasm/internal/instantiate.js.map +1 -0
- package/dist/wasm/internal/mnemonic.d.ts +4 -0
- package/dist/wasm/internal/mnemonic.d.ts.map +1 -0
- package/dist/wasm/internal/mnemonic.js +45 -0
- package/dist/wasm/internal/mnemonic.js.map +1 -0
- package/dist/wasm/internal/pbkdf2.d.ts +12 -0
- package/dist/wasm/internal/pbkdf2.d.ts.map +1 -0
- package/dist/wasm/internal/pbkdf2.js +51 -0
- package/dist/wasm/internal/pbkdf2.js.map +1 -0
- package/dist/wasm/internal/x25519.d.ts +4 -0
- package/dist/wasm/internal/x25519.d.ts.map +1 -0
- package/dist/wasm/internal/x25519.js +21 -0
- package/dist/wasm/internal/x25519.js.map +1 -0
- package/dist/zod/TypedData.d.ts +12 -12
- package/package.json +81 -1
- package/src/core/Base64.ts +19 -166
- package/src/core/BinaryStateTree.ts +2 -3
- package/src/core/Bls.ts +27 -77
- package/src/core/Ed25519.ts +7 -7
- package/src/core/Engine.ts +308 -0
- package/src/core/Hash.ts +9 -12
- package/src/core/Keystore.ts +17 -17
- package/src/core/Mnemonic.ts +3 -6
- package/src/core/P256.ts +15 -24
- package/src/core/Rlp_tx.bench.ts +2 -4
- package/src/core/Secp256k1.ts +9 -14
- package/src/core/TxEnvelopeEip1559.bench.ts +0 -5
- package/src/core/WebCryptoP256.ts +2 -2
- package/src/core/X25519.ts +4 -3
- package/src/core/_test/AbiParameters.adversarial.fuzz.ts +1 -2
- package/src/core/_test/AbiParameters.fuzz.ts +1 -2
- package/src/core/_test/Base.fuzz.ts +1 -2
- package/src/core/_test/Cbor.fuzz.ts +1 -2
- package/src/core/_test/Engine.fuzz.ts +293 -0
- package/src/core/_test/Engine.test-d.ts +140 -0
- package/src/core/_test/Engine.test.ts +618 -0
- package/src/core/_test/Hash.vectors.test.ts +64 -0
- package/src/core/_test/Hex.fuzz.ts +1 -2
- package/src/core/_test/Rlp.fuzz.ts +1 -2
- package/src/core/_test/Signature.fuzz.ts +1 -2
- package/src/core/_test/curves.test.ts +7 -0
- package/src/core/_test/index.test.ts +1 -0
- package/src/core/internal/bls.ts +121 -0
- package/src/core/internal/codec/_test/base64.conformance.ts +156 -0
- package/src/core/internal/codec/_test/hex.conformance.ts +204 -0
- package/src/core/internal/codec/_test/hex.fuzz.ts +234 -0
- package/src/core/internal/codec/_test/hex.test.ts +124 -0
- package/src/core/internal/codec/base64.ts +222 -0
- package/src/core/internal/codec/hex.ts +115 -34
- package/src/core/internal/curves.ts +18 -0
- package/src/core/internal/ed25519.ts +64 -0
- package/src/core/internal/engine.ts +410 -0
- package/src/core/internal/hash.ts +48 -0
- package/src/core/internal/keystore.ts +107 -0
- package/src/core/internal/mnemonic.ts +18 -0
- package/src/core/internal/p256.ts +91 -0
- package/src/core/internal/secp256k1.ts +91 -0
- package/src/core/internal/x25519.ts +40 -0
- package/src/index.docs.ts +2 -0
- package/src/index.ts +39 -0
- package/src/node/Ed25519.ts +87 -0
- package/src/node/Engine.ts +125 -0
- package/src/node/Hash.ts +51 -0
- package/src/node/Keystore.ts +103 -0
- package/src/node/Mnemonic.ts +68 -0
- package/src/node/P256.ts +48 -0
- package/src/node/X25519.ts +93 -0
- package/src/node/_test/Curves.fuzz.ts +76 -0
- package/src/node/_test/Ed25519.test-d.ts +35 -0
- package/src/node/_test/Ed25519.test.ts +220 -0
- package/src/node/_test/Engine.test-d.ts +28 -0
- package/src/node/_test/Engine.test.ts +102 -0
- package/src/node/_test/Hash.test-d.ts +32 -0
- package/src/node/_test/Hash.test.ts +101 -0
- package/src/node/_test/Keystore.fuzz.ts +58 -0
- package/src/node/_test/Keystore.test-d.ts +43 -0
- package/src/node/_test/Keystore.test.ts +198 -0
- package/src/node/_test/Mnemonic.fuzz.ts +31 -0
- package/src/node/_test/Mnemonic.test-d.ts +21 -0
- package/src/node/_test/Mnemonic.test.ts +98 -0
- package/src/node/_test/P256.test-d.ts +29 -0
- package/src/node/_test/P256.test.ts +102 -0
- package/src/node/_test/X25519.test-d.ts +28 -0
- package/src/node/_test/X25519.test.ts +239 -0
- package/src/node/index.ts +132 -0
- package/src/tempo/VirtualMaster.test.ts +75 -0
- package/src/tempo/VirtualMaster.ts +28 -6
- package/src/tempo/internal/mine.wasm.ts +7 -13
- package/src/tempo/internal/virtualMasterPool.ts +4 -1
- package/src/tsconfig.json +2 -1
- package/src/version.ts +1 -1
- package/src/wasm/Ed25519.ts +114 -0
- package/src/wasm/Engine.ts +121 -0
- package/src/wasm/Hash.bench.ts +60 -0
- package/src/wasm/Hash.ts +88 -0
- package/src/wasm/Keystore.ts +48 -0
- package/src/wasm/Mnemonic.ts +44 -0
- package/src/wasm/X25519.ts +70 -0
- package/src/wasm/_test/Crypto25519.conformance.ts +57 -0
- package/src/wasm/_test/Crypto25519.fuzz.ts +187 -0
- package/src/wasm/_test/Ed25519.test-d.ts +28 -0
- package/src/wasm/_test/Ed25519.test.ts +168 -0
- package/src/wasm/_test/Ed25519.vectors.test.ts +73 -0
- package/src/wasm/_test/Engine.test-d.ts +28 -0
- package/src/wasm/_test/Engine.test.ts +96 -0
- package/src/wasm/_test/Hash.browser.test.ts +54 -0
- package/src/wasm/_test/Hash.fuzz.ts +223 -0
- package/src/wasm/_test/Hash.test-d.ts +33 -0
- package/src/wasm/_test/Hash.test.ts +311 -0
- package/src/wasm/_test/Hash.vectors.test.ts +124 -0
- package/src/wasm/_test/Keystore.browser.test.ts +42 -0
- package/src/wasm/_test/Keystore.fuzz.ts +113 -0
- package/src/wasm/_test/Keystore.test-d.ts +33 -0
- package/src/wasm/_test/Keystore.test.ts +192 -0
- package/src/wasm/_test/Keystore.vectors.test.ts +21 -0
- package/src/wasm/_test/Mnemonic.test-d.ts +17 -0
- package/src/wasm/_test/Mnemonic.test.ts +110 -0
- package/src/wasm/_test/Runtime.test.ts +21 -0
- package/src/wasm/_test/X25519.test-d.ts +21 -0
- package/src/wasm/_test/X25519.test.ts +194 -0
- package/src/wasm/_test/fixtures.ts +4 -0
- package/src/wasm/_test/runtime.wasm.ts +11 -0
- package/src/wasm/index.ts +120 -0
- package/src/wasm/internal/blake3.ts +45 -0
- package/src/wasm/internal/blake3.wasm.ts +11 -0
- package/src/wasm/internal/crypto25519.ts +43 -0
- package/src/wasm/internal/crypto25519.wasm.ts +11 -0
- package/src/wasm/internal/ed25519.ts +31 -0
- package/src/wasm/internal/hash.ts +50 -0
- package/src/wasm/internal/hashes.ts +29 -0
- package/src/wasm/internal/hashes.wasm.ts +17 -0
- package/src/wasm/internal/instantiate.ts +135 -0
- package/src/wasm/internal/mnemonic.ts +56 -0
- package/src/wasm/internal/pbkdf2.ts +86 -0
- package/src/wasm/internal/x25519.ts +29 -0
- package/src/tempo/internal/mine.c +0 -182
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Engine } from 'ox/node'
|
|
2
|
+
import { expectTypeOf, test } from 'vp/test'
|
|
3
|
+
import * as CoreEngine from '../../core/Engine.js'
|
|
4
|
+
|
|
5
|
+
type Installed = Awaited<ReturnType<typeof Engine.install>>
|
|
6
|
+
type Uninstalled = Awaited<ReturnType<typeof Engine.engine>>
|
|
7
|
+
|
|
8
|
+
test('install and engine expose the same precise engine', () => {
|
|
9
|
+
expectTypeOf<Installed>().toEqualTypeOf<Uninstalled>()
|
|
10
|
+
expectTypeOf<Installed['Hash']['sha256']>().toEqualTypeOf<
|
|
11
|
+
(input: Uint8Array) => Uint8Array
|
|
12
|
+
>()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
test('the Node Engine namespace exposes synchronous core operations', () => {
|
|
16
|
+
expectTypeOf(Engine.get).toEqualTypeOf(CoreEngine.get)
|
|
17
|
+
expectTypeOf(Engine.InvalidSlotValueError).toEqualTypeOf(
|
|
18
|
+
CoreEngine.InvalidSlotValueError,
|
|
19
|
+
)
|
|
20
|
+
expectTypeOf(Engine.reset).toEqualTypeOf(CoreEngine.reset)
|
|
21
|
+
expectTypeOf(Engine.set).toEqualTypeOf(CoreEngine.set)
|
|
22
|
+
expectTypeOf(Engine.with).toEqualTypeOf(CoreEngine.with)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test('the replaced aliases are absent', () => {
|
|
26
|
+
expectTypeOf<typeof Engine>().not.toHaveProperty('create')
|
|
27
|
+
expectTypeOf<typeof Engine>().not.toHaveProperty('load')
|
|
28
|
+
})
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Engine as CoreEngine } from 'ox'
|
|
2
|
+
import { Engine, Hash } from 'ox/node'
|
|
3
|
+
import { describe, expect, test } from 'vp/test'
|
|
4
|
+
|
|
5
|
+
describe('engine', () => {
|
|
6
|
+
test('behavior: does not install', async () => {
|
|
7
|
+
const engine = await Engine.engine()
|
|
8
|
+
|
|
9
|
+
expect(Object.keys(engine)).toMatchInlineSnapshot(`
|
|
10
|
+
[
|
|
11
|
+
"Ed25519",
|
|
12
|
+
"Hash",
|
|
13
|
+
"Keystore",
|
|
14
|
+
"Mnemonic",
|
|
15
|
+
"P256",
|
|
16
|
+
"X25519",
|
|
17
|
+
]
|
|
18
|
+
`)
|
|
19
|
+
expect(Engine.get()).toMatchInlineSnapshot('{}')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
test('behavior: installs for the duration of a call', async () => {
|
|
23
|
+
const node = await Engine.engine()
|
|
24
|
+
const digest = Engine.with(node, () => Hash.sha256('0xdeadbeef'))
|
|
25
|
+
|
|
26
|
+
expect(digest).toMatchInlineSnapshot(
|
|
27
|
+
`"0x5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953"`,
|
|
28
|
+
)
|
|
29
|
+
expect(CoreEngine.get()).toMatchInlineSnapshot('{}')
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
describe('install', () => {
|
|
34
|
+
test('behavior: installs and returns what it installed', async () => {
|
|
35
|
+
const engine = await Engine.install()
|
|
36
|
+
|
|
37
|
+
expect(Engine.get()).toEqual(CoreEngine.get())
|
|
38
|
+
expect(Object.keys(Engine.get())).toEqual(Object.keys(engine))
|
|
39
|
+
expect(
|
|
40
|
+
Object.fromEntries(
|
|
41
|
+
Object.entries(Engine.get()).map(([slot, value]) => [
|
|
42
|
+
slot,
|
|
43
|
+
Object.keys(value ?? {}).sort(),
|
|
44
|
+
]),
|
|
45
|
+
),
|
|
46
|
+
).toMatchInlineSnapshot(`
|
|
47
|
+
{
|
|
48
|
+
"Ed25519": [
|
|
49
|
+
"getPublicKey",
|
|
50
|
+
"sign",
|
|
51
|
+
"toMontgomerySecret",
|
|
52
|
+
],
|
|
53
|
+
"Hash": [
|
|
54
|
+
"hmacSha256",
|
|
55
|
+
"ripemd160",
|
|
56
|
+
"sha256",
|
|
57
|
+
],
|
|
58
|
+
"Keystore": [
|
|
59
|
+
"aesCtrDecrypt",
|
|
60
|
+
"aesCtrEncrypt",
|
|
61
|
+
"pbkdf2Sha256",
|
|
62
|
+
"pbkdf2Sha256Async",
|
|
63
|
+
],
|
|
64
|
+
"Mnemonic": [
|
|
65
|
+
"toSeed",
|
|
66
|
+
],
|
|
67
|
+
"P256": [
|
|
68
|
+
"getPublicKey",
|
|
69
|
+
],
|
|
70
|
+
"X25519": [
|
|
71
|
+
"getPublicKey",
|
|
72
|
+
"getSharedSecret",
|
|
73
|
+
],
|
|
74
|
+
}
|
|
75
|
+
`)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
test('behavior: leaves unsupported primitives on the default', async () => {
|
|
79
|
+
await Engine.install()
|
|
80
|
+
|
|
81
|
+
expect(Hash.keccak256('0xdeadbeef')).toMatchInlineSnapshot(
|
|
82
|
+
`"0xd4fd4e189132273036449fc9e11198c739161b4c0116a9a2dccdfa1c492006f1"`,
|
|
83
|
+
)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
test('behavior: merges with later engines', async () => {
|
|
87
|
+
await Engine.install()
|
|
88
|
+
Engine.set({ Bls: { randomSecretKey: () => new Uint8Array(32) } })
|
|
89
|
+
|
|
90
|
+
expect(Object.keys(Engine.get()).sort()).toMatchInlineSnapshot(`
|
|
91
|
+
[
|
|
92
|
+
"Bls",
|
|
93
|
+
"Ed25519",
|
|
94
|
+
"Hash",
|
|
95
|
+
"Keystore",
|
|
96
|
+
"Mnemonic",
|
|
97
|
+
"P256",
|
|
98
|
+
"X25519",
|
|
99
|
+
]
|
|
100
|
+
`)
|
|
101
|
+
})
|
|
102
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Hash as NodeHash } from 'ox/node'
|
|
2
|
+
import { expectTypeOf, test } from 'vp/test'
|
|
3
|
+
import type * as CoreEngine from '../../core/Engine.js'
|
|
4
|
+
import * as CoreHash from '../../core/Hash.js'
|
|
5
|
+
|
|
6
|
+
type Slot = Awaited<ReturnType<typeof NodeHash.engine>>
|
|
7
|
+
|
|
8
|
+
test('every implemented primitive is present', () => {
|
|
9
|
+
expectTypeOf<Slot['hmacSha256']>().toEqualTypeOf<
|
|
10
|
+
(key: Uint8Array, message: Uint8Array) => Uint8Array
|
|
11
|
+
>()
|
|
12
|
+
expectTypeOf<Slot['ripemd160']>().toEqualTypeOf<
|
|
13
|
+
(input: Uint8Array) => Uint8Array
|
|
14
|
+
>()
|
|
15
|
+
expectTypeOf<Slot['sha256']>().toEqualTypeOf<
|
|
16
|
+
(input: Uint8Array) => Uint8Array
|
|
17
|
+
>()
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
test('unsupported primitives are absent', () => {
|
|
21
|
+
expectTypeOf<Slot>().not.toHaveProperty('blake3')
|
|
22
|
+
expectTypeOf<Slot>().not.toHaveProperty('keccak256')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test('the result is the raw slot, so `Engine.install` accepts it', () => {
|
|
26
|
+
expectTypeOf<{ Hash: Slot }>().toExtend<CoreEngine.Engine>()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('the Node namespace exposes the public Hash API', () => {
|
|
30
|
+
expectTypeOf(NodeHash.sha256).toEqualTypeOf(CoreHash.sha256)
|
|
31
|
+
expectTypeOf<typeof NodeHash>().not.toHaveProperty('create')
|
|
32
|
+
})
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Hash as CoreHash, Hex } from 'ox'
|
|
2
|
+
import { Hash } from 'ox/node'
|
|
3
|
+
import { describe, expect, test } from 'vp/test'
|
|
4
|
+
|
|
5
|
+
describe('engine', () => {
|
|
6
|
+
test('behavior: exposes the supported primitives', async () => {
|
|
7
|
+
const engine = await Hash.engine()
|
|
8
|
+
|
|
9
|
+
expect(Object.keys(engine).sort()).toMatchInlineSnapshot(`
|
|
10
|
+
[
|
|
11
|
+
"hmacSha256",
|
|
12
|
+
"ripemd160",
|
|
13
|
+
"sha256",
|
|
14
|
+
]
|
|
15
|
+
`)
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
test('behavior: matches published empty-input vectors', async () => {
|
|
19
|
+
const { hmacSha256, ripemd160, sha256 } = await Hash.engine()
|
|
20
|
+
const empty = new Uint8Array()
|
|
21
|
+
|
|
22
|
+
expect(Hex.fromBytes(sha256(empty))).toMatchInlineSnapshot(
|
|
23
|
+
`"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"`,
|
|
24
|
+
)
|
|
25
|
+
expect(Hex.fromBytes(ripemd160(empty))).toMatchInlineSnapshot(
|
|
26
|
+
`"0x9c1185a5c5e9fc54612808977ee8f548b2258d31"`,
|
|
27
|
+
)
|
|
28
|
+
expect(Hex.fromBytes(hmacSha256(empty, empty))).toMatchInlineSnapshot(
|
|
29
|
+
`"0xb613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad"`,
|
|
30
|
+
)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test('behavior: agrees with the default across block boundaries', async () => {
|
|
34
|
+
const node = await Hash.engine()
|
|
35
|
+
|
|
36
|
+
for (const size of [0, 1, 55, 56, 63, 64, 65, 127, 128, 129]) {
|
|
37
|
+
const input = Uint8Array.from({ length: size }, (_, index) => index % 251)
|
|
38
|
+
expect(node.sha256(input)).toEqual(
|
|
39
|
+
CoreHash.sha256(input, { as: 'Bytes' }),
|
|
40
|
+
)
|
|
41
|
+
expect(node.ripemd160(input)).toEqual(
|
|
42
|
+
CoreHash.ripemd160(input, { as: 'Bytes' }),
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
test('behavior: agrees with the default across HMAC key sizes', async () => {
|
|
48
|
+
const { hmacSha256 } = await Hash.engine()
|
|
49
|
+
const message = Uint8Array.from({ length: 65 }, (_, index) => index % 251)
|
|
50
|
+
|
|
51
|
+
for (const size of [0, 1, 32, 63, 64, 65, 200]) {
|
|
52
|
+
const key = Uint8Array.from({ length: size }, (_, index) => index % 239)
|
|
53
|
+
expect(hmacSha256(key, message)).toEqual(
|
|
54
|
+
CoreHash.hmac256(key, message, { as: 'Bytes' }),
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
test('behavior: respects typed-array offsets', async () => {
|
|
60
|
+
const node = await Hash.engine()
|
|
61
|
+
const input = Uint8Array.from(
|
|
62
|
+
{ length: 80 },
|
|
63
|
+
(_, index) => (index * 17) % 251,
|
|
64
|
+
).subarray(7, 71)
|
|
65
|
+
const key = Uint8Array.from(
|
|
66
|
+
{ length: 48 },
|
|
67
|
+
(_, index) => (index * 29) % 239,
|
|
68
|
+
).subarray(5, 37)
|
|
69
|
+
|
|
70
|
+
expect(node.sha256(input)).toEqual(CoreHash.sha256(input, { as: 'Bytes' }))
|
|
71
|
+
expect(node.ripemd160(input)).toEqual(
|
|
72
|
+
CoreHash.ripemd160(input, { as: 'Bytes' }),
|
|
73
|
+
)
|
|
74
|
+
expect(node.hmacSha256(key, input)).toEqual(
|
|
75
|
+
CoreHash.hmac256(key, input, { as: 'Bytes' }),
|
|
76
|
+
)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
test('behavior: returns a fresh engine', async () => {
|
|
80
|
+
const first = await Hash.engine()
|
|
81
|
+
const second = await Hash.engine()
|
|
82
|
+
|
|
83
|
+
expect(first === second).toMatchInlineSnapshot('false')
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
test('behavior: returns owned Uint8Array values', async () => {
|
|
87
|
+
const { hmacSha256, ripemd160, sha256 } = await Hash.engine()
|
|
88
|
+
const input = Uint8Array.of(1, 2, 3)
|
|
89
|
+
const outputs = [hmacSha256(input, input), ripemd160(input), sha256(input)]
|
|
90
|
+
|
|
91
|
+
expect(outputs.map((output) => output.constructor === Uint8Array))
|
|
92
|
+
.toMatchInlineSnapshot(`
|
|
93
|
+
[
|
|
94
|
+
true,
|
|
95
|
+
true,
|
|
96
|
+
true,
|
|
97
|
+
]
|
|
98
|
+
`)
|
|
99
|
+
expect(sha256(input) === sha256(input)).toMatchInlineSnapshot('false')
|
|
100
|
+
})
|
|
101
|
+
})
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ctr } from '@noble/ciphers/aes.js'
|
|
2
|
+
import { pbkdf2 } from '@noble/hashes/pbkdf2.js'
|
|
3
|
+
import { sha256 } from '@noble/hashes/sha2.js'
|
|
4
|
+
import { fc, test } from '@fast-check/vitest'
|
|
5
|
+
import { expect } from 'vp/test'
|
|
6
|
+
import { numRuns } from '../../../test/fuzz/numRuns.js'
|
|
7
|
+
import * as Keystore from '../Keystore.js'
|
|
8
|
+
|
|
9
|
+
const subview = (bytes: Uint8Array) => {
|
|
10
|
+
const value = new Uint8Array(bytes.length + 4)
|
|
11
|
+
value.set(bytes, 2)
|
|
12
|
+
return value.subarray(2, bytes.length + 2)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const arbitraryKey = fc
|
|
16
|
+
.oneof(
|
|
17
|
+
fc.uint8Array({ maxLength: 16, minLength: 16 }),
|
|
18
|
+
fc.uint8Array({ maxLength: 24, minLength: 24 }),
|
|
19
|
+
fc.uint8Array({ maxLength: 32, minLength: 32 }),
|
|
20
|
+
)
|
|
21
|
+
.map(subview)
|
|
22
|
+
|
|
23
|
+
test.prop(
|
|
24
|
+
{
|
|
25
|
+
data: fc.uint8Array({ maxLength: 256 }).map(subview),
|
|
26
|
+
iv: fc.uint8Array({ maxLength: 16, minLength: 16 }).map(subview),
|
|
27
|
+
key: arbitraryKey,
|
|
28
|
+
},
|
|
29
|
+
{ numRuns },
|
|
30
|
+
)('Node AES-CTR agrees with the default', async ({ data, iv, key }) => {
|
|
31
|
+
const { aesCtrDecrypt, aesCtrEncrypt } = await Keystore.engine()
|
|
32
|
+
const expected = ctr(key, iv).encrypt(data)
|
|
33
|
+
const encrypted = aesCtrEncrypt(key, iv, data)
|
|
34
|
+
|
|
35
|
+
expect(encrypted).toEqual(expected)
|
|
36
|
+
expect(aesCtrDecrypt(key, iv, encrypted)).toEqual(data)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test.prop(
|
|
40
|
+
{
|
|
41
|
+
c: fc.integer({ max: 32, min: 1 }),
|
|
42
|
+
dkLen: fc.integer({ max: 96, min: 1 }),
|
|
43
|
+
password: fc.uint8Array({ maxLength: 96 }).map(subview),
|
|
44
|
+
salt: fc.uint8Array({ maxLength: 96 }).map(subview),
|
|
45
|
+
},
|
|
46
|
+
{ numRuns },
|
|
47
|
+
)(
|
|
48
|
+
'Node PBKDF2-HMAC-SHA256 agrees with the default',
|
|
49
|
+
async ({ c, dkLen, password, salt }) => {
|
|
50
|
+
const { pbkdf2Sha256, pbkdf2Sha256Async } = await Keystore.engine()
|
|
51
|
+
const expected = pbkdf2(sha256, password, salt, { c, dkLen })
|
|
52
|
+
|
|
53
|
+
expect(pbkdf2Sha256(password, salt, { c, dkLen })).toEqual(expected)
|
|
54
|
+
expect(await pbkdf2Sha256Async(password, salt, { c, dkLen })).toEqual(
|
|
55
|
+
expected,
|
|
56
|
+
)
|
|
57
|
+
},
|
|
58
|
+
)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Engine } from 'ox'
|
|
2
|
+
import { expectTypeOf, test } from 'vp/test'
|
|
3
|
+
import * as core_Keystore from '../../core/Keystore.js'
|
|
4
|
+
import * as NodeKeystore from '../Keystore.js'
|
|
5
|
+
|
|
6
|
+
type Slot = Awaited<ReturnType<typeof NodeKeystore.engine>>
|
|
7
|
+
|
|
8
|
+
test('every implemented primitive is present', () => {
|
|
9
|
+
expectTypeOf<Slot['aesCtrDecrypt']>().toEqualTypeOf<
|
|
10
|
+
(key: Uint8Array, iv: Uint8Array, data: Uint8Array) => Uint8Array
|
|
11
|
+
>()
|
|
12
|
+
expectTypeOf<Slot['aesCtrEncrypt']>().toEqualTypeOf<
|
|
13
|
+
(key: Uint8Array, iv: Uint8Array, data: Uint8Array) => Uint8Array
|
|
14
|
+
>()
|
|
15
|
+
expectTypeOf<Slot['pbkdf2Sha256']>().toEqualTypeOf<
|
|
16
|
+
(
|
|
17
|
+
password: Uint8Array,
|
|
18
|
+
salt: Uint8Array,
|
|
19
|
+
options: { c: number; dkLen: number },
|
|
20
|
+
) => Uint8Array
|
|
21
|
+
>()
|
|
22
|
+
expectTypeOf<Slot['pbkdf2Sha256Async']>().toEqualTypeOf<
|
|
23
|
+
(
|
|
24
|
+
password: Uint8Array,
|
|
25
|
+
salt: Uint8Array,
|
|
26
|
+
options: { c: number; dkLen: number },
|
|
27
|
+
) => Promise<Uint8Array>
|
|
28
|
+
>()
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test('unsupported primitives are absent', () => {
|
|
32
|
+
expectTypeOf<Slot>().not.toHaveProperty('scrypt')
|
|
33
|
+
expectTypeOf<Slot>().not.toHaveProperty('scryptAsync')
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test('the result is the raw slot', () => {
|
|
37
|
+
expectTypeOf<{ Keystore: Slot }>().toExtend<Engine.Engine>()
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('the Node namespace exposes the public Keystore API', () => {
|
|
41
|
+
expectTypeOf(NodeKeystore.pbkdf2).toEqualTypeOf(core_Keystore.pbkdf2)
|
|
42
|
+
expectTypeOf<typeof NodeKeystore>().not.toHaveProperty('create')
|
|
43
|
+
})
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { ctr } from '@noble/ciphers/aes.js'
|
|
2
|
+
import { pbkdf2 } from '@noble/hashes/pbkdf2.js'
|
|
3
|
+
import { sha256 } from '@noble/hashes/sha2.js'
|
|
4
|
+
import { Hex } from 'ox'
|
|
5
|
+
import { describe, expect, test } from 'vp/test'
|
|
6
|
+
import * as vectors from '../../../test/vectors/pbkdf2/index.js'
|
|
7
|
+
import * as Keystore from '../Keystore.js'
|
|
8
|
+
|
|
9
|
+
describe('engine', () => {
|
|
10
|
+
test('behavior: matches NIST SP 800-38A AES-CTR vectors', async () => {
|
|
11
|
+
const { aesCtrDecrypt, aesCtrEncrypt } = await Keystore.engine()
|
|
12
|
+
const iv = Hex.toBytes('0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff')
|
|
13
|
+
const plaintext = Hex.toBytes('0x6bc1bee22e409f96e93d7e117393172a')
|
|
14
|
+
const vectors = [
|
|
15
|
+
{
|
|
16
|
+
ciphertext: '0x874d6191b620e3261bef6864990db6ce',
|
|
17
|
+
key: '0x2b7e151628aed2a6abf7158809cf4f3c',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
ciphertext: '0x1abc932417521ca24f2b0459fe7e6e0b',
|
|
21
|
+
key: '0x8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
ciphertext: '0x601ec313775789a5b7a7f504bbf3d228',
|
|
25
|
+
key: '0x603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4',
|
|
26
|
+
},
|
|
27
|
+
] as const
|
|
28
|
+
|
|
29
|
+
expect(
|
|
30
|
+
vectors.map(({ ciphertext, key }) => {
|
|
31
|
+
const encrypted = aesCtrEncrypt(Hex.toBytes(key), iv, plaintext)
|
|
32
|
+
const decrypted = aesCtrDecrypt(
|
|
33
|
+
Hex.toBytes(key),
|
|
34
|
+
iv,
|
|
35
|
+
Hex.toBytes(ciphertext),
|
|
36
|
+
)
|
|
37
|
+
return {
|
|
38
|
+
decrypted: Hex.fromBytes(decrypted),
|
|
39
|
+
encrypted: Hex.fromBytes(encrypted),
|
|
40
|
+
}
|
|
41
|
+
}),
|
|
42
|
+
).toMatchInlineSnapshot(`
|
|
43
|
+
[
|
|
44
|
+
{
|
|
45
|
+
"decrypted": "0x6bc1bee22e409f96e93d7e117393172a",
|
|
46
|
+
"encrypted": "0x874d6191b620e3261bef6864990db6ce",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"decrypted": "0x6bc1bee22e409f96e93d7e117393172a",
|
|
50
|
+
"encrypted": "0x1abc932417521ca24f2b0459fe7e6e0b",
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"decrypted": "0x6bc1bee22e409f96e93d7e117393172a",
|
|
54
|
+
"encrypted": "0x601ec313775789a5b7a7f504bbf3d228",
|
|
55
|
+
},
|
|
56
|
+
]
|
|
57
|
+
`)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('behavior: matches RFC 7914 PBKDF2-HMAC-SHA256 vectors', async () => {
|
|
61
|
+
const { pbkdf2Sha256 } = await Keystore.engine()
|
|
62
|
+
|
|
63
|
+
for (const { iterations, key, password, salt } of vectors.vectors)
|
|
64
|
+
expect(
|
|
65
|
+
pbkdf2Sha256(password, salt, {
|
|
66
|
+
c: iterations,
|
|
67
|
+
dkLen: key.length,
|
|
68
|
+
}),
|
|
69
|
+
).toEqual(key)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
test('behavior: agrees with the defaults across boundary sizes', async () => {
|
|
73
|
+
const node = await Keystore.engine()
|
|
74
|
+
const iv = Uint8Array.from(
|
|
75
|
+
{ length: 20 },
|
|
76
|
+
(_, index) => (index * 13) % 251,
|
|
77
|
+
).subarray(2, 18)
|
|
78
|
+
|
|
79
|
+
for (const keySize of [16, 24, 32]) {
|
|
80
|
+
const key = Uint8Array.from(
|
|
81
|
+
{ length: keySize + 4 },
|
|
82
|
+
(_, index) => (index * 17) % 251,
|
|
83
|
+
).subarray(2, keySize + 2)
|
|
84
|
+
|
|
85
|
+
for (const size of [0, 1, 15, 16, 17, 31, 32, 33]) {
|
|
86
|
+
const data = Uint8Array.from(
|
|
87
|
+
{ length: size + 6 },
|
|
88
|
+
(_, index) => (index * 29) % 251,
|
|
89
|
+
).subarray(3, size + 3)
|
|
90
|
+
const encrypted = node.aesCtrEncrypt(key, iv, data)
|
|
91
|
+
|
|
92
|
+
expect(encrypted).toEqual(ctr(key, iv).encrypt(data))
|
|
93
|
+
expect(node.aesCtrDecrypt(key, iv, encrypted)).toEqual(data)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const password = Uint8Array.from(
|
|
98
|
+
{ length: 37 },
|
|
99
|
+
(_, index) => (index * 31) % 251,
|
|
100
|
+
).subarray(3, 34)
|
|
101
|
+
const salt = Uint8Array.from(
|
|
102
|
+
{ length: 41 },
|
|
103
|
+
(_, index) => (index * 37) % 251,
|
|
104
|
+
).subarray(5, 37)
|
|
105
|
+
|
|
106
|
+
for (const options of [
|
|
107
|
+
{ c: 1, dkLen: 1 },
|
|
108
|
+
{ c: 2, dkLen: 31 },
|
|
109
|
+
{ c: 3, dkLen: 32 },
|
|
110
|
+
{ c: 4, dkLen: 33 },
|
|
111
|
+
{ c: 16, dkLen: 64 },
|
|
112
|
+
]) {
|
|
113
|
+
const expected = pbkdf2(sha256, password, salt, options)
|
|
114
|
+
expect(node.pbkdf2Sha256(password, salt, options)).toEqual(expected)
|
|
115
|
+
expect(await node.pbkdf2Sha256Async(password, salt, options)).toEqual(
|
|
116
|
+
expected,
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
test('behavior: does not mutate inputs and returns owned arrays', async () => {
|
|
122
|
+
const node = await Keystore.engine()
|
|
123
|
+
const data = Uint8Array.of(1, 2, 3, 4, 5)
|
|
124
|
+
const iv = new Uint8Array(16).fill(2)
|
|
125
|
+
const key = new Uint8Array(16).fill(3)
|
|
126
|
+
const password = Uint8Array.of(4, 5, 6)
|
|
127
|
+
const salt = Uint8Array.of(7, 8, 9)
|
|
128
|
+
const inputs = [data, iv, key, password, salt]
|
|
129
|
+
const before = inputs.map((input) => input.slice())
|
|
130
|
+
|
|
131
|
+
const outputs = [
|
|
132
|
+
node.aesCtrEncrypt(key, iv, data),
|
|
133
|
+
node.aesCtrDecrypt(key, iv, data),
|
|
134
|
+
node.pbkdf2Sha256(password, salt, { c: 1, dkLen: 32 }),
|
|
135
|
+
await node.pbkdf2Sha256Async(password, salt, { c: 1, dkLen: 32 }),
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
expect(inputs).toEqual(before)
|
|
139
|
+
expect(outputs.map((output) => output.constructor === Uint8Array))
|
|
140
|
+
.toMatchInlineSnapshot(`
|
|
141
|
+
[
|
|
142
|
+
true,
|
|
143
|
+
true,
|
|
144
|
+
true,
|
|
145
|
+
true,
|
|
146
|
+
]
|
|
147
|
+
`)
|
|
148
|
+
expect(
|
|
149
|
+
node.aesCtrEncrypt(key, iv, data) === node.aesCtrEncrypt(key, iv, data),
|
|
150
|
+
).toMatchInlineSnapshot('false')
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
test('behavior: rejects malformed AES and PBKDF2 parameters', async () => {
|
|
154
|
+
const node = await Keystore.engine()
|
|
155
|
+
const data = new Uint8Array()
|
|
156
|
+
const iv = new Uint8Array(16)
|
|
157
|
+
const key = new Uint8Array(16)
|
|
158
|
+
|
|
159
|
+
for (const keyLength of [0, 15, 17, 23, 25, 31, 33]) {
|
|
160
|
+
expect(() => ctr(new Uint8Array(keyLength), iv).encrypt(data)).toThrow()
|
|
161
|
+
expect(() =>
|
|
162
|
+
node.aesCtrEncrypt(new Uint8Array(keyLength), iv, data),
|
|
163
|
+
).toThrow()
|
|
164
|
+
expect(() =>
|
|
165
|
+
node.aesCtrDecrypt(new Uint8Array(keyLength), iv, data),
|
|
166
|
+
).toThrow()
|
|
167
|
+
}
|
|
168
|
+
for (const ivLength of [0, 15, 17]) {
|
|
169
|
+
expect(() => ctr(key, new Uint8Array(ivLength)).encrypt(data)).toThrow()
|
|
170
|
+
expect(() =>
|
|
171
|
+
node.aesCtrEncrypt(key, new Uint8Array(ivLength), data),
|
|
172
|
+
).toThrow()
|
|
173
|
+
expect(() =>
|
|
174
|
+
node.aesCtrDecrypt(key, new Uint8Array(ivLength), data),
|
|
175
|
+
).toThrow()
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
for (const options of [
|
|
179
|
+
{ c: 0, dkLen: 32 },
|
|
180
|
+
{ c: 1.5, dkLen: 32 },
|
|
181
|
+
{ c: 1, dkLen: 0 },
|
|
182
|
+
{ c: 1, dkLen: 1.5 },
|
|
183
|
+
]) {
|
|
184
|
+
expect(() => pbkdf2(sha256, data, data, options)).toThrow()
|
|
185
|
+
expect(() => node.pbkdf2Sha256(data, data, options)).toThrow()
|
|
186
|
+
await expect(
|
|
187
|
+
node.pbkdf2Sha256Async(data, data, options),
|
|
188
|
+
).rejects.toThrow()
|
|
189
|
+
}
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
test('behavior: returns a fresh engine', async () => {
|
|
193
|
+
const first = await Keystore.engine()
|
|
194
|
+
const second = await Keystore.engine()
|
|
195
|
+
|
|
196
|
+
expect(first === second).toMatchInlineSnapshot('false')
|
|
197
|
+
})
|
|
198
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { mnemonicToSeedSync } from '@scure/bip39'
|
|
2
|
+
import { fc, test } from '@fast-check/vitest'
|
|
3
|
+
import { expect } from 'vp/test'
|
|
4
|
+
import { numRuns } from '../../../test/fuzz/numRuns.js'
|
|
5
|
+
import * as Mnemonic from '../Mnemonic.js'
|
|
6
|
+
|
|
7
|
+
const arbitraryWord = fc.oneof(
|
|
8
|
+
fc
|
|
9
|
+
.string({ maxLength: 16, minLength: 1 })
|
|
10
|
+
.filter((value) => !value.normalize('NFKD').includes(' ')),
|
|
11
|
+
fc.constantFrom('café', 'cafe\u0301', 'あおぞら', '㍍ガバヴァ'),
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
test.prop(
|
|
15
|
+
{
|
|
16
|
+
mnemonic: fc
|
|
17
|
+
.array(arbitraryWord, { maxLength: 12, minLength: 12 })
|
|
18
|
+
.map((words) => words.join(' ')),
|
|
19
|
+
passphrase: fc.string({ maxLength: 32 }),
|
|
20
|
+
},
|
|
21
|
+
{ numRuns },
|
|
22
|
+
)(
|
|
23
|
+
'Node BIP-39 seed derivation agrees with the default',
|
|
24
|
+
async ({ mnemonic, passphrase }) => {
|
|
25
|
+
const { toSeed } = await Mnemonic.engine()
|
|
26
|
+
|
|
27
|
+
expect(toSeed(mnemonic, passphrase)).toEqual(
|
|
28
|
+
mnemonicToSeedSync(mnemonic, passphrase),
|
|
29
|
+
)
|
|
30
|
+
},
|
|
31
|
+
)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { expectTypeOf, test } from 'vp/test'
|
|
2
|
+
import type * as Engine from '../../core/Engine.js'
|
|
3
|
+
import * as core_Mnemonic from '../../core/Mnemonic.js'
|
|
4
|
+
import * as NodeMnemonic from '../Mnemonic.js'
|
|
5
|
+
|
|
6
|
+
type Slot = Awaited<ReturnType<typeof NodeMnemonic.engine>>
|
|
7
|
+
|
|
8
|
+
test('every implemented primitive is present', () => {
|
|
9
|
+
expectTypeOf<Slot['toSeed']>().toEqualTypeOf<
|
|
10
|
+
(mnemonic: string, passphrase?: string) => Uint8Array
|
|
11
|
+
>()
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test('the result is the raw slot', () => {
|
|
15
|
+
expectTypeOf<{ Mnemonic: Slot }>().toExtend<Engine.Engine>()
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
test('the Node namespace exposes the public Mnemonic API', () => {
|
|
19
|
+
expectTypeOf(NodeMnemonic.toSeed).toEqualTypeOf(core_Mnemonic.toSeed)
|
|
20
|
+
expectTypeOf<typeof NodeMnemonic>().not.toHaveProperty('create')
|
|
21
|
+
})
|