@vaultkeepr/core 0.1.2 → 0.2.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/README.md +60 -0
- package/dist/index.d.mts +146 -3
- package/dist/index.d.ts +146 -3
- package/dist/index.js +407 -35
- package/dist/index.mjs +384 -35
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ __export(index_exports, {
|
|
|
33
33
|
EXTENSION_MIN_PAYLOAD_VERSION: () => EXTENSION_MIN_PAYLOAD_VERSION,
|
|
34
34
|
FRAGMENTED_DEFAULT_THRESHOLD: () => FRAGMENTED_DEFAULT_THRESHOLD,
|
|
35
35
|
FRAGMENTED_DEFAULT_TOTAL: () => FRAGMENTED_DEFAULT_TOTAL,
|
|
36
|
+
KeyJoinError: () => KeyJoinError,
|
|
36
37
|
MOBILE_MAX_PAYLOAD_VERSION: () => MOBILE_MAX_PAYLOAD_VERSION,
|
|
37
38
|
MOBILE_MIN_PAYLOAD_VERSION: () => MOBILE_MIN_PAYLOAD_VERSION,
|
|
38
39
|
P256_SPKI_HEADER: () => P256_SPKI_HEADER,
|
|
@@ -43,11 +44,14 @@ __export(index_exports, {
|
|
|
43
44
|
PAYLOAD_VERSION_V2: () => PAYLOAD_VERSION_V2,
|
|
44
45
|
PAYLOAD_VERSION_V3: () => PAYLOAD_VERSION_V3,
|
|
45
46
|
PAYLOAD_VERSION_V4: () => PAYLOAD_VERSION_V4,
|
|
47
|
+
RECOVERY_CODE_LENGTH: () => RECOVERY_CODE_LENGTH,
|
|
46
48
|
TAG_COLORS: () => TAG_COLORS,
|
|
47
49
|
VALID_TAGS: () => VALID_TAGS,
|
|
48
50
|
VaultKeepR_SLM: () => VaultKeepR_SLM,
|
|
51
|
+
accountKeyState: () => accountKeyState,
|
|
49
52
|
addEntry: () => addEntry,
|
|
50
53
|
analyzeVaultHealth: () => analyzeVaultHealth,
|
|
54
|
+
argon2RecoveryKdf: () => argon2RecoveryKdf,
|
|
51
55
|
buildAttestationObject: () => buildAttestationObject,
|
|
52
56
|
buildAuthDataForCreate: () => buildAuthDataForCreate,
|
|
53
57
|
buildAuthDataForGet: () => buildAuthDataForGet,
|
|
@@ -62,6 +66,7 @@ __export(index_exports, {
|
|
|
62
66
|
captureError: () => captureError,
|
|
63
67
|
checkEmailBreaches: () => checkEmailBreaches,
|
|
64
68
|
checkVaultBreaches: () => checkVaultBreaches,
|
|
69
|
+
cleanEntryTitle: () => cleanEntryTitle,
|
|
65
70
|
cleanMrzField: () => cleanMrzField,
|
|
66
71
|
clearErrorBuffer: () => clearErrorBuffer,
|
|
67
72
|
clearHiddenWalletCache: () => clearHiddenWalletCache,
|
|
@@ -72,8 +77,10 @@ __export(index_exports, {
|
|
|
72
77
|
createExportPayload: () => createExportPayload,
|
|
73
78
|
createFolder: () => createFolder,
|
|
74
79
|
createKeyEnvelope: () => createKeyEnvelope,
|
|
80
|
+
createRecoveryBlob: () => createRecoveryBlob,
|
|
75
81
|
createSecureShare: () => createSecureShare,
|
|
76
82
|
createVaultPayload: () => createVaultPayload,
|
|
83
|
+
decideEncryptedImport: () => decideEncryptedImport,
|
|
77
84
|
decompressVault: () => decompressVault,
|
|
78
85
|
decryptFromPair: () => decryptFromPair,
|
|
79
86
|
decryptKeyEnvelope: () => decryptKeyEnvelope,
|
|
@@ -95,6 +102,7 @@ __export(index_exports, {
|
|
|
95
102
|
deriveMrzKseed: () => deriveMrzKseed,
|
|
96
103
|
deriveNfcKey: () => deriveNfcKey,
|
|
97
104
|
derivePairSecret: () => derivePairSecret,
|
|
105
|
+
deriveRecoveryId: () => deriveRecoveryId,
|
|
98
106
|
digitsOnly: () => digitsOnly,
|
|
99
107
|
encryptAndFragmentDocument: () => encryptAndFragmentDocument,
|
|
100
108
|
encryptForPair: () => encryptForPair,
|
|
@@ -112,6 +120,7 @@ __export(index_exports, {
|
|
|
112
120
|
formatCardDisplayMasked: () => formatCardDisplayMasked,
|
|
113
121
|
formatCardNumber: () => formatCardNumber,
|
|
114
122
|
formatErrorReport: () => formatErrorReport,
|
|
123
|
+
formatRecoveryCode: () => formatRecoveryCode,
|
|
115
124
|
fromBase64Url: () => fromBase64Url,
|
|
116
125
|
generateBlurredThumbnailCanvas: () => generateBlurredThumbnailCanvas,
|
|
117
126
|
generateCredentialId: () => generateCredentialId,
|
|
@@ -123,17 +132,22 @@ __export(index_exports, {
|
|
|
123
132
|
generatePassphrase: () => generatePassphrase,
|
|
124
133
|
generatePassword: () => generatePassword,
|
|
125
134
|
generatePrfSalt: () => generatePrfSalt,
|
|
135
|
+
generateRecoveryCode: () => generateRecoveryCode,
|
|
126
136
|
generateSaltArgon2: () => generateSaltArgon2,
|
|
127
137
|
generateSharePin: () => generateSharePin,
|
|
128
138
|
getCardBrand: () => getCardBrand,
|
|
129
139
|
getChecksumAddress: () => getChecksumAddress,
|
|
140
|
+
getEntryDisplayName: () => getEntryDisplayName,
|
|
130
141
|
getEntryGroupLabel: () => getEntryGroupLabel,
|
|
131
142
|
getErrorBuffer: () => getErrorBuffer,
|
|
132
143
|
getHiddenWalletFromPassword: () => getHiddenWalletFromPassword,
|
|
144
|
+
getHiddenWalletFromSecretKey: () => getHiddenWalletFromSecretKey,
|
|
133
145
|
getHiddenWalletLegacy: () => getHiddenWalletLegacy,
|
|
134
146
|
getHiddenWalletPrivateKey: () => getHiddenWalletPrivateKey,
|
|
147
|
+
getHiddenWalletPrivateKeyFromSecretKey: () => getHiddenWalletPrivateKeyFromSecretKey,
|
|
135
148
|
getLast4: () => getLast4,
|
|
136
149
|
getMostUsedEntries: () => getMostUsedEntries,
|
|
150
|
+
getPwnedCountForHash: () => getPwnedCountForHash,
|
|
137
151
|
getPwnedPasswordCount: () => getPwnedPasswordCount,
|
|
138
152
|
getTOTPCode: () => getTOTPCode,
|
|
139
153
|
getTOTPRemainingSeconds: () => getTOTPRemainingSeconds,
|
|
@@ -147,6 +161,7 @@ __export(index_exports, {
|
|
|
147
161
|
importProtonPassJson: () => importProtonPassJson,
|
|
148
162
|
importVaultText: () => importVaultText,
|
|
149
163
|
isAcceptablePayloadVersion: () => isAcceptablePayloadVersion,
|
|
164
|
+
isAccountKeyText: () => isAccountKeyText,
|
|
150
165
|
isCurrentPayloadVersion: () => isCurrentPayloadVersion,
|
|
151
166
|
isEncryptedExport: () => isEncryptedExport,
|
|
152
167
|
isNfcPayloadV1: () => isNfcPayloadV1,
|
|
@@ -158,15 +173,19 @@ __export(index_exports, {
|
|
|
158
173
|
isPasskeyPrivateKeyEncrypted: () => isPasskeyPrivateKeyEncrypted,
|
|
159
174
|
isPrfSupported: () => isPrfSupported,
|
|
160
175
|
isProtonPassExport: () => isProtonPassExport,
|
|
176
|
+
isValidRecoveryCode: () => isValidRecoveryCode,
|
|
161
177
|
isWebAuthnSupported: () => isWebAuthnSupported,
|
|
178
|
+
joinWithKeyCode: () => joinWithKeyCode,
|
|
162
179
|
maskCardNumber: () => maskCardNumber,
|
|
163
180
|
mergeFolderTrees: () => mergeFolderTrees,
|
|
164
181
|
mergeFolders: () => mergeFolders,
|
|
165
182
|
mergeFragments: () => mergeFragments,
|
|
166
183
|
mergeImportedEntries: () => mergeImportedEntries,
|
|
167
184
|
moveFolder: () => moveFolder,
|
|
185
|
+
normalizeRecoveryCode: () => normalizeRecoveryCode,
|
|
168
186
|
normalizeSignatureForKdf: () => normalizeSignatureForKdf,
|
|
169
187
|
normalizeUrl: () => normalizeUrl,
|
|
188
|
+
openRecoveryBlob: () => openRecoveryBlob,
|
|
170
189
|
parseMRZ: () => parseMRZ,
|
|
171
190
|
parseMrzDate: () => parseMrzDate,
|
|
172
191
|
parsePairPayload: () => parsePairPayload,
|
|
@@ -176,6 +195,10 @@ __export(index_exports, {
|
|
|
176
195
|
parseTOTPUri: () => parseTOTPUri,
|
|
177
196
|
parseVault: () => parseVault,
|
|
178
197
|
parseVaultPayload: () => parseVaultPayload,
|
|
198
|
+
passageIdentity: () => passageIdentity,
|
|
199
|
+
passageNext: () => passageNext,
|
|
200
|
+
pointerWalletFor: () => pointerWalletFor,
|
|
201
|
+
prepareKeyJoin: () => prepareKeyJoin,
|
|
179
202
|
publicKeyToCose: () => publicKeyToCose,
|
|
180
203
|
publicKeyToSpki: () => publicKeyToSpki,
|
|
181
204
|
reassembleAndDecryptDocument: () => reassembleAndDecryptDocument,
|
|
@@ -239,6 +262,78 @@ function getEntryGroupLabel(folder) {
|
|
|
239
262
|
if (!folder) return ENTRY_GROUP_LABELS.identifiants;
|
|
240
263
|
return ENTRY_GROUP_LABELS[folder] ?? folder;
|
|
241
264
|
}
|
|
265
|
+
var JUNK_SUBDOMAIN_PREFIXES = /* @__PURE__ */ new Set([
|
|
266
|
+
"www",
|
|
267
|
+
"app",
|
|
268
|
+
"mobile",
|
|
269
|
+
"accounts",
|
|
270
|
+
"dashboard",
|
|
271
|
+
"kyc",
|
|
272
|
+
"mail",
|
|
273
|
+
"web",
|
|
274
|
+
"my",
|
|
275
|
+
"login",
|
|
276
|
+
"portal",
|
|
277
|
+
"id",
|
|
278
|
+
"news"
|
|
279
|
+
]);
|
|
280
|
+
function brandFrom(url) {
|
|
281
|
+
if (!url?.trim()) return null;
|
|
282
|
+
try {
|
|
283
|
+
const raw = url.includes("://") ? url : `https://${url}`;
|
|
284
|
+
const host = new URL(raw).hostname.replace(/^www\./i, "");
|
|
285
|
+
if (/^\d+(\.\d+){3}$/.test(host)) return null;
|
|
286
|
+
const parts = host.split(".").filter(Boolean);
|
|
287
|
+
if (parts.length < 2) return null;
|
|
288
|
+
let label = parts[0];
|
|
289
|
+
if (JUNK_SUBDOMAIN_PREFIXES.has(label.toLowerCase()) && parts.length > 2) label = parts[1];
|
|
290
|
+
if (!label) return null;
|
|
291
|
+
return { brand: label.charAt(0).toUpperCase() + label.slice(1).toLowerCase(), host: host.toLowerCase() };
|
|
292
|
+
} catch {
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
function cleanEntryTitle(rawTitle, url) {
|
|
297
|
+
const raw = rawTitle.trim();
|
|
298
|
+
let candidate = raw;
|
|
299
|
+
{
|
|
300
|
+
const lower = raw.toLowerCase();
|
|
301
|
+
let pos = lower.indexOf("passkey");
|
|
302
|
+
while (pos > 0) {
|
|
303
|
+
let i = pos;
|
|
304
|
+
while (i > 0 && /\s/.test(raw.charAt(i - 1))) i--;
|
|
305
|
+
const prefix = raw.slice(0, i);
|
|
306
|
+
if (i < pos && !prefix.includes("\n")) {
|
|
307
|
+
let j = pos + 7;
|
|
308
|
+
while (j < raw.length && /\s/.test(raw.charAt(j))) j++;
|
|
309
|
+
const tail = raw.slice(j);
|
|
310
|
+
if (j > pos + 7 && tail.length > 0 && !tail.includes("\n")) {
|
|
311
|
+
if (prefix.trim() !== "" && /\d/.test(tail)) candidate = prefix.trim();
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
pos = lower.indexOf("passkey", pos + 1);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
const brandInfo = brandFrom(url);
|
|
319
|
+
if (brandInfo) {
|
|
320
|
+
if (!candidate) return brandInfo.brand;
|
|
321
|
+
if (/^[\d\s()+.-]+$/.test(candidate)) return brandInfo.brand;
|
|
322
|
+
if (candidate.toLowerCase() === brandInfo.brand.toLowerCase()) return brandInfo.brand;
|
|
323
|
+
const schemeStripped = candidate.replace(/^https?:\/\//i, "");
|
|
324
|
+
const nl = schemeStripped.lastIndexOf("\n");
|
|
325
|
+
const slash = schemeStripped.indexOf("/", nl + 1);
|
|
326
|
+
const hostCandidate = slash === -1 ? schemeStripped : schemeStripped.slice(0, slash);
|
|
327
|
+
if (hostCandidate.toLowerCase() === brandInfo.host) {
|
|
328
|
+
return brandInfo.brand;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return candidate || brandInfo?.brand || raw;
|
|
332
|
+
}
|
|
333
|
+
function getEntryDisplayName(entry, primaryUrl) {
|
|
334
|
+
const url = primaryUrl ?? entry.urls?.[0]?.uri ?? entry.url ?? void 0;
|
|
335
|
+
return cleanEntryTitle(entry.title ?? entry.username ?? "", url);
|
|
336
|
+
}
|
|
242
337
|
function resolveFolderName(folderId, folderTree) {
|
|
243
338
|
if (!folderId) return ENTRY_GROUP_LABELS.identifiants;
|
|
244
339
|
if (folderId in ENTRY_GROUP_LABELS) return ENTRY_GROUP_LABELS[folderId];
|
|
@@ -737,9 +832,12 @@ function normalizeUrl(raw) {
|
|
|
737
832
|
let u = (raw ?? "").trim().toLowerCase();
|
|
738
833
|
u = u.replace(/^https?:\/\//, "");
|
|
739
834
|
u = u.replace(/^www\./, "");
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
835
|
+
const nl = u.lastIndexOf("\n");
|
|
836
|
+
const hash = u.indexOf("#", nl + 1);
|
|
837
|
+
if (hash !== -1) u = u.slice(0, hash);
|
|
838
|
+
let end = u.length;
|
|
839
|
+
while (end > 0 && u.charAt(end - 1) === "/") end--;
|
|
840
|
+
return u.slice(0, end);
|
|
743
841
|
}
|
|
744
842
|
function entryFingerprint(entry) {
|
|
745
843
|
const url = normalizeUrl(entry.url ?? "");
|
|
@@ -908,14 +1006,14 @@ function isEncryptedExport(jsonStr) {
|
|
|
908
1006
|
return false;
|
|
909
1007
|
}
|
|
910
1008
|
}
|
|
911
|
-
async function importEncryptedVault(encryptedJson, password, argon2Opts) {
|
|
1009
|
+
async function importEncryptedVault(encryptedJson, password, argon2Opts, precomputed) {
|
|
912
1010
|
const payload = JSON.parse(encryptedJson.trim());
|
|
913
1011
|
if (payload?.format !== ENCRYPTED_EXPORT_FORMAT || !payload.salt || !payload.nonce || !payload.ciphertext) {
|
|
914
1012
|
throw new Error("Format d'export chiffr\xE9 invalide.");
|
|
915
1013
|
}
|
|
916
1014
|
const salt = (0, import_utils5.hexToBytes)(payload.salt);
|
|
917
1015
|
const effectiveOpts = payload.kdf ? { t: payload.kdf.t, m: payload.kdf.m, p: payload.kdf.p, dkLen: payload.kdf.dkLen } : argon2Opts ?? {};
|
|
918
|
-
const key = await deriveKeyFromPasswordArgon2(password, salt, effectiveOpts);
|
|
1016
|
+
const key = precomputed?.key ?? await deriveKeyFromPasswordArgon2(password, precomputed?.salt ?? salt, effectiveOpts);
|
|
919
1017
|
const plaintext = decryptVault(
|
|
920
1018
|
{
|
|
921
1019
|
ciphertext: payload.ciphertext,
|
|
@@ -1627,7 +1725,6 @@ function isEnpassCsv(text) {
|
|
|
1627
1725
|
const firstLine = text.split(/\r?\n/)[0];
|
|
1628
1726
|
if (!firstLine) return false;
|
|
1629
1727
|
const rawHeaders = firstLine.split(",");
|
|
1630
|
-
const headers = rawHeaders.map((h) => h.replace(/^["']|["']$/g, "").trim());
|
|
1631
1728
|
return rawHeaders.some((h) => {
|
|
1632
1729
|
const clean = h.replace(/^["']|["']$/g, "").trim();
|
|
1633
1730
|
return clean === "Title";
|
|
@@ -2165,22 +2262,28 @@ function parseCsvNoteExtras(rawNote) {
|
|
|
2165
2262
|
let totpSecret;
|
|
2166
2263
|
const customFields = [];
|
|
2167
2264
|
for (const line of lines) {
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2265
|
+
if (line.startsWith("TOTP:")) {
|
|
2266
|
+
let j = 5;
|
|
2267
|
+
while (j < line.length && /\s/.test(line.charAt(j))) j++;
|
|
2268
|
+
if (j > 5 && j < line.length) {
|
|
2269
|
+
totpSecret = line.slice(j).trim();
|
|
2270
|
+
continue;
|
|
2271
|
+
}
|
|
2172
2272
|
}
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
const
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2273
|
+
if (line.startsWith("Fields:")) {
|
|
2274
|
+
let j = 7;
|
|
2275
|
+
while (j < line.length && /\s/.test(line.charAt(j))) j++;
|
|
2276
|
+
if (j > 7 && j < line.length) {
|
|
2277
|
+
const entries = line.slice(j).split("|");
|
|
2278
|
+
for (const entry of entries) {
|
|
2279
|
+
const colonIdx = entry.indexOf(":");
|
|
2280
|
+
if (colonIdx > 0) {
|
|
2281
|
+
customFields.push({
|
|
2282
|
+
name: entry.slice(0, colonIdx).trim(),
|
|
2283
|
+
value: entry.slice(colonIdx + 1).trim(),
|
|
2284
|
+
type: "text"
|
|
2285
|
+
});
|
|
2286
|
+
}
|
|
2184
2287
|
}
|
|
2185
2288
|
}
|
|
2186
2289
|
}
|
|
@@ -2681,7 +2784,6 @@ function exportCsv(vault, opts = {}) {
|
|
|
2681
2784
|
continue;
|
|
2682
2785
|
}
|
|
2683
2786
|
if (e.folder === "cartes") {
|
|
2684
|
-
const m = parseCardMeta(e.notes);
|
|
2685
2787
|
rows.push(
|
|
2686
2788
|
[
|
|
2687
2789
|
csvEscape("cartes"),
|
|
@@ -3037,7 +3139,10 @@ var import_sha25 = require("@noble/hashes/sha2.js");
|
|
|
3037
3139
|
var TOTP_STEP_SEC = 30;
|
|
3038
3140
|
function base32Decode(input) {
|
|
3039
3141
|
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
|
3040
|
-
const
|
|
3142
|
+
const upper = input.replace(/\s/g, "").toUpperCase();
|
|
3143
|
+
let end = upper.length;
|
|
3144
|
+
while (end > 0 && upper.charAt(end - 1) === "=") end--;
|
|
3145
|
+
const clean = upper.slice(0, end);
|
|
3041
3146
|
const bits = [];
|
|
3042
3147
|
for (let i = 0; i < clean.length; i++) {
|
|
3043
3148
|
const idx = alphabet.indexOf(clean[i]);
|
|
@@ -3108,9 +3213,9 @@ function parseTOTPUri(uri) {
|
|
|
3108
3213
|
var import_legacy2 = require("@noble/hashes/legacy.js");
|
|
3109
3214
|
var import_utils9 = require("@noble/hashes/utils.js");
|
|
3110
3215
|
var RANGE_BASE = "https://api.pwnedpasswords.com/range/";
|
|
3111
|
-
async function
|
|
3112
|
-
|
|
3113
|
-
|
|
3216
|
+
async function getPwnedCountForHash(sha1Hex, options) {
|
|
3217
|
+
const hash = sha1Hex.trim().toUpperCase();
|
|
3218
|
+
if (hash.length !== 40) throw new Error(`Invalid SHA-1 length: ${hash.length}`);
|
|
3114
3219
|
const prefix = hash.slice(0, 5);
|
|
3115
3220
|
const suffix = hash.slice(5);
|
|
3116
3221
|
const fetchFn = options?.fetchFn ?? fetch;
|
|
@@ -3126,7 +3231,6 @@ async function getPwnedPasswordCount(password, options) {
|
|
|
3126
3231
|
throw new Error(`PwnedPasswords API: ${res.status}`);
|
|
3127
3232
|
}
|
|
3128
3233
|
const text = await res.text();
|
|
3129
|
-
const suffixUpper = suffix.toUpperCase();
|
|
3130
3234
|
for (const line of text.split("\n")) {
|
|
3131
3235
|
const trimmed = line.trim();
|
|
3132
3236
|
if (!trimmed) continue;
|
|
@@ -3134,13 +3238,18 @@ async function getPwnedPasswordCount(password, options) {
|
|
|
3134
3238
|
if (colon < 0) continue;
|
|
3135
3239
|
const h = trimmed.slice(0, colon).toUpperCase();
|
|
3136
3240
|
const countStr = trimmed.slice(colon + 1);
|
|
3137
|
-
if (h ===
|
|
3241
|
+
if (h === suffix) {
|
|
3138
3242
|
const n = parseInt(countStr, 10);
|
|
3139
3243
|
return Number.isFinite(n) ? n : 0;
|
|
3140
3244
|
}
|
|
3141
3245
|
}
|
|
3142
3246
|
return 0;
|
|
3143
3247
|
}
|
|
3248
|
+
async function getPwnedPasswordCount(password, options) {
|
|
3249
|
+
if (!password.length) return 0;
|
|
3250
|
+
const hash = (0, import_utils9.bytesToHex)((0, import_legacy2.sha1)((0, import_utils9.utf8ToBytes)(password))).toUpperCase();
|
|
3251
|
+
return getPwnedCountForHash(hash, options);
|
|
3252
|
+
}
|
|
3144
3253
|
|
|
3145
3254
|
// src/wordlist.ts
|
|
3146
3255
|
var EFF_WORDLIST = [
|
|
@@ -11718,7 +11827,10 @@ function toBase64Url2(bytes) {
|
|
|
11718
11827
|
for (let i = 0; i < bytes.length; i++) {
|
|
11719
11828
|
binary += String.fromCharCode(bytes[i]);
|
|
11720
11829
|
}
|
|
11721
|
-
|
|
11830
|
+
const b64 = btoa(binary).replace(/\+/g, "-").replace(/\//g, "_");
|
|
11831
|
+
let end = b64.length;
|
|
11832
|
+
while (end > 0 && b64.charAt(end - 1) === "=") end -= 1;
|
|
11833
|
+
return b64.slice(0, end);
|
|
11722
11834
|
}
|
|
11723
11835
|
function fromBase64Url2(str) {
|
|
11724
11836
|
const base64 = str.replace(/-/g, "+").replace(/_/g, "/");
|
|
@@ -11781,6 +11893,26 @@ async function getHiddenWalletFromPassword(masterPassword, secretKey) {
|
|
|
11781
11893
|
_hwCache.set(cacheKey, account);
|
|
11782
11894
|
return account;
|
|
11783
11895
|
}
|
|
11896
|
+
async function getHiddenWalletFromSecretKey(secretKey) {
|
|
11897
|
+
const cacheKey = (0, import_viem.keccak256)((0, import_viem.toHex)(`${secretKey}:sk-only:v1`));
|
|
11898
|
+
const cached = _hwCache.get(cacheKey);
|
|
11899
|
+
if (cached) return cached;
|
|
11900
|
+
const privateKey = await getHiddenWalletPrivateKeyFromSecretKey(secretKey);
|
|
11901
|
+
const account = (0, import_accounts.privateKeyToAccount)(privateKey);
|
|
11902
|
+
_hwCache.set(cacheKey, account);
|
|
11903
|
+
return account;
|
|
11904
|
+
}
|
|
11905
|
+
async function getHiddenWalletPrivateKeyFromSecretKey(secretKey) {
|
|
11906
|
+
const salt = deriveHwSalt(secretKey);
|
|
11907
|
+
const inputBytes = new TextEncoder().encode(secretKey);
|
|
11908
|
+
let derived;
|
|
11909
|
+
if (_argon2Provider) {
|
|
11910
|
+
derived = await _argon2Provider(inputBytes, salt, HW_ARGON2_OPTS);
|
|
11911
|
+
} else {
|
|
11912
|
+
derived = (0, import_argon22.argon2id)(inputBytes, salt, HW_ARGON2_OPTS);
|
|
11913
|
+
}
|
|
11914
|
+
return (0, import_viem.bytesToHex)(derived);
|
|
11915
|
+
}
|
|
11784
11916
|
function clearHiddenWalletCache() {
|
|
11785
11917
|
_hwCache.clear();
|
|
11786
11918
|
}
|
|
@@ -11943,7 +12075,9 @@ function calculateMrzChecksum(str) {
|
|
|
11943
12075
|
return sum % 10;
|
|
11944
12076
|
}
|
|
11945
12077
|
function cleanMrzField(str) {
|
|
11946
|
-
|
|
12078
|
+
let end = str.length;
|
|
12079
|
+
while (end > 0 && str.charAt(end - 1) === "<") end--;
|
|
12080
|
+
return str.slice(0, end).replace(/</g, " ").trim();
|
|
11947
12081
|
}
|
|
11948
12082
|
function parseMrzDate(str) {
|
|
11949
12083
|
if (str.length !== 6) return "";
|
|
@@ -12212,6 +12346,7 @@ var import_secp256k12 = require("@noble/curves/secp256k1.js");
|
|
|
12212
12346
|
var import_chacha7 = require("@noble/ciphers/chacha.js");
|
|
12213
12347
|
var import_utils19 = require("@noble/ciphers/utils.js");
|
|
12214
12348
|
var import_hkdf5 = require("@noble/hashes/hkdf.js");
|
|
12349
|
+
var import_hmac4 = require("@noble/hashes/hmac.js");
|
|
12215
12350
|
var import_sha29 = require("@noble/hashes/sha2.js");
|
|
12216
12351
|
var import_utils20 = require("@noble/hashes/utils.js");
|
|
12217
12352
|
var NONCE_LENGTH5 = 24;
|
|
@@ -12226,8 +12361,10 @@ function generateSharePin() {
|
|
|
12226
12361
|
const num = (bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3]) >>> 0;
|
|
12227
12362
|
return String(num % 1e6).padStart(PIN_LENGTH, "0");
|
|
12228
12363
|
}
|
|
12229
|
-
|
|
12230
|
-
|
|
12364
|
+
var PIN_PROOF_INFO = (0, import_utils20.utf8ToBytes)("vaultkeepr-share-pin-proof-v1");
|
|
12365
|
+
function computeApiPinHash(pin, keyHex) {
|
|
12366
|
+
const proofKey = (0, import_hmac4.hmac)(import_sha29.sha256, (0, import_utils20.hexToBytes)(keyHex), PIN_PROOF_INFO);
|
|
12367
|
+
return (0, import_utils20.bytesToHex)((0, import_hmac4.hmac)(import_sha29.sha256, proofKey, (0, import_utils20.utf8ToBytes)(pin)));
|
|
12231
12368
|
}
|
|
12232
12369
|
function generateShareId() {
|
|
12233
12370
|
const ts = Date.now().toString(36);
|
|
@@ -12245,7 +12382,6 @@ function deriveShareKeyV1(sharedSecret, pin) {
|
|
|
12245
12382
|
function createSecureShare(payload, pin) {
|
|
12246
12383
|
const sharePin = pin ?? generateSharePin();
|
|
12247
12384
|
const shareId = generateShareId();
|
|
12248
|
-
const apiPinHash = computeApiPinHash(sharePin);
|
|
12249
12385
|
const fullPayload = {
|
|
12250
12386
|
...payload,
|
|
12251
12387
|
version: SHARE_VERSION,
|
|
@@ -12258,6 +12394,7 @@ function createSecureShare(payload, pin) {
|
|
|
12258
12394
|
}
|
|
12259
12395
|
const ephemeralPrivate = import_secp256k12.secp256k1.utils.randomSecretKey();
|
|
12260
12396
|
const ephemeralPublic = import_secp256k12.secp256k1.getPublicKey(ephemeralPrivate, false);
|
|
12397
|
+
const apiPinHash = computeApiPinHash(sharePin, (0, import_utils20.bytesToHex)(ephemeralPrivate));
|
|
12261
12398
|
const shareKey = deriveShareKeyV2(ephemeralPrivate, sharePin);
|
|
12262
12399
|
const nonce = (0, import_utils19.randomBytes)(NONCE_LENGTH5);
|
|
12263
12400
|
const chacha = (0, import_chacha7.xchacha20poly1305)(shareKey, nonce);
|
|
@@ -12393,7 +12530,7 @@ function calculatePasswordStrength(password) {
|
|
|
12393
12530
|
} else {
|
|
12394
12531
|
feedback.push("passwordFeedback.addSpecialChars");
|
|
12395
12532
|
}
|
|
12396
|
-
if (!/(.)
|
|
12533
|
+
if (!/(.)\1{2,}/.test(password)) {
|
|
12397
12534
|
score += 10;
|
|
12398
12535
|
} else {
|
|
12399
12536
|
feedback.push("passwordFeedback.avoidRepeated");
|
|
@@ -12600,6 +12737,59 @@ function mergePrfCredentials(local, remote) {
|
|
|
12600
12737
|
for (const cred of local) byId.set(cred.credentialId, cred);
|
|
12601
12738
|
return Array.from(byId.values());
|
|
12602
12739
|
}
|
|
12740
|
+
function legacyContactKey(c) {
|
|
12741
|
+
return JSON.stringify([c.label, c.email, c.telegram, c.address, c.publicKey]);
|
|
12742
|
+
}
|
|
12743
|
+
function mergeLegacyContacts(base, local, remote) {
|
|
12744
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
12745
|
+
for (const c of [...local ?? [], ...remote ?? []]) {
|
|
12746
|
+
const key = legacyContactKey(c);
|
|
12747
|
+
const existing = byKey.get(key);
|
|
12748
|
+
if (!existing) {
|
|
12749
|
+
byKey.set(key, c);
|
|
12750
|
+
continue;
|
|
12751
|
+
}
|
|
12752
|
+
if (c.addedAt !== existing.addedAt) {
|
|
12753
|
+
byKey.set(key, c.addedAt > existing.addedAt ? c : existing);
|
|
12754
|
+
} else {
|
|
12755
|
+
byKey.set(key, deterministicPick(existing, c));
|
|
12756
|
+
}
|
|
12757
|
+
}
|
|
12758
|
+
if (byKey.size === 0) return void 0;
|
|
12759
|
+
const ordered = [];
|
|
12760
|
+
const placed = /* @__PURE__ */ new Set();
|
|
12761
|
+
for (const c of base ?? []) {
|
|
12762
|
+
const key = legacyContactKey(c);
|
|
12763
|
+
const kept = byKey.get(key);
|
|
12764
|
+
if (kept && !placed.has(key)) {
|
|
12765
|
+
placed.add(key);
|
|
12766
|
+
ordered.push(kept);
|
|
12767
|
+
}
|
|
12768
|
+
}
|
|
12769
|
+
const additions = Array.from(byKey.entries()).filter(([key]) => !placed.has(key));
|
|
12770
|
+
additions.sort((a, b) => {
|
|
12771
|
+
if (a[1].addedAt !== b[1].addedAt) return a[1].addedAt < b[1].addedAt ? -1 : 1;
|
|
12772
|
+
return JSON.stringify(a[1]) <= JSON.stringify(b[1]) ? -1 : 1;
|
|
12773
|
+
});
|
|
12774
|
+
for (const [, c] of additions) ordered.push(c);
|
|
12775
|
+
return ordered;
|
|
12776
|
+
}
|
|
12777
|
+
function mergeMonitoredEmails(base, local, remote) {
|
|
12778
|
+
const present = /* @__PURE__ */ new Set();
|
|
12779
|
+
for (const v of [...local ?? [], ...remote ?? []]) present.add(v);
|
|
12780
|
+
if (present.size === 0) return void 0;
|
|
12781
|
+
const ordered = [];
|
|
12782
|
+
for (const v of base ?? []) {
|
|
12783
|
+
if (present.has(v) && !ordered.includes(v)) ordered.push(v);
|
|
12784
|
+
}
|
|
12785
|
+
const additions = [];
|
|
12786
|
+
for (const v of present) {
|
|
12787
|
+
if (!ordered.includes(v)) additions.push(v);
|
|
12788
|
+
}
|
|
12789
|
+
additions.sort((a, b) => a.localeCompare(b));
|
|
12790
|
+
for (const v of additions) ordered.push(v);
|
|
12791
|
+
return ordered;
|
|
12792
|
+
}
|
|
12603
12793
|
function threeWayMerge(base, local, remote) {
|
|
12604
12794
|
const effectiveBase = base ?? {
|
|
12605
12795
|
version: local.version,
|
|
@@ -12663,6 +12853,16 @@ function threeWayMerge(base, local, remote) {
|
|
|
12663
12853
|
(sum, f) => sum + (f.originalSize || 0),
|
|
12664
12854
|
0
|
|
12665
12855
|
);
|
|
12856
|
+
const mergedLegacyContacts = mergeLegacyContacts(
|
|
12857
|
+
base ? base.legacyContacts : void 0,
|
|
12858
|
+
local.legacyContacts,
|
|
12859
|
+
remote.legacyContacts
|
|
12860
|
+
);
|
|
12861
|
+
const mergedMonitoredEmails = mergeMonitoredEmails(
|
|
12862
|
+
base ? base.monitoredEmails : void 0,
|
|
12863
|
+
local.monitoredEmails,
|
|
12864
|
+
remote.monitoredEmails
|
|
12865
|
+
);
|
|
12666
12866
|
const out = {
|
|
12667
12867
|
version: Math.max(local.version, remote.version),
|
|
12668
12868
|
createdAt: local.createdAt,
|
|
@@ -12687,6 +12887,15 @@ function threeWayMerge(base, local, remote) {
|
|
|
12687
12887
|
if (Object.keys(mergedEntryTombstones).length > 0) {
|
|
12688
12888
|
out.entryTombstones = mergedEntryTombstones;
|
|
12689
12889
|
}
|
|
12890
|
+
if (mergedLegacyContacts) {
|
|
12891
|
+
out.legacyContacts = mergedLegacyContacts;
|
|
12892
|
+
}
|
|
12893
|
+
if (mergedMonitoredEmails) {
|
|
12894
|
+
out.monitoredEmails = mergedMonitoredEmails;
|
|
12895
|
+
}
|
|
12896
|
+
if (local.secretKey !== void 0 || remote.secretKey !== void 0) {
|
|
12897
|
+
out.secretKey = local.secretKey !== void 0 && remote.secretKey !== void 0 ? deterministicPick(local.secretKey, remote.secretKey) : local.secretKey ?? remote.secretKey;
|
|
12898
|
+
}
|
|
12690
12899
|
return out;
|
|
12691
12900
|
}
|
|
12692
12901
|
function mergeFolders(base, local, remote, baseTombstones, localTombstones, remoteTombstones, now) {
|
|
@@ -14928,7 +15137,7 @@ var BIP39_WORDLIST = [
|
|
|
14928
15137
|
"zoo"
|
|
14929
15138
|
];
|
|
14930
15139
|
function suggestBip39Words(prefix, limit = 5) {
|
|
14931
|
-
const p = prefix.toLowerCase().trim();
|
|
15140
|
+
const p = (prefix ?? "").toLowerCase().trim();
|
|
14932
15141
|
if (!p) return [];
|
|
14933
15142
|
const results = [];
|
|
14934
15143
|
for (const word of BIP39_WORDLIST) {
|
|
@@ -15206,6 +15415,146 @@ var VaultKeepR_SLM = class {
|
|
|
15206
15415
|
return { severity, ...data };
|
|
15207
15416
|
}
|
|
15208
15417
|
};
|
|
15418
|
+
|
|
15419
|
+
// src/account-state.ts
|
|
15420
|
+
function accountKeyState(input) {
|
|
15421
|
+
if (input.hasSecretKey) return { kind: "ready" };
|
|
15422
|
+
if (input.remote?.moved) return { kind: "read_only_pair" };
|
|
15423
|
+
if (input.remote?.exists || input.hasLocalVault) return { kind: "passage" };
|
|
15424
|
+
return { kind: "choose" };
|
|
15425
|
+
}
|
|
15426
|
+
function pointerWalletFor(input) {
|
|
15427
|
+
return input.hasSecretKey && input.remoteMoved ? input.smartAccount : input.eoa;
|
|
15428
|
+
}
|
|
15429
|
+
function passageNext(step, event) {
|
|
15430
|
+
switch (`${step}:${event}`) {
|
|
15431
|
+
case "idle:key_generated":
|
|
15432
|
+
return { step: "key_pending", discardPendingKey: false };
|
|
15433
|
+
case "key_pending:copy_ok":
|
|
15434
|
+
return { step: "copied", discardPendingKey: false };
|
|
15435
|
+
case "key_pending:copy_failed":
|
|
15436
|
+
return { step: "idle", discardPendingKey: true };
|
|
15437
|
+
case "copied:move_ok":
|
|
15438
|
+
return { step: "moved", discardPendingKey: false };
|
|
15439
|
+
case "copied:move_failed":
|
|
15440
|
+
return { step: "copied", discardPendingKey: false };
|
|
15441
|
+
case "copied:move_conflict":
|
|
15442
|
+
return { step: "idle", discardPendingKey: true };
|
|
15443
|
+
case "moved:promote_ok":
|
|
15444
|
+
return { step: "done", discardPendingKey: false };
|
|
15445
|
+
default:
|
|
15446
|
+
return { error: `invalid passage transition: ${step} + ${event}` };
|
|
15447
|
+
}
|
|
15448
|
+
}
|
|
15449
|
+
function passageIdentity(step) {
|
|
15450
|
+
return step === "done" ? "smart_account" : "legacy";
|
|
15451
|
+
}
|
|
15452
|
+
|
|
15453
|
+
// src/recovery-code.ts
|
|
15454
|
+
var import_argon23 = require("@noble/hashes/argon2.js");
|
|
15455
|
+
var import_utils23 = require("@noble/hashes/utils.js");
|
|
15456
|
+
var import_utils24 = require("@noble/ciphers/utils.js");
|
|
15457
|
+
var RECOVERY_CODE_LENGTH = 20;
|
|
15458
|
+
var ALPHABET = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
15459
|
+
var ID_SALT = new TextEncoder().encode("vaultkeepr-recovery-id-v1");
|
|
15460
|
+
var SALT_LENGTH2 = 16;
|
|
15461
|
+
var ARGON2_OPTS2 = { t: 3, m: 65536, p: 4, dkLen: 32 };
|
|
15462
|
+
var SECRET_KEY_HEX = /^[0-9a-fA-F]{64}$/;
|
|
15463
|
+
function isAccountKeyText(value) {
|
|
15464
|
+
if (SECRET_KEY_HEX.test(value)) return true;
|
|
15465
|
+
if (value.length < 32 || value.length > 4096 || value.includes("BEGIN PGP")) return false;
|
|
15466
|
+
return !isEnvelopeText(value);
|
|
15467
|
+
}
|
|
15468
|
+
function isEnvelopeText(value) {
|
|
15469
|
+
if (!value.startsWith("{")) return false;
|
|
15470
|
+
try {
|
|
15471
|
+
const o = JSON.parse(value);
|
|
15472
|
+
return !!o && typeof o === "object" && typeof o.v === "number" && typeof o.iv === "string" && typeof o.ct === "string";
|
|
15473
|
+
} catch {
|
|
15474
|
+
return false;
|
|
15475
|
+
}
|
|
15476
|
+
}
|
|
15477
|
+
var argon2RecoveryKdf = (codeBytes2, salt) => (0, import_argon23.argon2id)(codeBytes2, salt, ARGON2_OPTS2);
|
|
15478
|
+
function generateRecoveryCode() {
|
|
15479
|
+
const bytes = (0, import_utils24.randomBytes)(RECOVERY_CODE_LENGTH);
|
|
15480
|
+
let code = "";
|
|
15481
|
+
for (const b of bytes) code += ALPHABET[b % 32];
|
|
15482
|
+
return code;
|
|
15483
|
+
}
|
|
15484
|
+
function normalizeRecoveryCode(input) {
|
|
15485
|
+
return input.toUpperCase().replace(/[\s-]/g, "").replace(/O/g, "0").replace(/[IL]/g, "1");
|
|
15486
|
+
}
|
|
15487
|
+
function isValidRecoveryCode(input) {
|
|
15488
|
+
const code = normalizeRecoveryCode(input);
|
|
15489
|
+
return code.length === RECOVERY_CODE_LENGTH && [...code].every((c) => ALPHABET.includes(c));
|
|
15490
|
+
}
|
|
15491
|
+
function formatRecoveryCode(code) {
|
|
15492
|
+
const canonical = normalizeRecoveryCode(code);
|
|
15493
|
+
return canonical.match(/.{1,5}/g)?.join("-") ?? canonical;
|
|
15494
|
+
}
|
|
15495
|
+
function codeBytes(code) {
|
|
15496
|
+
const canonical = normalizeRecoveryCode(code);
|
|
15497
|
+
if (!isValidRecoveryCode(canonical)) throw new Error("Invalid recovery code");
|
|
15498
|
+
return new TextEncoder().encode(canonical);
|
|
15499
|
+
}
|
|
15500
|
+
async function deriveRecoveryId(code, kdf = argon2RecoveryKdf) {
|
|
15501
|
+
return (0, import_utils23.bytesToHex)(await kdf(codeBytes(code), ID_SALT));
|
|
15502
|
+
}
|
|
15503
|
+
async function createRecoveryBlob(secretKeyHex, code, kdf = argon2RecoveryKdf) {
|
|
15504
|
+
if (!isAccountKeyText(secretKeyHex)) throw new Error("Invalid secret key");
|
|
15505
|
+
const salt = (0, import_utils24.randomBytes)(SALT_LENGTH2);
|
|
15506
|
+
const key = await kdf(codeBytes(code), salt);
|
|
15507
|
+
const encrypted = encryptVault(secretKeyHex, key);
|
|
15508
|
+
return { version: 1, salt: (0, import_utils23.bytesToHex)(salt), encrypted };
|
|
15509
|
+
}
|
|
15510
|
+
async function openRecoveryBlob(blob, code, kdf = argon2RecoveryKdf) {
|
|
15511
|
+
if (blob.version !== 1) throw new Error("Unsupported recovery blob version");
|
|
15512
|
+
let plain;
|
|
15513
|
+
try {
|
|
15514
|
+
const key = await kdf(codeBytes(code), (0, import_utils23.hexToBytes)(blob.salt));
|
|
15515
|
+
plain = decryptVault(blob.encrypted, key);
|
|
15516
|
+
} catch {
|
|
15517
|
+
throw new Error("Recovery failed");
|
|
15518
|
+
}
|
|
15519
|
+
const secretKey = typeof plain === "string" ? plain : new TextDecoder().decode(plain);
|
|
15520
|
+
if (!isAccountKeyText(secretKey)) throw new Error("Recovery failed");
|
|
15521
|
+
return secretKey;
|
|
15522
|
+
}
|
|
15523
|
+
|
|
15524
|
+
// src/key-join.ts
|
|
15525
|
+
var KeyJoinError = class extends Error {
|
|
15526
|
+
constructor(code) {
|
|
15527
|
+
super(code);
|
|
15528
|
+
this.code = code;
|
|
15529
|
+
this.name = "KeyJoinError";
|
|
15530
|
+
}
|
|
15531
|
+
code;
|
|
15532
|
+
};
|
|
15533
|
+
async function prepareKeyJoin(secretKeyHex, post, kdf) {
|
|
15534
|
+
const code = generateRecoveryCode();
|
|
15535
|
+
const blob = await createRecoveryBlob(secretKeyHex, code, kdf);
|
|
15536
|
+
const id = await deriveRecoveryId(code, kdf);
|
|
15537
|
+
await post(id, blob);
|
|
15538
|
+
return { code: formatRecoveryCode(code) };
|
|
15539
|
+
}
|
|
15540
|
+
async function joinWithKeyCode(input, fetchBlob, kdf) {
|
|
15541
|
+
const code = normalizeRecoveryCode(input);
|
|
15542
|
+
if (!isValidRecoveryCode(code)) throw new KeyJoinError("invalid_code");
|
|
15543
|
+
const id = await deriveRecoveryId(code, kdf);
|
|
15544
|
+
const blob = await fetchBlob(id);
|
|
15545
|
+
if (!blob) throw new KeyJoinError("not_found");
|
|
15546
|
+
return openRecoveryBlob(blob, code, kdf);
|
|
15547
|
+
}
|
|
15548
|
+
|
|
15549
|
+
// src/import-key-policy.ts
|
|
15550
|
+
function decideEncryptedImport(input) {
|
|
15551
|
+
const device = input.deviceKey ? input.deviceKey.toLowerCase() : null;
|
|
15552
|
+
const file = input.fileKey ? input.fileKey.toLowerCase() : null;
|
|
15553
|
+
if (!device && !file) return { action: "import_keyless" };
|
|
15554
|
+
if (!device && file) return { action: "join_with_file_key" };
|
|
15555
|
+
if (device && !file) return { action: "refuse", reason: "keyless_file_on_keyed_device" };
|
|
15556
|
+
return device === file ? { action: "keep_device_key" } : { action: "refuse", reason: "other_account" };
|
|
15557
|
+
}
|
|
15209
15558
|
// Annotate the CommonJS export names for ESM import in node:
|
|
15210
15559
|
0 && (module.exports = {
|
|
15211
15560
|
BIP39_WORDLIST,
|
|
@@ -15221,6 +15570,7 @@ var VaultKeepR_SLM = class {
|
|
|
15221
15570
|
EXTENSION_MIN_PAYLOAD_VERSION,
|
|
15222
15571
|
FRAGMENTED_DEFAULT_THRESHOLD,
|
|
15223
15572
|
FRAGMENTED_DEFAULT_TOTAL,
|
|
15573
|
+
KeyJoinError,
|
|
15224
15574
|
MOBILE_MAX_PAYLOAD_VERSION,
|
|
15225
15575
|
MOBILE_MIN_PAYLOAD_VERSION,
|
|
15226
15576
|
P256_SPKI_HEADER,
|
|
@@ -15231,11 +15581,14 @@ var VaultKeepR_SLM = class {
|
|
|
15231
15581
|
PAYLOAD_VERSION_V2,
|
|
15232
15582
|
PAYLOAD_VERSION_V3,
|
|
15233
15583
|
PAYLOAD_VERSION_V4,
|
|
15584
|
+
RECOVERY_CODE_LENGTH,
|
|
15234
15585
|
TAG_COLORS,
|
|
15235
15586
|
VALID_TAGS,
|
|
15236
15587
|
VaultKeepR_SLM,
|
|
15588
|
+
accountKeyState,
|
|
15237
15589
|
addEntry,
|
|
15238
15590
|
analyzeVaultHealth,
|
|
15591
|
+
argon2RecoveryKdf,
|
|
15239
15592
|
buildAttestationObject,
|
|
15240
15593
|
buildAuthDataForCreate,
|
|
15241
15594
|
buildAuthDataForGet,
|
|
@@ -15250,6 +15603,7 @@ var VaultKeepR_SLM = class {
|
|
|
15250
15603
|
captureError,
|
|
15251
15604
|
checkEmailBreaches,
|
|
15252
15605
|
checkVaultBreaches,
|
|
15606
|
+
cleanEntryTitle,
|
|
15253
15607
|
cleanMrzField,
|
|
15254
15608
|
clearErrorBuffer,
|
|
15255
15609
|
clearHiddenWalletCache,
|
|
@@ -15260,8 +15614,10 @@ var VaultKeepR_SLM = class {
|
|
|
15260
15614
|
createExportPayload,
|
|
15261
15615
|
createFolder,
|
|
15262
15616
|
createKeyEnvelope,
|
|
15617
|
+
createRecoveryBlob,
|
|
15263
15618
|
createSecureShare,
|
|
15264
15619
|
createVaultPayload,
|
|
15620
|
+
decideEncryptedImport,
|
|
15265
15621
|
decompressVault,
|
|
15266
15622
|
decryptFromPair,
|
|
15267
15623
|
decryptKeyEnvelope,
|
|
@@ -15283,6 +15639,7 @@ var VaultKeepR_SLM = class {
|
|
|
15283
15639
|
deriveMrzKseed,
|
|
15284
15640
|
deriveNfcKey,
|
|
15285
15641
|
derivePairSecret,
|
|
15642
|
+
deriveRecoveryId,
|
|
15286
15643
|
digitsOnly,
|
|
15287
15644
|
encryptAndFragmentDocument,
|
|
15288
15645
|
encryptForPair,
|
|
@@ -15300,6 +15657,7 @@ var VaultKeepR_SLM = class {
|
|
|
15300
15657
|
formatCardDisplayMasked,
|
|
15301
15658
|
formatCardNumber,
|
|
15302
15659
|
formatErrorReport,
|
|
15660
|
+
formatRecoveryCode,
|
|
15303
15661
|
fromBase64Url,
|
|
15304
15662
|
generateBlurredThumbnailCanvas,
|
|
15305
15663
|
generateCredentialId,
|
|
@@ -15311,17 +15669,22 @@ var VaultKeepR_SLM = class {
|
|
|
15311
15669
|
generatePassphrase,
|
|
15312
15670
|
generatePassword,
|
|
15313
15671
|
generatePrfSalt,
|
|
15672
|
+
generateRecoveryCode,
|
|
15314
15673
|
generateSaltArgon2,
|
|
15315
15674
|
generateSharePin,
|
|
15316
15675
|
getCardBrand,
|
|
15317
15676
|
getChecksumAddress,
|
|
15677
|
+
getEntryDisplayName,
|
|
15318
15678
|
getEntryGroupLabel,
|
|
15319
15679
|
getErrorBuffer,
|
|
15320
15680
|
getHiddenWalletFromPassword,
|
|
15681
|
+
getHiddenWalletFromSecretKey,
|
|
15321
15682
|
getHiddenWalletLegacy,
|
|
15322
15683
|
getHiddenWalletPrivateKey,
|
|
15684
|
+
getHiddenWalletPrivateKeyFromSecretKey,
|
|
15323
15685
|
getLast4,
|
|
15324
15686
|
getMostUsedEntries,
|
|
15687
|
+
getPwnedCountForHash,
|
|
15325
15688
|
getPwnedPasswordCount,
|
|
15326
15689
|
getTOTPCode,
|
|
15327
15690
|
getTOTPRemainingSeconds,
|
|
@@ -15335,6 +15698,7 @@ var VaultKeepR_SLM = class {
|
|
|
15335
15698
|
importProtonPassJson,
|
|
15336
15699
|
importVaultText,
|
|
15337
15700
|
isAcceptablePayloadVersion,
|
|
15701
|
+
isAccountKeyText,
|
|
15338
15702
|
isCurrentPayloadVersion,
|
|
15339
15703
|
isEncryptedExport,
|
|
15340
15704
|
isNfcPayloadV1,
|
|
@@ -15346,15 +15710,19 @@ var VaultKeepR_SLM = class {
|
|
|
15346
15710
|
isPasskeyPrivateKeyEncrypted,
|
|
15347
15711
|
isPrfSupported,
|
|
15348
15712
|
isProtonPassExport,
|
|
15713
|
+
isValidRecoveryCode,
|
|
15349
15714
|
isWebAuthnSupported,
|
|
15715
|
+
joinWithKeyCode,
|
|
15350
15716
|
maskCardNumber,
|
|
15351
15717
|
mergeFolderTrees,
|
|
15352
15718
|
mergeFolders,
|
|
15353
15719
|
mergeFragments,
|
|
15354
15720
|
mergeImportedEntries,
|
|
15355
15721
|
moveFolder,
|
|
15722
|
+
normalizeRecoveryCode,
|
|
15356
15723
|
normalizeSignatureForKdf,
|
|
15357
15724
|
normalizeUrl,
|
|
15725
|
+
openRecoveryBlob,
|
|
15358
15726
|
parseMRZ,
|
|
15359
15727
|
parseMrzDate,
|
|
15360
15728
|
parsePairPayload,
|
|
@@ -15364,6 +15732,10 @@ var VaultKeepR_SLM = class {
|
|
|
15364
15732
|
parseTOTPUri,
|
|
15365
15733
|
parseVault,
|
|
15366
15734
|
parseVaultPayload,
|
|
15735
|
+
passageIdentity,
|
|
15736
|
+
passageNext,
|
|
15737
|
+
pointerWalletFor,
|
|
15738
|
+
prepareKeyJoin,
|
|
15367
15739
|
publicKeyToCose,
|
|
15368
15740
|
publicKeyToSpki,
|
|
15369
15741
|
reassembleAndDecryptDocument,
|