ox 1.2.0 → 1.3.1
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 +40 -0
- package/dist/core/AbiFunction.d.ts +1 -1
- package/dist/core/AbiFunction.d.ts.map +1 -1
- package/dist/core/AbiFunction.js +6 -2
- package/dist/core/AbiFunction.js.map +1 -1
- package/dist/core/AbiParameters.d.ts +1 -1
- package/dist/core/AbiParameters.d.ts.map +1 -1
- package/dist/core/AbiParameters.js +1 -13
- package/dist/core/AbiParameters.js.map +1 -1
- package/dist/core/AesGcm.d.ts +36 -1
- package/dist/core/AesGcm.d.ts.map +1 -1
- package/dist/core/AesGcm.js +44 -0
- package/dist/core/AesGcm.js.map +1 -1
- package/dist/core/Ed25519.d.ts +46 -1
- package/dist/core/Ed25519.d.ts.map +1 -1
- package/dist/core/Ed25519.js +43 -0
- package/dist/core/Ed25519.js.map +1 -1
- package/dist/core/Engine.d.ts +1 -1
- package/dist/core/Engine.d.ts.map +1 -1
- package/dist/core/Engine.js.map +1 -1
- package/dist/core/Hash.d.ts +164 -1
- package/dist/core/Hash.d.ts.map +1 -1
- package/dist/core/Hash.js +172 -0
- package/dist/core/Hash.js.map +1 -1
- package/dist/core/Hex.d.ts.map +1 -1
- package/dist/core/Hex.js +1 -4
- package/dist/core/Hex.js.map +1 -1
- package/dist/core/Rlp.d.ts +32 -0
- package/dist/core/Rlp.d.ts.map +1 -1
- package/dist/core/Rlp.js +146 -0
- package/dist/core/Rlp.js.map +1 -1
- package/dist/core/Secp256k1.d.ts +46 -1
- package/dist/core/Secp256k1.d.ts.map +1 -1
- package/dist/core/Secp256k1.js +48 -0
- package/dist/core/Secp256k1.js.map +1 -1
- package/dist/core/WebAuthn.d.ts +224 -0
- package/dist/core/WebAuthn.d.ts.map +1 -0
- package/dist/core/WebAuthn.js +343 -0
- package/dist/core/WebAuthn.js.map +1 -0
- package/dist/core/WebAuthnP256.d.ts +46 -50
- package/dist/core/WebAuthnP256.d.ts.map +1 -1
- package/dist/core/WebAuthnP256.js +44 -50
- package/dist/core/WebAuthnP256.js.map +1 -1
- package/dist/core/internal/abiParameters.d.ts +7 -87
- package/dist/core/internal/abiParameters.d.ts.map +1 -1
- package/dist/core/internal/abiParameters.js +339 -194
- package/dist/core/internal/abiParameters.js.map +1 -1
- package/dist/core/internal/engine.d.ts +35 -2
- package/dist/core/internal/engine.d.ts.map +1 -1
- package/dist/core/internal/engine.js +12 -1
- package/dist/core/internal/engine.js.map +1 -1
- package/dist/core/internal/hash.d.ts +10 -0
- package/dist/core/internal/hash.d.ts.map +1 -1
- package/dist/core/internal/hash.js +26 -1
- package/dist/core/internal/hash.js.map +1 -1
- package/dist/index.d.ts +23 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -14
- package/dist/index.js.map +1 -1
- package/dist/node/Engine.d.ts +1 -1
- package/dist/node/Engine.d.ts.map +1 -1
- package/dist/node/Engine.js.map +1 -1
- package/dist/node/Hash.d.ts +6 -4
- package/dist/node/Hash.d.ts.map +1 -1
- package/dist/node/Hash.js +35 -3
- package/dist/node/Hash.js.map +1 -1
- package/dist/tempo/AuthorizationTempo.d.ts +6 -6
- package/dist/tempo/AuthorizationTempo.js +6 -6
- package/dist/tempo/KeyAuthorization.d.ts +3 -8
- package/dist/tempo/KeyAuthorization.d.ts.map +1 -1
- package/dist/tempo/KeyAuthorization.js +3 -8
- package/dist/tempo/KeyAuthorization.js.map +1 -1
- package/dist/tempo/SignatureEnvelope.d.ts +8 -8
- package/dist/tempo/SignatureEnvelope.js +8 -8
- package/dist/wasm/Engine.d.ts +1 -1
- package/dist/wasm/Engine.d.ts.map +1 -1
- package/dist/wasm/Engine.js.map +1 -1
- package/dist/wasm/Hash.d.ts +1 -1
- package/dist/wasm/Hash.d.ts.map +1 -1
- package/dist/wasm/Hash.js +5 -0
- package/dist/wasm/Hash.js.map +1 -1
- package/dist/wasm/internal/blake3.d.ts +10 -1
- package/dist/wasm/internal/blake3.d.ts.map +1 -1
- package/dist/wasm/internal/blake3.js +12 -1
- package/dist/wasm/internal/blake3.js.map +1 -1
- package/dist/wasm/internal/blake3.wasm.d.ts +3 -1
- package/dist/wasm/internal/blake3.wasm.d.ts.map +1 -1
- package/dist/wasm/internal/blake3.wasm.js +3 -1
- package/dist/wasm/internal/blake3.wasm.js.map +1 -1
- package/dist/wasm/internal/hash.d.ts +9 -0
- package/dist/wasm/internal/hash.d.ts.map +1 -1
- package/dist/wasm/internal/hash.js +13 -1
- package/dist/wasm/internal/hash.js.map +1 -1
- package/dist/wasm/internal/hashState.d.ts +25 -0
- package/dist/wasm/internal/hashState.d.ts.map +1 -0
- package/dist/wasm/internal/hashState.js +105 -0
- package/dist/wasm/internal/hashState.js.map +1 -0
- package/dist/wasm/internal/hashes.d.ts +12 -1
- package/dist/wasm/internal/hashes.d.ts.map +1 -1
- package/dist/wasm/internal/hashes.js +18 -1
- package/dist/wasm/internal/hashes.js.map +1 -1
- package/dist/wasm/internal/hashes.wasm.d.ts +11 -3
- package/dist/wasm/internal/hashes.wasm.d.ts.map +1 -1
- package/dist/wasm/internal/hashes.wasm.js +11 -3
- package/dist/wasm/internal/hashes.wasm.js.map +1 -1
- package/dist/webauthn/Authentication.d.ts +2 -0
- package/dist/webauthn/Authentication.d.ts.map +1 -1
- package/dist/webauthn/Authentication.js +2 -1
- package/dist/webauthn/Authentication.js.map +1 -1
- package/dist/webauthn/Registration.d.ts.map +1 -1
- package/dist/webauthn/Registration.js +2 -1
- package/dist/webauthn/Registration.js.map +1 -1
- package/dist/webauthn/Types.d.ts +27 -6
- package/dist/webauthn/Types.d.ts.map +1 -1
- package/dist/webauthn/internal/utils.d.ts.map +1 -1
- package/dist/webauthn/internal/utils.js +35 -9
- package/dist/webauthn/internal/utils.js.map +1 -1
- package/dist/zod/TypedData.d.ts +2 -2
- package/package.json +13 -1
- package/src/benchmarks/Ox.bench.ts +6 -0
- package/src/benchmarks/OxNode.bench.ts +8 -0
- package/src/benchmarks/OxV0.bench.ts +4 -0
- package/src/benchmarks/OxWasm.bench.ts +22 -0
- package/src/core/AbiFunction.ts +5 -5
- package/src/core/AbiParameters.ts +8 -20
- package/src/core/AesGcm.ts +86 -1
- package/src/core/Ed25519.ts +87 -1
- package/src/core/Engine.ts +1 -0
- package/src/core/Hash.ts +262 -1
- package/src/core/Hex.ts +1 -4
- package/src/core/Rlp.ts +172 -5
- package/src/core/Secp256k1.ts +92 -1
- package/src/core/WebAuthn.ts +579 -0
- package/src/core/WebAuthnP256.ts +47 -50
- package/src/core/_test/AbiFunction.test.ts +9 -0
- package/src/core/_test/AbiParameters.differential.fuzz.ts +156 -0
- package/src/core/_test/AbiParameters.encode.test.ts +22 -0
- package/src/core/_test/AbiParameters.fuzz.ts +4 -0
- package/src/core/_test/AesGcm.test.ts +76 -0
- package/src/core/_test/Ed25519.test-d.ts +13 -1
- package/src/core/_test/Ed25519.test.ts +120 -1
- package/src/core/_test/Engine.test-d.ts +9 -0
- package/src/core/_test/Engine.test.ts +1 -1
- package/src/core/_test/Hash.test-d.ts +23 -0
- package/src/core/_test/Hash.test.ts +179 -1
- package/src/core/_test/Hex.test.ts +2 -0
- package/src/core/_test/Rlp.test-d.ts +18 -0
- package/src/core/_test/Rlp.test.ts +109 -0
- package/src/core/_test/Secp256k1.test-d.ts +14 -0
- package/src/core/_test/Secp256k1.test.ts +91 -1
- package/src/core/_test/WebAuthn.test-d.ts +142 -0
- package/src/core/_test/WebAuthn.test.ts +766 -0
- package/src/core/_test/index.test.ts +1 -0
- package/src/core/internal/abiParameters.ts +466 -326
- package/src/core/internal/engine.ts +47 -2
- package/src/core/internal/hash.ts +53 -1
- package/src/index.ts +24 -14
- package/src/node/Engine.ts +1 -0
- package/src/node/Hash.ts +43 -6
- package/src/node/_test/Engine.test-d.ts +1 -0
- package/src/node/_test/Engine.test.ts +2 -0
- package/src/node/_test/Hash.test-d.ts +10 -0
- package/src/node/_test/Hash.test.ts +46 -0
- package/src/tempo/AuthorizationTempo.ts +6 -6
- package/src/tempo/KeyAuthorization.ts +3 -8
- package/src/tempo/SignatureEnvelope.ts +8 -8
- package/src/version.ts +1 -1
- package/src/wasm/Engine.ts +1 -0
- package/src/wasm/Hash.ts +10 -0
- package/src/wasm/_test/Engine.test-d.ts +1 -0
- package/src/wasm/_test/Engine.test.ts +5 -0
- package/src/wasm/_test/Hash.browser.test.ts +28 -0
- package/src/wasm/_test/Hash.test-d.ts +16 -0
- package/src/wasm/_test/Hash.test.ts +250 -1
- package/src/wasm/internal/blake3.ts +23 -2
- package/src/wasm/internal/blake3.wasm.ts +4 -1
- package/src/wasm/internal/hash.ts +27 -1
- package/src/wasm/internal/hashState.ts +154 -0
- package/src/wasm/internal/hashes.ts +56 -15
- package/src/wasm/internal/hashes.wasm.ts +15 -3
- package/src/webauthn/Authentication.ts +4 -0
- package/src/webauthn/Registration.ts +2 -0
- package/src/webauthn/Types.ts +32 -2
- package/src/webauthn/_test/Authentication.test.ts +123 -1
- package/src/webauthn/_test/Registration.test.ts +26 -6
- package/src/webauthn/_test/WebAuthn.browser.test.ts +28 -0
- package/src/webauthn/internal/utils.ts +41 -8
|
@@ -19,13 +19,47 @@
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
22
|
+
* Mutable hash state.
|
|
23
|
+
*
|
|
24
|
+
* `digestInto` consumes the state. `destroy` is idempotent, and no other method
|
|
25
|
+
* may be called after the state is consumed or destroyed.
|
|
26
|
+
*
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
export type HashState = {
|
|
30
|
+
/** Clones the current state. */
|
|
31
|
+
clone(): HashState
|
|
32
|
+
/** Destroys the state. */
|
|
33
|
+
destroy(): void
|
|
34
|
+
/**
|
|
35
|
+
* Finalizes into `output` and consumes the state.
|
|
36
|
+
*
|
|
37
|
+
* A short output throws without consuming the state. A longer output keeps
|
|
38
|
+
* bytes after the digest unchanged.
|
|
39
|
+
*/
|
|
40
|
+
digestInto(output: Uint8Array): void
|
|
41
|
+
/** Absorbs a message chunk. */
|
|
42
|
+
update(input: Uint8Array): void
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Hash primitives. Synchronous, bytes in / bytes out.
|
|
23
47
|
*
|
|
24
48
|
* @internal
|
|
25
49
|
*/
|
|
26
50
|
export type Hash = {
|
|
27
51
|
/** BLAKE3, 32-byte digest. */
|
|
28
52
|
blake3?: ((input: Uint8Array) => Uint8Array) | undefined
|
|
53
|
+
/** Creates a BLAKE3 state. */
|
|
54
|
+
createBlake3?: (() => HashState) | undefined
|
|
55
|
+
/** Creates an HMAC-SHA256 state. */
|
|
56
|
+
createHmacSha256?: ((key: Uint8Array) => HashState) | undefined
|
|
57
|
+
/** Creates a Keccak256 state. */
|
|
58
|
+
createKeccak256?: (() => HashState) | undefined
|
|
59
|
+
/** Creates a RIPEMD-160 state. */
|
|
60
|
+
createRipemd160?: (() => HashState) | undefined
|
|
61
|
+
/** Creates a SHA-256 state. */
|
|
62
|
+
createSha256?: (() => HashState) | undefined
|
|
29
63
|
/** HMAC-SHA256. */
|
|
30
64
|
hmacSha256?:
|
|
31
65
|
| ((key: Uint8Array, message: Uint8Array) => Uint8Array)
|
|
@@ -331,7 +365,18 @@ export const primitives = {
|
|
|
331
365
|
'toMontgomerySecret',
|
|
332
366
|
'verify',
|
|
333
367
|
],
|
|
334
|
-
Hash: [
|
|
368
|
+
Hash: [
|
|
369
|
+
'blake3',
|
|
370
|
+
'createBlake3',
|
|
371
|
+
'createHmacSha256',
|
|
372
|
+
'createKeccak256',
|
|
373
|
+
'createRipemd160',
|
|
374
|
+
'createSha256',
|
|
375
|
+
'hmacSha256',
|
|
376
|
+
'keccak256',
|
|
377
|
+
'ripemd160',
|
|
378
|
+
'sha256',
|
|
379
|
+
],
|
|
335
380
|
Keystore: [
|
|
336
381
|
'aesCtrDecrypt',
|
|
337
382
|
'aesCtrEncrypt',
|
|
@@ -3,7 +3,13 @@ import { hmac } from '@noble/hashes/hmac.js'
|
|
|
3
3
|
import { ripemd160 as noble_ripemd160 } from '@noble/hashes/legacy.js'
|
|
4
4
|
import { sha256 as noble_sha256 } from '@noble/hashes/sha2.js'
|
|
5
5
|
import { keccak_256 as noble_keccak256 } from '@noble/hashes/sha3.js'
|
|
6
|
-
import
|
|
6
|
+
import type { Hash as NobleHash } from '@noble/hashes/utils.js'
|
|
7
|
+
import {
|
|
8
|
+
type Complete,
|
|
9
|
+
type Hash,
|
|
10
|
+
type HashState,
|
|
11
|
+
overrides,
|
|
12
|
+
} from './engine.js'
|
|
7
13
|
|
|
8
14
|
/**
|
|
9
15
|
* Resolvers for the `Hash` slot, and ox's defaults for it, backed by
|
|
@@ -16,6 +22,21 @@ import { type Complete, type Hash, overrides } from './engine.js'
|
|
|
16
22
|
|
|
17
23
|
const blake3Default: Complete<Hash>['blake3'] = (input) => noble_blake3(input)
|
|
18
24
|
|
|
25
|
+
const createBlake3Default: Complete<Hash>['createBlake3'] = () =>
|
|
26
|
+
fromNoble(noble_blake3.create())
|
|
27
|
+
|
|
28
|
+
const createHmacSha256Default: Complete<Hash>['createHmacSha256'] = (key) =>
|
|
29
|
+
fromNoble(hmac.create(noble_sha256, key))
|
|
30
|
+
|
|
31
|
+
const createKeccak256Default: Complete<Hash>['createKeccak256'] = () =>
|
|
32
|
+
fromNoble(noble_keccak256.create())
|
|
33
|
+
|
|
34
|
+
const createRipemd160Default: Complete<Hash>['createRipemd160'] = () =>
|
|
35
|
+
fromNoble(noble_ripemd160.create())
|
|
36
|
+
|
|
37
|
+
const createSha256Default: Complete<Hash>['createSha256'] = () =>
|
|
38
|
+
fromNoble(noble_sha256.create())
|
|
39
|
+
|
|
19
40
|
const hmacSha256Default: Complete<Hash>['hmacSha256'] = (key, message) =>
|
|
20
41
|
hmac(noble_sha256, key, message)
|
|
21
42
|
|
|
@@ -31,6 +52,26 @@ const sha256Default: Complete<Hash>['sha256'] = (input) => noble_sha256(input)
|
|
|
31
52
|
export const blake3: Complete<Hash>['blake3'] = (input) =>
|
|
32
53
|
(overrides.Hash?.blake3 ?? blake3Default)(input)
|
|
33
54
|
|
|
55
|
+
/** @internal */
|
|
56
|
+
export const createBlake3: Complete<Hash>['createBlake3'] = () =>
|
|
57
|
+
(overrides.Hash?.createBlake3 ?? createBlake3Default)()
|
|
58
|
+
|
|
59
|
+
/** @internal */
|
|
60
|
+
export const createHmacSha256: Complete<Hash>['createHmacSha256'] = (key) =>
|
|
61
|
+
(overrides.Hash?.createHmacSha256 ?? createHmacSha256Default)(key)
|
|
62
|
+
|
|
63
|
+
/** @internal */
|
|
64
|
+
export const createKeccak256: Complete<Hash>['createKeccak256'] = () =>
|
|
65
|
+
(overrides.Hash?.createKeccak256 ?? createKeccak256Default)()
|
|
66
|
+
|
|
67
|
+
/** @internal */
|
|
68
|
+
export const createRipemd160: Complete<Hash>['createRipemd160'] = () =>
|
|
69
|
+
(overrides.Hash?.createRipemd160 ?? createRipemd160Default)()
|
|
70
|
+
|
|
71
|
+
/** @internal */
|
|
72
|
+
export const createSha256: Complete<Hash>['createSha256'] = () =>
|
|
73
|
+
(overrides.Hash?.createSha256 ?? createSha256Default)()
|
|
74
|
+
|
|
34
75
|
/** @internal */
|
|
35
76
|
export const hmacSha256: Complete<Hash>['hmacSha256'] = (key, message) =>
|
|
36
77
|
(overrides.Hash?.hmacSha256 ?? hmacSha256Default)(key, message)
|
|
@@ -46,3 +87,14 @@ export const ripemd160: Complete<Hash>['ripemd160'] = (input) =>
|
|
|
46
87
|
/** @internal */
|
|
47
88
|
export const sha256: Complete<Hash>['sha256'] = (input) =>
|
|
48
89
|
(overrides.Hash?.sha256 ?? sha256Default)(input)
|
|
90
|
+
|
|
91
|
+
function fromNoble<hash extends NobleHash<hash>>(hash: hash): HashState {
|
|
92
|
+
return {
|
|
93
|
+
clone: () => fromNoble(hash.clone()),
|
|
94
|
+
destroy: () => hash.destroy(),
|
|
95
|
+
digestInto: (output) => hash.digestInto(output),
|
|
96
|
+
update: (input) => {
|
|
97
|
+
hash.update(input)
|
|
98
|
+
},
|
|
99
|
+
}
|
|
100
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -3708,17 +3708,19 @@ export * as ValidatorData from './core/ValidatorData.js'
|
|
|
3708
3708
|
export * as Value from './core/Value.js'
|
|
3709
3709
|
|
|
3710
3710
|
/**
|
|
3711
|
-
*
|
|
3711
|
+
* Utilities for WebAuthn credentials, credential-bound PRFs, and
|
|
3712
|
+
* [NIST P256](https://csrc.nist.gov/csrc/media/events/workshop-on-elliptic-curve-cryptography-standards/documents/papers/session6-adalier-mehmet.pdf)
|
|
3713
|
+
* signatures.
|
|
3712
3714
|
*
|
|
3713
3715
|
* @example
|
|
3714
3716
|
* ### Creating Credentials
|
|
3715
3717
|
*
|
|
3716
|
-
* Credentials can be created using {@link ox#
|
|
3718
|
+
* Credentials can be created using {@link ox#WebAuthn.(createCredential:function)}:
|
|
3717
3719
|
*
|
|
3718
3720
|
* ```ts twoslash
|
|
3719
|
-
* import {
|
|
3721
|
+
* import { WebAuthn } from 'ox'
|
|
3720
3722
|
*
|
|
3721
|
-
* const credential = await
|
|
3723
|
+
* const credential = await WebAuthn.createCredential({
|
|
3722
3724
|
* name: 'Example'
|
|
3723
3725
|
* }) // [!code focus]
|
|
3724
3726
|
* // @log: {
|
|
@@ -3727,7 +3729,7 @@ export * as Value from './core/Value.js'
|
|
|
3727
3729
|
* // @log: raw: PublicKeyCredential {},
|
|
3728
3730
|
* // @log: }
|
|
3729
3731
|
*
|
|
3730
|
-
* const { metadata, signature } = await
|
|
3732
|
+
* const { metadata, signature } = await WebAuthn.sign({
|
|
3731
3733
|
* credentialId: credential.id,
|
|
3732
3734
|
* challenge: '0xdeadbeef'
|
|
3733
3735
|
* })
|
|
@@ -3736,16 +3738,16 @@ export * as Value from './core/Value.js'
|
|
|
3736
3738
|
* @example
|
|
3737
3739
|
* ### Signing Payloads
|
|
3738
3740
|
*
|
|
3739
|
-
* Payloads can be signed using {@link ox#
|
|
3741
|
+
* Payloads can be signed using {@link ox#WebAuthn.(sign:function)}:
|
|
3740
3742
|
*
|
|
3741
3743
|
* ```ts twoslash
|
|
3742
|
-
* import {
|
|
3744
|
+
* import { WebAuthn } from 'ox'
|
|
3743
3745
|
*
|
|
3744
|
-
* const credential = await
|
|
3746
|
+
* const credential = await WebAuthn.createCredential({
|
|
3745
3747
|
* name: 'Example'
|
|
3746
3748
|
* })
|
|
3747
3749
|
*
|
|
3748
|
-
* const { metadata, signature } = await
|
|
3750
|
+
* const { metadata, signature } = await WebAuthn.sign({
|
|
3749
3751
|
* // [!code focus]
|
|
3750
3752
|
* credentialId: credential.id, // [!code focus]
|
|
3751
3753
|
* challenge: '0xdeadbeef' // [!code focus]
|
|
@@ -3765,21 +3767,21 @@ export * as Value from './core/Value.js'
|
|
|
3765
3767
|
* @example
|
|
3766
3768
|
* ### Verifying Signatures
|
|
3767
3769
|
*
|
|
3768
|
-
* Signatures can be verified using {@link ox#
|
|
3770
|
+
* Signatures can be verified using {@link ox#WebAuthn.(verify:function)}:
|
|
3769
3771
|
*
|
|
3770
3772
|
* ```ts twoslash
|
|
3771
|
-
* import {
|
|
3773
|
+
* import { WebAuthn } from 'ox'
|
|
3772
3774
|
*
|
|
3773
|
-
* const credential = await
|
|
3775
|
+
* const credential = await WebAuthn.createCredential({
|
|
3774
3776
|
* name: 'Example'
|
|
3775
3777
|
* })
|
|
3776
3778
|
*
|
|
3777
|
-
* const { metadata, signature } = await
|
|
3779
|
+
* const { metadata, signature } = await WebAuthn.sign({
|
|
3778
3780
|
* credentialId: credential.id,
|
|
3779
3781
|
* challenge: '0xdeadbeef'
|
|
3780
3782
|
* })
|
|
3781
3783
|
*
|
|
3782
|
-
* const result = await
|
|
3784
|
+
* const result = await WebAuthn.verify({
|
|
3783
3785
|
* // [!code focus]
|
|
3784
3786
|
* metadata, // [!code focus]
|
|
3785
3787
|
* challenge: '0xdeadbeef', // [!code focus]
|
|
@@ -3791,6 +3793,14 @@ export * as Value from './core/Value.js'
|
|
|
3791
3793
|
*
|
|
3792
3794
|
* @category Crypto
|
|
3793
3795
|
*/
|
|
3796
|
+
export * as WebAuthn from './core/WebAuthn.js'
|
|
3797
|
+
|
|
3798
|
+
/**
|
|
3799
|
+
* `WebAuthnP256` is deprecated. Use `WebAuthn` instead.
|
|
3800
|
+
*
|
|
3801
|
+
* @deprecated Use `WebAuthn` instead.
|
|
3802
|
+
* @category Crypto
|
|
3803
|
+
*/
|
|
3794
3804
|
export * as WebAuthnP256 from './core/WebAuthnP256.js'
|
|
3795
3805
|
|
|
3796
3806
|
/**
|
package/src/node/Engine.ts
CHANGED
package/src/node/Hash.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as crypto from 'node:crypto'
|
|
2
2
|
import type * as Engine from '../core/Engine.js'
|
|
3
3
|
import type * as Errors from '../core/Errors.js'
|
|
4
|
+
import * as CoreHash from '../core/Hash.js'
|
|
4
5
|
|
|
5
6
|
export * from '../core/Hash.js'
|
|
6
7
|
|
|
@@ -12,9 +13,11 @@ export * from '../core/Hash.js'
|
|
|
12
13
|
* which installs every implementation this entrypoint provides. Reach for this
|
|
13
14
|
* to install or hold the `Hash` slot on its own.
|
|
14
15
|
*
|
|
15
|
-
* Node does not provide BLAKE3, and its `sha3-256` is not Ethereum Keccak256
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
* Node does not provide BLAKE3, and its `sha3-256` is not Ethereum Keccak256.
|
|
17
|
+
* Node HMAC states cannot be cloned.
|
|
18
|
+
*
|
|
19
|
+
* The engine omits those implementations. Earlier overrides remain installed;
|
|
20
|
+
* Ox uses its defaults when no override exists.
|
|
18
21
|
*
|
|
19
22
|
* @example
|
|
20
23
|
* ```ts twoslash
|
|
@@ -31,6 +34,8 @@ export * from '../core/Hash.js'
|
|
|
31
34
|
*/
|
|
32
35
|
export function engine(): Promise<engine.ReturnType> {
|
|
33
36
|
return Promise.resolve({
|
|
37
|
+
createRipemd160: () => fromHash(crypto.createHash('ripemd160'), 20),
|
|
38
|
+
createSha256: () => fromHash(crypto.createHash('sha256'), 32),
|
|
34
39
|
hmacSha256: (key, message) =>
|
|
35
40
|
new Uint8Array(crypto.createHmac('sha256', key).update(message).digest()),
|
|
36
41
|
ripemd160: (input) =>
|
|
@@ -42,10 +47,42 @@ export function engine(): Promise<engine.ReturnType> {
|
|
|
42
47
|
export declare namespace engine {
|
|
43
48
|
/** Every `Hash` primitive this module implements. */
|
|
44
49
|
type ReturnType = {
|
|
45
|
-
[key in
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
[key in
|
|
51
|
+
| 'createRipemd160'
|
|
52
|
+
| 'createSha256'
|
|
53
|
+
| 'hmacSha256'
|
|
54
|
+
| 'ripemd160'
|
|
55
|
+
| 'sha256']-?: NonNullable<Engine.Hash[key]>
|
|
48
56
|
}
|
|
49
57
|
|
|
50
58
|
type ErrorType = Errors.GlobalErrorType
|
|
51
59
|
}
|
|
60
|
+
|
|
61
|
+
function fromHash(initial: crypto.Hash, digestSize: number): Engine.HashState {
|
|
62
|
+
let hash: crypto.Hash | undefined = initial
|
|
63
|
+
|
|
64
|
+
const get = () => {
|
|
65
|
+
if (!hash) throw new CoreHash.HasherDestroyedError()
|
|
66
|
+
return hash
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
clone: () => fromHash(get().copy(), digestSize),
|
|
71
|
+
destroy: () => {
|
|
72
|
+
hash = undefined
|
|
73
|
+
},
|
|
74
|
+
digestInto: (output) => {
|
|
75
|
+
const active = get()
|
|
76
|
+
if (output.length < digestSize)
|
|
77
|
+
throw new CoreHash.InvalidDigestSizeError({
|
|
78
|
+
minimum: digestSize,
|
|
79
|
+
size: output.length,
|
|
80
|
+
})
|
|
81
|
+
hash = undefined
|
|
82
|
+
output.set(active.digest())
|
|
83
|
+
},
|
|
84
|
+
update: (input) => {
|
|
85
|
+
get().update(input)
|
|
86
|
+
},
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -13,6 +13,7 @@ test('install and engine expose the same precise engine', () => {
|
|
|
13
13
|
})
|
|
14
14
|
|
|
15
15
|
test('the Node Engine namespace exposes synchronous core operations', () => {
|
|
16
|
+
expectTypeOf<Engine.HashState>().toEqualTypeOf<CoreEngine.HashState>()
|
|
16
17
|
expectTypeOf(Engine.get).toEqualTypeOf(CoreEngine.get)
|
|
17
18
|
expectTypeOf(Engine.InvalidSlotValueError).toEqualTypeOf(
|
|
18
19
|
CoreEngine.InvalidSlotValueError,
|
|
@@ -6,6 +6,12 @@ import * as CoreHash from '../../core/Hash.js'
|
|
|
6
6
|
type Slot = Awaited<ReturnType<typeof NodeHash.engine>>
|
|
7
7
|
|
|
8
8
|
test('every implemented primitive is present', () => {
|
|
9
|
+
expectTypeOf<Slot['createRipemd160']>().toEqualTypeOf<
|
|
10
|
+
() => CoreEngine.HashState
|
|
11
|
+
>()
|
|
12
|
+
expectTypeOf<Slot['createSha256']>().toEqualTypeOf<
|
|
13
|
+
() => CoreEngine.HashState
|
|
14
|
+
>()
|
|
9
15
|
expectTypeOf<Slot['hmacSha256']>().toEqualTypeOf<
|
|
10
16
|
(key: Uint8Array, message: Uint8Array) => Uint8Array
|
|
11
17
|
>()
|
|
@@ -19,6 +25,9 @@ test('every implemented primitive is present', () => {
|
|
|
19
25
|
|
|
20
26
|
test('unsupported primitives are absent', () => {
|
|
21
27
|
expectTypeOf<Slot>().not.toHaveProperty('blake3')
|
|
28
|
+
expectTypeOf<Slot>().not.toHaveProperty('createBlake3')
|
|
29
|
+
expectTypeOf<Slot>().not.toHaveProperty('createHmacSha256')
|
|
30
|
+
expectTypeOf<Slot>().not.toHaveProperty('createKeccak256')
|
|
22
31
|
expectTypeOf<Slot>().not.toHaveProperty('keccak256')
|
|
23
32
|
})
|
|
24
33
|
|
|
@@ -28,6 +37,7 @@ test('the result is the raw slot, so `Engine.install` accepts it', () => {
|
|
|
28
37
|
|
|
29
38
|
test('the Node namespace exposes the public Hash API', () => {
|
|
30
39
|
expectTypeOf(NodeHash.blake3).toEqualTypeOf(CoreHash.blake3)
|
|
40
|
+
expectTypeOf(NodeHash.createSha256).toEqualTypeOf(CoreHash.createSha256)
|
|
31
41
|
expectTypeOf(NodeHash.sha256).toEqualTypeOf(CoreHash.sha256)
|
|
32
42
|
expectTypeOf<typeof NodeHash>().not.toHaveProperty('create')
|
|
33
43
|
})
|
|
@@ -8,6 +8,8 @@ describe('engine', () => {
|
|
|
8
8
|
|
|
9
9
|
expect(Object.keys(engine).sort()).toMatchInlineSnapshot(`
|
|
10
10
|
[
|
|
11
|
+
"createRipemd160",
|
|
12
|
+
"createSha256",
|
|
11
13
|
"hmacSha256",
|
|
12
14
|
"ripemd160",
|
|
13
15
|
"sha256",
|
|
@@ -98,4 +100,48 @@ describe('engine', () => {
|
|
|
98
100
|
`)
|
|
99
101
|
expect(sha256(input) === sha256(input)).toMatchInlineSnapshot('false')
|
|
100
102
|
})
|
|
103
|
+
|
|
104
|
+
test('behavior: incremental states support chunking and cloning', async () => {
|
|
105
|
+
const { createRipemd160, createSha256 } = await Hash.engine()
|
|
106
|
+
|
|
107
|
+
for (const [create, digest, size] of [
|
|
108
|
+
[createRipemd160, CoreHash.ripemd160, 20],
|
|
109
|
+
[createSha256, CoreHash.sha256, 32],
|
|
110
|
+
] as const) {
|
|
111
|
+
const first = create()
|
|
112
|
+
first.update(Uint8Array.of(0xde, 0xad))
|
|
113
|
+
const second = first.clone()
|
|
114
|
+
first.update(Uint8Array.of(0xbe, 0xef))
|
|
115
|
+
second.update(Uint8Array.of(0xca, 0xfe))
|
|
116
|
+
|
|
117
|
+
const firstOutput = new Uint8Array(size)
|
|
118
|
+
const secondOutput = new Uint8Array(size)
|
|
119
|
+
first.digestInto(firstOutput)
|
|
120
|
+
second.digestInto(secondOutput)
|
|
121
|
+
|
|
122
|
+
expect(firstOutput).toEqual(digest('0xdeadbeef', { as: 'Bytes' }))
|
|
123
|
+
expect(secondOutput).toEqual(digest('0xdeadcafe', { as: 'Bytes' }))
|
|
124
|
+
}
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
test('behavior: incremental states enforce lifecycle and output bounds', async () => {
|
|
128
|
+
const { createSha256 } = await Hash.engine()
|
|
129
|
+
const hash = createSha256()
|
|
130
|
+
hash.update(Uint8Array.of(0xde, 0xad))
|
|
131
|
+
|
|
132
|
+
expect(() => hash.digestInto(new Uint8Array(31))).toThrowError(
|
|
133
|
+
Hash.InvalidDigestSizeError,
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
const output = new Uint8Array(34).fill(0xff)
|
|
137
|
+
hash.digestInto(output)
|
|
138
|
+
expect(output.slice(32)).toEqual(Uint8Array.of(0xff, 0xff))
|
|
139
|
+
expect(() => hash.update(new Uint8Array())).toThrowError(
|
|
140
|
+
Hash.HasherDestroyedError,
|
|
141
|
+
)
|
|
142
|
+
expect(() => {
|
|
143
|
+
hash.destroy()
|
|
144
|
+
hash.destroy()
|
|
145
|
+
}).not.toThrow()
|
|
146
|
+
})
|
|
101
147
|
})
|
|
@@ -219,13 +219,13 @@ export type TupleListSigned = TupleList<true>
|
|
|
219
219
|
*
|
|
220
220
|
* ```ts twoslash
|
|
221
221
|
* // @noErrors
|
|
222
|
-
* import {
|
|
222
|
+
* import { WebAuthn } from 'ox'
|
|
223
223
|
* import {
|
|
224
224
|
* AuthorizationTempo,
|
|
225
225
|
* SignatureEnvelope
|
|
226
226
|
* } from 'ox/tempo'
|
|
227
227
|
*
|
|
228
|
-
* const credential = await
|
|
228
|
+
* const credential = await WebAuthn.createCredential({
|
|
229
229
|
* name: 'Example'
|
|
230
230
|
* })
|
|
231
231
|
*
|
|
@@ -235,7 +235,7 @@ export type TupleListSigned = TupleList<true>
|
|
|
235
235
|
* nonce: 40n
|
|
236
236
|
* })
|
|
237
237
|
*
|
|
238
|
-
* const { metadata, signature } = await
|
|
238
|
+
* const { metadata, signature } = await WebAuthn.sign({
|
|
239
239
|
* challenge:
|
|
240
240
|
* AuthorizationTempo.getSignPayload(authorization),
|
|
241
241
|
* credentialId: credential.id
|
|
@@ -657,13 +657,13 @@ export declare namespace fromTupleList {
|
|
|
657
657
|
*
|
|
658
658
|
* ```ts twoslash
|
|
659
659
|
* // @noErrors
|
|
660
|
-
* import {
|
|
660
|
+
* import { WebAuthn } from 'ox'
|
|
661
661
|
* import {
|
|
662
662
|
* AuthorizationTempo,
|
|
663
663
|
* SignatureEnvelope
|
|
664
664
|
* } from 'ox/tempo'
|
|
665
665
|
*
|
|
666
|
-
* const credential = await
|
|
666
|
+
* const credential = await WebAuthn.createCredential({
|
|
667
667
|
* name: 'Example'
|
|
668
668
|
* })
|
|
669
669
|
*
|
|
@@ -676,7 +676,7 @@ export declare namespace fromTupleList {
|
|
|
676
676
|
* const challenge =
|
|
677
677
|
* AuthorizationTempo.getSignPayload(authorization) // [!code focus]
|
|
678
678
|
*
|
|
679
|
-
* const { metadata, signature } = await
|
|
679
|
+
* const { metadata, signature } = await WebAuthn.sign({
|
|
680
680
|
* challenge,
|
|
681
681
|
* credentialId: credential.id
|
|
682
682
|
* })
|
|
@@ -366,12 +366,7 @@ export type TokenLimit<bigintType = bigint, numberType = number> = {
|
|
|
366
366
|
*
|
|
367
367
|
* ```ts twoslash
|
|
368
368
|
* // @noErrors
|
|
369
|
-
* import {
|
|
370
|
-
* Address,
|
|
371
|
-
* Value,
|
|
372
|
-
* WebCryptoP256,
|
|
373
|
-
* WebAuthnP256
|
|
374
|
-
* } from 'ox'
|
|
369
|
+
* import { Address, Value, WebCryptoP256, WebAuthn } from 'ox'
|
|
375
370
|
* import {
|
|
376
371
|
* KeyAuthorization,
|
|
377
372
|
* SignatureEnvelope
|
|
@@ -393,11 +388,11 @@ export type TokenLimit<bigintType = bigint, numberType = number> = {
|
|
|
393
388
|
* ]
|
|
394
389
|
* })
|
|
395
390
|
*
|
|
396
|
-
* const credential = await
|
|
391
|
+
* const credential = await WebAuthn.createCredential({
|
|
397
392
|
* name: 'Example'
|
|
398
393
|
* })
|
|
399
394
|
*
|
|
400
|
-
* const { metadata, signature } = await
|
|
395
|
+
* const { metadata, signature } = await WebAuthn.sign({
|
|
401
396
|
* challenge: KeyAuthorization.getSignPayload(authorization),
|
|
402
397
|
* credentialId: credential.id
|
|
403
398
|
* })
|
|
@@ -814,7 +814,7 @@ function deserialize_(
|
|
|
814
814
|
*
|
|
815
815
|
* Accepts either a serialized hex string or an existing signature envelope object.
|
|
816
816
|
* Use this to wrap raw signatures from {@link ox#Secp256k1.(sign:function)}, {@link ox#P256.(sign:function)},
|
|
817
|
-
* {@link ox#WebCryptoP256.(sign:function)}, or {@link ox#
|
|
817
|
+
* {@link ox#WebCryptoP256.(sign:function)}, or {@link ox#WebAuthn.(sign:function)} into the envelope format
|
|
818
818
|
* required by Tempo transactions.
|
|
819
819
|
*
|
|
820
820
|
* [Signature Types](https://docs.tempo.xyz/protocol/transactions/spec-tempo-transaction#signature-types)
|
|
@@ -893,14 +893,14 @@ function deserialize_(
|
|
|
893
893
|
*
|
|
894
894
|
* ```ts twoslash
|
|
895
895
|
* // @noErrors
|
|
896
|
-
* import {
|
|
896
|
+
* import { WebAuthn } from 'ox'
|
|
897
897
|
* import { SignatureEnvelope } from 'ox/tempo'
|
|
898
898
|
*
|
|
899
|
-
* const credential = await
|
|
899
|
+
* const credential = await WebAuthn.createCredential({
|
|
900
900
|
* name: 'Example'
|
|
901
901
|
* })
|
|
902
902
|
*
|
|
903
|
-
* const { metadata, signature } = await
|
|
903
|
+
* const { metadata, signature } = await WebAuthn.sign({
|
|
904
904
|
* challenge: '0xdeadbeef',
|
|
905
905
|
* credentialId: credential.id
|
|
906
906
|
* })
|
|
@@ -1819,18 +1819,18 @@ export declare namespace validate {
|
|
|
1819
1819
|
* ```
|
|
1820
1820
|
*
|
|
1821
1821
|
* @example
|
|
1822
|
-
* ###
|
|
1822
|
+
* ### WebAuthn
|
|
1823
1823
|
*
|
|
1824
1824
|
* ```ts twoslash
|
|
1825
1825
|
* import { SignatureEnvelope } from 'ox/tempo'
|
|
1826
|
-
* import {
|
|
1826
|
+
* import { WebAuthn } from 'ox'
|
|
1827
1827
|
*
|
|
1828
|
-
* const credential = await
|
|
1828
|
+
* const credential = await WebAuthn.createCredential({
|
|
1829
1829
|
* name: 'Example'
|
|
1830
1830
|
* })
|
|
1831
1831
|
* const payload = '0xdeadbeef'
|
|
1832
1832
|
*
|
|
1833
|
-
* const { metadata, signature } = await
|
|
1833
|
+
* const { metadata, signature } = await WebAuthn.sign({
|
|
1834
1834
|
* challenge: payload,
|
|
1835
1835
|
* credentialId: credential.id
|
|
1836
1836
|
* })
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** @internal */
|
|
2
|
-
export const version = '1.
|
|
2
|
+
export const version = '1.3.1'
|
package/src/wasm/Engine.ts
CHANGED
package/src/wasm/Hash.ts
CHANGED
|
@@ -65,6 +65,11 @@ export async function engine(): Promise<engine.ReturnType> {
|
|
|
65
65
|
|
|
66
66
|
return {
|
|
67
67
|
blake3: (input) => blake3.hash(blake3Module, input),
|
|
68
|
+
createBlake3: () => blake3.create(blake3Module),
|
|
69
|
+
createHmacSha256: (key) => hash.createHmacSha256(module, key),
|
|
70
|
+
createKeccak256: () => hashes.create(module, 'keccak256'),
|
|
71
|
+
createRipemd160: () => hashes.create(module, 'ripemd160'),
|
|
72
|
+
createSha256: () => hashes.create(module, 'sha256'),
|
|
68
73
|
hmacSha256: (key, message) => hash.hmacSha256(module, key, message),
|
|
69
74
|
keccak256: (input) => call('keccak256', input),
|
|
70
75
|
ripemd160: (input) => call('ripemd160', input),
|
|
@@ -78,6 +83,11 @@ export declare namespace engine {
|
|
|
78
83
|
type ReturnType = {
|
|
79
84
|
[key in
|
|
80
85
|
| 'blake3'
|
|
86
|
+
| 'createBlake3'
|
|
87
|
+
| 'createHmacSha256'
|
|
88
|
+
| 'createKeccak256'
|
|
89
|
+
| 'createRipemd160'
|
|
90
|
+
| 'createSha256'
|
|
81
91
|
| 'hmacSha256'
|
|
82
92
|
| 'keccak256'
|
|
83
93
|
| 'ripemd160'
|
|
@@ -14,6 +14,7 @@ test('install and engine expose the same precise engine', () => {
|
|
|
14
14
|
})
|
|
15
15
|
|
|
16
16
|
test('the WASM Engine namespace exposes synchronous core operations', () => {
|
|
17
|
+
expectTypeOf<Engine.HashState>().toEqualTypeOf<CoreEngine.HashState>()
|
|
17
18
|
expectTypeOf(Engine.get).toEqualTypeOf(CoreEngine.get)
|
|
18
19
|
expectTypeOf(Engine.InvalidSlotValueError).toEqualTypeOf(
|
|
19
20
|
CoreEngine.InvalidSlotValueError,
|
|
@@ -27,6 +27,28 @@ describe('engine', () => {
|
|
|
27
27
|
}
|
|
28
28
|
})
|
|
29
29
|
|
|
30
|
+
test('behavior: incremental states clone and cross block boundaries', async () => {
|
|
31
|
+
const engine = await WasmHash.engine()
|
|
32
|
+
const prefix = new Uint8Array(137).fill(1)
|
|
33
|
+
const left = new Uint8Array(1025).fill(2)
|
|
34
|
+
const right = new Uint8Array(65).fill(3)
|
|
35
|
+
const state = engine.createBlake3()
|
|
36
|
+
state.update(prefix.subarray(0, 1))
|
|
37
|
+
state.update(prefix.subarray(1, 136))
|
|
38
|
+
state.update(prefix.subarray(136))
|
|
39
|
+
const clone = state.clone()
|
|
40
|
+
state.update(left)
|
|
41
|
+
clone.update(right)
|
|
42
|
+
|
|
43
|
+
const output = new Uint8Array(32)
|
|
44
|
+
state.digestInto(output)
|
|
45
|
+
expect(output).toEqual(blake3(new Uint8Array([...prefix, ...left])))
|
|
46
|
+
|
|
47
|
+
const clonedOutput = new Uint8Array(32)
|
|
48
|
+
clone.digestInto(clonedOutput)
|
|
49
|
+
expect(clonedOutput).toEqual(blake3(new Uint8Array([...prefix, ...right])))
|
|
50
|
+
})
|
|
51
|
+
|
|
30
52
|
test('behavior: grows memory in a real browser, then hashes a small input', async () => {
|
|
31
53
|
const engine = await WasmHash.engine()
|
|
32
54
|
|
|
@@ -50,6 +72,12 @@ describe('engine', () => {
|
|
|
50
72
|
expect(Hash.keccak256('0xdeadbeef')).toBe(
|
|
51
73
|
'0xd4fd4e189132273036449fc9e11198c739161b4c0116a9a2dccdfa1c492006f1',
|
|
52
74
|
)
|
|
75
|
+
const state = Hash.createKeccak256()
|
|
76
|
+
state.update('0xdead')
|
|
77
|
+
state.update('0xbeef')
|
|
78
|
+
expect(state.digest()).toBe(
|
|
79
|
+
'0xd4fd4e189132273036449fc9e11198c739161b4c0116a9a2dccdfa1c492006f1',
|
|
80
|
+
)
|
|
53
81
|
} finally {
|
|
54
82
|
Engine.reset()
|
|
55
83
|
}
|