@learncard/sss-key-manager 0.2.2 → 0.2.3
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/dist/escrow-authority.d.ts +26 -0
- package/dist/escrow-authority.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/sss-key-manager.cjs.development.js +60 -1
- package/dist/sss-key-manager.cjs.development.js.map +2 -2
- package/dist/sss-key-manager.cjs.production.min.js +5 -5
- package/dist/sss-key-manager.cjs.production.min.js.map +3 -3
- package/dist/sss-key-manager.esm.js +60 -1
- package/dist/sss-key-manager.esm.js.map +2 -2
- package/dist/sss-strategy.d.ts +2 -1
- package/dist/sss-strategy.d.ts.map +1 -1
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/escrow-authority.test.ts +114 -0
- package/src/escrow-authority.ts +74 -0
- package/src/index.ts +2 -0
- package/src/sss-strategy.test.ts +32 -0
- package/src/sss-strategy.ts +24 -1
- package/src/types.ts +5 -0
package/dist/sss-strategy.d.ts
CHANGED
|
@@ -59,7 +59,8 @@ export declare const SERVER_REQUEST_TIMEOUT_MS = 30000;
|
|
|
59
59
|
/** HTTP failure metadata without potentially sensitive server response text. */
|
|
60
60
|
export declare class EscrowRequestError extends Error {
|
|
61
61
|
readonly status: number;
|
|
62
|
-
|
|
62
|
+
readonly reason?: "codeMismatch" | "codeExpired" | "codeLocked" | undefined;
|
|
63
|
+
constructor(status: number, reason?: "codeMismatch" | "codeExpired" | "codeLocked" | undefined);
|
|
63
64
|
}
|
|
64
65
|
/**
|
|
65
66
|
* Signals that an identity-recovery attempt failed after the one-shot server
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sss-strategy.d.ts","sourceRoot":"","sources":["../src/sss-strategy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EACR,wBAAwB,EAaxB,uBAAuB,EAI1B,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"sss-strategy.d.ts","sourceRoot":"","sources":["../src/sss-strategy.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -63,6 +63,11 @@ export interface EscrowHoldStatus {
|
|
|
63
63
|
}
|
|
64
64
|
/** Persist these secrets securely until completion; a null token means an existing hold. */
|
|
65
65
|
export type EscrowRecoveryStart = EscrowHoldStatus & {
|
|
66
|
+
codeSent?: boolean;
|
|
67
|
+
delivery?: {
|
|
68
|
+
codeSent: boolean;
|
|
69
|
+
proof: import('./escrow-authority.types').EscrowAuthorityRecord;
|
|
70
|
+
};
|
|
66
71
|
/** Persist with the secrets, never rebuild from server status. Required for Nitro resume. */
|
|
67
72
|
expectations?: import('@learncard/types').EscrowRecoveryExpectations;
|
|
68
73
|
resumeToken: string | null;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@learncard/sss-key-manager",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Shamir Secret Sharing key manager for LearnCard - replaces Web3Auth SFA",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/sss-key-manager.esm.js",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"vitest": "4.1.11"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@learncard/types": "5.23.
|
|
42
|
+
"@learncard/types": "5.23.2",
|
|
43
43
|
"@noble/ed25519": "^2.0.0",
|
|
44
44
|
"@peculiar/x509": "^2.1.0",
|
|
45
45
|
"@scure/bip39": "^1.2.1",
|
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
verifyEscrowAuthorityState,
|
|
7
7
|
verifyEscrowEnrollmentCommit,
|
|
8
8
|
verifyEscrowHoldRecord,
|
|
9
|
+
verifyEscrowCodeDelivery,
|
|
10
|
+
verifyEscrowHoldState,
|
|
9
11
|
verifyEscrowHoldConfirmation,
|
|
10
12
|
createEscrowEnrollmentIntent,
|
|
11
13
|
resolveEscrowEnrollmentAction,
|
|
@@ -436,6 +438,118 @@ describe('verifyEscrowHoldRecord / verifyEscrowHoldConfirmation (client-boundary
|
|
|
436
438
|
ledgerSeq: 0,
|
|
437
439
|
});
|
|
438
440
|
|
|
441
|
+
it('authenticates delivery failure and rejects transplanted or altered delivery evidence', async () => {
|
|
442
|
+
const { sign, identity } = await makeSigner();
|
|
443
|
+
const expected = {
|
|
444
|
+
tenant: 'learncard',
|
|
445
|
+
authorityGeneration: 'g1',
|
|
446
|
+
holdDigest: 'ab'.repeat(32),
|
|
447
|
+
};
|
|
448
|
+
const proof = await sign('snapshot', [
|
|
449
|
+
'learncard-authority-code-delivery-v1',
|
|
450
|
+
expected.tenant,
|
|
451
|
+
expected.authorityGeneration,
|
|
452
|
+
expected.holdDigest,
|
|
453
|
+
false,
|
|
454
|
+
]);
|
|
455
|
+
await expect(
|
|
456
|
+
verifyEscrowCodeDelivery({ codeSent: false, proof }, expected, identity)
|
|
457
|
+
).resolves.toBe(false);
|
|
458
|
+
await expect(
|
|
459
|
+
verifyEscrowCodeDelivery({ codeSent: true, proof }, expected, identity)
|
|
460
|
+
).rejects.toThrow();
|
|
461
|
+
for (const changed of [
|
|
462
|
+
{ tenant: 'other' },
|
|
463
|
+
{ authorityGeneration: 'g2' },
|
|
464
|
+
{ holdDigest: '00'.repeat(32) },
|
|
465
|
+
]) {
|
|
466
|
+
await expect(
|
|
467
|
+
verifyEscrowCodeDelivery(
|
|
468
|
+
{ codeSent: false, proof },
|
|
469
|
+
{ ...expected, ...changed },
|
|
470
|
+
identity
|
|
471
|
+
)
|
|
472
|
+
).rejects.toThrow();
|
|
473
|
+
}
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
it('verifies nonce-bound hold reads and rejects replay, scope substitution and malformed state', async () => {
|
|
477
|
+
const { sign, identity } = await makeSigner();
|
|
478
|
+
const nonce = 'ab'.repeat(32);
|
|
479
|
+
const expected = {
|
|
480
|
+
tenant: 'learncard',
|
|
481
|
+
authorityGeneration: 'g1',
|
|
482
|
+
did,
|
|
483
|
+
holdId: 'hold-1',
|
|
484
|
+
holdDigest: 'cd'.repeat(32),
|
|
485
|
+
};
|
|
486
|
+
const payload = [
|
|
487
|
+
'learncard-authority-hold-state-v3',
|
|
488
|
+
nonce,
|
|
489
|
+
expected.tenant,
|
|
490
|
+
expected.authorityGeneration,
|
|
491
|
+
did,
|
|
492
|
+
expected.holdId,
|
|
493
|
+
expected.holdDigest,
|
|
494
|
+
'pending',
|
|
495
|
+
1000,
|
|
496
|
+
2000,
|
|
497
|
+
4,
|
|
498
|
+
'unknown',
|
|
499
|
+
];
|
|
500
|
+
const response = { proof: await sign('snapshot', payload) };
|
|
501
|
+
await expect(verifyEscrowHoldState(response, nonce, expected, identity)).resolves.toEqual({
|
|
502
|
+
status: 'pending',
|
|
503
|
+
confirmedHiMs: 1000,
|
|
504
|
+
releaseWarningSentHiMs: 2000,
|
|
505
|
+
attemptsRemaining: 4,
|
|
506
|
+
codeSendStatus: 'unknown',
|
|
507
|
+
});
|
|
508
|
+
await expect(
|
|
509
|
+
verifyEscrowHoldState(response, 'ff'.repeat(32), expected, identity)
|
|
510
|
+
).rejects.toThrow();
|
|
511
|
+
for (const changed of [
|
|
512
|
+
{ tenant: 'other' },
|
|
513
|
+
{ authorityGeneration: 'g2' },
|
|
514
|
+
{ did: 'other' },
|
|
515
|
+
{ holdId: 'other' },
|
|
516
|
+
{ holdDigest: '00'.repeat(32) },
|
|
517
|
+
]) {
|
|
518
|
+
await expect(
|
|
519
|
+
verifyEscrowHoldState(response, nonce, { ...expected, ...changed }, identity)
|
|
520
|
+
).rejects.toThrow();
|
|
521
|
+
}
|
|
522
|
+
for (const [index, value] of [
|
|
523
|
+
[7, 'invalid'],
|
|
524
|
+
[8, -1],
|
|
525
|
+
[10, 6],
|
|
526
|
+
[11, 'sent'],
|
|
527
|
+
] as const) {
|
|
528
|
+
const malformed = [...payload];
|
|
529
|
+
malformed[index] = value;
|
|
530
|
+
await expect(
|
|
531
|
+
verifyEscrowHoldState(
|
|
532
|
+
{ proof: await sign('snapshot', malformed) },
|
|
533
|
+
nonce,
|
|
534
|
+
expected,
|
|
535
|
+
identity
|
|
536
|
+
)
|
|
537
|
+
).rejects.toThrow();
|
|
538
|
+
}
|
|
539
|
+
await expect(
|
|
540
|
+
verifyEscrowHoldState(
|
|
541
|
+
{ proof: await sign('commit', payload) },
|
|
542
|
+
nonce,
|
|
543
|
+
expected,
|
|
544
|
+
identity
|
|
545
|
+
)
|
|
546
|
+
).rejects.toThrow();
|
|
547
|
+
const other = await makeSigner();
|
|
548
|
+
await expect(
|
|
549
|
+
verifyEscrowHoldState(response, nonce, expected, other.identity)
|
|
550
|
+
).rejects.toThrow();
|
|
551
|
+
});
|
|
552
|
+
|
|
439
553
|
const signedHoldRecord = async (
|
|
440
554
|
sign: Awaited<ReturnType<typeof makeSigner>>['sign'],
|
|
441
555
|
record: EscrowHoldRecordLike
|
package/src/escrow-authority.ts
CHANGED
|
@@ -23,6 +23,80 @@ import type {
|
|
|
23
23
|
const fail = (): never => {
|
|
24
24
|
throw new EscrowEvidenceError();
|
|
25
25
|
};
|
|
26
|
+
|
|
27
|
+
/** Verify a fresh hold-state response using an independently retained hold binding
|
|
28
|
+
* and a newly generated 32-byte nonce. Never reuse the nonce for another read. */
|
|
29
|
+
export const verifyEscrowHoldState = async (
|
|
30
|
+
response: { proof: unknown },
|
|
31
|
+
nonce: string,
|
|
32
|
+
expected: {
|
|
33
|
+
tenant: string;
|
|
34
|
+
authorityGeneration: string;
|
|
35
|
+
did: string;
|
|
36
|
+
holdId: string;
|
|
37
|
+
holdDigest: string;
|
|
38
|
+
},
|
|
39
|
+
identity: VerifiedEnclaveIdentity
|
|
40
|
+
): Promise<{
|
|
41
|
+
status: 'awaitingConfirmation' | 'pending' | 'released' | 'cancelled';
|
|
42
|
+
confirmedHiMs: number | null;
|
|
43
|
+
releaseWarningSentHiMs: number | null;
|
|
44
|
+
attemptsRemaining: number;
|
|
45
|
+
codeSendStatus: 'unknown' | 'notRequired';
|
|
46
|
+
}> => {
|
|
47
|
+
requireEvidence(/^[0-9a-f]{64}$/.test(nonce));
|
|
48
|
+
const { payload } = await verifyRecord(response.proof, 'snapshot', identity);
|
|
49
|
+
requireEvidence(Array.isArray(payload) && payload.length === 12);
|
|
50
|
+
const p = payload as unknown[];
|
|
51
|
+
requireEvidence(
|
|
52
|
+
p[0] === 'learncard-authority-hold-state-v3' &&
|
|
53
|
+
p[1] === nonce &&
|
|
54
|
+
p[2] === expected.tenant &&
|
|
55
|
+
p[3] === expected.authorityGeneration &&
|
|
56
|
+
p[4] === expected.did &&
|
|
57
|
+
p[5] === expected.holdId &&
|
|
58
|
+
p[6] === expected.holdDigest
|
|
59
|
+
);
|
|
60
|
+
const status = p[7];
|
|
61
|
+
if (
|
|
62
|
+
status !== 'awaitingConfirmation' &&
|
|
63
|
+
status !== 'pending' &&
|
|
64
|
+
status !== 'released' &&
|
|
65
|
+
status !== 'cancelled'
|
|
66
|
+
)
|
|
67
|
+
return fail();
|
|
68
|
+
const confirmedHiMs = p[8] === null ? null : integer(p[8]);
|
|
69
|
+
const releaseWarningSentHiMs = p[9] === null ? null : integer(p[9]);
|
|
70
|
+
const attemptsRemaining = integer(p[10], 0, 5);
|
|
71
|
+
const codeSendStatus = p[11];
|
|
72
|
+
if (codeSendStatus !== 'unknown' && codeSendStatus !== 'notRequired') return fail();
|
|
73
|
+
requireEvidence(
|
|
74
|
+
status !== 'awaitingConfirmation' ||
|
|
75
|
+
(confirmedHiMs === null && releaseWarningSentHiMs === null)
|
|
76
|
+
);
|
|
77
|
+
requireEvidence((status !== 'pending' && status !== 'released') || confirmedHiMs !== null);
|
|
78
|
+
return { status, confirmedHiMs, releaseWarningSentHiMs, attemptsRemaining, codeSendStatus };
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/** Authenticate advisory send acceptance without changing the immutable hold commitment. */
|
|
82
|
+
export const verifyEscrowCodeDelivery = async (
|
|
83
|
+
delivery: { codeSent: boolean; proof: unknown },
|
|
84
|
+
expected: { tenant: string; authorityGeneration: string; holdDigest: string },
|
|
85
|
+
identity: VerifiedEnclaveIdentity
|
|
86
|
+
): Promise<boolean> => {
|
|
87
|
+
const { payload } = await verifyRecord(delivery.proof, 'snapshot', identity);
|
|
88
|
+
requireEvidence(Array.isArray(payload) && payload.length === 5);
|
|
89
|
+
const values = payload as unknown[];
|
|
90
|
+
requireEvidence(
|
|
91
|
+
values[0] === 'learncard-authority-code-delivery-v1' &&
|
|
92
|
+
values[1] === expected.tenant &&
|
|
93
|
+
values[2] === expected.authorityGeneration &&
|
|
94
|
+
values[3] === expected.holdDigest &&
|
|
95
|
+
typeof values[4] === 'boolean' &&
|
|
96
|
+
values[4] === delivery.codeSent
|
|
97
|
+
);
|
|
98
|
+
return delivery.codeSent;
|
|
99
|
+
};
|
|
26
100
|
const requireEvidence = (condition: boolean): void => {
|
|
27
101
|
if (!condition) fail();
|
|
28
102
|
};
|
package/src/index.ts
CHANGED
|
@@ -92,6 +92,8 @@ export type { HistoricalEscrowEvidence } from './escrow-authority.types';
|
|
|
92
92
|
export type { EscrowRecoveryExpectations } from '@learncard/types';
|
|
93
93
|
export {
|
|
94
94
|
verifyEscrowAuthorityState,
|
|
95
|
+
verifyEscrowHoldState,
|
|
96
|
+
verifyEscrowCodeDelivery,
|
|
95
97
|
verifyEscrowEnrollmentCommit,
|
|
96
98
|
createEscrowEnrollmentIntent,
|
|
97
99
|
resolveEscrowEnrollmentAction,
|
package/src/sss-strategy.test.ts
CHANGED
|
@@ -458,6 +458,38 @@ describe('escrow strategy', () => {
|
|
|
458
458
|
});
|
|
459
459
|
});
|
|
460
460
|
|
|
461
|
+
it.each(
|
|
462
|
+
[
|
|
463
|
+
'codeMismatch',
|
|
464
|
+
'codeExpired',
|
|
465
|
+
'codeLocked',
|
|
466
|
+
'secret response',
|
|
467
|
+
null,
|
|
468
|
+
403,
|
|
469
|
+
{ code: 'codeMismatch' },
|
|
470
|
+
['codeLocked'],
|
|
471
|
+
].map(message => ({ message }))
|
|
472
|
+
)('only exposes allowlisted code refusal metadata: %s', async ({ message }) => {
|
|
473
|
+
vi.spyOn(globalThis, 'fetch').mockResolvedValue(
|
|
474
|
+
new Response(JSON.stringify({ message }), { status: 403 })
|
|
475
|
+
);
|
|
476
|
+
await expect(
|
|
477
|
+
strategy.confirmEscrowRecovery!({
|
|
478
|
+
holdId: 'hold',
|
|
479
|
+
resumeToken: 'resume',
|
|
480
|
+
code: '12345678',
|
|
481
|
+
})
|
|
482
|
+
).rejects.toMatchObject({
|
|
483
|
+
name: 'EscrowRequestError',
|
|
484
|
+
status: 403,
|
|
485
|
+
message: 'Escrow request failed',
|
|
486
|
+
reason:
|
|
487
|
+
message === 'codeMismatch' || message === 'codeExpired' || message === 'codeLocked'
|
|
488
|
+
? message
|
|
489
|
+
: undefined,
|
|
490
|
+
});
|
|
491
|
+
});
|
|
492
|
+
|
|
461
493
|
it('exposes the precondition status without exposing the response body', async () => {
|
|
462
494
|
optOutStatus = 412;
|
|
463
495
|
await expect(strategy.disableEscrowRecovery!(params)).rejects.toMatchObject({
|
package/src/sss-strategy.ts
CHANGED
|
@@ -59,6 +59,7 @@ import {
|
|
|
59
59
|
verifyEscrowAuthorityState,
|
|
60
60
|
verifyEscrowEnrollmentCommit,
|
|
61
61
|
verifyEscrowHoldRecord,
|
|
62
|
+
verifyEscrowCodeDelivery,
|
|
62
63
|
verifyEscrowHoldConfirmation,
|
|
63
64
|
escrowAuthorityMeasurements,
|
|
64
65
|
type EscrowHoldRecordLike,
|
|
@@ -198,7 +199,10 @@ type EscrowEnrollmentResult =
|
|
|
198
199
|
|
|
199
200
|
/** HTTP failure metadata without potentially sensitive server response text. */
|
|
200
201
|
export class EscrowRequestError extends Error {
|
|
201
|
-
constructor(
|
|
202
|
+
constructor(
|
|
203
|
+
public readonly status: number,
|
|
204
|
+
public readonly reason?: 'codeMismatch' | 'codeExpired' | 'codeLocked'
|
|
205
|
+
) {
|
|
202
206
|
super('Escrow request failed');
|
|
203
207
|
this.name = 'EscrowRequestError';
|
|
204
208
|
}
|
|
@@ -1099,6 +1103,22 @@ export function createSSSStrategy(config: SSSStrategyConfig): SSSKeyDerivationSt
|
|
|
1099
1103
|
});
|
|
1100
1104
|
// Never propagate response bodies or status text that could contain secrets.
|
|
1101
1105
|
if (!response.ok) {
|
|
1106
|
+
if (path === '/confirm' && response.status === 403) {
|
|
1107
|
+
const body: unknown = await response.json().catch(() => undefined);
|
|
1108
|
+
const reason =
|
|
1109
|
+
body &&
|
|
1110
|
+
typeof body === 'object' &&
|
|
1111
|
+
'message' in body &&
|
|
1112
|
+
typeof body.message === 'string'
|
|
1113
|
+
? body.message
|
|
1114
|
+
: undefined;
|
|
1115
|
+
throw new EscrowRequestError(
|
|
1116
|
+
response.status,
|
|
1117
|
+
reason === 'codeMismatch' || reason === 'codeExpired' || reason === 'codeLocked'
|
|
1118
|
+
? reason
|
|
1119
|
+
: undefined
|
|
1120
|
+
);
|
|
1121
|
+
}
|
|
1102
1122
|
if (!pinAttempt && path === '/recover' && response.status === 429) {
|
|
1103
1123
|
const body: unknown = await response.json().catch(() => undefined);
|
|
1104
1124
|
const message =
|
|
@@ -2334,6 +2354,9 @@ export function createSSSStrategy(config: SSSStrategyConfig): SSSKeyDerivationSt
|
|
|
2334
2354
|
ledgerPublicKey: identity.authority.ledgerPublicKey,
|
|
2335
2355
|
keyId: verified.receipt.keyId,
|
|
2336
2356
|
};
|
|
2357
|
+
result.codeSent = result.delivery
|
|
2358
|
+
? await verifyEscrowCodeDelivery(result.delivery, expectations, identity)
|
|
2359
|
+
: undefined;
|
|
2337
2360
|
}
|
|
2338
2361
|
// Never accept a server-supplied expectations object, even in software mode.
|
|
2339
2362
|
return { ...result, clientEphemeralPrivateKey: pair.privateKey, expectations };
|
package/src/types.ts
CHANGED
|
@@ -104,6 +104,11 @@ export interface EscrowHoldStatus {
|
|
|
104
104
|
|
|
105
105
|
/** Persist these secrets securely until completion; a null token means an existing hold. */
|
|
106
106
|
export type EscrowRecoveryStart = EscrowHoldStatus & {
|
|
107
|
+
codeSent?: boolean;
|
|
108
|
+
delivery?: {
|
|
109
|
+
codeSent: boolean;
|
|
110
|
+
proof: import('./escrow-authority.types').EscrowAuthorityRecord;
|
|
111
|
+
};
|
|
107
112
|
/** Persist with the secrets, never rebuild from server status. Required for Nitro resume. */
|
|
108
113
|
expectations?: import('@learncard/types').EscrowRecoveryExpectations;
|
|
109
114
|
resumeToken: string | null;
|