ox 1.2.0 → 1.3.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 +34 -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 +9 -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
package/src/core/Rlp.ts
CHANGED
|
@@ -192,6 +192,48 @@ export declare namespace readList {
|
|
|
192
192
|
| Errors.GlobalErrorType
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
/**
|
|
196
|
+
* Encodes a value as Recursive-Length Prefix (RLP) and writes the encoded bytes
|
|
197
|
+
* through a synchronous callback without allocating the complete encoding.
|
|
198
|
+
*
|
|
199
|
+
* Ox validates the complete input before the first write. If the callback
|
|
200
|
+
* throws, the error propagates and earlier callback side effects remain.
|
|
201
|
+
*
|
|
202
|
+
* Ox does not mutate a chunk after the callback returns. A chunk may alias a
|
|
203
|
+
* byte-array leaf from the encoded value. The callback must not mutate the
|
|
204
|
+
* chunk before `encodeTo` returns.
|
|
205
|
+
*
|
|
206
|
+
* @example
|
|
207
|
+
* ```ts twoslash
|
|
208
|
+
* import { Bytes, Rlp } from 'ox'
|
|
209
|
+
*
|
|
210
|
+
* const chunks: Uint8Array[] = []
|
|
211
|
+
* Rlp.encodeTo(['0x01', '0x0203'], (chunk) => {
|
|
212
|
+
* chunks.push(chunk)
|
|
213
|
+
* })
|
|
214
|
+
*
|
|
215
|
+
* const encoded = Bytes.concat(...chunks)
|
|
216
|
+
* // @log: Uint8Array([196, 1, 130, 2, 3])
|
|
217
|
+
* ```
|
|
218
|
+
*
|
|
219
|
+
* @param value - The bytes or Hex value, or nested list of values, to encode.
|
|
220
|
+
* @param write - The synchronous callback for encoded chunks.
|
|
221
|
+
* @returns Nothing.
|
|
222
|
+
*/
|
|
223
|
+
export function encodeTo(
|
|
224
|
+
value: RecursiveArray<Bytes.Bytes> | RecursiveArray<Hex.Hex>,
|
|
225
|
+
write: (chunk: Bytes.Bytes) => undefined,
|
|
226
|
+
): void {
|
|
227
|
+
const snapshot = snapshotValue(value)
|
|
228
|
+
const ctx: EncodeCtx = { lengths: [], cursor: 0 }
|
|
229
|
+
measure(snapshot, ctx)
|
|
230
|
+
writeEncodedTo(write, snapshot, { lengths: ctx.lengths, cursor: 0 })
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export declare namespace encodeTo {
|
|
234
|
+
type ErrorType = Errors.BaseError | Errors.GlobalErrorType
|
|
235
|
+
}
|
|
236
|
+
|
|
195
237
|
/**
|
|
196
238
|
* Encodes a {@link ox#Bytes.Bytes} or {@link ox#Hex.Hex} value into a Recursive-Length Prefix (RLP) value.
|
|
197
239
|
*
|
|
@@ -368,7 +410,29 @@ function getSizeOfLength(length: number) {
|
|
|
368
410
|
*
|
|
369
411
|
* @internal
|
|
370
412
|
*/
|
|
371
|
-
type EncodeCtx = {
|
|
413
|
+
type EncodeCtx = {
|
|
414
|
+
cursor: number
|
|
415
|
+
lengths: number[]
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
type Encodable = RecursiveArray<Bytes.Bytes | Hex.Hex>
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Validates Hex leaves and copies list structure before the callback can mutate
|
|
422
|
+
* the input during encoding. Byte leaves remain zero-copy.
|
|
423
|
+
*
|
|
424
|
+
* @internal
|
|
425
|
+
*/
|
|
426
|
+
function snapshotValue(value: Encodable): Encodable {
|
|
427
|
+
if (Array.isArray(value)) {
|
|
428
|
+
const snapshot: Encodable[] = []
|
|
429
|
+
for (let i = 0; i < value.length; i++)
|
|
430
|
+
snapshot.push(snapshotValue(value[i]!))
|
|
431
|
+
return snapshot
|
|
432
|
+
}
|
|
433
|
+
if (typeof value === 'string') validateHexLeaf(value)
|
|
434
|
+
return value
|
|
435
|
+
}
|
|
372
436
|
|
|
373
437
|
/**
|
|
374
438
|
* Walks `value` once, caches each list's `bodyLength` into `ctx.lengths`,
|
|
@@ -377,10 +441,7 @@ type EncodeCtx = { lengths: number[]; cursor: number }
|
|
|
377
441
|
*
|
|
378
442
|
* @internal
|
|
379
443
|
*/
|
|
380
|
-
function measure(
|
|
381
|
-
value: RecursiveArray<Bytes.Bytes> | RecursiveArray<Hex.Hex>,
|
|
382
|
-
ctx: EncodeCtx,
|
|
383
|
-
): number {
|
|
444
|
+
function measure(value: Encodable, ctx: EncodeCtx): number {
|
|
384
445
|
if (Array.isArray(value)) {
|
|
385
446
|
// Reserve this list's slot before descending so children's slots come
|
|
386
447
|
// after ours; `writeEncoded` walks in the same order and reads slot N
|
|
@@ -458,6 +519,112 @@ function writeEncoded(
|
|
|
458
519
|
return writeBytesLeaf(bytes, offset, value as Bytes.Bytes)
|
|
459
520
|
}
|
|
460
521
|
|
|
522
|
+
const writeChunkSize = 16_384
|
|
523
|
+
|
|
524
|
+
type Write = (chunk: Bytes.Bytes) => undefined
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Writes an RLP value using list lengths cached by `measure`.
|
|
528
|
+
*
|
|
529
|
+
* @internal
|
|
530
|
+
*/
|
|
531
|
+
function writeEncodedTo(write: Write, value: Encodable, ctx: EncodeCtx): void {
|
|
532
|
+
if (Array.isArray(value)) {
|
|
533
|
+
write(encodePrefix(ctx.lengths[ctx.cursor++]!, 0xc0))
|
|
534
|
+
for (let i = 0; i < value.length; i++) writeEncodedTo(write, value[i]!, ctx)
|
|
535
|
+
return
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
if (typeof value === 'string') {
|
|
539
|
+
writeHexLeafTo(write, value)
|
|
540
|
+
return
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
writeBytesLeafTo(write, value as Bytes.Bytes)
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Writes a Hex leaf in bounded chunks. `snapshotValue` validated every nibble
|
|
548
|
+
* before this function can run.
|
|
549
|
+
*
|
|
550
|
+
* @internal
|
|
551
|
+
*/
|
|
552
|
+
function writeHexLeafTo(write: Write, hex: Hex.Hex): void {
|
|
553
|
+
const byteLength = (hex.length - 1) >> 1
|
|
554
|
+
if (byteLength === 1 && readHexByte(hex, 0) < 0x80) {
|
|
555
|
+
write(Uint8Array.of(readHexByte(hex, 0)))
|
|
556
|
+
return
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
write(encodePrefix(byteLength, 0x80))
|
|
560
|
+
for (let offset = 0; offset < byteLength; offset += writeChunkSize) {
|
|
561
|
+
const length = Math.min(writeChunkSize, byteLength - offset)
|
|
562
|
+
const chunk = new Uint8Array(length)
|
|
563
|
+
for (let i = 0; i < length; i++) chunk[i] = readHexByte(hex, offset + i)
|
|
564
|
+
write(chunk)
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Writes a byte leaf without copying its body.
|
|
570
|
+
*
|
|
571
|
+
* @internal
|
|
572
|
+
*/
|
|
573
|
+
function writeBytesLeafTo(write: Write, leaf: Bytes.Bytes): void {
|
|
574
|
+
const length = leaf.length
|
|
575
|
+
if (length === 1 && leaf[0]! < 0x80) {
|
|
576
|
+
write(leaf)
|
|
577
|
+
return
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
write(encodePrefix(length, 0x80))
|
|
581
|
+
if (length > 0) write(leaf)
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Encodes a string or list length prefix.
|
|
586
|
+
*
|
|
587
|
+
* @internal
|
|
588
|
+
*/
|
|
589
|
+
function encodePrefix(length: number, offset: 0x80 | 0xc0): Uint8Array {
|
|
590
|
+
if (length <= 55) return Uint8Array.of(offset + length)
|
|
591
|
+
|
|
592
|
+
const size = getSizeOfLength(length)
|
|
593
|
+
const prefix = new Uint8Array(size + 1)
|
|
594
|
+
prefix[0] = offset + 55 + size
|
|
595
|
+
writeBigEndian(prefix, 1, length, size)
|
|
596
|
+
return prefix
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* Reads one byte from an odd- or even-nibble Hex value.
|
|
601
|
+
*
|
|
602
|
+
* @internal
|
|
603
|
+
*/
|
|
604
|
+
function readHexByte(hex: Hex.Hex, index: number): number {
|
|
605
|
+
const odd = (hex.length & 1) === 1
|
|
606
|
+
if (odd && index === 0)
|
|
607
|
+
return internal_bytes.charCodeToBase16(hex.charCodeAt(2))!
|
|
608
|
+
|
|
609
|
+
const nibble = odd ? index * 2 - 1 : index * 2
|
|
610
|
+
const high = internal_bytes.charCodeToBase16(hex.charCodeAt(2 + nibble))!
|
|
611
|
+
const low = internal_bytes.charCodeToBase16(hex.charCodeAt(3 + nibble))!
|
|
612
|
+
return (high << 4) | low
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Validates a Hex leaf while preserving RLP's odd-nibble left-padding.
|
|
617
|
+
*
|
|
618
|
+
* @internal
|
|
619
|
+
*/
|
|
620
|
+
function validateHexLeaf(hex: string): asserts hex is Hex.Hex {
|
|
621
|
+
if (hex.length < 2 || hex.charCodeAt(0) !== 48 || hex.charCodeAt(1) !== 120)
|
|
622
|
+
throw invalidNibble(hex as Hex.Hex)
|
|
623
|
+
for (let i = 2; i < hex.length; i++)
|
|
624
|
+
if (internal_bytes.charCodeToBase16(hex.charCodeAt(i)) === undefined)
|
|
625
|
+
throw invalidNibble(hex as Hex.Hex)
|
|
626
|
+
}
|
|
627
|
+
|
|
461
628
|
/**
|
|
462
629
|
* Hex-leaf fast path: writes the RLP encoding of a hex string directly into
|
|
463
630
|
* `bytes` by nibble-decoding the source hex chars into the destination
|
package/src/core/Secp256k1.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { secp256k1 } from '@noble/curves/secp256k1.js'
|
|
2
2
|
import * as Address from './Address.js'
|
|
3
3
|
import * as Bytes from './Bytes.js'
|
|
4
|
-
import
|
|
4
|
+
import * as Errors from './Errors.js'
|
|
5
|
+
import * as Hash from './Hash.js'
|
|
5
6
|
import * as Hex from './Hex.js'
|
|
6
7
|
import {
|
|
7
8
|
formatPublicKey,
|
|
@@ -71,6 +72,75 @@ export declare namespace createKeyPair {
|
|
|
71
72
|
| Errors.GlobalErrorType
|
|
72
73
|
}
|
|
73
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Derives a valid secp256k1 private key from a 32-byte WebAuthn PRF output.
|
|
77
|
+
*
|
|
78
|
+
* The permanent derivation contract uses the PRF output as the HMAC-SHA256
|
|
79
|
+
* key. Its message is the UTF-8 bytes of `ox.secp256k1.fromPrf.v1` followed by
|
|
80
|
+
* a 32-bit big-endian counter starting at zero. Invalid scalars are skipped.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts twoslash
|
|
84
|
+
* import { Secp256k1 } from 'ox'
|
|
85
|
+
*
|
|
86
|
+
* const privateKey = Secp256k1.fromPrf(
|
|
87
|
+
* '0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f'
|
|
88
|
+
* )
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @param value - A 32-byte WebAuthn PRF output.
|
|
92
|
+
* @param options - Options.
|
|
93
|
+
* @returns A valid secp256k1 private key.
|
|
94
|
+
*/
|
|
95
|
+
export function fromPrf<as extends 'Hex' | 'Bytes' = 'Hex'>(
|
|
96
|
+
value: Hex.Hex | Bytes.Bytes,
|
|
97
|
+
options: fromPrf.Options<as> = {},
|
|
98
|
+
): fromPrf.ReturnType<as> {
|
|
99
|
+
const { as = 'Hex' } = options
|
|
100
|
+
const bytes = Bytes.from(value)
|
|
101
|
+
if (bytes.length !== 32) throw new InvalidPrfSizeError({ size: bytes.length })
|
|
102
|
+
|
|
103
|
+
for (let counter = 0; ; counter++) {
|
|
104
|
+
const candidate = Hash.hmac256(
|
|
105
|
+
bytes,
|
|
106
|
+
Bytes.concat(fromPrfLabel, Bytes.fromNumber(counter, { size: 4 })),
|
|
107
|
+
{ as: 'Bytes' },
|
|
108
|
+
)
|
|
109
|
+
if (noble.utils.isValidSecretKey(candidate)) {
|
|
110
|
+
if (as === 'Hex') {
|
|
111
|
+
const value = Hex.fromBytes(candidate)
|
|
112
|
+
candidate.fill(0)
|
|
113
|
+
return value as never
|
|
114
|
+
}
|
|
115
|
+
return candidate as never
|
|
116
|
+
}
|
|
117
|
+
candidate.fill(0)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export declare namespace fromPrf {
|
|
122
|
+
type Options<as extends 'Hex' | 'Bytes' = 'Hex'> = {
|
|
123
|
+
/**
|
|
124
|
+
* Format of the returned private key.
|
|
125
|
+
* @default 'Hex'
|
|
126
|
+
*/
|
|
127
|
+
as?: as | 'Hex' | 'Bytes' | undefined
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
type ReturnType<as extends 'Hex' | 'Bytes'> =
|
|
131
|
+
| (as extends 'Bytes' ? Bytes.Bytes : never)
|
|
132
|
+
| (as extends 'Hex' ? Hex.Hex : never)
|
|
133
|
+
|
|
134
|
+
type ErrorType =
|
|
135
|
+
| Bytes.concat.ErrorType
|
|
136
|
+
| Bytes.from.ErrorType
|
|
137
|
+
| Bytes.fromNumber.ErrorType
|
|
138
|
+
| Hash.hmac256.ErrorType
|
|
139
|
+
| Hex.fromBytes.ErrorType
|
|
140
|
+
| InvalidPrfSizeError
|
|
141
|
+
| Errors.GlobalErrorType
|
|
142
|
+
}
|
|
143
|
+
|
|
74
144
|
/**
|
|
75
145
|
* Computes the secp256k1 ECDSA public key from a provided private key.
|
|
76
146
|
*
|
|
@@ -503,3 +573,24 @@ export declare namespace verify {
|
|
|
503
573
|
|
|
504
574
|
type ErrorType = Errors.GlobalErrorType
|
|
505
575
|
}
|
|
576
|
+
|
|
577
|
+
/** Thrown when a WebAuthn PRF output is not 32 bytes. */
|
|
578
|
+
export class InvalidPrfSizeError extends Errors.BaseError {
|
|
579
|
+
override readonly name = 'Secp256k1.InvalidPrfSizeError'
|
|
580
|
+
|
|
581
|
+
constructor(options: InvalidPrfSizeError.Options) {
|
|
582
|
+
super(
|
|
583
|
+
`PRF output must be exactly 32 bytes. Received ${options.size} bytes.`,
|
|
584
|
+
)
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
export declare namespace InvalidPrfSizeError {
|
|
589
|
+
/** Options for {@link ox#Secp256k1.InvalidPrfSizeError}. */
|
|
590
|
+
type Options = {
|
|
591
|
+
/** Received PRF output size. */
|
|
592
|
+
size: number
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
const fromPrfLabel = Bytes.fromString('ox.secp256k1.fromPrf.v1')
|