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,248 @@
|
|
|
1
|
+
import type * as Engine from '../core/Engine.js'
|
|
2
|
+
import * as Errors from '../core/Errors.js'
|
|
3
|
+
import * as internal from './internal/instantiate.js'
|
|
4
|
+
import * as secp256k1 from './internal/secp256k1.js'
|
|
5
|
+
|
|
6
|
+
export * from '../core/Secp256k1.js'
|
|
7
|
+
export { MemoryError } from './internal/instantiate.js'
|
|
8
|
+
|
|
9
|
+
const privateKeySize = 32
|
|
10
|
+
const publicKeySize = 65
|
|
11
|
+
const sharedSecretSize = 33
|
|
12
|
+
const compactSignatureSize = 64
|
|
13
|
+
const recoveredSignatureSize = 65
|
|
14
|
+
const maxRawMessageSize = 8192
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Compiles WASM implementations of deterministic
|
|
18
|
+
* [`Secp256k1`](/api/Secp256k1) primitives, without installing them.
|
|
19
|
+
*
|
|
20
|
+
* Random key generation remains on Ox's host-backed default implementation.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts twoslash
|
|
24
|
+
* // @noErrors
|
|
25
|
+
* import { Engine } from 'ox'
|
|
26
|
+
* import { Secp256k1 } from 'ox/wasm'
|
|
27
|
+
*
|
|
28
|
+
* await Engine.install({ Secp256k1: Secp256k1.engine() })
|
|
29
|
+
*
|
|
30
|
+
* Secp256k1.getPublicKey({ privateKey: '0x...' })
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @returns The WASM implementation of the deterministic `Secp256k1` primitives.
|
|
34
|
+
*/
|
|
35
|
+
export async function engine(): Promise<engine.ReturnType> {
|
|
36
|
+
const module = await secp256k1.load()
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
getPublicKey(privateKey) {
|
|
40
|
+
assertLength(privateKey, privateKeySize, 'private key')
|
|
41
|
+
const size = privateKeySize + publicKeySize
|
|
42
|
+
module.reserve(size)
|
|
43
|
+
const privateKeyPtr = module.heapBase
|
|
44
|
+
const publicKeyPtr = privateKeyPtr + privateKeySize
|
|
45
|
+
try {
|
|
46
|
+
module.view().set(privateKey, privateKeyPtr)
|
|
47
|
+
if (
|
|
48
|
+
module.exports.secp256k1_get_public_key(
|
|
49
|
+
privateKeyPtr,
|
|
50
|
+
publicKeyPtr,
|
|
51
|
+
) !== 1
|
|
52
|
+
)
|
|
53
|
+
throw new InvalidInputError({ operation: 'getPublicKey' })
|
|
54
|
+
return module.view().slice(publicKeyPtr, publicKeyPtr + publicKeySize)
|
|
55
|
+
} finally {
|
|
56
|
+
module.exports.zero(privateKeyPtr, size)
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
getSharedSecret(privateKey, publicKey) {
|
|
60
|
+
assertLength(privateKey, privateKeySize, 'private key')
|
|
61
|
+
assertPublicKeyLength(publicKey)
|
|
62
|
+
const size = privateKeySize + publicKey.length + sharedSecretSize
|
|
63
|
+
module.reserve(size)
|
|
64
|
+
const privateKeyPtr = module.heapBase
|
|
65
|
+
const publicKeyPtr = privateKeyPtr + privateKeySize
|
|
66
|
+
const sharedSecretPtr = publicKeyPtr + publicKey.length
|
|
67
|
+
try {
|
|
68
|
+
const memory = module.view()
|
|
69
|
+
memory.set(privateKey, privateKeyPtr)
|
|
70
|
+
memory.set(publicKey, publicKeyPtr)
|
|
71
|
+
if (
|
|
72
|
+
module.exports.secp256k1_get_shared_secret(
|
|
73
|
+
privateKeyPtr,
|
|
74
|
+
publicKeyPtr,
|
|
75
|
+
publicKey.length,
|
|
76
|
+
sharedSecretPtr,
|
|
77
|
+
) !== 1
|
|
78
|
+
)
|
|
79
|
+
throw new InvalidInputError({ operation: 'getSharedSecret' })
|
|
80
|
+
return module
|
|
81
|
+
.view()
|
|
82
|
+
.slice(sharedSecretPtr, sharedSecretPtr + sharedSecretSize)
|
|
83
|
+
} finally {
|
|
84
|
+
module.exports.zero(privateKeyPtr, size)
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
recoverPublicKey(signature, payload) {
|
|
88
|
+
assertLength(signature, recoveredSignatureSize, 'signature')
|
|
89
|
+
assertRawMessageLength(payload)
|
|
90
|
+
const size = recoveredSignatureSize + payload.length + publicKeySize
|
|
91
|
+
module.reserve(size)
|
|
92
|
+
const signaturePtr = module.heapBase
|
|
93
|
+
const payloadPtr = signaturePtr + recoveredSignatureSize
|
|
94
|
+
const publicKeyPtr = payloadPtr + payload.length
|
|
95
|
+
try {
|
|
96
|
+
const memory = module.view()
|
|
97
|
+
memory.set(signature, signaturePtr)
|
|
98
|
+
memory.set(payload, payloadPtr)
|
|
99
|
+
if (
|
|
100
|
+
module.exports.secp256k1_recover_public_key(
|
|
101
|
+
signaturePtr,
|
|
102
|
+
payloadPtr,
|
|
103
|
+
payload.length,
|
|
104
|
+
publicKeyPtr,
|
|
105
|
+
) !== 1
|
|
106
|
+
)
|
|
107
|
+
throw new InvalidInputError({ operation: 'recoverPublicKey' })
|
|
108
|
+
return module.view().slice(publicKeyPtr, publicKeyPtr + publicKeySize)
|
|
109
|
+
} finally {
|
|
110
|
+
module.exports.zero(signaturePtr, size)
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
sign(payload, privateKey, options) {
|
|
114
|
+
assertLength(privateKey, privateKeySize, 'private key')
|
|
115
|
+
if (!options.prehash) assertRawMessageLength(payload)
|
|
116
|
+
const entropy =
|
|
117
|
+
options.extraEntropy === true
|
|
118
|
+
? crypto.getRandomValues(new Uint8Array(privateKeySize))
|
|
119
|
+
: options.extraEntropy === false
|
|
120
|
+
? undefined
|
|
121
|
+
: options.extraEntropy
|
|
122
|
+
const entropySize = entropy?.length ?? 0
|
|
123
|
+
const size =
|
|
124
|
+
payload.length + privateKeySize + entropySize + recoveredSignatureSize
|
|
125
|
+
module.reserve(size)
|
|
126
|
+
const payloadPtr = module.heapBase
|
|
127
|
+
const privateKeyPtr = payloadPtr + payload.length
|
|
128
|
+
const entropyPtr = entropy ? privateKeyPtr + privateKeySize : 0
|
|
129
|
+
const signaturePtr = privateKeyPtr + privateKeySize + entropySize
|
|
130
|
+
try {
|
|
131
|
+
const memory = module.view()
|
|
132
|
+
memory.set(payload, payloadPtr)
|
|
133
|
+
memory.set(privateKey, privateKeyPtr)
|
|
134
|
+
if (entropy) memory.set(entropy, entropyPtr)
|
|
135
|
+
if (
|
|
136
|
+
module.exports.secp256k1_sign(
|
|
137
|
+
payloadPtr,
|
|
138
|
+
payload.length,
|
|
139
|
+
privateKeyPtr,
|
|
140
|
+
entropyPtr,
|
|
141
|
+
entropySize,
|
|
142
|
+
Number(options.prehash),
|
|
143
|
+
signaturePtr,
|
|
144
|
+
) !== 1
|
|
145
|
+
)
|
|
146
|
+
throw new InvalidInputError({ operation: 'sign' })
|
|
147
|
+
return module
|
|
148
|
+
.view()
|
|
149
|
+
.slice(signaturePtr, signaturePtr + recoveredSignatureSize)
|
|
150
|
+
} finally {
|
|
151
|
+
module.exports.zero(payloadPtr, size)
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
verify(signature, payload, publicKey, options) {
|
|
155
|
+
assertLength(signature, compactSignatureSize, 'signature')
|
|
156
|
+
assertPublicKeyLength(publicKey)
|
|
157
|
+
if (!options.prehash && payload.length > maxRawMessageSize) return false
|
|
158
|
+
const size = compactSignatureSize + payload.length + publicKey.length
|
|
159
|
+
module.reserve(size)
|
|
160
|
+
const signaturePtr = module.heapBase
|
|
161
|
+
const payloadPtr = signaturePtr + compactSignatureSize
|
|
162
|
+
const publicKeyPtr = payloadPtr + payload.length
|
|
163
|
+
try {
|
|
164
|
+
const memory = module.view()
|
|
165
|
+
memory.set(signature, signaturePtr)
|
|
166
|
+
memory.set(payload, payloadPtr)
|
|
167
|
+
memory.set(publicKey, publicKeyPtr)
|
|
168
|
+
return (
|
|
169
|
+
module.exports.secp256k1_verify(
|
|
170
|
+
signaturePtr,
|
|
171
|
+
payloadPtr,
|
|
172
|
+
payload.length,
|
|
173
|
+
publicKeyPtr,
|
|
174
|
+
publicKey.length,
|
|
175
|
+
Number(options.prehash),
|
|
176
|
+
) === 1
|
|
177
|
+
)
|
|
178
|
+
} finally {
|
|
179
|
+
module.exports.zero(signaturePtr, size)
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export declare namespace engine {
|
|
186
|
+
/** Every `Secp256k1` primitive this module implements. */
|
|
187
|
+
type ReturnType = {
|
|
188
|
+
[key in
|
|
189
|
+
| 'getPublicKey'
|
|
190
|
+
| 'getSharedSecret'
|
|
191
|
+
| 'recoverPublicKey'
|
|
192
|
+
| 'sign'
|
|
193
|
+
| 'verify']-?: NonNullable<Engine.Ecdsa[key]>
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
type ErrorType =
|
|
197
|
+
| InvalidInputError
|
|
198
|
+
| internal.MemoryError
|
|
199
|
+
| Errors.GlobalErrorType
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function assertLength(value: Uint8Array, length: number, name: string): void {
|
|
203
|
+
if (value.length !== length)
|
|
204
|
+
throw new RangeError(
|
|
205
|
+
`Secp256k1 ${name} must be ${length} bytes, got ${value.length}`,
|
|
206
|
+
)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function assertPublicKeyLength(publicKey: Uint8Array): void {
|
|
210
|
+
if (
|
|
211
|
+
publicKey.length !== sharedSecretSize &&
|
|
212
|
+
publicKey.length !== publicKeySize
|
|
213
|
+
)
|
|
214
|
+
throw new RangeError(
|
|
215
|
+
`Secp256k1 public key must be 33 or 65 bytes, got ${publicKey.length}`,
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function assertRawMessageLength(payload: Uint8Array): void {
|
|
220
|
+
if (payload.length > maxRawMessageSize)
|
|
221
|
+
throw new RangeError(
|
|
222
|
+
`Secp256k1 unhashed payload must not exceed ${maxRawMessageSize} bytes, got ${payload.length}`,
|
|
223
|
+
)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Thrown when libsecp256k1 rejects a key or recovered signature.
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* ```ts twoslash
|
|
231
|
+
* import { Secp256k1 } from 'ox/wasm'
|
|
232
|
+
*
|
|
233
|
+
* try {
|
|
234
|
+
* const engine = await Secp256k1.engine()
|
|
235
|
+
* engine.getPublicKey(new Uint8Array(32))
|
|
236
|
+
* } catch (error) {
|
|
237
|
+
* if (error instanceof Secp256k1.InvalidInputError)
|
|
238
|
+
* console.error(error.message)
|
|
239
|
+
* }
|
|
240
|
+
* ```
|
|
241
|
+
*/
|
|
242
|
+
export class InvalidInputError extends Errors.BaseError {
|
|
243
|
+
override readonly name = 'Secp256k1.InvalidInputError'
|
|
244
|
+
|
|
245
|
+
constructor({ operation }: { operation: string }) {
|
|
246
|
+
super(`WASM secp256k1 ${operation} received invalid input.`)
|
|
247
|
+
}
|
|
248
|
+
}
|
|
@@ -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
|
+
})
|