@forgezero/runtime 0.1.24 → 0.1.25
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/README.md +3 -3
- package/dist/custody-share.d.ts +87 -2
- package/dist/custody-share.js +162 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -814,7 +814,7 @@ Threshold-share parsing, validation and reconstruction. This is a supported entr
|
|
|
814
814
|
|
|
815
815
|
```text
|
|
816
816
|
import {
|
|
817
|
-
|
|
817
|
+
CUSTODY_ENVELOPE_SUITE,
|
|
818
818
|
} from '@forgezero/runtime/custody-share';
|
|
819
819
|
```
|
|
820
820
|
|
|
@@ -824,10 +824,10 @@ This minimal executable use imports one concrete value from this exact entry poi
|
|
|
824
824
|
|
|
825
825
|
```text
|
|
826
826
|
import {
|
|
827
|
-
|
|
827
|
+
CUSTODY_ENVELOPE_SUITE,
|
|
828
828
|
} from '@forgezero/runtime/custody-share';
|
|
829
829
|
|
|
830
|
-
export const selectedCapability =
|
|
830
|
+
export const selectedCapability = CUSTODY_ENVELOPE_SUITE;
|
|
831
831
|
```
|
|
832
832
|
|
|
833
833
|
<a id="forgezero-runtime-custody-crypto"></a>
|
package/dist/custody-share.d.ts
CHANGED
|
@@ -1,8 +1,55 @@
|
|
|
1
1
|
import { type CipherBox, type SealedToKey } from './custody-crypto';
|
|
2
|
+
export declare const CUSTODY_ENVELOPE_VERSION: 3;
|
|
3
|
+
export declare const CUSTODY_ENVELOPE_SUITE: "ml-kem-768+x25519+hkdf-sha256+aes-256-gcm+ml-dsa-65";
|
|
4
|
+
export declare const CUSTODY_FACTOR_PROOF_VERSION: 1;
|
|
5
|
+
export type CustodyCredentialPurpose = 'custody';
|
|
6
|
+
export type CustodyCredentialLifecycle = 'pending' | 'active' | 'retired';
|
|
7
|
+
export type CustodyFactor = 'ceremony_passkey' | 'recovery_phrase';
|
|
8
|
+
export type CustodyEnvelopeGeneration = number;
|
|
9
|
+
export type CustodyTransactionOutcome = 'completed' | 'factor_mismatch' | 'credential_mismatch' | 'replayed' | 'expired' | 'batch_mismatch' | 'seed_fingerprint_mismatch';
|
|
10
|
+
export interface CustodyFactorBinding {
|
|
11
|
+
version: typeof CUSTODY_FACTOR_PROOF_VERSION;
|
|
12
|
+
realmId: string;
|
|
13
|
+
ceremonyKey: string;
|
|
14
|
+
custodianKey: string;
|
|
15
|
+
factor: CustodyFactor;
|
|
16
|
+
requestKey: string;
|
|
17
|
+
method: 'POST';
|
|
18
|
+
path: string;
|
|
19
|
+
payloadDigest: string;
|
|
20
|
+
challenge: string;
|
|
21
|
+
expiresAtSec: number;
|
|
22
|
+
}
|
|
23
|
+
export interface CustodyPasskeyProofV1 {
|
|
24
|
+
version: typeof CUSTODY_FACTOR_PROOF_VERSION;
|
|
25
|
+
factor: 'ceremony_passkey';
|
|
26
|
+
credentialId: string;
|
|
27
|
+
signature: string;
|
|
28
|
+
}
|
|
29
|
+
export interface CustodyPhraseProofV1 {
|
|
30
|
+
version: typeof CUSTODY_FACTOR_PROOF_VERSION;
|
|
31
|
+
factor: 'recovery_phrase';
|
|
32
|
+
signature: string;
|
|
33
|
+
}
|
|
34
|
+
export type CustodyFactorProof = CustodyPasskeyProofV1 | CustodyPhraseProofV1;
|
|
35
|
+
export interface CustodyActionRequest {
|
|
36
|
+
_key: string;
|
|
37
|
+
ceremonyKey: string;
|
|
38
|
+
ownerUserKey: string;
|
|
39
|
+
operation: 'seal' | 'verify' | 'reshare' | 'unlock' | 'rotate' | 'verify_rotation';
|
|
40
|
+
allowedFactors: CustodyFactor[];
|
|
41
|
+
payloadDigest: string;
|
|
42
|
+
challenge: string;
|
|
43
|
+
status: 'open' | 'consumed' | 'expired';
|
|
44
|
+
expiresAtSec: number;
|
|
45
|
+
revision: number;
|
|
46
|
+
}
|
|
2
47
|
export interface SealedShare {
|
|
3
48
|
shareIndex: number;
|
|
4
|
-
/**
|
|
49
|
+
/** Dedicated custody credential whose PRF deterministically derives this passkey key. */
|
|
5
50
|
passkeyCredentialId?: string;
|
|
51
|
+
/** Base64url ceremony salt persisted with that exact custody credential. */
|
|
52
|
+
passkeyPrfSalt?: string;
|
|
6
53
|
passkeyEnvelope: CipherBox;
|
|
7
54
|
phraseEnvelope: CipherBox;
|
|
8
55
|
/** base64 — the HKDF salt for the phrase key and the verifier. */
|
|
@@ -10,6 +57,22 @@ export interface SealedShare {
|
|
|
10
57
|
/** hex — proves the right phrase without being able to rebuild it. */
|
|
11
58
|
phraseVerifier: string;
|
|
12
59
|
}
|
|
60
|
+
/** New writes use this shape. V2 is retained only for bounded unlock-and-rotate migration. */
|
|
61
|
+
export interface CustodyEnvelopeV3 extends SealedShare {
|
|
62
|
+
version: typeof CUSTODY_ENVELOPE_VERSION;
|
|
63
|
+
suite: typeof CUSTODY_ENVELOPE_SUITE;
|
|
64
|
+
generation: CustodyEnvelopeGeneration;
|
|
65
|
+
passkeyGeneration?: CustodyEnvelopeGeneration;
|
|
66
|
+
phraseGeneration?: CustodyEnvelopeGeneration;
|
|
67
|
+
realmId: string;
|
|
68
|
+
ceremonyKey: string;
|
|
69
|
+
custodianKey: string;
|
|
70
|
+
passkeyCredentialId: string;
|
|
71
|
+
passkeyPrfSalt: string;
|
|
72
|
+
passkeyActionPublicKey: string;
|
|
73
|
+
phraseActionPublicKey: string;
|
|
74
|
+
}
|
|
75
|
+
export declare function isCustodyEnvelopeV3(value: SealedShare): value is CustodyEnvelopeV3;
|
|
13
76
|
type EnvelopeKind = 'passkey' | 'phrase';
|
|
14
77
|
/** The x-coordinate a share was cut at — its custodian-facing share number. */
|
|
15
78
|
export declare function shareIndexOf(share: Uint8Array): number;
|
|
@@ -44,12 +107,15 @@ export declare function openShareWithPhrase(sealed: SealedShare, custodianKey: s
|
|
|
44
107
|
* ever sent.
|
|
45
108
|
*/
|
|
46
109
|
export interface WrappingKeys {
|
|
47
|
-
/** The verified, PRF-capable
|
|
110
|
+
/** The verified, PRF-capable custody credential selected by the browser. */
|
|
48
111
|
passkeyCredentialId: string;
|
|
112
|
+
passkeyPrfSalt: string;
|
|
49
113
|
passkeyPublicKey: string;
|
|
50
114
|
phrasePublicKey: string;
|
|
51
115
|
phraseSalt: string;
|
|
52
116
|
phraseVerifier: string;
|
|
117
|
+
passkeyActionPublicKey: string;
|
|
118
|
+
phraseActionPublicKey: string;
|
|
53
119
|
}
|
|
54
120
|
/** The private half for one factor. Never leaves the machine that made it. */
|
|
55
121
|
export declare function passkeyWrappingKey(custodianKey: string, passkeyPrfOutput: Uint8Array): {
|
|
@@ -65,9 +131,25 @@ export declare function phraseWrappingKey(custodianKey: string, phraseWords: str
|
|
|
65
131
|
export declare function wrappingKeysFor(args: {
|
|
66
132
|
custodianKey: string;
|
|
67
133
|
passkeyCredentialId: string;
|
|
134
|
+
passkeyPrfSalt: string;
|
|
68
135
|
passkeyPrfOutput: Uint8Array;
|
|
69
136
|
phraseWords: string[];
|
|
70
137
|
}): WrappingKeys;
|
|
138
|
+
export declare function custodyFactorActionPublicKey(factor: CustodyFactor, custodianKey: string, factorMaterial: Uint8Array): string;
|
|
139
|
+
/** Stable browser/API digest used to bind a custody proof to one exact payload. */
|
|
140
|
+
export declare function custodyActionPayloadDigest(value: unknown): string;
|
|
141
|
+
export declare function createCustodyFactorProof(args: {
|
|
142
|
+
binding: CustodyFactorBinding;
|
|
143
|
+
factorMaterial: Uint8Array;
|
|
144
|
+
credentialId?: string;
|
|
145
|
+
}): CustodyFactorProof;
|
|
146
|
+
export declare function createCustodyPasskeyProof(binding: CustodyFactorBinding, passkeyPrfOutput: Uint8Array, credentialId: string): CustodyPasskeyProofV1;
|
|
147
|
+
export declare function createCustodyPhraseProof(binding: CustodyFactorBinding, phraseWords: string[], phraseSalt: string): CustodyPhraseProofV1;
|
|
148
|
+
export declare function verifyCustodyFactorProof(args: {
|
|
149
|
+
binding: CustodyFactorBinding;
|
|
150
|
+
proof: CustodyFactorProof;
|
|
151
|
+
publicKey: string;
|
|
152
|
+
}): boolean;
|
|
71
153
|
/** Open something the server sealed to one of those public keys. */
|
|
72
154
|
export declare function openSealedToFactor(args: {
|
|
73
155
|
custodianKey: string;
|
|
@@ -76,9 +158,12 @@ export declare function openSealedToFactor(args: {
|
|
|
76
158
|
passkeyPrfOutput?: Uint8Array;
|
|
77
159
|
phraseWords?: string[];
|
|
78
160
|
phraseSalt?: string;
|
|
161
|
+
aad?: string;
|
|
79
162
|
}): Uint8Array;
|
|
80
163
|
/** The aad the server must use when sealing to a custodian's factor key. */
|
|
81
164
|
export declare const factorWrapAad: (custodianKey: string, factor: EnvelopeKind) => string;
|
|
165
|
+
/** Canonical AAD for V3. Length-prefixing prevents ambiguous concatenation. */
|
|
166
|
+
export declare function custodyEnvelopeV3Aad(envelope: Pick<CustodyEnvelopeV3, 'version' | 'suite' | 'realmId' | 'ceremonyKey' | 'custodianKey' | 'shareIndex' | 'passkeyCredentialId' | 'generation' | 'passkeyGeneration' | 'phraseGeneration'>, factor: EnvelopeKind): string;
|
|
82
167
|
/**
|
|
83
168
|
* A share plus a probe, sealed together.
|
|
84
169
|
*
|
package/dist/custody-share.js
CHANGED
|
@@ -174,9 +174,18 @@ function phraseVerifier(words, salt) {
|
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
// src/custody-share.ts
|
|
177
|
+
import { ml_dsa65 } from "@noble/post-quantum/ml-dsa.js";
|
|
178
|
+
import { hkdf as hkdf3 } from "@noble/hashes/hkdf.js";
|
|
179
|
+
import { sha256 as sha2563 } from "@noble/hashes/sha2.js";
|
|
180
|
+
var CUSTODY_ENVELOPE_VERSION = 3;
|
|
181
|
+
var CUSTODY_ENVELOPE_SUITE = "ml-kem-768+x25519+hkdf-sha256+aes-256-gcm+ml-dsa-65";
|
|
182
|
+
var CUSTODY_FACTOR_PROOF_VERSION = 1;
|
|
177
183
|
var KEY_BYTES3 = 32;
|
|
178
184
|
var MIN_PRF_BYTES = 32;
|
|
179
185
|
var PASSKEY_KEY_SALT = "forgezero:custodian:passkey:v1";
|
|
186
|
+
function isCustodyEnvelopeV3(value) {
|
|
187
|
+
return value.version === CUSTODY_ENVELOPE_VERSION && value.suite === CUSTODY_ENVELOPE_SUITE;
|
|
188
|
+
}
|
|
180
189
|
var utf82 = (value) => new TextEncoder().encode(value);
|
|
181
190
|
var toBase642 = (bytes) => {
|
|
182
191
|
let binary = "";
|
|
@@ -283,31 +292,167 @@ function phraseWrappingKey(custodianKey, phraseWords, salt) {
|
|
|
283
292
|
function wrappingKeysFor(args) {
|
|
284
293
|
if (!args.passkeyCredentialId)
|
|
285
294
|
throw new Error("custody-share: passkey credential id is required");
|
|
295
|
+
if (!/^[A-Za-z0-9_-]{43}$/.test(args.passkeyPrfSalt)) {
|
|
296
|
+
throw new Error("custody-share: ceremony passkey PRF salt is required");
|
|
297
|
+
}
|
|
286
298
|
const salt = newSalt();
|
|
287
299
|
const passkey = passkeyWrappingKey(args.custodianKey, args.passkeyPrfOutput);
|
|
288
300
|
const phrase = phraseWrappingKey(args.custodianKey, args.phraseWords, salt);
|
|
301
|
+
const passkeyAction = custodyFactorActionKeyPair("ceremony_passkey", args.custodianKey, args.passkeyPrfOutput);
|
|
302
|
+
const phraseMaterial = phraseToKey(args.phraseWords, salt);
|
|
303
|
+
const phraseAction = custodyFactorActionKeyPair("recovery_phrase", args.custodianKey, phraseMaterial);
|
|
289
304
|
try {
|
|
290
305
|
return {
|
|
291
306
|
passkeyCredentialId: args.passkeyCredentialId,
|
|
307
|
+
passkeyPrfSalt: args.passkeyPrfSalt,
|
|
292
308
|
passkeyPublicKey: toBase642(passkey.publicKey),
|
|
293
309
|
phrasePublicKey: toBase642(phrase.publicKey),
|
|
294
310
|
phraseSalt: toBase642(salt),
|
|
295
|
-
phraseVerifier: phraseVerifier(args.phraseWords, salt)
|
|
311
|
+
phraseVerifier: phraseVerifier(args.phraseWords, salt),
|
|
312
|
+
passkeyActionPublicKey: toBase642(passkeyAction.publicKey),
|
|
313
|
+
phraseActionPublicKey: toBase642(phraseAction.publicKey)
|
|
296
314
|
};
|
|
297
315
|
} finally {
|
|
298
316
|
passkey.secretKey.fill(0);
|
|
299
317
|
phrase.secretKey.fill(0);
|
|
318
|
+
passkeyAction.secretKey.fill(0);
|
|
319
|
+
phraseAction.secretKey.fill(0);
|
|
320
|
+
phraseMaterial.fill(0);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
var actionInfo = (factor, custodianKey) => `forgezero:custody:factor-action:ml-dsa-65:v1:${factor}:${custodianKey.length}:${custodianKey}`;
|
|
324
|
+
function custodyFactorActionKeyPair(factor, custodianKey, factorMaterial) {
|
|
325
|
+
assertCustodianKey(custodianKey);
|
|
326
|
+
if (factorMaterial.length < 32)
|
|
327
|
+
throw new Error("custody-share: action factor must be at least 32 bytes");
|
|
328
|
+
const seed = hkdf3(sha2563, factorMaterial, utf82("forgezero:custody:factor-action:ml-dsa-65:v1"), utf82(actionInfo(factor, custodianKey)), 32);
|
|
329
|
+
try {
|
|
330
|
+
const pair = ml_dsa65.keygen(seed);
|
|
331
|
+
return { publicKey: Uint8Array.from(pair.publicKey), secretKey: Uint8Array.from(pair.secretKey) };
|
|
332
|
+
} finally {
|
|
333
|
+
seed.fill(0);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
function custodyFactorActionPublicKey(factor, custodianKey, factorMaterial) {
|
|
337
|
+
const pair = custodyFactorActionKeyPair(factor, custodianKey, factorMaterial);
|
|
338
|
+
try {
|
|
339
|
+
return toBase642(pair.publicKey);
|
|
340
|
+
} finally {
|
|
341
|
+
pair.secretKey.fill(0);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
var proofBytes = (binding) => {
|
|
345
|
+
const values = [
|
|
346
|
+
"forgezero-custody-factor-proof-v1",
|
|
347
|
+
String(binding.version),
|
|
348
|
+
binding.realmId,
|
|
349
|
+
binding.ceremonyKey,
|
|
350
|
+
binding.custodianKey,
|
|
351
|
+
binding.factor,
|
|
352
|
+
binding.requestKey,
|
|
353
|
+
binding.method,
|
|
354
|
+
binding.path,
|
|
355
|
+
binding.payloadDigest,
|
|
356
|
+
binding.challenge,
|
|
357
|
+
String(binding.expiresAtSec)
|
|
358
|
+
];
|
|
359
|
+
return utf82(values.map((value) => `${utf82(value).length}:${value}`).join(`
|
|
360
|
+
`));
|
|
361
|
+
};
|
|
362
|
+
function canonicalJson(value) {
|
|
363
|
+
if (value === null || typeof value === "boolean" || typeof value === "string")
|
|
364
|
+
return JSON.stringify(value);
|
|
365
|
+
if (typeof value === "number") {
|
|
366
|
+
if (!Number.isFinite(value))
|
|
367
|
+
throw new Error("custody-share: non-finite action payload number");
|
|
368
|
+
return JSON.stringify(value);
|
|
369
|
+
}
|
|
370
|
+
if (Array.isArray(value))
|
|
371
|
+
return `[${value.map(canonicalJson).join(",")}]`;
|
|
372
|
+
if (typeof value === "object") {
|
|
373
|
+
return `{${Object.entries(value).filter(([, item]) => item !== undefined).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${canonicalJson(item)}`).join(",")}}`;
|
|
374
|
+
}
|
|
375
|
+
throw new Error("custody-share: unsupported action payload value");
|
|
376
|
+
}
|
|
377
|
+
function custodyActionPayloadDigest(value) {
|
|
378
|
+
return Array.from(sha2563(utf82(canonicalJson(value))), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
379
|
+
}
|
|
380
|
+
function createCustodyFactorProof(args) {
|
|
381
|
+
if (args.binding.version !== CUSTODY_FACTOR_PROOF_VERSION) {
|
|
382
|
+
throw new Error("custody-share: unsupported factor proof version");
|
|
383
|
+
}
|
|
384
|
+
const pair = custodyFactorActionKeyPair(args.binding.factor, args.binding.custodianKey, args.factorMaterial);
|
|
385
|
+
try {
|
|
386
|
+
const signature = toBase642(ml_dsa65.sign(proofBytes(args.binding), pair.secretKey));
|
|
387
|
+
return args.binding.factor === "ceremony_passkey" ? {
|
|
388
|
+
version: CUSTODY_FACTOR_PROOF_VERSION,
|
|
389
|
+
factor: "ceremony_passkey",
|
|
390
|
+
credentialId: args.credentialId ?? "",
|
|
391
|
+
signature
|
|
392
|
+
} : { version: CUSTODY_FACTOR_PROOF_VERSION, factor: "recovery_phrase", signature };
|
|
393
|
+
} finally {
|
|
394
|
+
pair.secretKey.fill(0);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
function createCustodyPasskeyProof(binding, passkeyPrfOutput, credentialId) {
|
|
398
|
+
if (binding.factor !== "ceremony_passkey") {
|
|
399
|
+
throw new Error("custody-share: passkey proof requires ceremony_passkey binding");
|
|
400
|
+
}
|
|
401
|
+
return createCustodyFactorProof({
|
|
402
|
+
binding,
|
|
403
|
+
factorMaterial: passkeyPrfOutput,
|
|
404
|
+
credentialId
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
function createCustodyPhraseProof(binding, phraseWords, phraseSalt) {
|
|
408
|
+
if (binding.factor !== "recovery_phrase") {
|
|
409
|
+
throw new Error("custody-share: phrase proof requires recovery_phrase binding");
|
|
410
|
+
}
|
|
411
|
+
if (!validatePhrase(phraseWords))
|
|
412
|
+
throw new Error("INVALID_PHRASE");
|
|
413
|
+
const material = phraseToKey(phraseWords, fromBase642(phraseSalt));
|
|
414
|
+
try {
|
|
415
|
+
return createCustodyFactorProof({ binding, factorMaterial: material });
|
|
416
|
+
} finally {
|
|
417
|
+
material.fill(0);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
function verifyCustodyFactorProof(args) {
|
|
421
|
+
try {
|
|
422
|
+
if (args.proof.version !== CUSTODY_FACTOR_PROOF_VERSION || args.proof.factor !== args.binding.factor)
|
|
423
|
+
return false;
|
|
424
|
+
const publicKey = fromBase642(args.publicKey);
|
|
425
|
+
const signature = fromBase642(args.proof.signature);
|
|
426
|
+
return publicKey.length === ml_dsa65.lengths.publicKey && signature.length === ml_dsa65.lengths.signature && ml_dsa65.verify(signature, proofBytes(args.binding), publicKey);
|
|
427
|
+
} catch {
|
|
428
|
+
return false;
|
|
300
429
|
}
|
|
301
430
|
}
|
|
302
431
|
function openSealedToFactor(args) {
|
|
303
432
|
const pair = args.factor === "passkey" ? passkeyWrappingKey(args.custodianKey, args.passkeyPrfOutput) : phraseWrappingKey(args.custodianKey, args.phraseWords, fromBase642(args.phraseSalt));
|
|
304
433
|
try {
|
|
305
|
-
return openFromKey(pair.secretKey, args.box, wrapInfo(args.custodianKey, args.factor));
|
|
434
|
+
return openFromKey(pair.secretKey, args.box, args.aad ?? wrapInfo(args.custodianKey, args.factor));
|
|
306
435
|
} finally {
|
|
307
436
|
pair.secretKey.fill(0);
|
|
308
437
|
}
|
|
309
438
|
}
|
|
310
439
|
var factorWrapAad = (custodianKey, factor) => wrapInfo(custodianKey, factor);
|
|
440
|
+
function custodyEnvelopeV3Aad(envelope, factor) {
|
|
441
|
+
const values = [
|
|
442
|
+
"forgezero-custody-envelope-aad",
|
|
443
|
+
String(envelope.version),
|
|
444
|
+
envelope.suite,
|
|
445
|
+
envelope.realmId,
|
|
446
|
+
envelope.ceremonyKey,
|
|
447
|
+
envelope.custodianKey,
|
|
448
|
+
String(envelope.shareIndex),
|
|
449
|
+
factor,
|
|
450
|
+
factor === "passkey" ? envelope.passkeyCredentialId : "recovery_phrase",
|
|
451
|
+
String(factor === "passkey" ? envelope.passkeyGeneration ?? envelope.generation : envelope.phraseGeneration ?? envelope.generation)
|
|
452
|
+
];
|
|
453
|
+
return values.map((value) => `${utf82(value).length}:${value}`).join(`
|
|
454
|
+
`);
|
|
455
|
+
}
|
|
311
456
|
var PROBE_BYTES = 32;
|
|
312
457
|
function joinProbeAndShare(probe, share) {
|
|
313
458
|
if (probe.length !== PROBE_BYTES)
|
|
@@ -324,17 +469,20 @@ function splitProbeAndShare(opened) {
|
|
|
324
469
|
}
|
|
325
470
|
function openFactorEnvelope(args) {
|
|
326
471
|
const box = args.factor === "passkey" ? args.sealed.passkeyEnvelope : args.sealed.phraseEnvelope;
|
|
472
|
+
const aad = isCustodyEnvelopeV3(args.sealed) ? custodyEnvelopeV3Aad(args.sealed, args.factor) : undefined;
|
|
327
473
|
return splitProbeAndShare(openSealedToFactor({
|
|
328
474
|
custodianKey: args.custodianKey,
|
|
329
475
|
factor: args.factor,
|
|
330
476
|
box,
|
|
331
477
|
passkeyPrfOutput: args.passkeyPrfOutput,
|
|
332
478
|
phraseWords: args.phraseWords,
|
|
333
|
-
phraseSalt: args.sealed.phraseSalt
|
|
479
|
+
phraseSalt: args.sealed.phraseSalt,
|
|
480
|
+
aad
|
|
334
481
|
}));
|
|
335
482
|
}
|
|
336
483
|
export {
|
|
337
484
|
wrappingKeysFor,
|
|
485
|
+
verifyCustodyFactorProof,
|
|
338
486
|
splitProbeAndShare,
|
|
339
487
|
shareIndexOf,
|
|
340
488
|
sealShare,
|
|
@@ -345,6 +493,16 @@ export {
|
|
|
345
493
|
openSealedToFactor,
|
|
346
494
|
openFactorEnvelope,
|
|
347
495
|
joinProbeAndShare,
|
|
496
|
+
isCustodyEnvelopeV3,
|
|
348
497
|
factorWrapAad,
|
|
349
|
-
|
|
498
|
+
custodyFactorActionPublicKey,
|
|
499
|
+
custodyEnvelopeV3Aad,
|
|
500
|
+
custodyActionPayloadDigest,
|
|
501
|
+
createCustodyPhraseProof,
|
|
502
|
+
createCustodyPasskeyProof,
|
|
503
|
+
createCustodyFactorProof,
|
|
504
|
+
PROBE_BYTES,
|
|
505
|
+
CUSTODY_FACTOR_PROOF_VERSION,
|
|
506
|
+
CUSTODY_ENVELOPE_VERSION,
|
|
507
|
+
CUSTODY_ENVELOPE_SUITE
|
|
350
508
|
};
|