ox 1.1.0 → 1.2.0
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 +54 -0
- package/dist/core/Engine.d.ts +43 -11
- package/dist/core/Engine.d.ts.map +1 -1
- package/dist/core/Engine.js +40 -10
- package/dist/core/Engine.js.map +1 -1
- package/dist/core/Hash.d.ts +36 -0
- package/dist/core/Hash.d.ts.map +1 -1
- package/dist/core/Hash.js +35 -0
- package/dist/core/Hash.js.map +1 -1
- package/dist/core/internal/engine.d.ts +8 -8
- package/dist/core/internal/engine.d.ts.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- 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 +29 -16
- package/dist/node/Engine.d.ts.map +1 -1
- package/dist/node/Engine.js +38 -14
- package/dist/node/Engine.js.map +1 -1
- package/dist/node/Hash.d.ts +17 -19
- package/dist/node/Hash.d.ts.map +1 -1
- package/dist/node/Hash.js +17 -19
- package/dist/node/Hash.js.map +1 -1
- 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 +95 -8
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +95 -8
- package/dist/node/index.js.map +1 -1
- package/dist/trusted-setups/Paths.d.ts +1 -0
- package/dist/trusted-setups/Paths.d.ts.map +1 -1
- package/dist/trusted-setups/Paths.js +1 -0
- package/dist/trusted-setups/Paths.js.map +1 -1
- package/dist/trusted-setups/Setups.d.ts +35 -0
- package/dist/trusted-setups/Setups.d.ts.map +1 -0
- package/dist/trusted-setups/Setups.js +29 -0
- package/dist/trusted-setups/Setups.js.map +1 -0
- package/dist/trusted-setups/index.d.ts +20 -0
- package/dist/trusted-setups/index.d.ts.map +1 -1
- package/dist/trusted-setups/index.js +20 -0
- package/dist/trusted-setups/index.js.map +1 -1
- package/dist/trusted-setups/internal/paths.d.ts.map +1 -1
- package/dist/trusted-setups/internal/paths.js +1 -1
- package/dist/trusted-setups/internal/paths.js.map +1 -1
- package/dist/trusted-setups/internal/setups/mainnet.d.ts +7 -0
- package/dist/trusted-setups/internal/setups/mainnet.d.ts.map +1 -0
- package/dist/trusted-setups/internal/setups/mainnet.js +11 -0
- package/dist/trusted-setups/internal/setups/mainnet.js.map +1 -0
- 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 +36 -26
- package/dist/wasm/Engine.d.ts.map +1 -1
- package/dist/wasm/Engine.js +44 -25
- package/dist/wasm/Engine.js.map +1 -1
- package/dist/wasm/Hash.d.ts +13 -19
- package/dist/wasm/Hash.d.ts.map +1 -1
- package/dist/wasm/Hash.js +21 -27
- package/dist/wasm/Hash.js.map +1 -1
- package/dist/wasm/Keystore.d.ts +51 -0
- package/dist/wasm/Keystore.d.ts.map +1 -0
- package/dist/wasm/Keystore.js +51 -0
- package/dist/wasm/Keystore.js.map +1 -0
- package/dist/wasm/Kzg.d.ts +112 -0
- package/dist/wasm/Kzg.d.ts.map +1 -0
- package/dist/wasm/Kzg.js +333 -0
- package/dist/wasm/Kzg.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/Secp256k1.d.ts +55 -0
- package/dist/wasm/Secp256k1.d.ts.map +1 -0
- package/dist/wasm/Secp256k1.js +181 -0
- package/dist/wasm/Secp256k1.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 +124 -12
- package/dist/wasm/index.d.ts.map +1 -1
- package/dist/wasm/index.js +124 -12
- package/dist/wasm/index.js.map +1 -1
- 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/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 +4 -2
- package/dist/wasm/internal/hashes.wasm.d.ts.map +1 -1
- package/dist/wasm/internal/hashes.wasm.js +4 -2
- package/dist/wasm/internal/hashes.wasm.js.map +1 -1
- package/dist/wasm/internal/instantiate.d.ts +12 -0
- package/dist/wasm/internal/instantiate.d.ts.map +1 -1
- package/dist/wasm/internal/instantiate.js +23 -7
- package/dist/wasm/internal/instantiate.js.map +1 -1
- package/dist/wasm/internal/keystore.d.ts +10 -0
- package/dist/wasm/internal/keystore.d.ts.map +1 -0
- package/dist/wasm/internal/keystore.js +10 -0
- package/dist/wasm/internal/keystore.js.map +1 -0
- package/dist/wasm/internal/kzg.d.ts +17 -0
- package/dist/wasm/internal/kzg.d.ts.map +1 -0
- package/dist/wasm/internal/kzg.js +8 -0
- package/dist/wasm/internal/kzg.js.map +1 -0
- package/dist/wasm/internal/kzg.wasm.d.ts +3 -0
- package/dist/wasm/internal/kzg.wasm.d.ts.map +1 -0
- package/dist/wasm/internal/kzg.wasm.js +10 -0
- package/dist/wasm/internal/kzg.wasm.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/scrypt.d.ts +16 -0
- package/dist/wasm/internal/scrypt.d.ts.map +1 -0
- package/dist/wasm/internal/scrypt.js +78 -0
- package/dist/wasm/internal/scrypt.js.map +1 -0
- package/dist/wasm/internal/scrypt.wasm.d.ts +7 -0
- package/dist/wasm/internal/scrypt.wasm.d.ts.map +1 -0
- package/dist/wasm/internal/scrypt.wasm.js +14 -0
- package/dist/wasm/internal/scrypt.wasm.js.map +1 -0
- package/dist/wasm/internal/secp256k1.d.ts +16 -0
- package/dist/wasm/internal/secp256k1.d.ts.map +1 -0
- package/dist/wasm/internal/secp256k1.js +20 -0
- package/dist/wasm/internal/secp256k1.js.map +1 -0
- package/dist/wasm/internal/secp256k1.wasm.d.ts +3 -0
- package/dist/wasm/internal/secp256k1.wasm.d.ts.map +1 -0
- package/dist/wasm/internal/secp256k1.wasm.js +10 -0
- package/dist/wasm/internal/secp256k1.wasm.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/package.json +64 -2
- package/src/core/Engine.ts +84 -11
- package/src/core/Hash.ts +59 -0
- package/src/core/_test/Block.test.ts +9 -2
- package/src/core/_test/Engine.test-d.ts +56 -0
- package/src/core/_test/Engine.test.ts +95 -0
- package/src/core/_test/Hash.test-d.ts +18 -0
- package/src/core/_test/Hash.test.ts +100 -1
- package/src/core/_test/Hash.vectors.test.ts +7 -0
- package/src/core/_test/Transaction.test.ts +11 -2
- package/src/core/internal/engine.ts +8 -8
- package/src/index.ts +5 -2
- package/src/node/Ed25519.ts +87 -0
- package/src/node/Engine.ts +79 -23
- package/src/node/Hash.ts +25 -30
- 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 +62 -22
- package/src/node/_test/Hash.test-d.ts +16 -9
- package/src/node/_test/Hash.test.ts +10 -11
- 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 +100 -8
- package/src/trusted-setups/Paths.ts +1 -0
- package/src/trusted-setups/README.md +39 -0
- package/src/trusted-setups/Setups.ts +46 -0
- package/src/trusted-setups/_test/Paths.test.ts +16 -0
- package/src/trusted-setups/_test/Setups.test-d.ts +7 -0
- package/src/trusted-setups/_test/Setups.test.ts +43 -0
- package/src/trusted-setups/_test/index.test.ts +1 -0
- package/src/trusted-setups/index.ts +21 -0
- package/src/trusted-setups/internal/paths.ts +4 -1
- package/src/trusted-setups/internal/setups/mainnet.source.json +7 -0
- package/src/trusted-setups/internal/setups/mainnet.ts +16 -0
- package/src/version.ts +1 -1
- package/src/wasm/Ed25519.ts +114 -0
- package/src/wasm/Engine.ts +78 -31
- package/src/wasm/Hash.bench.ts +2 -2
- package/src/wasm/Hash.ts +29 -50
- package/src/wasm/Keystore.bench.ts +26 -0
- package/src/wasm/Keystore.ts +66 -0
- package/src/wasm/Kzg.bench.ts +63 -0
- package/src/wasm/Kzg.ts +518 -0
- package/src/wasm/Mnemonic.ts +44 -0
- package/src/wasm/Secp256k1.bench.ts +79 -0
- package/src/wasm/Secp256k1.ts +248 -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 +29 -0
- package/src/wasm/_test/Engine.test.ts +59 -25
- package/src/wasm/_test/Hash.browser.test.ts +14 -7
- package/src/wasm/_test/Hash.fuzz.ts +58 -23
- package/src/wasm/_test/Hash.test-d.ts +16 -10
- package/src/wasm/_test/Hash.test.ts +148 -48
- package/src/wasm/_test/Hash.vectors.test.ts +15 -8
- package/src/wasm/_test/Keystore.browser.test.ts +73 -0
- package/src/wasm/_test/Keystore.fuzz.ts +163 -0
- package/src/wasm/_test/Keystore.test-d.ts +42 -0
- package/src/wasm/_test/Keystore.test.ts +477 -0
- package/src/wasm/_test/Keystore.vectors.test.ts +21 -0
- package/src/wasm/_test/Kzg.test-d.ts +19 -0
- package/src/wasm/_test/Kzg.test.ts +220 -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 +9 -0
- package/src/wasm/_test/Secp256k1.test-d.ts +35 -0
- package/src/wasm/_test/Secp256k1.test.ts +354 -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/index.ts +130 -12
- 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/hashes.ts +29 -0
- package/src/wasm/internal/hashes.wasm.ts +5 -2
- package/src/wasm/internal/instantiate.ts +29 -9
- package/src/wasm/internal/keystore.ts +19 -0
- package/src/wasm/internal/kzg.ts +50 -0
- package/src/wasm/internal/kzg.wasm.ts +11 -0
- package/src/wasm/internal/mnemonic.ts +56 -0
- package/src/wasm/internal/pbkdf2.ts +86 -0
- package/src/wasm/internal/scrypt.ts +131 -0
- package/src/wasm/internal/scrypt.wasm.ts +17 -0
- package/src/wasm/internal/secp256k1.ts +62 -0
- package/src/wasm/internal/secp256k1.wasm.ts +11 -0
- package/src/wasm/internal/x25519.ts +29 -0
- package/wasm/vendor/c-kzg-4844/LICENSE +201 -0
- package/wasm/vendor/c-kzg-4844/blst/LICENSE +201 -0
- package/src/trusted-setups/internal/setups/mainnet.txt +0 -4163
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
import { pbkdf2 as pbkdf2_noble } from '@noble/hashes/pbkdf2.js'
|
|
2
|
+
import { scrypt as scrypt_noble } from '@noble/hashes/scrypt.js'
|
|
3
|
+
import { sha256 } from '@noble/hashes/sha2.js'
|
|
4
|
+
import { beforeAll, describe, expect, test } from 'vp/test'
|
|
5
|
+
import * as Bytes from '../../core/Bytes.js'
|
|
6
|
+
import * as Engine from '../../core/Engine.js'
|
|
7
|
+
import * as Keystore from '../../core/Keystore.js'
|
|
8
|
+
import * as WasmKeystore from '../Keystore.js'
|
|
9
|
+
import * as hashes from '../internal/hashes.js'
|
|
10
|
+
import { wasmBase64 as hashesWasmBase64 } from '../internal/hashes.wasm.js'
|
|
11
|
+
import * as internal from '../internal/instantiate.js'
|
|
12
|
+
import * as pbkdf2 from '../internal/pbkdf2.js'
|
|
13
|
+
import * as scrypt from '../internal/scrypt.js'
|
|
14
|
+
import { wasmBase64 as scryptWasmBase64 } from '../internal/scrypt.wasm.js'
|
|
15
|
+
|
|
16
|
+
let engine: WasmKeystore.engine.ReturnType
|
|
17
|
+
|
|
18
|
+
beforeAll(async () => {
|
|
19
|
+
engine = await WasmKeystore.engine()
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
function input(size: number) {
|
|
23
|
+
return new Uint8Array(size).map((_, index) => (index * 37 + 11) & 0xff)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe('engine', () => {
|
|
27
|
+
test('default', async () => {
|
|
28
|
+
expect(Object.keys(await WasmKeystore.engine())).toMatchInlineSnapshot(`
|
|
29
|
+
[
|
|
30
|
+
"pbkdf2Sha256",
|
|
31
|
+
"scrypt",
|
|
32
|
+
]
|
|
33
|
+
`)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test('behavior: shares the compiled hashes instance', async () => {
|
|
37
|
+
const [a, b] = await Promise.all([hashes.load(), hashes.load()])
|
|
38
|
+
expect(a).toBe(b)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
test('behavior: shares the compiled scrypt instance', async () => {
|
|
42
|
+
const [a, b] = await Promise.all([scrypt.load(), scrypt.load()])
|
|
43
|
+
expect(a).toBe(b)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test('behavior: hands every caller its own engine', async () => {
|
|
47
|
+
const [a, b] = await Promise.all([
|
|
48
|
+
WasmKeystore.engine(),
|
|
49
|
+
WasmKeystore.engine(),
|
|
50
|
+
])
|
|
51
|
+
expect(a).not.toBe(b)
|
|
52
|
+
|
|
53
|
+
a.pbkdf2Sha256 = () => new Uint8Array([9])
|
|
54
|
+
const c = await WasmKeystore.engine()
|
|
55
|
+
expect(c.pbkdf2Sha256(input(8), input(16), { c: 2, dkLen: 33 })).toEqual(
|
|
56
|
+
b.pbkdf2Sha256(input(8), input(16), { c: 2, dkLen: 33 }),
|
|
57
|
+
)
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
const cases = [
|
|
62
|
+
{ c: 1, dkLen: 1, password: 0, salt: 0 },
|
|
63
|
+
{ c: 2, dkLen: 31, password: 1, salt: 51 },
|
|
64
|
+
{ c: 3, dkLen: 32, password: 63, salt: 52 },
|
|
65
|
+
{ c: 4, dkLen: 33, password: 64, salt: 55 },
|
|
66
|
+
{ c: 7, dkLen: 64, password: 65, salt: 64 },
|
|
67
|
+
{ c: 2, dkLen: 65, password: 129, salt: 137 },
|
|
68
|
+
] as const
|
|
69
|
+
|
|
70
|
+
describe('pbkdf2Sha256', () => {
|
|
71
|
+
test.each(cases)(
|
|
72
|
+
'matches the default for password=$password salt=$salt c=$c dkLen=$dkLen',
|
|
73
|
+
({ c, dkLen, password: passwordLength, salt: saltLength }) => {
|
|
74
|
+
const password = input(passwordLength)
|
|
75
|
+
const salt = input(saltLength)
|
|
76
|
+
expect(engine.pbkdf2Sha256(password, salt, { c, dkLen })).toEqual(
|
|
77
|
+
pbkdf2_noble(sha256, password, salt, { c, dkLen }),
|
|
78
|
+
)
|
|
79
|
+
},
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
test('behavior: reads non-zero-offset views without mutating their backing buffers', () => {
|
|
83
|
+
const passwordBacking = new Uint8Array(80).fill(0xa5)
|
|
84
|
+
const saltBacking = new Uint8Array(90).fill(0x5a)
|
|
85
|
+
const password = passwordBacking.subarray(7, 72)
|
|
86
|
+
const salt = saltBacking.subarray(11, 63)
|
|
87
|
+
password.set(input(password.length))
|
|
88
|
+
salt.set(input(salt.length))
|
|
89
|
+
const passwordSnapshot = passwordBacking.slice()
|
|
90
|
+
const saltSnapshot = saltBacking.slice()
|
|
91
|
+
|
|
92
|
+
expect(engine.pbkdf2Sha256(password, salt, { c: 3, dkLen: 65 })).toEqual(
|
|
93
|
+
pbkdf2_noble(sha256, password, salt, { c: 3, dkLen: 65 }),
|
|
94
|
+
)
|
|
95
|
+
expect(passwordBacking).toEqual(passwordSnapshot)
|
|
96
|
+
expect(saltBacking).toEqual(saltSnapshot)
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
test('behavior: results are fresh and never alias WASM memory', () => {
|
|
100
|
+
const password = input(65)
|
|
101
|
+
const salt = input(52)
|
|
102
|
+
const first = engine.pbkdf2Sha256(password, salt, {
|
|
103
|
+
c: 2,
|
|
104
|
+
dkLen: 65,
|
|
105
|
+
})
|
|
106
|
+
const snapshot = first.slice()
|
|
107
|
+
const second = engine.pbkdf2Sha256(input(5), input(9), {
|
|
108
|
+
c: 3,
|
|
109
|
+
dkLen: 97,
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
expect(first).not.toBe(second)
|
|
113
|
+
expect(first).toEqual(snapshot)
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
test('behavior: clears passwords, salts, outputs, and scratch', async () => {
|
|
117
|
+
const module = await internal.instantiate<hashes.Exports>(hashesWasmBase64)
|
|
118
|
+
const password = input(65)
|
|
119
|
+
const salt = input(52)
|
|
120
|
+
const stack = module.view().slice(0, module.heapBase)
|
|
121
|
+
|
|
122
|
+
expect(
|
|
123
|
+
pbkdf2.pbkdf2Sha256(module, password, salt, { c: 3, dkLen: 65 }),
|
|
124
|
+
).toEqual(pbkdf2_noble(sha256, password, salt, { c: 3, dkLen: 65 }))
|
|
125
|
+
expect(module.view().slice(0, module.heapBase)).toEqual(stack)
|
|
126
|
+
expect(module.view().slice(module.heapBase)).toEqual(
|
|
127
|
+
new Uint8Array(module.view().length - module.heapBase),
|
|
128
|
+
)
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
test('behavior: clears the complete region after a late trap', async () => {
|
|
132
|
+
const module = await internal.instantiate<hashes.Exports>(hashesWasmBase64)
|
|
133
|
+
const password = input(65)
|
|
134
|
+
const salt = input(52)
|
|
135
|
+
const exports: pbkdf2.Exports = {
|
|
136
|
+
pbkdf2_sha256(...parameters) {
|
|
137
|
+
module.exports.pbkdf2_sha256(...parameters)
|
|
138
|
+
throw new WebAssembly.RuntimeError('forced late trap')
|
|
139
|
+
},
|
|
140
|
+
zero: (ptr, length) => module.exports.zero(ptr, length),
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
expect(() =>
|
|
144
|
+
pbkdf2.pbkdf2Sha256({ ...module, exports }, password, salt, {
|
|
145
|
+
c: 3,
|
|
146
|
+
dkLen: 65,
|
|
147
|
+
}),
|
|
148
|
+
).toThrow(WebAssembly.RuntimeError)
|
|
149
|
+
expect(module.view().slice(module.heapBase)).toEqual(
|
|
150
|
+
new Uint8Array(module.view().length - module.heapBase),
|
|
151
|
+
)
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
test('behavior: rejects a workspace that overflows wasm32 before growing memory', async () => {
|
|
155
|
+
const module = await internal.instantiate<hashes.Exports>(hashesWasmBase64)
|
|
156
|
+
const memory = module.view().length
|
|
157
|
+
|
|
158
|
+
expect(() =>
|
|
159
|
+
pbkdf2.pbkdf2Sha256(module, new Uint8Array(), new Uint8Array(), {
|
|
160
|
+
c: 1,
|
|
161
|
+
dkLen: 0xffff_ffff,
|
|
162
|
+
}),
|
|
163
|
+
).toThrow(internal.MemoryError)
|
|
164
|
+
expect(module.view()).toHaveLength(memory)
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
test.each([
|
|
168
|
+
{ name: 'c', options: { c: 0, dkLen: 32 } },
|
|
169
|
+
{ name: 'c', options: { c: 1.5, dkLen: 32 } },
|
|
170
|
+
{ name: 'c', options: { c: 0x1_0000_0000, dkLen: 32 } },
|
|
171
|
+
{ name: 'dkLen', options: { c: 1, dkLen: 0 } },
|
|
172
|
+
{ name: 'dkLen', options: { c: 1, dkLen: 1.5 } },
|
|
173
|
+
{ name: 'dkLen', options: { c: 1, dkLen: 0x1_0000_0000 } },
|
|
174
|
+
])('behavior: rejects invalid $name before entering WASM', ({ options }) => {
|
|
175
|
+
expect(() => engine.pbkdf2Sha256(input(8), input(16), options)).toThrow()
|
|
176
|
+
})
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
const scryptCases = [
|
|
180
|
+
{ N: 16, dkLen: 64, p: 1, password: 0, r: 1, salt: 0 },
|
|
181
|
+
{ N: 1024, dkLen: 32, p: 1, password: 8, r: 1, salt: 16 },
|
|
182
|
+
{ N: 1024, dkLen: 64, p: 1, password: 65, r: 8, salt: 52 },
|
|
183
|
+
{ N: 1024, dkLen: 33, p: 2, password: 9, r: 4, salt: 17 },
|
|
184
|
+
] as const
|
|
185
|
+
|
|
186
|
+
describe('scrypt', () => {
|
|
187
|
+
test.each(scryptCases)(
|
|
188
|
+
'matches the default for password=$password salt=$salt N=$N r=$r p=$p dkLen=$dkLen',
|
|
189
|
+
({ N, dkLen, p, password: passwordLength, r, salt: saltLength }) => {
|
|
190
|
+
const password = input(passwordLength)
|
|
191
|
+
const salt = input(saltLength)
|
|
192
|
+
const options = { N, dkLen, p, r }
|
|
193
|
+
expect(engine.scrypt(password, salt, options)).toEqual(
|
|
194
|
+
scrypt_noble(password, salt, options),
|
|
195
|
+
)
|
|
196
|
+
},
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
test.each([
|
|
200
|
+
{
|
|
201
|
+
N: 16,
|
|
202
|
+
expected:
|
|
203
|
+
'0x77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906',
|
|
204
|
+
p: 1,
|
|
205
|
+
password: '',
|
|
206
|
+
r: 1,
|
|
207
|
+
salt: '',
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
N: 1024,
|
|
211
|
+
expected:
|
|
212
|
+
'0xfdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640',
|
|
213
|
+
p: 16,
|
|
214
|
+
password: 'password',
|
|
215
|
+
r: 8,
|
|
216
|
+
salt: 'NaCl',
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
N: 16_384,
|
|
220
|
+
expected:
|
|
221
|
+
'0x7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887',
|
|
222
|
+
p: 1,
|
|
223
|
+
password: 'pleaseletmein',
|
|
224
|
+
r: 8,
|
|
225
|
+
salt: 'SodiumChloride',
|
|
226
|
+
},
|
|
227
|
+
])(
|
|
228
|
+
'matches the RFC 7914 vector for N=$N r=$r p=$p',
|
|
229
|
+
({ N, expected, p, password, r, salt }) => {
|
|
230
|
+
expect(
|
|
231
|
+
Bytes.toHex(
|
|
232
|
+
engine.scrypt(Bytes.fromString(password), Bytes.fromString(salt), {
|
|
233
|
+
N,
|
|
234
|
+
dkLen: 64,
|
|
235
|
+
p,
|
|
236
|
+
r,
|
|
237
|
+
}),
|
|
238
|
+
),
|
|
239
|
+
).toBe(expected)
|
|
240
|
+
},
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
test('behavior: reads non-zero-offset views without mutating their backing buffers', () => {
|
|
244
|
+
const passwordBacking = new Uint8Array(80).fill(0xa5)
|
|
245
|
+
const saltBacking = new Uint8Array(90).fill(0x5a)
|
|
246
|
+
const password = passwordBacking.subarray(7, 72)
|
|
247
|
+
const salt = saltBacking.subarray(11, 63)
|
|
248
|
+
password.set(input(password.length))
|
|
249
|
+
salt.set(input(salt.length))
|
|
250
|
+
const passwordSnapshot = passwordBacking.slice()
|
|
251
|
+
const saltSnapshot = saltBacking.slice()
|
|
252
|
+
const options = { N: 1024, dkLen: 65, p: 2, r: 1 }
|
|
253
|
+
|
|
254
|
+
expect(engine.scrypt(password, salt, options)).toEqual(
|
|
255
|
+
scrypt_noble(password, salt, options),
|
|
256
|
+
)
|
|
257
|
+
expect(passwordBacking).toEqual(passwordSnapshot)
|
|
258
|
+
expect(saltBacking).toEqual(saltSnapshot)
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
test('behavior: results are fresh and never alias WASM memory', () => {
|
|
262
|
+
const first = engine.scrypt(input(65), input(52), {
|
|
263
|
+
N: 16,
|
|
264
|
+
dkLen: 65,
|
|
265
|
+
p: 1,
|
|
266
|
+
r: 1,
|
|
267
|
+
})
|
|
268
|
+
const snapshot = first.slice()
|
|
269
|
+
const second = engine.scrypt(input(5), input(9), {
|
|
270
|
+
N: 32,
|
|
271
|
+
dkLen: 97,
|
|
272
|
+
p: 1,
|
|
273
|
+
r: 1,
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
expect(first).not.toBe(second)
|
|
277
|
+
expect(first).toEqual(snapshot)
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
test('behavior: clears inputs, outputs, and every workspace', async () => {
|
|
281
|
+
const module = await internal.instantiate<scrypt.Exports>(scryptWasmBase64)
|
|
282
|
+
const password = input(65)
|
|
283
|
+
const salt = input(52)
|
|
284
|
+
const options = { N: 16, dkLen: 65, p: 2, r: 2 }
|
|
285
|
+
const stack = module.view().slice(0, module.heapBase)
|
|
286
|
+
|
|
287
|
+
expect(scrypt.derive(module, password, salt, options)).toEqual(
|
|
288
|
+
scrypt_noble(password, salt, options),
|
|
289
|
+
)
|
|
290
|
+
expect(module.view().slice(0, module.heapBase)).toEqual(stack)
|
|
291
|
+
expect(module.view().slice(module.heapBase)).toEqual(
|
|
292
|
+
new Uint8Array(module.view().length - module.heapBase),
|
|
293
|
+
)
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
test('behavior: clears the complete region after a late trap', async () => {
|
|
297
|
+
const module = await internal.instantiate<scrypt.Exports>(scryptWasmBase64)
|
|
298
|
+
const password = input(65)
|
|
299
|
+
const salt = input(52)
|
|
300
|
+
const exports: scrypt.Exports = {
|
|
301
|
+
scrypt(...parameters) {
|
|
302
|
+
module.exports.scrypt(...parameters)
|
|
303
|
+
throw new WebAssembly.RuntimeError('forced late trap')
|
|
304
|
+
},
|
|
305
|
+
zero: (ptr, length) => module.exports.zero(ptr, length),
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
expect(() =>
|
|
309
|
+
scrypt.derive({ ...module, exports }, password, salt, {
|
|
310
|
+
N: 16,
|
|
311
|
+
dkLen: 65,
|
|
312
|
+
p: 2,
|
|
313
|
+
r: 2,
|
|
314
|
+
}),
|
|
315
|
+
).toThrow(WebAssembly.RuntimeError)
|
|
316
|
+
expect(module.view().slice(module.heapBase)).toEqual(
|
|
317
|
+
new Uint8Array(module.view().length - module.heapBase),
|
|
318
|
+
)
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
test('behavior: rejects the workspace limit before growing memory', async () => {
|
|
322
|
+
const module = await internal.instantiate<scrypt.Exports>(scryptWasmBase64)
|
|
323
|
+
const memory = module.view().length
|
|
324
|
+
|
|
325
|
+
expect(() =>
|
|
326
|
+
scrypt.derive(module, new Uint8Array(), new Uint8Array(), {
|
|
327
|
+
N: 1_048_576,
|
|
328
|
+
dkLen: 32,
|
|
329
|
+
p: 1,
|
|
330
|
+
r: 16,
|
|
331
|
+
}),
|
|
332
|
+
).toThrow(
|
|
333
|
+
'"maxmem" limit was hit: memUsed(128*r*(N+p+1))=2147487744, maxmem=1073742848',
|
|
334
|
+
)
|
|
335
|
+
expect(module.view()).toHaveLength(memory)
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
test('behavior: rejects the WASM memory limit before growing memory', async () => {
|
|
339
|
+
const module = await internal.instantiate<scrypt.Exports>(scryptWasmBase64)
|
|
340
|
+
const memory = module.view().length
|
|
341
|
+
|
|
342
|
+
expect(() =>
|
|
343
|
+
scrypt.derive(module, new Uint8Array(), new Uint8Array(), {
|
|
344
|
+
N: 2,
|
|
345
|
+
dkLen: 1_074_790_400,
|
|
346
|
+
p: 1,
|
|
347
|
+
r: 1,
|
|
348
|
+
}),
|
|
349
|
+
).toThrow(internal.MemoryError)
|
|
350
|
+
expect(module.view()).toHaveLength(memory)
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
test('behavior: rejects reentrant use of one instance without corrupting the outer call', async () => {
|
|
354
|
+
const module = await internal.instantiate<scrypt.Exports>(scryptWasmBase64)
|
|
355
|
+
const password = input(8)
|
|
356
|
+
const salt = input(16)
|
|
357
|
+
const options = { N: 16, dkLen: 32, p: 1, r: 1 }
|
|
358
|
+
let reentered = false
|
|
359
|
+
const wrapper: internal.Module<scrypt.Exports> = {
|
|
360
|
+
...module,
|
|
361
|
+
exports: {
|
|
362
|
+
scrypt(...parameters) {
|
|
363
|
+
expect(() => scrypt.derive(wrapper, password, salt, options)).toThrow(
|
|
364
|
+
'The scrypt WASM instance is already deriving a key.',
|
|
365
|
+
)
|
|
366
|
+
reentered = true
|
|
367
|
+
module.exports.scrypt(...parameters)
|
|
368
|
+
},
|
|
369
|
+
zero: (ptr, length) => module.exports.zero(ptr, length),
|
|
370
|
+
},
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
expect(scrypt.derive(wrapper, password, salt, options)).toEqual(
|
|
374
|
+
scrypt_noble(password, salt, options),
|
|
375
|
+
)
|
|
376
|
+
expect(reentered).toBe(true)
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
test.each([
|
|
380
|
+
{ N: 1, dkLen: 32, p: 1, r: 8 },
|
|
381
|
+
{ N: 3, dkLen: 32, p: 1, r: 8 },
|
|
382
|
+
{ N: 1024.5, dkLen: 32, p: 1, r: 8 },
|
|
383
|
+
{ N: 1024, dkLen: 32, p: 1, r: -1 },
|
|
384
|
+
{ N: 1024, dkLen: 32, p: 0, r: 8 },
|
|
385
|
+
{ N: 1024, dkLen: 0, p: 1, r: 8 },
|
|
386
|
+
{ N: 1024, dkLen: 32, p: 1, r: 0 },
|
|
387
|
+
])(
|
|
388
|
+
'behavior: matches the default error for N=$N r=$r p=$p dkLen=$dkLen',
|
|
389
|
+
(options) => {
|
|
390
|
+
const getError = (fn: () => unknown) => {
|
|
391
|
+
try {
|
|
392
|
+
fn()
|
|
393
|
+
} catch (error) {
|
|
394
|
+
return {
|
|
395
|
+
message: (error as Error).message,
|
|
396
|
+
name: (error as Error).constructor.name,
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
throw new Error('Expected derivation to throw.')
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
expect(
|
|
403
|
+
getError(() => engine.scrypt(input(8), input(16), options)),
|
|
404
|
+
).toEqual(getError(() => scrypt_noble(input(8), input(16), options)))
|
|
405
|
+
},
|
|
406
|
+
)
|
|
407
|
+
})
|
|
408
|
+
|
|
409
|
+
describe('Engine.install', () => {
|
|
410
|
+
test('behavior: ox uses synchronous WASM PBKDF2 once installed', async () => {
|
|
411
|
+
await Engine.install({ Keystore: engine })
|
|
412
|
+
try {
|
|
413
|
+
const salt = input(32)
|
|
414
|
+
const [key] = Keystore.pbkdf2({
|
|
415
|
+
iterations: 1_000,
|
|
416
|
+
password: 'testpassword',
|
|
417
|
+
salt,
|
|
418
|
+
})
|
|
419
|
+
expect(key()).toBe(
|
|
420
|
+
Bytes.toHex(
|
|
421
|
+
pbkdf2_noble(sha256, Bytes.fromString('testpassword'), salt, {
|
|
422
|
+
c: 1_000,
|
|
423
|
+
dkLen: 32,
|
|
424
|
+
}),
|
|
425
|
+
),
|
|
426
|
+
)
|
|
427
|
+
} finally {
|
|
428
|
+
Engine.reset()
|
|
429
|
+
}
|
|
430
|
+
})
|
|
431
|
+
|
|
432
|
+
test('behavior: ox uses synchronous WASM scrypt once installed', async () => {
|
|
433
|
+
const wasm = engine.scrypt
|
|
434
|
+
let calls = 0
|
|
435
|
+
await Engine.install({
|
|
436
|
+
Keystore: {
|
|
437
|
+
...engine,
|
|
438
|
+
scrypt(...parameters) {
|
|
439
|
+
calls++
|
|
440
|
+
return wasm(...parameters)
|
|
441
|
+
},
|
|
442
|
+
},
|
|
443
|
+
})
|
|
444
|
+
try {
|
|
445
|
+
const salt = input(32)
|
|
446
|
+
const [key] = Keystore.scrypt({
|
|
447
|
+
n: 1024,
|
|
448
|
+
p: 2,
|
|
449
|
+
password: 'testpassword',
|
|
450
|
+
r: 1,
|
|
451
|
+
salt,
|
|
452
|
+
})
|
|
453
|
+
expect(key()).toBe(
|
|
454
|
+
Bytes.toHex(
|
|
455
|
+
scrypt_noble(Bytes.fromString('testpassword'), salt, {
|
|
456
|
+
N: 1024,
|
|
457
|
+
dkLen: 32,
|
|
458
|
+
p: 2,
|
|
459
|
+
r: 1,
|
|
460
|
+
}),
|
|
461
|
+
),
|
|
462
|
+
)
|
|
463
|
+
expect(calls).toBe(1)
|
|
464
|
+
|
|
465
|
+
await Keystore.scryptAsync({
|
|
466
|
+
n: 1024,
|
|
467
|
+
p: 1,
|
|
468
|
+
password: 'testpassword',
|
|
469
|
+
r: 1,
|
|
470
|
+
salt,
|
|
471
|
+
})
|
|
472
|
+
expect(calls).toBe(1)
|
|
473
|
+
} finally {
|
|
474
|
+
Engine.reset()
|
|
475
|
+
}
|
|
476
|
+
})
|
|
477
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { beforeAll, describe, expect, test } from 'vp/test'
|
|
2
|
+
import * as vectors from '../../../test/vectors/pbkdf2/index.js'
|
|
3
|
+
import * as WasmKeystore from '../Keystore.js'
|
|
4
|
+
|
|
5
|
+
let engine: WasmKeystore.engine.ReturnType
|
|
6
|
+
|
|
7
|
+
beforeAll(async () => {
|
|
8
|
+
engine = await WasmKeystore.engine()
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
describe('pbkdf2Sha256', () => {
|
|
12
|
+
test(`matches ${vectors.vectors.length} RFC 7914 vectors`, () => {
|
|
13
|
+
for (const { iterations, key, password, salt } of vectors.vectors)
|
|
14
|
+
expect(
|
|
15
|
+
engine.pbkdf2Sha256(password, salt, {
|
|
16
|
+
c: iterations,
|
|
17
|
+
dkLen: key.length,
|
|
18
|
+
}),
|
|
19
|
+
).toEqual(key)
|
|
20
|
+
})
|
|
21
|
+
})
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { expectTypeOf, test } from 'vp/test'
|
|
2
|
+
import type * as CoreKzg from '../../core/Kzg.js'
|
|
3
|
+
import { mainnet as trustedSetup } from '../../trusted-setups/Setups.js'
|
|
4
|
+
import * as Kzg from '../Kzg.js'
|
|
5
|
+
|
|
6
|
+
test('create returns a disposable Kzg.Kzg implementation', async () => {
|
|
7
|
+
const instance = await Kzg.create({ trustedSetup })
|
|
8
|
+
|
|
9
|
+
expectTypeOf(instance).toMatchTypeOf<CoreKzg.Kzg>()
|
|
10
|
+
expectTypeOf<Kzg.create.ReturnType['dispose']>().toEqualTypeOf<() => void>()
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
test('trusted setup accepts packed bytes', () => {
|
|
14
|
+
expectTypeOf<Kzg.TrustedSetup>().toEqualTypeOf<{
|
|
15
|
+
readonly g1_lagrange: Uint8Array | readonly string[]
|
|
16
|
+
readonly g1_monomial: Uint8Array | readonly string[]
|
|
17
|
+
readonly g2_monomial: Uint8Array | readonly string[]
|
|
18
|
+
}>()
|
|
19
|
+
})
|