@learncard/sss-key-manager 0.2.6 → 0.2.7
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/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/sss-key-manager.cjs.development.js +56 -16
- package/dist/sss-key-manager.cjs.development.js.map +2 -2
- package/dist/sss-key-manager.cjs.production.min.js +23 -23
- package/dist/sss-key-manager.cjs.production.min.js.map +3 -3
- package/dist/sss-key-manager.esm.js +56 -16
- package/dist/sss-key-manager.esm.js.map +2 -2
- package/dist/sss-strategy.d.ts.map +1 -1
- package/dist/types.d.ts +28 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +6 -1
- package/src/sss-strategy.test.ts +238 -0
- package/src/sss-strategy.ts +179 -96
- package/src/types.ts +29 -0
|
@@ -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,
|
|
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
|
@@ -78,6 +78,28 @@ export type EscrowRecoveryStart = EscrowHoldStatus & {
|
|
|
78
78
|
export declare class EscrowPinUnavailableError extends Error {
|
|
79
79
|
constructor();
|
|
80
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* What this client saw during one PIN sign-in flow (own-typos rule, E). A flow starts
|
|
83
|
+
* with the first PIN status read before the first attempt and ends when the sign-in
|
|
84
|
+
* completes; a new modal or app start begins a new flow.
|
|
85
|
+
*/
|
|
86
|
+
export interface EscrowPinAttemptContext {
|
|
87
|
+
/**
|
|
88
|
+
* Verified wrong entries recorded against the PIN when the flow started, before
|
|
89
|
+
* any attempt here. Undefined when the server could not say (legacy record, failed
|
|
90
|
+
* read): treated as "wrong entries recorded".
|
|
91
|
+
*/
|
|
92
|
+
priorWrongAttempts?: number;
|
|
93
|
+
/** Wrong entries this client itself submitted in this flow (mismatch responses). */
|
|
94
|
+
ownWrongAttempts: number;
|
|
95
|
+
/**
|
|
96
|
+
* Salt of the PIN generation the counts belong to (from the flow's first status).
|
|
97
|
+
* A status read during the release that shows another salt (a new PIN, or a
|
|
98
|
+
* same-PIN re-set elsewhere) means the counts describe a different PIN, so they
|
|
99
|
+
* are ignored and the stricter #1905 rule applies.
|
|
100
|
+
*/
|
|
101
|
+
pinSalt?: string;
|
|
102
|
+
}
|
|
81
103
|
/** A failed PIN attempt consumes its hold; another attempt must start a fresh hold. */
|
|
82
104
|
export declare class EscrowPinMismatchError extends Error {
|
|
83
105
|
readonly attemptsRemaining: number;
|
|
@@ -128,6 +150,12 @@ export type RecoveryInput = {
|
|
|
128
150
|
expectedDid?: string;
|
|
129
151
|
/** Verified recovery-email session; set only when no login is bound yet. */
|
|
130
152
|
recoverySessionToken?: string;
|
|
153
|
+
/**
|
|
154
|
+
* Own-typos rule (E): wrong entries this client observed in the current PIN
|
|
155
|
+
* sign-in flow. Omitted by older callers, which keeps the stricter rule (any
|
|
156
|
+
* recorded wrong entry blocks the same-PIN re-set).
|
|
157
|
+
*/
|
|
158
|
+
pinAttempts?: EscrowPinAttemptContext;
|
|
131
159
|
} | {
|
|
132
160
|
method: 'escrow';
|
|
133
161
|
holdId: string;
|
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.7",
|
|
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.24.
|
|
42
|
+
"@learncard/types": "5.24.2",
|
|
43
43
|
"@noble/ed25519": "^2.0.0",
|
|
44
44
|
"@peculiar/x509": "^2.1.0",
|
|
45
45
|
"@scure/bip39": "^1.2.1",
|
package/src/index.ts
CHANGED
|
@@ -108,7 +108,12 @@ export type {
|
|
|
108
108
|
} from './escrow-authority.types';
|
|
109
109
|
export { verifyNitroAttestationDocument, NitroAttestationError } from './escrow-nitro-attestation';
|
|
110
110
|
export type { NitroAttestationReason } from './escrow-nitro-attestation';
|
|
111
|
-
export type {
|
|
111
|
+
export type {
|
|
112
|
+
EscrowAttestationPolicy,
|
|
113
|
+
EscrowHoldStatus,
|
|
114
|
+
EscrowPinAttemptContext,
|
|
115
|
+
EscrowRecoveryStart,
|
|
116
|
+
} from './types';
|
|
112
117
|
export type {
|
|
113
118
|
EscrowEnrollmentOptions,
|
|
114
119
|
EscrowEnrollmentState,
|
package/src/sss-strategy.test.ts
CHANGED
|
@@ -1042,6 +1042,244 @@ describe('escrow strategy', () => {
|
|
|
1042
1042
|
expect(attemptsRemaining).toBe(8);
|
|
1043
1043
|
});
|
|
1044
1044
|
|
|
1045
|
+
describe('own-typos rule (wrong entries made in this sign-in flow)', () => {
|
|
1046
|
+
const recoverInFlow = (
|
|
1047
|
+
pin: string,
|
|
1048
|
+
pinAttempts: { priorWrongAttempts?: number; ownWrongAttempts: number; pinSalt?: string }
|
|
1049
|
+
) =>
|
|
1050
|
+
strategy.executeRecovery({
|
|
1051
|
+
...params,
|
|
1052
|
+
input: { method: 'escrow-pin', pin, pinAttempts },
|
|
1053
|
+
didFromPrivateKey: async key => (key === privateKey ? did : ''),
|
|
1054
|
+
});
|
|
1055
|
+
|
|
1056
|
+
it("refreshes the budget after the user's own typo, sending their wrong entry as expected", async () => {
|
|
1057
|
+
await strategy.setEscrowPin!({ ...params, pin: '135790' });
|
|
1058
|
+
const saltBefore = pinSalt;
|
|
1059
|
+
enrollBodies = [];
|
|
1060
|
+
// Flow starts with a clean PIN; the user mistypes once, then gets it right.
|
|
1061
|
+
await expect(
|
|
1062
|
+
recoverInFlow('246802', { priorWrongAttempts: 0, ownWrongAttempts: 0 })
|
|
1063
|
+
).rejects.toMatchObject({ name: 'EscrowPinMismatchError' });
|
|
1064
|
+
await expect(
|
|
1065
|
+
recoverInFlow('135790', { priorWrongAttempts: 0, ownWrongAttempts: 1 })
|
|
1066
|
+
).resolves.toMatchObject({
|
|
1067
|
+
pinSignIn: { mode: 'kept', pinRefreshed: true, newPinRequired: false },
|
|
1068
|
+
});
|
|
1069
|
+
expect(enrollBodies.at(-1)?.expectedPinCharges).toEqual({
|
|
1070
|
+
attemptsRemaining: 8,
|
|
1071
|
+
wrongAttempts: 1,
|
|
1072
|
+
});
|
|
1073
|
+
expect(pinSalt).not.toBe(saltBefore);
|
|
1074
|
+
expect(attemptsRemaining).toBe(10);
|
|
1075
|
+
expect(wrongAttempts).toBe(0);
|
|
1076
|
+
});
|
|
1077
|
+
|
|
1078
|
+
it('keeps the reduced budget when wrong entries were recorded before the flow started', async () => {
|
|
1079
|
+
await strategy.setEscrowPin!({ ...params, pin: '135790' });
|
|
1080
|
+
// Someone else's guess, before this sign-in.
|
|
1081
|
+
await expect(recoverPin('246802')).rejects.toMatchObject({
|
|
1082
|
+
name: 'EscrowPinMismatchError',
|
|
1083
|
+
});
|
|
1084
|
+
calls = [];
|
|
1085
|
+
await expect(
|
|
1086
|
+
recoverInFlow('135790', { priorWrongAttempts: 1, ownWrongAttempts: 0 })
|
|
1087
|
+
).resolves.toMatchObject({
|
|
1088
|
+
pinSignIn: { mode: 'kept', pinRefreshed: false, newPinRequired: true },
|
|
1089
|
+
});
|
|
1090
|
+
expect(calls.some(call => call.path === '/keys/escrow')).toBe(false);
|
|
1091
|
+
expect(attemptsRemaining).toBe(8);
|
|
1092
|
+
});
|
|
1093
|
+
|
|
1094
|
+
it('does not excuse a foreign wrong entry that landed during the flow', async () => {
|
|
1095
|
+
await strategy.setEscrowPin!({ ...params, pin: '135790' });
|
|
1096
|
+
await expect(
|
|
1097
|
+
recoverInFlow('246802', { priorWrongAttempts: 0, ownWrongAttempts: 0 })
|
|
1098
|
+
).rejects.toMatchObject({ name: 'EscrowPinMismatchError' });
|
|
1099
|
+
// A guess from somewhere else between the user's typo and their right PIN.
|
|
1100
|
+
await expect(recoverPin('975310')).rejects.toMatchObject({
|
|
1101
|
+
name: 'EscrowPinMismatchError',
|
|
1102
|
+
});
|
|
1103
|
+
calls = [];
|
|
1104
|
+
await expect(
|
|
1105
|
+
recoverInFlow('135790', { priorWrongAttempts: 0, ownWrongAttempts: 1 })
|
|
1106
|
+
).resolves.toMatchObject({
|
|
1107
|
+
pinSignIn: { mode: 'kept', pinRefreshed: false, newPinRequired: true },
|
|
1108
|
+
});
|
|
1109
|
+
expect(calls.some(call => call.path === '/keys/escrow')).toBe(false);
|
|
1110
|
+
});
|
|
1111
|
+
|
|
1112
|
+
it('does not excuse a foreign wrong entry that lands during the release', async () => {
|
|
1113
|
+
await strategy.setEscrowPin!({ ...params, pin: '135790' });
|
|
1114
|
+
await expect(
|
|
1115
|
+
recoverInFlow('246802', { priorWrongAttempts: 0, ownWrongAttempts: 0 })
|
|
1116
|
+
).rejects.toMatchObject({ name: 'EscrowPinMismatchError' });
|
|
1117
|
+
const originalFetch = vi.mocked(fetch).getMockImplementation()!;
|
|
1118
|
+
vi.mocked(fetch).mockImplementation(async (url, init) => {
|
|
1119
|
+
const response = await originalFetch(url, init);
|
|
1120
|
+
// A foreign wrong entry resolved right after this release.
|
|
1121
|
+
if (String(url).endsWith('/keys/escrow/complete') && response.ok) {
|
|
1122
|
+
attemptsRemaining--;
|
|
1123
|
+
wrongAttempts = (wrongAttempts ?? 0) + 1;
|
|
1124
|
+
}
|
|
1125
|
+
return response;
|
|
1126
|
+
});
|
|
1127
|
+
calls = [];
|
|
1128
|
+
await expect(
|
|
1129
|
+
recoverInFlow('135790', { priorWrongAttempts: 0, ownWrongAttempts: 1 })
|
|
1130
|
+
).resolves.toMatchObject({
|
|
1131
|
+
pinSignIn: { mode: 'kept', pinRefreshed: false, newPinRequired: true },
|
|
1132
|
+
});
|
|
1133
|
+
expect(calls.some(call => call.path === '/keys/escrow')).toBe(false);
|
|
1134
|
+
});
|
|
1135
|
+
|
|
1136
|
+
it('lets the server refuse the refresh when a foreign wrong entry lands after the checks', async () => {
|
|
1137
|
+
await strategy.setEscrowPin!({ ...params, pin: '135790' });
|
|
1138
|
+
await expect(
|
|
1139
|
+
recoverInFlow('246802', { priorWrongAttempts: 0, ownWrongAttempts: 0 })
|
|
1140
|
+
).rejects.toMatchObject({ name: 'EscrowPinMismatchError' });
|
|
1141
|
+
const originalFetch = vi.mocked(fetch).getMockImplementation()!;
|
|
1142
|
+
vi.mocked(fetch).mockImplementation(async (url, init) => {
|
|
1143
|
+
const path = new URL(String(url)).pathname.replace('/api', '');
|
|
1144
|
+
if (path === '/keys/escrow' && init?.method === 'POST') {
|
|
1145
|
+
attemptsRemaining--;
|
|
1146
|
+
wrongAttempts = (wrongAttempts ?? 0) + 1;
|
|
1147
|
+
}
|
|
1148
|
+
return originalFetch(url, init);
|
|
1149
|
+
});
|
|
1150
|
+
const saltBefore = pinSalt;
|
|
1151
|
+
await expect(
|
|
1152
|
+
recoverInFlow('135790', { priorWrongAttempts: 0, ownWrongAttempts: 1 })
|
|
1153
|
+
).resolves.toMatchObject({
|
|
1154
|
+
// The refused refresh re-checks the status: the foreign entry shows, so
|
|
1155
|
+
// the user gets the warning sheet, not "You're signed in".
|
|
1156
|
+
pinSignIn: {
|
|
1157
|
+
mode: 'kept',
|
|
1158
|
+
pinRefreshed: false,
|
|
1159
|
+
newPinRequired: true,
|
|
1160
|
+
pinRefreshFailed: true,
|
|
1161
|
+
},
|
|
1162
|
+
});
|
|
1163
|
+
expect(pinSalt).toBe(saltBefore);
|
|
1164
|
+
expect(wrongAttempts).toBe(2);
|
|
1165
|
+
});
|
|
1166
|
+
|
|
1167
|
+
it('warns on a 409-refused refresh when the status cannot be re-read', async () => {
|
|
1168
|
+
await strategy.setEscrowPin!({ ...params, pin: '135790' });
|
|
1169
|
+
await expect(
|
|
1170
|
+
recoverInFlow('246802', { priorWrongAttempts: 0, ownWrongAttempts: 0 })
|
|
1171
|
+
).rejects.toMatchObject({ name: 'EscrowPinMismatchError' });
|
|
1172
|
+
const originalFetch = vi.mocked(fetch).getMockImplementation()!;
|
|
1173
|
+
let refused = false;
|
|
1174
|
+
vi.mocked(fetch).mockImplementation(async (url, init) => {
|
|
1175
|
+
const path = new URL(String(url)).pathname.replace('/api', '');
|
|
1176
|
+
if (path === '/keys/escrow' && init?.method === 'POST') {
|
|
1177
|
+
refused = true;
|
|
1178
|
+
return new Response(JSON.stringify({ message: 'changed' }), { status: 409 });
|
|
1179
|
+
}
|
|
1180
|
+
if (refused && path === '/keys/auth-share') throw new TypeError('offline');
|
|
1181
|
+
return originalFetch(url, init);
|
|
1182
|
+
});
|
|
1183
|
+
await expect(
|
|
1184
|
+
recoverInFlow('135790', { priorWrongAttempts: 0, ownWrongAttempts: 1 })
|
|
1185
|
+
).resolves.toMatchObject({
|
|
1186
|
+
pinSignIn: { pinRefreshed: false, newPinRequired: true, pinRefreshFailed: true },
|
|
1187
|
+
});
|
|
1188
|
+
});
|
|
1189
|
+
|
|
1190
|
+
it('ignores flow counts taken against another PIN generation (new salt)', async () => {
|
|
1191
|
+
await strategy.setEscrowPin!({ ...params, pin: '135790' });
|
|
1192
|
+
// The flow's own typo was against an earlier PIN; this record's one wrong
|
|
1193
|
+
// entry is someone else's guess against the current PIN.
|
|
1194
|
+
await expect(recoverPin('246802')).rejects.toMatchObject({
|
|
1195
|
+
name: 'EscrowPinMismatchError',
|
|
1196
|
+
});
|
|
1197
|
+
calls = [];
|
|
1198
|
+
await expect(
|
|
1199
|
+
recoverInFlow('135790', {
|
|
1200
|
+
priorWrongAttempts: 0,
|
|
1201
|
+
ownWrongAttempts: 1,
|
|
1202
|
+
pinSalt: 'an-earlier-generation-salt',
|
|
1203
|
+
})
|
|
1204
|
+
).resolves.toMatchObject({
|
|
1205
|
+
pinSignIn: { mode: 'kept', pinRefreshed: false, newPinRequired: true },
|
|
1206
|
+
});
|
|
1207
|
+
expect(calls.some(call => call.path === '/keys/escrow')).toBe(false);
|
|
1208
|
+
expect(wrongAttempts).toBe(1);
|
|
1209
|
+
});
|
|
1210
|
+
|
|
1211
|
+
it('still refreshes after an own typo when the flow saw the same PIN generation', async () => {
|
|
1212
|
+
await strategy.setEscrowPin!({ ...params, pin: '135790' });
|
|
1213
|
+
const flowSalt = pinSalt;
|
|
1214
|
+
await expect(
|
|
1215
|
+
recoverInFlow('246802', {
|
|
1216
|
+
priorWrongAttempts: 0,
|
|
1217
|
+
ownWrongAttempts: 0,
|
|
1218
|
+
pinSalt: flowSalt,
|
|
1219
|
+
})
|
|
1220
|
+
).rejects.toMatchObject({ name: 'EscrowPinMismatchError' });
|
|
1221
|
+
await expect(
|
|
1222
|
+
recoverInFlow('135790', {
|
|
1223
|
+
priorWrongAttempts: 0,
|
|
1224
|
+
ownWrongAttempts: 1,
|
|
1225
|
+
pinSalt: flowSalt,
|
|
1226
|
+
})
|
|
1227
|
+
).resolves.toMatchObject({
|
|
1228
|
+
pinSignIn: { mode: 'kept', pinRefreshed: true, newPinRequired: false },
|
|
1229
|
+
});
|
|
1230
|
+
});
|
|
1231
|
+
|
|
1232
|
+
it.each([
|
|
1233
|
+
['an unknown prior count', { ownWrongAttempts: 0 }],
|
|
1234
|
+
['an invalid own count', { priorWrongAttempts: 0, ownWrongAttempts: -1 }],
|
|
1235
|
+
])('treats %s as wrong entries recorded', async (_label, pinAttempts) => {
|
|
1236
|
+
await strategy.setEscrowPin!({ ...params, pin: '135790' });
|
|
1237
|
+
calls = [];
|
|
1238
|
+
await expect(recoverInFlow('135790', pinAttempts)).resolves.toMatchObject({
|
|
1239
|
+
pinSignIn: { mode: 'kept', pinRefreshed: false, newPinRequired: true },
|
|
1240
|
+
});
|
|
1241
|
+
expect(calls.some(call => call.path === '/keys/escrow')).toBe(false);
|
|
1242
|
+
});
|
|
1243
|
+
|
|
1244
|
+
it('keeps a legacy record (no verified count) blocked even with a clean prior count', async () => {
|
|
1245
|
+
await strategy.setEscrowPin!({ ...params, pin: '135790' });
|
|
1246
|
+
wrongAttempts = undefined;
|
|
1247
|
+
calls = [];
|
|
1248
|
+
await expect(
|
|
1249
|
+
recoverInFlow('135790', { priorWrongAttempts: 0, ownWrongAttempts: 0 })
|
|
1250
|
+
).resolves.toMatchObject({
|
|
1251
|
+
pinSignIn: { pinRefreshed: false, newPinRequired: true },
|
|
1252
|
+
});
|
|
1253
|
+
expect(calls.some(call => call.path === '/keys/escrow')).toBe(false);
|
|
1254
|
+
});
|
|
1255
|
+
|
|
1256
|
+
it.each([
|
|
1257
|
+
[1, 0, false],
|
|
1258
|
+
[2, 0, true],
|
|
1259
|
+
[1, 1, true],
|
|
1260
|
+
])(
|
|
1261
|
+
'excuses only own typos after a lost-login sign-in (recorded %s, prior %s)',
|
|
1262
|
+
async (recorded, prior, expected) => {
|
|
1263
|
+
await strategy.setEscrowPin!({ ...params, pin: '135790' });
|
|
1264
|
+
wrongAttempts = recorded;
|
|
1265
|
+
await strategy.executeRecovery({
|
|
1266
|
+
token: '',
|
|
1267
|
+
providerType,
|
|
1268
|
+
input: {
|
|
1269
|
+
method: 'escrow-pin',
|
|
1270
|
+
pin: '135790',
|
|
1271
|
+
recoverySessionToken: 'otp',
|
|
1272
|
+
pinAttempts: { priorWrongAttempts: prior, ownWrongAttempts: 1 },
|
|
1273
|
+
},
|
|
1274
|
+
didFromPrivateKey: async () => did,
|
|
1275
|
+
});
|
|
1276
|
+
await expect(strategy.completeIdentityRecovery!(params)).resolves.toMatchObject({
|
|
1277
|
+
pinSignIn: { mode: 'relinked', pinRefreshed: false, newPinRequired: expected },
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
);
|
|
1281
|
+
});
|
|
1282
|
+
|
|
1045
1283
|
it.each([
|
|
1046
1284
|
[0, false],
|
|
1047
1285
|
[2, true],
|