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,44 @@
|
|
|
1
|
+
import type * as Engine from '../core/Engine.js'
|
|
2
|
+
import type * as Errors from '../core/Errors.js'
|
|
3
|
+
import * as crypto25519 from './internal/crypto25519.js'
|
|
4
|
+
import * as internal from './internal/instantiate.js'
|
|
5
|
+
import * as mnemonic from './internal/mnemonic.js'
|
|
6
|
+
|
|
7
|
+
export * from '../core/Mnemonic.js'
|
|
8
|
+
export { MemoryError } from './internal/instantiate.js'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Compiles the WASM implementation of [`Mnemonic.toSeed`](/api/Mnemonic/toSeed),
|
|
12
|
+
* without installing it.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts twoslash
|
|
16
|
+
* // @noErrors
|
|
17
|
+
* import { Engine } from 'ox'
|
|
18
|
+
* import { Mnemonic } from 'ox/wasm'
|
|
19
|
+
*
|
|
20
|
+
* await Engine.install({ Mnemonic: Mnemonic.engine() })
|
|
21
|
+
*
|
|
22
|
+
* Mnemonic.toSeed(
|
|
23
|
+
* 'test test test test test test test test test test test junk'
|
|
24
|
+
* )
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @returns The WASM implementation of the `Mnemonic` slot.
|
|
28
|
+
*/
|
|
29
|
+
export async function engine(): Promise<engine.ReturnType> {
|
|
30
|
+
const module = await crypto25519.load()
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
toSeed: (value, passphrase) => mnemonic.toSeed(module, value, passphrase),
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export declare namespace engine {
|
|
38
|
+
/** Every `Mnemonic` primitive this module implements. */
|
|
39
|
+
type ReturnType = {
|
|
40
|
+
toSeed: NonNullable<Engine.Mnemonic['toSeed']>
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type ErrorType = internal.MemoryError | Errors.GlobalErrorType
|
|
44
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type * as Engine from '../core/Engine.js'
|
|
2
|
+
import type * as Errors from '../core/Errors.js'
|
|
3
|
+
import * as crypto25519 from './internal/crypto25519.js'
|
|
4
|
+
import * as internal from './internal/instantiate.js'
|
|
5
|
+
import * as x25519 from './internal/x25519.js'
|
|
6
|
+
|
|
7
|
+
export * from '../core/X25519.js'
|
|
8
|
+
export { MemoryError } from './internal/instantiate.js'
|
|
9
|
+
|
|
10
|
+
const keySize = 32
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Compiles WASM implementations of selected [`X25519`](/api/X25519)
|
|
14
|
+
* primitives, without installing them.
|
|
15
|
+
*
|
|
16
|
+
* Random key generation remains on Ox's default implementation.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts twoslash
|
|
20
|
+
* // @noErrors
|
|
21
|
+
* import { Engine } from 'ox'
|
|
22
|
+
* import { X25519 } from 'ox/wasm'
|
|
23
|
+
*
|
|
24
|
+
* await Engine.install({ X25519: X25519.engine() })
|
|
25
|
+
*
|
|
26
|
+
* X25519.getPublicKey({ privateKey: '0x...' })
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @returns The WASM implementation of part of the `X25519` slot.
|
|
30
|
+
*/
|
|
31
|
+
export async function engine(): Promise<engine.ReturnType> {
|
|
32
|
+
const module = await crypto25519.load()
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
getPublicKey(privateKey) {
|
|
36
|
+
assertLength(privateKey, 'private')
|
|
37
|
+
module.reserve(keySize * 2)
|
|
38
|
+
const privateKeyPtr = module.heapBase
|
|
39
|
+
const publicKeyPtr = privateKeyPtr + keySize
|
|
40
|
+
try {
|
|
41
|
+
module.view().set(privateKey, privateKeyPtr)
|
|
42
|
+
module.exports.x25519_get_public_key(privateKeyPtr, publicKeyPtr)
|
|
43
|
+
return module.view().slice(publicKeyPtr, publicKeyPtr + keySize)
|
|
44
|
+
} finally {
|
|
45
|
+
module.exports.zero(privateKeyPtr, keySize * 2)
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
getSharedSecret(privateKey, publicKey) {
|
|
49
|
+
assertLength(privateKey, 'private')
|
|
50
|
+
assertLength(publicKey, 'public')
|
|
51
|
+
return x25519.getSharedSecret(module, privateKey, publicKey)
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export declare namespace engine {
|
|
57
|
+
/** Every `X25519` primitive this module implements. */
|
|
58
|
+
type ReturnType = {
|
|
59
|
+
[key in 'getPublicKey' | 'getSharedSecret']-?: NonNullable<Engine.Ecdh[key]>
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
type ErrorType = internal.MemoryError | Errors.GlobalErrorType
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function assertLength(key: Uint8Array, type: 'private' | 'public'): void {
|
|
66
|
+
if (key.length !== keySize)
|
|
67
|
+
throw new RangeError(
|
|
68
|
+
`X25519 ${type} key must be ${keySize} bytes, got ${key.length}`,
|
|
69
|
+
)
|
|
70
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { ed25519, x25519 } from '@noble/curves/ed25519.js'
|
|
2
|
+
import { mnemonicToSeedSync } from '@scure/bip39'
|
|
3
|
+
import { describe, expect, test } from 'vp/test'
|
|
4
|
+
import { vectors } from '../../../test/vectors/bip39/index.js'
|
|
5
|
+
import * as Ed25519 from '../Ed25519.js'
|
|
6
|
+
import * as Mnemonic from '../Mnemonic.js'
|
|
7
|
+
import * as X25519 from '../X25519.js'
|
|
8
|
+
|
|
9
|
+
describe('crypto25519 WASM', () => {
|
|
10
|
+
test('behavior: Ed25519 works in this runtime', async () => {
|
|
11
|
+
const engine = await Ed25519.engine()
|
|
12
|
+
const privateKey = fromHex(
|
|
13
|
+
'9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60',
|
|
14
|
+
)
|
|
15
|
+
const payload = new TextEncoder().encode('browser conformance')
|
|
16
|
+
const publicKey = engine.getPublicKey(privateKey)
|
|
17
|
+
const signature = engine.sign(payload, privateKey)
|
|
18
|
+
|
|
19
|
+
expect(publicKey).toEqual(ed25519.getPublicKey(privateKey))
|
|
20
|
+
expect(signature).toEqual(ed25519.sign(payload, privateKey))
|
|
21
|
+
expect(engine.verify(signature, payload, publicKey)).toBe(true)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test('behavior: X25519 works in this runtime', async () => {
|
|
25
|
+
const engine = await X25519.engine()
|
|
26
|
+
const privateKey = fromHex(
|
|
27
|
+
'77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a',
|
|
28
|
+
)
|
|
29
|
+
const peerPrivateKey = fromHex(
|
|
30
|
+
'5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb',
|
|
31
|
+
)
|
|
32
|
+
const publicKey = x25519.getPublicKey(peerPrivateKey)
|
|
33
|
+
|
|
34
|
+
expect(engine.getPublicKey(privateKey)).toEqual(
|
|
35
|
+
x25519.getPublicKey(privateKey),
|
|
36
|
+
)
|
|
37
|
+
expect(engine.getSharedSecret(privateKey, publicKey)).toEqual(
|
|
38
|
+
x25519.getSharedSecret(privateKey, publicKey),
|
|
39
|
+
)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
test('behavior: Unicode BIP-39 works in this runtime', async () => {
|
|
43
|
+
const engine = await Mnemonic.engine()
|
|
44
|
+
const vector = vectors.japanese
|
|
45
|
+
|
|
46
|
+
expect(engine.toSeed(vector.mnemonic, vector.passphrase)).toEqual(
|
|
47
|
+
mnemonicToSeedSync(vector.mnemonic, vector.passphrase),
|
|
48
|
+
)
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
function fromHex(value: string): Uint8Array {
|
|
53
|
+
const bytes = new Uint8Array(value.length / 2)
|
|
54
|
+
for (let index = 0; index < bytes.length; index++)
|
|
55
|
+
bytes[index] = Number.parseInt(value.slice(index * 2, index * 2 + 2), 16)
|
|
56
|
+
return bytes
|
|
57
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { fc, test } from '@fast-check/vitest'
|
|
2
|
+
import { ed25519, x25519 } from '@noble/curves/ed25519.js'
|
|
3
|
+
import { mnemonicToSeedSync } from '@scure/bip39'
|
|
4
|
+
import { beforeAll, describe, expect } from 'vp/test'
|
|
5
|
+
import { numRuns } from '../../../test/fuzz/numRuns.js'
|
|
6
|
+
import * as Ed25519 from '../Ed25519.js'
|
|
7
|
+
import * as Mnemonic from '../Mnemonic.js'
|
|
8
|
+
import * as X25519 from '../X25519.js'
|
|
9
|
+
import { x25519LowOrder } from './fixtures.js'
|
|
10
|
+
|
|
11
|
+
let ed25519Engine: Ed25519.engine.ReturnType
|
|
12
|
+
let mnemonicEngine: Mnemonic.engine.ReturnType
|
|
13
|
+
let x25519Engine: X25519.engine.ReturnType
|
|
14
|
+
|
|
15
|
+
beforeAll(async () => {
|
|
16
|
+
ed25519Engine = await Ed25519.engine()
|
|
17
|
+
mnemonicEngine = await Mnemonic.engine()
|
|
18
|
+
x25519Engine = await X25519.engine()
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const arbitraryKey = fc.uint8Array({ maxLength: 32, minLength: 32 })
|
|
22
|
+
const arbitraryPayload = fc.oneof(
|
|
23
|
+
fc.uint8Array({ maxLength: 512 }),
|
|
24
|
+
fc
|
|
25
|
+
.constantFrom(0, 1, 31, 32, 63, 64, 65, 127, 128, 129, 1024, 4096)
|
|
26
|
+
.chain((size) => fc.uint8Array({ maxLength: size, minLength: size })),
|
|
27
|
+
)
|
|
28
|
+
const arbitraryWord = fc.oneof(
|
|
29
|
+
fc
|
|
30
|
+
.string({ maxLength: 16, minLength: 1 })
|
|
31
|
+
.filter((value) => !value.normalize('NFKD').includes(' ')),
|
|
32
|
+
fc.constantFrom('café', 'cafe\u0301', 'あおぞら', '㍍ガバヴァ'),
|
|
33
|
+
)
|
|
34
|
+
const arbitraryMnemonic = fc
|
|
35
|
+
.tuple(
|
|
36
|
+
fc.constantFrom(12, 15, 18, 21, 24),
|
|
37
|
+
fc.array(arbitraryWord, { maxLength: 24, minLength: 24 }),
|
|
38
|
+
)
|
|
39
|
+
.map(([count, words]) => words.slice(0, count).join(' '))
|
|
40
|
+
|
|
41
|
+
describe('Ed25519', () => {
|
|
42
|
+
test.prop(
|
|
43
|
+
{ payload: arbitraryPayload, privateKey: arbitraryKey },
|
|
44
|
+
{ numRuns },
|
|
45
|
+
)('matches the default for arbitrary subviews', (options) => {
|
|
46
|
+
const payload = offsetView(options.payload)
|
|
47
|
+
const privateKey = offsetView(options.privateKey)
|
|
48
|
+
const publicKey = ed25519Engine.getPublicKey(privateKey)
|
|
49
|
+
const signature = ed25519Engine.sign(payload, privateKey)
|
|
50
|
+
|
|
51
|
+
expect(publicKey).toEqual(ed25519.getPublicKey(privateKey))
|
|
52
|
+
expect(signature).toEqual(ed25519.sign(payload, privateKey))
|
|
53
|
+
expect(ed25519Engine.verify(signature, payload, publicKey)).toBe(true)
|
|
54
|
+
expect(
|
|
55
|
+
ed25519Engine.verify(signature, Uint8Array.of(...payload, 1), publicKey),
|
|
56
|
+
).toBe(false)
|
|
57
|
+
expect(ed25519Engine.toMontgomerySecret(privateKey)).toEqual(
|
|
58
|
+
ed25519.utils.toMontgomerySecret(privateKey),
|
|
59
|
+
)
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
test.prop(
|
|
63
|
+
{
|
|
64
|
+
payload: arbitraryPayload,
|
|
65
|
+
publicKey: arbitraryKey,
|
|
66
|
+
signature: fc.uint8Array({ maxLength: 64, minLength: 64 }),
|
|
67
|
+
},
|
|
68
|
+
{ numRuns },
|
|
69
|
+
)('verification matches ZIP-215 for arbitrary encodings', (options) => {
|
|
70
|
+
expect(
|
|
71
|
+
ed25519Engine.verify(
|
|
72
|
+
options.signature,
|
|
73
|
+
options.payload,
|
|
74
|
+
options.publicKey,
|
|
75
|
+
),
|
|
76
|
+
).toBe(
|
|
77
|
+
ed25519.verify(options.signature, options.payload, options.publicKey),
|
|
78
|
+
)
|
|
79
|
+
})
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
describe('X25519', () => {
|
|
83
|
+
test.prop(
|
|
84
|
+
{ privateKey: arbitraryKey, publicKeySeed: arbitraryKey },
|
|
85
|
+
{ numRuns },
|
|
86
|
+
)('matches the default for arbitrary subviews', (options) => {
|
|
87
|
+
const privateKey = offsetView(options.privateKey)
|
|
88
|
+
const publicKey = offsetView(x25519.getPublicKey(options.publicKeySeed))
|
|
89
|
+
|
|
90
|
+
expect(x25519Engine.getPublicKey(privateKey)).toEqual(
|
|
91
|
+
x25519.getPublicKey(privateKey),
|
|
92
|
+
)
|
|
93
|
+
expect(x25519Engine.getSharedSecret(privateKey, publicKey)).toEqual(
|
|
94
|
+
x25519.getSharedSecret(privateKey, publicKey),
|
|
95
|
+
)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
test.prop(
|
|
99
|
+
{
|
|
100
|
+
highBit: fc.boolean(),
|
|
101
|
+
privateKey: arbitraryKey,
|
|
102
|
+
vector: fc.constantFrom(...x25519LowOrder),
|
|
103
|
+
},
|
|
104
|
+
{ numRuns },
|
|
105
|
+
)(
|
|
106
|
+
'rejects arbitrary private keys paired with low-order points',
|
|
107
|
+
(options) => {
|
|
108
|
+
const publicKey = fromHex(options.vector.publicKey)
|
|
109
|
+
if (options.highBit) publicKey[31]! |= 0x80
|
|
110
|
+
expect(() =>
|
|
111
|
+
x25519Engine.getSharedSecret(options.privateKey, publicKey),
|
|
112
|
+
).toThrow()
|
|
113
|
+
},
|
|
114
|
+
)
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
describe('Mnemonic', () => {
|
|
118
|
+
test.prop(
|
|
119
|
+
{
|
|
120
|
+
mnemonic: arbitraryMnemonic,
|
|
121
|
+
passphrase: fc.string({ maxLength: 64 }),
|
|
122
|
+
},
|
|
123
|
+
{ numRuns },
|
|
124
|
+
)('matches the default for arbitrary normalized text', (options) => {
|
|
125
|
+
expect(mnemonicEngine.toSeed(options.mnemonic, options.passphrase)).toEqual(
|
|
126
|
+
mnemonicToSeedSync(options.mnemonic, options.passphrase),
|
|
127
|
+
)
|
|
128
|
+
})
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
describe('memory', () => {
|
|
132
|
+
test.prop(
|
|
133
|
+
{
|
|
134
|
+
operations: fc.array(
|
|
135
|
+
fc.record({
|
|
136
|
+
payload: arbitraryPayload,
|
|
137
|
+
privateKey: arbitraryKey,
|
|
138
|
+
publicKeySeed: arbitraryKey,
|
|
139
|
+
}),
|
|
140
|
+
{ maxLength: 8, minLength: 2 },
|
|
141
|
+
),
|
|
142
|
+
},
|
|
143
|
+
{ numRuns },
|
|
144
|
+
)(
|
|
145
|
+
'interleaved providers remain isolated and outputs stay owned',
|
|
146
|
+
(options) => {
|
|
147
|
+
const held: Uint8Array[] = []
|
|
148
|
+
const snapshots: Uint8Array[] = []
|
|
149
|
+
|
|
150
|
+
for (const operation of options.operations) {
|
|
151
|
+
const edPublicKey = ed25519Engine.getPublicKey(operation.privateKey)
|
|
152
|
+
const signature = ed25519Engine.sign(
|
|
153
|
+
operation.payload,
|
|
154
|
+
operation.privateKey,
|
|
155
|
+
)
|
|
156
|
+
const xPublicKey = x25519.getPublicKey(operation.publicKeySeed)
|
|
157
|
+
const sharedSecret = x25519Engine.getSharedSecret(
|
|
158
|
+
operation.privateKey,
|
|
159
|
+
xPublicKey,
|
|
160
|
+
)
|
|
161
|
+
expect(
|
|
162
|
+
ed25519Engine.verify(signature, operation.payload, edPublicKey),
|
|
163
|
+
).toBe(true)
|
|
164
|
+
expect(sharedSecret).toEqual(
|
|
165
|
+
x25519.getSharedSecret(operation.privateKey, xPublicKey),
|
|
166
|
+
)
|
|
167
|
+
held.push(signature, sharedSecret)
|
|
168
|
+
snapshots.push(signature.slice(), sharedSecret.slice())
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
expect(held).toEqual(snapshots)
|
|
172
|
+
},
|
|
173
|
+
)
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
function offsetView(value: Uint8Array): Uint8Array {
|
|
177
|
+
const bytes = new Uint8Array(value.length + 4).fill(0xff)
|
|
178
|
+
bytes.set(value, 2)
|
|
179
|
+
return bytes.subarray(2, -2)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function fromHex(value: string): Uint8Array {
|
|
183
|
+
const bytes = new Uint8Array(value.length / 2)
|
|
184
|
+
for (let index = 0; index < bytes.length; index++)
|
|
185
|
+
bytes[index] = Number.parseInt(value.slice(index * 2, index * 2 + 2), 16)
|
|
186
|
+
return bytes
|
|
187
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { expectTypeOf, test } from 'vp/test'
|
|
2
|
+
import type * as Engine from '../../core/Engine.js'
|
|
3
|
+
import * as core_Ed25519 from '../../core/Ed25519.js'
|
|
4
|
+
import * as Ed25519 from '../Ed25519.js'
|
|
5
|
+
|
|
6
|
+
type Slot = Awaited<ReturnType<typeof Ed25519.engine>>
|
|
7
|
+
|
|
8
|
+
test('return type exposes only implemented Ed25519 primitives', () => {
|
|
9
|
+
expectTypeOf<Slot['getPublicKey']>().toEqualTypeOf<
|
|
10
|
+
NonNullable<Engine.Eddsa['getPublicKey']>
|
|
11
|
+
>()
|
|
12
|
+
expectTypeOf<Slot['sign']>().toEqualTypeOf<
|
|
13
|
+
NonNullable<Engine.Eddsa['sign']>
|
|
14
|
+
>()
|
|
15
|
+
expectTypeOf<Slot['toMontgomerySecret']>().toEqualTypeOf<
|
|
16
|
+
NonNullable<Engine.Eddsa['toMontgomerySecret']>
|
|
17
|
+
>()
|
|
18
|
+
expectTypeOf<Slot['verify']>().toEqualTypeOf<
|
|
19
|
+
NonNullable<Engine.Eddsa['verify']>
|
|
20
|
+
>()
|
|
21
|
+
expectTypeOf<Slot>().not.toHaveProperty('randomSecretKey')
|
|
22
|
+
expectTypeOf<Slot>().not.toHaveProperty('toMontgomery')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test('the WASM namespace exposes the public Ed25519 API', () => {
|
|
26
|
+
expectTypeOf(Ed25519.getPublicKey).toEqualTypeOf(core_Ed25519.getPublicKey)
|
|
27
|
+
expectTypeOf<typeof Ed25519>().not.toHaveProperty('create')
|
|
28
|
+
})
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { ed25519 } from '@noble/curves/ed25519.js'
|
|
2
|
+
import { describe, expect, test } from 'vp/test'
|
|
3
|
+
import * as Ed25519 from '../Ed25519.js'
|
|
4
|
+
import * as crypto25519 from '../internal/crypto25519.js'
|
|
5
|
+
import { wasmBase64 } from '../internal/crypto25519.wasm.js'
|
|
6
|
+
import * as ed25519_internal from '../internal/ed25519.js'
|
|
7
|
+
import * as internal from '../internal/instantiate.js'
|
|
8
|
+
|
|
9
|
+
const privateKey = fromHex(
|
|
10
|
+
'9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60',
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
describe('engine', () => {
|
|
14
|
+
test('behavior: exposes only semantics-compatible primitives', async () => {
|
|
15
|
+
const engine = await Ed25519.engine()
|
|
16
|
+
|
|
17
|
+
expect(Object.keys(engine).sort()).toMatchInlineSnapshot(`
|
|
18
|
+
[
|
|
19
|
+
"getPublicKey",
|
|
20
|
+
"sign",
|
|
21
|
+
"toMontgomerySecret",
|
|
22
|
+
"verify",
|
|
23
|
+
]
|
|
24
|
+
`)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
test('behavior: signs and verifies boundary-sized messages', async () => {
|
|
28
|
+
const engine = await Ed25519.engine()
|
|
29
|
+
|
|
30
|
+
for (const size of [0, 1, 31, 32, 63, 64, 65, 127, 128, 129, 1024]) {
|
|
31
|
+
const payload = Uint8Array.from(
|
|
32
|
+
{ length: size },
|
|
33
|
+
(_, index) => (index * 29 + size) % 251,
|
|
34
|
+
)
|
|
35
|
+
const signature = engine.sign(payload, privateKey)
|
|
36
|
+
const publicKey = engine.getPublicKey(privateKey)
|
|
37
|
+
|
|
38
|
+
expect(signature).toEqual(ed25519.sign(payload, privateKey))
|
|
39
|
+
expect(engine.verify(signature, payload, publicKey)).toBe(true)
|
|
40
|
+
expect(
|
|
41
|
+
engine.verify(signature, Uint8Array.of(...payload, 1), publicKey),
|
|
42
|
+
).toBe(false)
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test('behavior: matches private-key conversion', async () => {
|
|
47
|
+
const engine = await Ed25519.engine()
|
|
48
|
+
|
|
49
|
+
expect(engine.toMontgomerySecret(privateKey)).toEqual(
|
|
50
|
+
ed25519.utils.toMontgomerySecret(privateKey),
|
|
51
|
+
)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('behavior: respects subviews and leaves inputs immutable', async () => {
|
|
55
|
+
const engine = await Ed25519.engine()
|
|
56
|
+
const key = offsetView(privateKey)
|
|
57
|
+
const payload = offsetView(new Uint8Array(257).fill(0xa5))
|
|
58
|
+
const keyBefore = key.slice()
|
|
59
|
+
const payloadBefore = payload.slice()
|
|
60
|
+
const publicKey = offsetView(engine.getPublicKey(key))
|
|
61
|
+
const signature = offsetView(engine.sign(payload, key))
|
|
62
|
+
const publicKeyBefore = publicKey.slice()
|
|
63
|
+
const signatureBefore = signature.slice()
|
|
64
|
+
|
|
65
|
+
expect(engine.getPublicKey(key)).toEqual(ed25519.getPublicKey(key))
|
|
66
|
+
expect(engine.verify(signature, payload, publicKey)).toBe(true)
|
|
67
|
+
expect(engine.toMontgomerySecret(key)).toEqual(
|
|
68
|
+
ed25519.utils.toMontgomerySecret(key),
|
|
69
|
+
)
|
|
70
|
+
expect({ key, payload, publicKey, signature }).toEqual({
|
|
71
|
+
key: keyBefore,
|
|
72
|
+
payload: payloadBefore,
|
|
73
|
+
publicKey: publicKeyBefore,
|
|
74
|
+
signature: signatureBefore,
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
test('behavior: rejects malformed key and signature lengths', async () => {
|
|
79
|
+
const engine = await Ed25519.engine()
|
|
80
|
+
const publicKey = engine.getPublicKey(privateKey)
|
|
81
|
+
|
|
82
|
+
for (const size of [0, 1, 31, 33, 63, 64]) {
|
|
83
|
+
if (size !== 32) {
|
|
84
|
+
expect(() => engine.getPublicKey(new Uint8Array(size))).toThrowError(
|
|
85
|
+
`Ed25519 private key must be 32 bytes, got ${size}`,
|
|
86
|
+
)
|
|
87
|
+
expect(() =>
|
|
88
|
+
engine.sign(new Uint8Array(), new Uint8Array(size)),
|
|
89
|
+
).toThrowError(`Ed25519 private key must be 32 bytes, got ${size}`)
|
|
90
|
+
}
|
|
91
|
+
if (size !== 64)
|
|
92
|
+
expect(() =>
|
|
93
|
+
engine.verify(new Uint8Array(size), new Uint8Array(), publicKey),
|
|
94
|
+
).toThrowError(`Ed25519 signature must be 64 bytes, got ${size}`)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
expect(() =>
|
|
98
|
+
engine.verify(new Uint8Array(64), new Uint8Array(), new Uint8Array(31)),
|
|
99
|
+
).toThrowError('Ed25519 public key must be 32 bytes, got 31')
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
test('behavior: outputs are owned across calls and memory growth', async () => {
|
|
103
|
+
const engine = await Ed25519.engine()
|
|
104
|
+
const publicKey = engine.getPublicKey(privateKey)
|
|
105
|
+
const signature = engine.sign(new Uint8Array(), privateKey)
|
|
106
|
+
const snapshots = [publicKey.slice(), signature.slice()]
|
|
107
|
+
|
|
108
|
+
engine.sign(new Uint8Array(1024 * 1024).fill(0x5a), privateKey)
|
|
109
|
+
|
|
110
|
+
expect([publicKey, signature]).toEqual(snapshots)
|
|
111
|
+
expect(engine.getPublicKey(privateKey) === publicKey).toBe(false)
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
test('behavior: clears the shared staging region', async () => {
|
|
115
|
+
const engine = await Ed25519.engine()
|
|
116
|
+
const payload = new Uint8Array(1024).fill(0xa5)
|
|
117
|
+
engine.sign(payload, privateKey)
|
|
118
|
+
|
|
119
|
+
const module = await crypto25519.load()
|
|
120
|
+
const size = 32 + payload.length + 64
|
|
121
|
+
expect(
|
|
122
|
+
module
|
|
123
|
+
.view()
|
|
124
|
+
.subarray(module.heapBase, module.heapBase + size)
|
|
125
|
+
.every((byte) => byte === 0),
|
|
126
|
+
).toBe(true)
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
test('behavior: clears the complete region after a late trap', async () => {
|
|
130
|
+
const module = await internal.instantiate<crypto25519.Exports>(wasmBase64)
|
|
131
|
+
const payload = new Uint8Array(1024).fill(0xa5)
|
|
132
|
+
const exports: crypto25519.Exports = {
|
|
133
|
+
...module.exports,
|
|
134
|
+
ed25519_sign(...parameters) {
|
|
135
|
+
module.exports.ed25519_sign(...parameters)
|
|
136
|
+
throw new WebAssembly.RuntimeError('forced late trap')
|
|
137
|
+
},
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
expect(() =>
|
|
141
|
+
ed25519_internal.sign({ ...module, exports }, payload, privateKey),
|
|
142
|
+
).toThrow(WebAssembly.RuntimeError)
|
|
143
|
+
expect(
|
|
144
|
+
module
|
|
145
|
+
.view()
|
|
146
|
+
.subarray(module.heapBase, module.heapBase + 32 + payload.length + 64)
|
|
147
|
+
.every((byte) => byte === 0),
|
|
148
|
+
).toBe(true)
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
test('behavior: rejects a workspace beyond wasm32 without growing', async () => {
|
|
152
|
+
const module = await internal.instantiate<crypto25519.Exports>(wasmBase64)
|
|
153
|
+
const memory = module.view().length
|
|
154
|
+
|
|
155
|
+
expect(() => module.reserve(0x1_0000_0000)).toThrow(internal.MemoryError)
|
|
156
|
+
expect(module.view()).toHaveLength(memory)
|
|
157
|
+
})
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
function fromHex(value: string): Uint8Array {
|
|
161
|
+
return Uint8Array.from(Buffer.from(value, 'hex'))
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function offsetView(value: Uint8Array): Uint8Array {
|
|
165
|
+
const bytes = new Uint8Array(value.length + 4).fill(0xff)
|
|
166
|
+
bytes.set(value, 2)
|
|
167
|
+
return bytes.subarray(2, -2)
|
|
168
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import * as fs from 'node:fs'
|
|
2
|
+
import { describe, expect, test } from 'vp/test'
|
|
3
|
+
import * as Ed25519 from '../Ed25519.js'
|
|
4
|
+
|
|
5
|
+
type Zip215Vector = {
|
|
6
|
+
sig_bytes: string
|
|
7
|
+
valid_legacy: boolean
|
|
8
|
+
valid_zip215: boolean
|
|
9
|
+
vk_bytes: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const zip215 = JSON.parse(
|
|
13
|
+
fs.readFileSync(
|
|
14
|
+
new URL('../../../test/vectors/ed25519/zip215.json', import.meta.url),
|
|
15
|
+
'utf8',
|
|
16
|
+
),
|
|
17
|
+
) as readonly Zip215Vector[]
|
|
18
|
+
|
|
19
|
+
const rfc8032 = [
|
|
20
|
+
{
|
|
21
|
+
message: '',
|
|
22
|
+
publicKey:
|
|
23
|
+
'd75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a',
|
|
24
|
+
seed: '9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60',
|
|
25
|
+
signature:
|
|
26
|
+
'e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
message: '72',
|
|
30
|
+
publicKey:
|
|
31
|
+
'3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c',
|
|
32
|
+
seed: '4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb',
|
|
33
|
+
signature:
|
|
34
|
+
'92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00',
|
|
35
|
+
},
|
|
36
|
+
] as const
|
|
37
|
+
|
|
38
|
+
describe('engine', () => {
|
|
39
|
+
test('vectors: matches RFC 8032 key, signature, and verification cases', async () => {
|
|
40
|
+
const engine = await Ed25519.engine()
|
|
41
|
+
|
|
42
|
+
for (const vector of rfc8032) {
|
|
43
|
+
const seed = fromHex(vector.seed)
|
|
44
|
+
const message = fromHex(vector.message)
|
|
45
|
+
const publicKey = fromHex(vector.publicKey)
|
|
46
|
+
const signature = fromHex(vector.signature)
|
|
47
|
+
|
|
48
|
+
expect(engine.getPublicKey(seed)).toEqual(publicKey)
|
|
49
|
+
expect(engine.sign(message, seed)).toEqual(signature)
|
|
50
|
+
expect(engine.verify(signature, message, publicKey)).toBe(true)
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('vectors: matches all 196 ZIP-215 compliance cases', async () => {
|
|
55
|
+
const engine = await Ed25519.engine()
|
|
56
|
+
const message = new TextEncoder().encode('Zcash')
|
|
57
|
+
|
|
58
|
+
expect(zip215).toHaveLength(196)
|
|
59
|
+
for (const vector of zip215)
|
|
60
|
+
expect(
|
|
61
|
+
engine.verify(
|
|
62
|
+
fromHex(vector.sig_bytes),
|
|
63
|
+
message,
|
|
64
|
+
fromHex(vector.vk_bytes),
|
|
65
|
+
),
|
|
66
|
+
JSON.stringify(vector),
|
|
67
|
+
).toBe(vector.valid_zip215)
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
function fromHex(value: string): Uint8Array {
|
|
72
|
+
return Uint8Array.from(Buffer.from(value, 'hex'))
|
|
73
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Engine } from 'ox/wasm'
|
|
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 WASM 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
|
+
})
|