@tgoliveira/vault-core 0.1.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/API_REFERENCE.md +36 -0
- package/ARCHITECTURE.md +32 -0
- package/LICENSE +21 -0
- package/MIGRATION_FROM_LIQSENSE.md +42 -0
- package/PASSKEY_PRF_ENVELOPES.md +9 -0
- package/PASSWORD_ENVELOPES.md +7 -0
- package/README.md +78 -0
- package/RECOVERY_PHRASE.md +9 -0
- package/SECURITY.md +31 -0
- package/dist/browser.d.ts +11 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +71 -0
- package/dist/browser.js.map +1 -0
- package/dist/constants.d.ts +5 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +5 -0
- package/dist/constants.js.map +1 -0
- package/dist/crypto/aad.d.ts +4 -0
- package/dist/crypto/aad.d.ts.map +1 -0
- package/dist/crypto/aad.js +23 -0
- package/dist/crypto/aad.js.map +1 -0
- package/dist/crypto/aes-gcm.d.ts +9 -0
- package/dist/crypto/aes-gcm.d.ts.map +1 -0
- package/dist/crypto/aes-gcm.js +58 -0
- package/dist/crypto/aes-gcm.js.map +1 -0
- package/dist/crypto/encoding.d.ts +6 -0
- package/dist/crypto/encoding.d.ts.map +1 -0
- package/dist/crypto/encoding.js +27 -0
- package/dist/crypto/encoding.js.map +1 -0
- package/dist/crypto/random.d.ts +2 -0
- package/dist/crypto/random.d.ts.map +1 -0
- package/dist/crypto/random.js +4 -0
- package/dist/crypto/random.js.map +1 -0
- package/dist/crypto/serialization.d.ts +3 -0
- package/dist/crypto/serialization.d.ts.map +1 -0
- package/dist/crypto/serialization.js +7 -0
- package/dist/crypto/serialization.js.map +1 -0
- package/dist/envelopes/passkey-prf.d.ts +21 -0
- package/dist/envelopes/passkey-prf.d.ts.map +1 -0
- package/dist/envelopes/passkey-prf.js +78 -0
- package/dist/envelopes/passkey-prf.js.map +1 -0
- package/dist/envelopes/password.d.ts +20 -0
- package/dist/envelopes/password.d.ts.map +1 -0
- package/dist/envelopes/password.js +41 -0
- package/dist/envelopes/password.js.map +1 -0
- package/dist/envelopes/recovery.d.ts +46 -0
- package/dist/envelopes/recovery.d.ts.map +1 -0
- package/dist/envelopes/recovery.js +167 -0
- package/dist/envelopes/recovery.js.map +1 -0
- package/dist/errors/vault-errors.d.ts +20 -0
- package/dist/errors/vault-errors.d.ts.map +1 -0
- package/dist/errors/vault-errors.js +37 -0
- package/dist/errors/vault-errors.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/kdf/argon2id.d.ts +24 -0
- package/dist/kdf/argon2id.d.ts.map +1 -0
- package/dist/kdf/argon2id.js +57 -0
- package/dist/kdf/argon2id.js.map +1 -0
- package/dist/kdf/params.d.ts +9 -0
- package/dist/kdf/params.d.ts.map +1 -0
- package/dist/kdf/params.js +8 -0
- package/dist/kdf/params.js.map +1 -0
- package/dist/keys/user-vault-key.d.ts +7 -0
- package/dist/keys/user-vault-key.d.ts.map +1 -0
- package/dist/keys/user-vault-key.js +15 -0
- package/dist/keys/user-vault-key.js.map +1 -0
- package/dist/payload/encrypted-payload.d.ts +5 -0
- package/dist/payload/encrypted-payload.d.ts.map +1 -0
- package/dist/payload/encrypted-payload.js +14 -0
- package/dist/payload/encrypted-payload.js.map +1 -0
- package/dist/profile.d.ts +21 -0
- package/dist/profile.d.ts.map +1 -0
- package/dist/profile.js +9 -0
- package/dist/profile.js.map +1 -0
- package/dist/react/index.d.ts +6 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +6 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/session/use-vault-session.d.ts +11 -0
- package/dist/react/session/use-vault-session.d.ts.map +1 -0
- package/dist/react/session/use-vault-session.js +29 -0
- package/dist/react/session/use-vault-session.js.map +1 -0
- package/dist/react/session/use-vault-unlocked.d.ts +3 -0
- package/dist/react/session/use-vault-unlocked.d.ts.map +1 -0
- package/dist/react/session/use-vault-unlocked.js +9 -0
- package/dist/react/session/use-vault-unlocked.js.map +1 -0
- package/dist/react/session/vault-session-provider.d.ts +9 -0
- package/dist/react/session/vault-session-provider.d.ts.map +1 -0
- package/dist/react/session/vault-session-provider.js +16 -0
- package/dist/react/session/vault-session-provider.js.map +1 -0
- package/dist/react/status/resolve-vault-client-status.d.ts +8 -0
- package/dist/react/status/resolve-vault-client-status.d.ts.map +1 -0
- package/dist/react/status/resolve-vault-client-status.js +13 -0
- package/dist/react/status/resolve-vault-client-status.js.map +1 -0
- package/dist/react/status/use-vault-client-status.d.ts +3 -0
- package/dist/react/status/use-vault-client-status.d.ts.map +1 -0
- package/dist/react/status/use-vault-client-status.js +8 -0
- package/dist/react/status/use-vault-client-status.js.map +1 -0
- package/dist/recovery/kit.d.ts +16 -0
- package/dist/recovery/kit.d.ts.map +1 -0
- package/dist/recovery/kit.js +33 -0
- package/dist/recovery/kit.js.map +1 -0
- package/dist/session/auto-lock.d.ts +18 -0
- package/dist/session/auto-lock.d.ts.map +1 -0
- package/dist/session/auto-lock.js +86 -0
- package/dist/session/auto-lock.js.map +1 -0
- package/dist/session/memory-session.d.ts +8 -0
- package/dist/session/memory-session.d.ts.map +1 -0
- package/dist/session/memory-session.js +20 -0
- package/dist/session/memory-session.js.map +1 -0
- package/dist/testing/fixtures/liqsense-compat.d.ts +32 -0
- package/dist/testing/fixtures/liqsense-compat.d.ts.map +1 -0
- package/dist/testing/fixtures/liqsense-compat.js +31 -0
- package/dist/testing/fixtures/liqsense-compat.js.map +1 -0
- package/dist/testing/no-plaintext.d.ts +2 -0
- package/dist/testing/no-plaintext.d.ts.map +1 -0
- package/dist/testing/no-plaintext.js +2 -0
- package/dist/testing/no-plaintext.js.map +1 -0
- package/dist/testing.d.ts +2 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +2 -0
- package/dist/testing.js.map +1 -0
- package/dist/validation/aad-assert.d.ts +5 -0
- package/dist/validation/aad-assert.d.ts.map +1 -0
- package/dist/validation/aad-assert.js +29 -0
- package/dist/validation/aad-assert.js.map +1 -0
- package/dist/validation/plaintext-reject.d.ts +23 -0
- package/dist/validation/plaintext-reject.d.ts.map +1 -0
- package/dist/validation/plaintext-reject.js +75 -0
- package/dist/validation/plaintext-reject.js.map +1 -0
- package/dist/validation/schemas.d.ts +203 -0
- package/dist/validation/schemas.d.ts.map +1 -0
- package/dist/validation/schemas.js +39 -0
- package/dist/validation/schemas.js.map +1 -0
- package/package.json +100 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { PasskeyPrfRequiredError, PasskeyUnlockError } from "../errors/vault-errors.js";
|
|
2
|
+
import { encryptField, decryptField, exportAesKey, importAesKey } from "../crypto/aes-gcm.js";
|
|
3
|
+
import { bytesToBase64Url, base64UrlToBytes, toBufferSource } from "../crypto/encoding.js";
|
|
4
|
+
export function isPasskeySupported() {
|
|
5
|
+
return typeof globalThis !== "undefined" &&
|
|
6
|
+
typeof globalThis.PublicKeyCredential !== "undefined";
|
|
7
|
+
}
|
|
8
|
+
export function isPrfExtensionSupported() {
|
|
9
|
+
if (!isPasskeySupported())
|
|
10
|
+
return false;
|
|
11
|
+
return typeof PublicKeyCredential !== "undefined" &&
|
|
12
|
+
"getClientExtensionResults" in PublicKeyCredential.prototype;
|
|
13
|
+
}
|
|
14
|
+
export function extractPasskeyPrfOutput(clientExtensionResults) {
|
|
15
|
+
const prf = clientExtensionResults.prf;
|
|
16
|
+
const first = prf?.results?.first;
|
|
17
|
+
if (!first || first.byteLength < 32)
|
|
18
|
+
return null;
|
|
19
|
+
return new Uint8Array(first);
|
|
20
|
+
}
|
|
21
|
+
async function importPrfAsAesKey(prfOutput) {
|
|
22
|
+
const keyBytes = prfOutput.byteLength === 32 ? prfOutput : prfOutput.slice(0, 32);
|
|
23
|
+
return crypto.subtle.importKey("raw", toBufferSource(keyBytes), { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
|
|
24
|
+
}
|
|
25
|
+
export async function createPasskeyPrfEnvelope(vaultKey, prfOutput, scope, profile, publicMetadata) {
|
|
26
|
+
if (prfOutput.byteLength < 32) {
|
|
27
|
+
throw new Error("PRF output must be at least 32 bytes");
|
|
28
|
+
}
|
|
29
|
+
const prfKey = await importPrfAsAesKey(prfOutput);
|
|
30
|
+
const encryptedVaultKey = await encryptField(bytesToBase64Url(await exportAesKey(vaultKey)), prfKey, {
|
|
31
|
+
userId: scope.userId,
|
|
32
|
+
resourceId: scope.resourceId,
|
|
33
|
+
field: "vault_key",
|
|
34
|
+
}, profile);
|
|
35
|
+
return {
|
|
36
|
+
method: "passkey_prf",
|
|
37
|
+
encryptedVaultKey,
|
|
38
|
+
kdfMetadata: null,
|
|
39
|
+
publicMetadata,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export async function unwrapVaultKeyFromPasskey(encryptedVaultKey, prfOutput) {
|
|
43
|
+
if (prfOutput.byteLength < 32) {
|
|
44
|
+
throw new Error("PRF output must be at least 32 bytes");
|
|
45
|
+
}
|
|
46
|
+
const prfKey = await importPrfAsAesKey(prfOutput);
|
|
47
|
+
const keyBytes = base64UrlToBytes(await decryptField(encryptedVaultKey, prfKey));
|
|
48
|
+
return importAesKey(keyBytes);
|
|
49
|
+
}
|
|
50
|
+
export async function unlockWithPasskeyPrfEnvelope(envelope, prfOutput, options) {
|
|
51
|
+
const prfRequired = options?.prfRequired ?? true;
|
|
52
|
+
if (prfRequired && !prfOutput) {
|
|
53
|
+
throw new PasskeyPrfRequiredError("This passkey requires browser PRF support to unlock your vault. Use your vault password or recovery phrase.");
|
|
54
|
+
}
|
|
55
|
+
if (!prfOutput) {
|
|
56
|
+
throw new PasskeyUnlockError("Could not unlock your vault with this passkey. Use your vault password or recovery phrase.");
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
return await unwrapVaultKeyFromPasskey(envelope.encryptedVaultKey, prfOutput);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
throw new PasskeyUnlockError("Could not decrypt your vault with this passkey. Use your vault password or recovery phrase.");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** @deprecated Use unlockWithPasskeyPrfEnvelope */
|
|
66
|
+
export async function unlockVaultFromPasskeyEnvelope(encryptedVaultKeyOrEnvelope, prfOutput, options) {
|
|
67
|
+
const envelope = "method" in encryptedVaultKeyOrEnvelope
|
|
68
|
+
? encryptedVaultKeyOrEnvelope
|
|
69
|
+
: { encryptedVaultKey: encryptedVaultKeyOrEnvelope, method: "passkey_prf", kdfMetadata: null };
|
|
70
|
+
return unlockWithPasskeyPrfEnvelope(envelope, prfOutput, options);
|
|
71
|
+
}
|
|
72
|
+
/** @deprecated Use createPasskeyPrfEnvelope */
|
|
73
|
+
export async function wrapVaultKeyForPasskey(vaultKey, prfOutput, userId, resourceId, profile, publicMetadata) {
|
|
74
|
+
const envelope = await createPasskeyPrfEnvelope(vaultKey, prfOutput, { userId, resourceId }, profile, publicMetadata);
|
|
75
|
+
return envelope.encryptedVaultKey;
|
|
76
|
+
}
|
|
77
|
+
export { PasskeyPrfRequiredError, PasskeyUnlockError } from "../errors/vault-errors.js";
|
|
78
|
+
//# sourceMappingURL=passkey-prf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passkey-prf.js","sourceRoot":"","sources":["../../src/envelopes/passkey-prf.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACxF,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC9F,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAU3F,MAAM,UAAU,kBAAkB;IAChC,OAAO,OAAO,UAAU,KAAK,WAAW;QACtC,OAAO,UAAU,CAAC,mBAAmB,KAAK,WAAW,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,IAAI,CAAC,kBAAkB,EAAE;QAAE,OAAO,KAAK,CAAC;IACxC,OAAO,OAAO,mBAAmB,KAAK,WAAW;QAC/C,2BAA2B,IAAI,mBAAmB,CAAC,SAAS,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,sBAA+C;IAE/C,MAAM,GAAG,GAAI,sBAAoD,CAAC,GAAG,CAAC;IACtE,MAAM,KAAK,GAAG,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC;IAClC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,UAAU,GAAG,EAAE;QAAE,OAAO,IAAI,CAAC;IACjD,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,SAAqB;IACpD,MAAM,QAAQ,GAAG,SAAS,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAClF,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,CAC5B,KAAK,EACL,cAAc,CAAC,QAAQ,CAAC,EACxB,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,EAChC,KAAK,EACL,CAAC,SAAS,EAAE,SAAS,CAAC,CACvB,CAAC;AACJ,CAAC;AAID,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,QAAmB,EACnB,SAAqB,EACrB,KAAgB,EAChB,OAA2B,EAC3B,cAAwC;IAExC,IAAI,SAAS,CAAC,UAAU,GAAG,EAAE,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAClD,MAAM,iBAAiB,GAAG,MAAM,YAAY,CAC1C,gBAAgB,CAAC,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC,EAC9C,MAAM,EACN;QACE,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,KAAK,EAAE,WAAW;KACnB,EACD,OAAO,CACR,CAAC;IACF,OAAO;QACL,MAAM,EAAE,aAAa;QACrB,iBAAiB;QACjB,WAAW,EAAE,IAAI;QACjB,cAAc;KACf,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,iBAAwC,EACxC,SAAqB;IAErB,IAAI,SAAS,CAAC,UAAU,GAAG,EAAE,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,MAAM,YAAY,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,CAAC;IACjF,OAAO,YAAY,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,QAA2E,EAC3E,SAA4B,EAC5B,OAAmC;IAEnC,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,IAAI,IAAI,CAAC;IAEjD,IAAI,WAAW,IAAI,CAAC,SAAS,EAAE,CAAC;QAC9B,MAAM,IAAI,uBAAuB,CAC/B,6GAA6G,CAC9G,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,kBAAkB,CAC1B,4FAA4F,CAC7F,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,OAAO,MAAM,yBAAyB,CAAC,QAAQ,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;IAChF,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,kBAAkB,CAC1B,6FAA6F,CAC9F,CAAC;IACJ,CAAC;AACH,CAAC;AAED,mDAAmD;AACnD,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,2BAAuE,EACvE,SAA4B,EAC5B,OAAmC;IAEnC,MAAM,QAAQ,GACZ,QAAQ,IAAI,2BAA2B;QACrC,CAAC,CAAC,2BAA2B;QAC7B,CAAC,CAAC,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,EAAE,aAAsB,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAC5G,OAAO,4BAA4B,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AACpE,CAAC;AAED,+CAA+C;AAC/C,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,QAAmB,EACnB,SAAqB,EACrB,MAAc,EACd,UAAkB,EAClB,OAA2B,EAC3B,cAAwC;IAExC,MAAM,QAAQ,GAAG,MAAM,wBAAwB,CAC7C,QAAQ,EACR,SAAS,EACT,EAAE,MAAM,EAAE,UAAU,EAAE,EACtB,OAAO,EACP,cAAc,CACf,CAAC;IACF,OAAO,QAAQ,CAAC,iBAAiB,CAAC;AACpC,CAAC;AAED,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Argon2idKdfMetadata, EncryptedVaultPayload, KdfMetadata, PasswordEnvelope } from "../validation/schemas.js";
|
|
2
|
+
import type { VaultCryptoProfile, VaultAadScope } from "../profile.js";
|
|
3
|
+
type WrapScope = Pick<VaultAadScope, "userId" | "resourceId">;
|
|
4
|
+
export declare function createPasswordEnvelope(vaultKey: CryptoKey, vaultPassword: string, scope: WrapScope, profile: VaultCryptoProfile, salt?: Uint8Array): Promise<{
|
|
5
|
+
envelope: PasswordEnvelope;
|
|
6
|
+
kdfMetadata: Argon2idKdfMetadata;
|
|
7
|
+
}>;
|
|
8
|
+
export declare function unlockWithPasswordEnvelope(vaultPassword: string, envelope: PasswordEnvelope | {
|
|
9
|
+
encryptedVaultKey: EncryptedVaultPayload;
|
|
10
|
+
kdfMetadata: KdfMetadata;
|
|
11
|
+
}): Promise<CryptoKey>;
|
|
12
|
+
/** @deprecated Use createPasswordEnvelope */
|
|
13
|
+
export declare function wrapVaultKeyForPassword(vaultKey: CryptoKey, vaultPassword: string, scope: WrapScope, profile: VaultCryptoProfile, salt?: Uint8Array): Promise<{
|
|
14
|
+
encryptedVaultKey: EncryptedVaultPayload;
|
|
15
|
+
kdfMetadata: Argon2idKdfMetadata;
|
|
16
|
+
}>;
|
|
17
|
+
/** @deprecated Use unlockWithPasswordEnvelope */
|
|
18
|
+
export declare const unwrapVaultKeyFromPassword: typeof unlockWithPasswordEnvelope;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=password.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password.d.ts","sourceRoot":"","sources":["../../src/envelopes/password.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,qBAAqB,EACrB,WAAW,EACX,gBAAgB,EACjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAQvE,KAAK,SAAS,GAAG,IAAI,CAAC,aAAa,EAAE,QAAQ,GAAG,YAAY,CAAC,CAAC;AAuB9D,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,SAAS,EACnB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,kBAAkB,EAC3B,IAAI,CAAC,EAAE,UAAU,GAChB,OAAO,CAAC;IAAE,QAAQ,EAAE,gBAAgB,CAAC;IAAC,WAAW,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAW3E;AAED,wBAAsB,0BAA0B,CAC9C,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,gBAAgB,GAAG;IAAE,iBAAiB,EAAE,qBAAqB,CAAC;IAAC,WAAW,EAAE,WAAW,CAAA;CAAE,GAClG,OAAO,CAAC,SAAS,CAAC,CAMpB;AAED,6CAA6C;AAC7C,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,SAAS,EACnB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,kBAAkB,EAC3B,IAAI,CAAC,EAAE,UAAU,GAChB,OAAO,CAAC;IAAE,iBAAiB,EAAE,qBAAqB,CAAC;IAAC,WAAW,EAAE,mBAAmB,CAAA;CAAE,CAAC,CASzF;AAED,iDAAiD;AACjD,eAAO,MAAM,0BAA0B,mCAA6B,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { encryptField, decryptField, exportAesKey, importAesKey } from "../crypto/aes-gcm.js";
|
|
2
|
+
import { bytesToBase64Url, base64UrlToBytes } from "../crypto/encoding.js";
|
|
3
|
+
import { deriveVaultPasswordKey, deriveVaultPasswordKeyFromMetadata, } from "../kdf/argon2id.js";
|
|
4
|
+
async function wrapVaultKeyWithDerivedKey(vaultKey, derivedKey, scope, profile) {
|
|
5
|
+
return encryptField(bytesToBase64Url(await exportAesKey(vaultKey)), derivedKey, {
|
|
6
|
+
userId: scope.userId,
|
|
7
|
+
resourceId: scope.resourceId,
|
|
8
|
+
field: "vault_key",
|
|
9
|
+
}, profile);
|
|
10
|
+
}
|
|
11
|
+
async function unwrapVaultKeyWithDerivedKey(encryptedVaultKey, derivedKey) {
|
|
12
|
+
const keyBytes = base64UrlToBytes(await decryptField(encryptedVaultKey, derivedKey));
|
|
13
|
+
return importAesKey(keyBytes);
|
|
14
|
+
}
|
|
15
|
+
export async function createPasswordEnvelope(vaultKey, vaultPassword, scope, profile, salt) {
|
|
16
|
+
const { key: derivedKey, metadata } = await deriveVaultPasswordKey(vaultPassword, salt);
|
|
17
|
+
const encryptedVaultKey = await wrapVaultKeyWithDerivedKey(vaultKey, derivedKey, scope, profile);
|
|
18
|
+
return {
|
|
19
|
+
envelope: {
|
|
20
|
+
method: "password",
|
|
21
|
+
encryptedVaultKey,
|
|
22
|
+
kdfMetadata: metadata,
|
|
23
|
+
},
|
|
24
|
+
kdfMetadata: metadata,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export async function unlockWithPasswordEnvelope(vaultPassword, envelope) {
|
|
28
|
+
if (envelope.kdfMetadata?.kdf !== "argon2id") {
|
|
29
|
+
throw new Error("Vault password envelope requires Argon2id metadata");
|
|
30
|
+
}
|
|
31
|
+
const derivedKey = await deriveVaultPasswordKeyFromMetadata(vaultPassword, envelope.kdfMetadata);
|
|
32
|
+
return unwrapVaultKeyWithDerivedKey(envelope.encryptedVaultKey, derivedKey);
|
|
33
|
+
}
|
|
34
|
+
/** @deprecated Use createPasswordEnvelope */
|
|
35
|
+
export async function wrapVaultKeyForPassword(vaultKey, vaultPassword, scope, profile, salt) {
|
|
36
|
+
const { envelope, kdfMetadata } = await createPasswordEnvelope(vaultKey, vaultPassword, scope, profile, salt);
|
|
37
|
+
return { encryptedVaultKey: envelope.encryptedVaultKey, kdfMetadata };
|
|
38
|
+
}
|
|
39
|
+
/** @deprecated Use unlockWithPasswordEnvelope */
|
|
40
|
+
export const unwrapVaultKeyFromPassword = unlockWithPasswordEnvelope;
|
|
41
|
+
//# sourceMappingURL=password.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password.js","sourceRoot":"","sources":["../../src/envelopes/password.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC9F,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EACL,sBAAsB,EACtB,kCAAkC,GACnC,MAAM,oBAAoB,CAAC;AAI5B,KAAK,UAAU,0BAA0B,CACvC,QAAmB,EACnB,UAAqB,EACrB,KAAgB,EAChB,OAA2B;IAE3B,OAAO,YAAY,CAAC,gBAAgB,CAAC,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC,EAAE,UAAU,EAAE;QAC9E,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,KAAK,EAAE,WAAW;KACnB,EAAE,OAAO,CAAC,CAAC;AACd,CAAC;AAED,KAAK,UAAU,4BAA4B,CACzC,iBAAwC,EACxC,UAAqB;IAErB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,MAAM,YAAY,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC,CAAC;IACrF,OAAO,YAAY,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,QAAmB,EACnB,aAAqB,EACrB,KAAgB,EAChB,OAA2B,EAC3B,IAAiB;IAEjB,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,MAAM,sBAAsB,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IACxF,MAAM,iBAAiB,GAAG,MAAM,0BAA0B,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACjG,OAAO;QACL,QAAQ,EAAE;YACR,MAAM,EAAE,UAAU;YAClB,iBAAiB;YACjB,WAAW,EAAE,QAAQ;SACtB;QACD,WAAW,EAAE,QAAQ;KACtB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,aAAqB,EACrB,QAAmG;IAEnG,IAAI,QAAQ,CAAC,WAAW,EAAE,GAAG,KAAK,UAAU,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,kCAAkC,CAAC,aAAa,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IACjG,OAAO,4BAA4B,CAAC,QAAQ,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;AAC9E,CAAC;AAED,6CAA6C;AAC7C,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,QAAmB,EACnB,aAAqB,EACrB,KAAgB,EAChB,OAA2B,EAC3B,IAAiB;IAEjB,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,sBAAsB,CAC5D,QAAQ,EACR,aAAa,EACb,KAAK,EACL,OAAO,EACP,IAAI,CACL,CAAC;IACF,OAAO,EAAE,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,EAAE,WAAW,EAAE,CAAC;AACxE,CAAC;AAED,iDAAiD;AACjD,MAAM,CAAC,MAAM,0BAA0B,GAAG,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Argon2idKdfMetadata, EncryptedVaultPayload, KdfMetadata, RecoveryPhraseEnvelope } from "../validation/schemas.js";
|
|
2
|
+
import type { RecoveryPhraseWordCount } from "../profile.js";
|
|
3
|
+
import type { VaultCryptoProfile, VaultAadScope } from "../profile.js";
|
|
4
|
+
export declare const RECOVERY_PHRASE_WORDLIST_SOURCE: "BIP39 English (BIP-0039)";
|
|
5
|
+
export declare const DEFAULT_RECOVERY_PHRASE_WORD_COUNT: RecoveryPhraseWordCount;
|
|
6
|
+
type WrapScope = Pick<VaultAadScope, "userId" | "resourceId">;
|
|
7
|
+
export declare function createRecoveryPhrase(options: {
|
|
8
|
+
wordCount: RecoveryPhraseWordCount;
|
|
9
|
+
}): string;
|
|
10
|
+
/** @deprecated Use createRecoveryPhrase */
|
|
11
|
+
export declare const generateRecoveryPhrase: typeof createRecoveryPhrase;
|
|
12
|
+
export declare function getRecoveryPhraseWordCount(phrase: string): RecoveryPhraseWordCount | null;
|
|
13
|
+
export declare function getRecoveryConfirmationPromptCount(wordCount: RecoveryPhraseWordCount): number;
|
|
14
|
+
export declare function parseRecoveryPhraseWordCount(publicMetadata?: Record<string, unknown> | null): RecoveryPhraseWordCount | null;
|
|
15
|
+
export declare function assertRecoveryPhraseUnlockInput(phrase: string, expectedWordCount?: RecoveryPhraseWordCount | null): void;
|
|
16
|
+
export declare function normalizeRecoveryPhrase(phrase: string): string;
|
|
17
|
+
export declare function validateRecoveryPhraseFormat(phrase: string): boolean;
|
|
18
|
+
export declare function assertRecoveryPhraseConfirmation(originalPhrase: string, confirmationPhrase: string): void;
|
|
19
|
+
export declare function pickRecoveryConfirmationIndices(wordCount: number, count?: number): number[];
|
|
20
|
+
export declare function assertRecoveryPhraseWordConfirmation(originalPhrase: string, answers: Record<number, string>): void;
|
|
21
|
+
export declare function deriveRecoveryPhraseKey(phrase: string, salt?: Uint8Array): Promise<{
|
|
22
|
+
key: CryptoKey;
|
|
23
|
+
metadata: Argon2idKdfMetadata;
|
|
24
|
+
}>;
|
|
25
|
+
export declare function deriveRecoveryPhraseKeyFromMetadata(phrase: string, metadata: Argon2idKdfMetadata): Promise<CryptoKey>;
|
|
26
|
+
export declare function createRecoveryEnvelope(vaultKey: CryptoKey, recoveryPhrase: string, scope: WrapScope, profile: VaultCryptoProfile, publicMetadata?: {
|
|
27
|
+
phraseLength: RecoveryPhraseWordCount;
|
|
28
|
+
}, salt?: Uint8Array): Promise<{
|
|
29
|
+
envelope: RecoveryPhraseEnvelope;
|
|
30
|
+
kdfMetadata: Argon2idKdfMetadata;
|
|
31
|
+
}>;
|
|
32
|
+
export declare function unlockWithRecoveryEnvelope(recoveryPhrase: string, envelope: RecoveryPhraseEnvelope | {
|
|
33
|
+
encryptedVaultKey: EncryptedVaultPayload;
|
|
34
|
+
kdfMetadata: KdfMetadata;
|
|
35
|
+
}, options?: {
|
|
36
|
+
expectedWordCount?: RecoveryPhraseWordCount | null;
|
|
37
|
+
}): Promise<CryptoKey>;
|
|
38
|
+
/** @deprecated Use createRecoveryEnvelope */
|
|
39
|
+
export declare function wrapVaultKeyForRecoveryPhrase(vaultKey: CryptoKey, recoveryPhrase: string, scope: WrapScope, profile: VaultCryptoProfile, salt?: Uint8Array): Promise<{
|
|
40
|
+
encryptedVaultKey: EncryptedVaultPayload;
|
|
41
|
+
kdfMetadata: Argon2idKdfMetadata;
|
|
42
|
+
}>;
|
|
43
|
+
/** @deprecated Use unlockWithRecoveryEnvelope */
|
|
44
|
+
export declare const unwrapVaultKeyFromRecoveryPhrase: typeof unlockWithRecoveryEnvelope;
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["../../src/envelopes/recovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { generateMnemonic, mnemonicToEntropy, validateMnemonic } from "@scure/bip39";
|
|
2
|
+
import { wordlist } from "@scure/bip39/wordlists/english.js";
|
|
3
|
+
import { stringToBytes, bytesToBase64Url, base64UrlToBytes } from "../crypto/encoding.js";
|
|
4
|
+
import { deriveArgon2idAesKey, deriveArgon2idAesKeyFromMetadata, serializeArgon2idMetadata, } from "../kdf/argon2id.js";
|
|
5
|
+
import { DEFAULT_ARGON2ID_PARAMS } from "../kdf/params.js";
|
|
6
|
+
import { RecoveryPhraseConfirmationError } from "../errors/vault-errors.js";
|
|
7
|
+
import { encryptField, decryptField, exportAesKey, importAesKey } from "../crypto/aes-gcm.js";
|
|
8
|
+
export const RECOVERY_PHRASE_WORDLIST_SOURCE = "BIP39 English (BIP-0039)";
|
|
9
|
+
export const DEFAULT_RECOVERY_PHRASE_WORD_COUNT = 24;
|
|
10
|
+
const STRENGTH_BITS = {
|
|
11
|
+
12: 128,
|
|
12
|
+
24: 256,
|
|
13
|
+
};
|
|
14
|
+
export function createRecoveryPhrase(options) {
|
|
15
|
+
const { wordCount } = options;
|
|
16
|
+
if (wordCount !== 12 && wordCount !== 24) {
|
|
17
|
+
throw new Error("Recovery phrase word count must be 12 or 24");
|
|
18
|
+
}
|
|
19
|
+
return generateMnemonic(wordlist, STRENGTH_BITS[wordCount]);
|
|
20
|
+
}
|
|
21
|
+
/** @deprecated Use createRecoveryPhrase */
|
|
22
|
+
export const generateRecoveryPhrase = createRecoveryPhrase;
|
|
23
|
+
export function getRecoveryPhraseWordCount(phrase) {
|
|
24
|
+
const normalized = normalizeRecoveryPhrase(phrase);
|
|
25
|
+
const count = normalized.split(" ").filter(Boolean).length;
|
|
26
|
+
if (count === 12 || count === 24)
|
|
27
|
+
return count;
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
export function getRecoveryConfirmationPromptCount(wordCount) {
|
|
31
|
+
return wordCount === 12 ? 3 : 4;
|
|
32
|
+
}
|
|
33
|
+
export function parseRecoveryPhraseWordCount(publicMetadata) {
|
|
34
|
+
const raw = publicMetadata?.phraseLength ?? publicMetadata?.wordCount;
|
|
35
|
+
if (raw === 12 || raw === 24)
|
|
36
|
+
return raw;
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
export function assertRecoveryPhraseUnlockInput(phrase, expectedWordCount) {
|
|
40
|
+
const normalized = normalizeRecoveryPhrase(phrase);
|
|
41
|
+
if (!validateRecoveryPhraseFormat(normalized)) {
|
|
42
|
+
throw new Error("Enter a valid 12- or 24-word BIP39 recovery phrase.");
|
|
43
|
+
}
|
|
44
|
+
const actualCount = getRecoveryPhraseWordCount(normalized);
|
|
45
|
+
if (expectedWordCount != null && actualCount !== expectedWordCount) {
|
|
46
|
+
throw new Error(`This vault uses a ${expectedWordCount}-word recovery phrase. You entered ${actualCount ?? "an invalid number of"} words.`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export function normalizeRecoveryPhrase(phrase) {
|
|
50
|
+
return phrase
|
|
51
|
+
.trim()
|
|
52
|
+
.toLowerCase()
|
|
53
|
+
.split(/\s+/)
|
|
54
|
+
.filter(Boolean)
|
|
55
|
+
.join(" ");
|
|
56
|
+
}
|
|
57
|
+
export function validateRecoveryPhraseFormat(phrase) {
|
|
58
|
+
const normalized = normalizeRecoveryPhrase(phrase);
|
|
59
|
+
if (!normalized)
|
|
60
|
+
return false;
|
|
61
|
+
const words = normalized.split(" ");
|
|
62
|
+
if (words.length !== 12 && words.length !== 24)
|
|
63
|
+
return false;
|
|
64
|
+
return validateMnemonic(normalized, wordlist);
|
|
65
|
+
}
|
|
66
|
+
export function assertRecoveryPhraseConfirmation(originalPhrase, confirmationPhrase) {
|
|
67
|
+
const a = normalizeRecoveryPhrase(originalPhrase);
|
|
68
|
+
const b = normalizeRecoveryPhrase(confirmationPhrase);
|
|
69
|
+
if (a !== b) {
|
|
70
|
+
throw new RecoveryPhraseConfirmationError("Recovery phrase confirmation does not match");
|
|
71
|
+
}
|
|
72
|
+
if (!validateRecoveryPhraseFormat(a)) {
|
|
73
|
+
throw new RecoveryPhraseConfirmationError("Recovery phrase is not valid");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
export function pickRecoveryConfirmationIndices(wordCount, count = 3) {
|
|
77
|
+
if (wordCount < count) {
|
|
78
|
+
throw new Error("Not enough words for confirmation");
|
|
79
|
+
}
|
|
80
|
+
const indices = [];
|
|
81
|
+
let seed = wordCount * 7919 + count * 104729;
|
|
82
|
+
while (indices.length < count) {
|
|
83
|
+
seed = (seed * 1103515245 + 12345) & 0x7fffffff;
|
|
84
|
+
const candidate = (seed % wordCount) + 1;
|
|
85
|
+
if (!indices.includes(candidate)) {
|
|
86
|
+
indices.push(candidate);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return indices.sort((a, b) => a - b);
|
|
90
|
+
}
|
|
91
|
+
export function assertRecoveryPhraseWordConfirmation(originalPhrase, answers) {
|
|
92
|
+
const words = normalizeRecoveryPhrase(originalPhrase).split(" ");
|
|
93
|
+
if (!validateRecoveryPhraseFormat(originalPhrase)) {
|
|
94
|
+
throw new RecoveryPhraseConfirmationError("Recovery phrase is not valid");
|
|
95
|
+
}
|
|
96
|
+
for (const [indexRaw, answer] of Object.entries(answers)) {
|
|
97
|
+
const index = Number.parseInt(indexRaw, 10);
|
|
98
|
+
const expected = words[index - 1];
|
|
99
|
+
const given = normalizeRecoveryPhrase(answer);
|
|
100
|
+
if (!expected || given !== expected) {
|
|
101
|
+
throw new RecoveryPhraseConfirmationError(`Word #${index} does not match your recovery phrase`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export async function deriveRecoveryPhraseKey(phrase, salt) {
|
|
106
|
+
const normalized = normalizeRecoveryPhrase(phrase);
|
|
107
|
+
if (!validateRecoveryPhraseFormat(normalized)) {
|
|
108
|
+
throw new Error("Invalid recovery phrase");
|
|
109
|
+
}
|
|
110
|
+
mnemonicToEntropy(normalized, wordlist);
|
|
111
|
+
const saltBytes = salt ?? crypto.getRandomValues(new Uint8Array(DEFAULT_ARGON2ID_PARAMS.saltLength));
|
|
112
|
+
const passwordBytes = stringToBytes(normalized);
|
|
113
|
+
const key = await deriveArgon2idAesKey(passwordBytes, saltBytes);
|
|
114
|
+
return {
|
|
115
|
+
key,
|
|
116
|
+
metadata: serializeArgon2idMetadata(saltBytes),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
export async function deriveRecoveryPhraseKeyFromMetadata(phrase, metadata) {
|
|
120
|
+
const normalized = normalizeRecoveryPhrase(phrase);
|
|
121
|
+
if (!validateRecoveryPhraseFormat(normalized)) {
|
|
122
|
+
throw new Error("Invalid recovery phrase");
|
|
123
|
+
}
|
|
124
|
+
return deriveArgon2idAesKeyFromMetadata(stringToBytes(normalized), metadata);
|
|
125
|
+
}
|
|
126
|
+
async function wrapVaultKeyWithDerivedKey(vaultKey, derivedKey, scope, profile) {
|
|
127
|
+
return encryptField(bytesToBase64Url(await exportAesKey(vaultKey)), derivedKey, {
|
|
128
|
+
userId: scope.userId,
|
|
129
|
+
resourceId: scope.resourceId,
|
|
130
|
+
field: "vault_key",
|
|
131
|
+
}, profile);
|
|
132
|
+
}
|
|
133
|
+
async function unwrapVaultKeyWithDerivedKey(encryptedVaultKey, derivedKey) {
|
|
134
|
+
const keyBytes = base64UrlToBytes(await decryptField(encryptedVaultKey, derivedKey));
|
|
135
|
+
return importAesKey(keyBytes);
|
|
136
|
+
}
|
|
137
|
+
export async function createRecoveryEnvelope(vaultKey, recoveryPhrase, scope, profile, publicMetadata, salt) {
|
|
138
|
+
const { key: derivedKey, metadata } = await deriveRecoveryPhraseKey(recoveryPhrase, salt);
|
|
139
|
+
const encryptedVaultKey = await wrapVaultKeyWithDerivedKey(vaultKey, derivedKey, scope, profile);
|
|
140
|
+
return {
|
|
141
|
+
envelope: {
|
|
142
|
+
method: "recovery_phrase",
|
|
143
|
+
encryptedVaultKey,
|
|
144
|
+
kdfMetadata: metadata,
|
|
145
|
+
publicMetadata,
|
|
146
|
+
},
|
|
147
|
+
kdfMetadata: metadata,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
export async function unlockWithRecoveryEnvelope(recoveryPhrase, envelope, options) {
|
|
151
|
+
if (options?.expectedWordCount != null) {
|
|
152
|
+
assertRecoveryPhraseUnlockInput(recoveryPhrase, options.expectedWordCount);
|
|
153
|
+
}
|
|
154
|
+
if (envelope.kdfMetadata?.kdf !== "argon2id") {
|
|
155
|
+
throw new Error("Recovery phrase envelope requires Argon2id metadata");
|
|
156
|
+
}
|
|
157
|
+
const derivedKey = await deriveRecoveryPhraseKeyFromMetadata(recoveryPhrase, envelope.kdfMetadata);
|
|
158
|
+
return unwrapVaultKeyWithDerivedKey(envelope.encryptedVaultKey, derivedKey);
|
|
159
|
+
}
|
|
160
|
+
/** @deprecated Use createRecoveryEnvelope */
|
|
161
|
+
export async function wrapVaultKeyForRecoveryPhrase(vaultKey, recoveryPhrase, scope, profile, salt) {
|
|
162
|
+
const { envelope, kdfMetadata } = await createRecoveryEnvelope(vaultKey, recoveryPhrase, scope, profile, undefined, salt);
|
|
163
|
+
return { encryptedVaultKey: envelope.encryptedVaultKey, kdfMetadata };
|
|
164
|
+
}
|
|
165
|
+
/** @deprecated Use unlockWithRecoveryEnvelope */
|
|
166
|
+
export const unwrapVaultKeyFromRecoveryPhrase = unlockWithRecoveryEnvelope;
|
|
167
|
+
//# sourceMappingURL=recovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.js","sourceRoot":"","sources":["../../src/envelopes/recovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare class VaultPlaintextRejectionError extends Error {
|
|
2
|
+
constructor(message: string);
|
|
3
|
+
}
|
|
4
|
+
export declare class VaultConflictError extends Error {
|
|
5
|
+
constructor(message: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class VaultNotFoundError extends Error {
|
|
8
|
+
constructor(message: string);
|
|
9
|
+
}
|
|
10
|
+
export declare class PasskeyPrfRequiredError extends Error {
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
|
13
|
+
export declare class PasskeyUnlockError extends Error {
|
|
14
|
+
constructor(message: string);
|
|
15
|
+
}
|
|
16
|
+
export declare class RecoveryPhraseConfirmationError extends Error {
|
|
17
|
+
constructor(message: string);
|
|
18
|
+
}
|
|
19
|
+
export type VaultCoreError = VaultPlaintextRejectionError | VaultConflictError | VaultNotFoundError | PasskeyPrfRequiredError | PasskeyUnlockError | RecoveryPhraseConfirmationError;
|
|
20
|
+
//# sourceMappingURL=vault-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vault-errors.d.ts","sourceRoot":"","sources":["../../src/errors/vault-errors.ts"],"names":[],"mappings":"AAAA,qBAAa,4BAA6B,SAAQ,KAAK;gBACzC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,+BAAgC,SAAQ,KAAK;gBAC5C,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,MAAM,cAAc,GACtB,4BAA4B,GAC5B,kBAAkB,GAClB,kBAAkB,GAClB,uBAAuB,GACvB,kBAAkB,GAClB,+BAA+B,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export class VaultPlaintextRejectionError extends Error {
|
|
2
|
+
constructor(message) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.name = "VaultPlaintextRejectionError";
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
export class VaultConflictError extends Error {
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "VaultConflictError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class VaultNotFoundError extends Error {
|
|
14
|
+
constructor(message) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = "VaultNotFoundError";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class PasskeyPrfRequiredError extends Error {
|
|
20
|
+
constructor(message) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = "PasskeyPrfRequiredError";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export class PasskeyUnlockError extends Error {
|
|
26
|
+
constructor(message) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = "PasskeyUnlockError";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export class RecoveryPhraseConfirmationError extends Error {
|
|
32
|
+
constructor(message) {
|
|
33
|
+
super(message);
|
|
34
|
+
this.name = "RecoveryPhraseConfirmationError";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=vault-errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vault-errors.js","sourceRoot":"","sources":["../../src/errors/vault-errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,4BAA6B,SAAQ,KAAK;IACrD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,8BAA8B,CAAC;IAC7C,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAChD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,+BAAgC,SAAQ,KAAK;IACxD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iCAAiC,CAAC;IAChD,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export * from "./constants.js";
|
|
2
|
+
export * from "./profile.js";
|
|
3
|
+
export * from "./errors/vault-errors.js";
|
|
4
|
+
export * from "./crypto/aes-gcm.js";
|
|
5
|
+
export * from "./crypto/aad.js";
|
|
6
|
+
export * from "./crypto/encoding.js";
|
|
7
|
+
export * from "./crypto/random.js";
|
|
8
|
+
export * from "./crypto/serialization.js";
|
|
9
|
+
export * from "./kdf/argon2id.js";
|
|
10
|
+
export * from "./kdf/params.js";
|
|
11
|
+
export * from "./keys/user-vault-key.js";
|
|
12
|
+
export * from "./validation/schemas.js";
|
|
13
|
+
export * from "./validation/aad-assert.js";
|
|
14
|
+
export { assertNoVaultPlaintextFields, rejectVaultPlaintextFields, validateNoPlaintextLeak, scanForSentinels, containsSentinel, PLAINTEXT_FORBIDDEN_VAULT_FIELDS, ALL_SENTINELS, SENTINEL_VAULT_PASSWORD, SENTINEL_RECOVERY_PHRASE, SENTINEL_12_WORD_RECOVERY_PHRASE, SENTINEL_24_WORD_RECOVERY_PHRASE, SENTINEL_PRIVATE_LABEL, SENTINEL_STRATEGY_NOTE, SENTINEL_SUBSCRIPTION_TOKEN, SENTINEL_MANAGEMENT_TOKEN, SENTINEL_PRIVATE_NOTE, SENTINEL_USER_VAULT_KEY, SENTINEL_PRF_OUTPUT, } from "./validation/plaintext-reject.js";
|
|
15
|
+
export * from "./payload/encrypted-payload.js";
|
|
16
|
+
export * from "./envelopes/password.js";
|
|
17
|
+
export * from "./envelopes/recovery.js";
|
|
18
|
+
export * from "./envelopes/passkey-prf.js";
|
|
19
|
+
export * from "./recovery/kit.js";
|
|
20
|
+
export type { VaultUnlockResult } from "./profile.js";
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,0BAA0B,CAAC;AAEzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAE1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAEhC,cAAc,0BAA0B,CAAC;AAEzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EACL,4BAA4B,EAC5B,0BAA0B,EAC1B,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,EAChB,gCAAgC,EAChC,aAAa,EACb,uBAAuB,EACvB,wBAAwB,EACxB,gCAAgC,EAChC,gCAAgC,EAChC,sBAAsB,EACtB,sBAAsB,EACtB,2BAA2B,EAC3B,yBAAyB,EACzB,qBAAqB,EACrB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,kCAAkC,CAAC;AAE1C,cAAc,gCAAgC,CAAC;AAE/C,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAE3C,cAAc,mBAAmB,CAAC;AAElC,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export * from "./constants.js";
|
|
2
|
+
export * from "./profile.js";
|
|
3
|
+
export * from "./errors/vault-errors.js";
|
|
4
|
+
export * from "./crypto/aes-gcm.js";
|
|
5
|
+
export * from "./crypto/aad.js";
|
|
6
|
+
export * from "./crypto/encoding.js";
|
|
7
|
+
export * from "./crypto/random.js";
|
|
8
|
+
export * from "./crypto/serialization.js";
|
|
9
|
+
export * from "./kdf/argon2id.js";
|
|
10
|
+
export * from "./kdf/params.js";
|
|
11
|
+
export * from "./keys/user-vault-key.js";
|
|
12
|
+
export * from "./validation/schemas.js";
|
|
13
|
+
export * from "./validation/aad-assert.js";
|
|
14
|
+
export { assertNoVaultPlaintextFields, rejectVaultPlaintextFields, validateNoPlaintextLeak, scanForSentinels, containsSentinel, PLAINTEXT_FORBIDDEN_VAULT_FIELDS, ALL_SENTINELS, SENTINEL_VAULT_PASSWORD, SENTINEL_RECOVERY_PHRASE, SENTINEL_12_WORD_RECOVERY_PHRASE, SENTINEL_24_WORD_RECOVERY_PHRASE, SENTINEL_PRIVATE_LABEL, SENTINEL_STRATEGY_NOTE, SENTINEL_SUBSCRIPTION_TOKEN, SENTINEL_MANAGEMENT_TOKEN, SENTINEL_PRIVATE_NOTE, SENTINEL_USER_VAULT_KEY, SENTINEL_PRF_OUTPUT, } from "./validation/plaintext-reject.js";
|
|
15
|
+
export * from "./payload/encrypted-payload.js";
|
|
16
|
+
export * from "./envelopes/password.js";
|
|
17
|
+
export * from "./envelopes/recovery.js";
|
|
18
|
+
export * from "./envelopes/passkey-prf.js";
|
|
19
|
+
export * from "./recovery/kit.js";
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,0BAA0B,CAAC;AAEzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAE1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAEhC,cAAc,0BAA0B,CAAC;AAEzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EACL,4BAA4B,EAC5B,0BAA0B,EAC1B,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,EAChB,gCAAgC,EAChC,aAAa,EACb,uBAAuB,EACvB,wBAAwB,EACxB,gCAAgC,EAChC,gCAAgC,EAChC,sBAAsB,EACtB,sBAAsB,EACtB,2BAA2B,EAC3B,yBAAyB,EACzB,qBAAqB,EACrB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,kCAAkC,CAAC;AAE1C,cAAc,gCAAgC,CAAC;AAE/C,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAE3C,cAAc,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Argon2idKdfMetadata } from "../validation/schemas.js";
|
|
2
|
+
import { DEFAULT_ARGON2ID_PARAMS } from "./params.js";
|
|
3
|
+
export { DEFAULT_ARGON2ID_PARAMS, type Argon2idParams } from "./params.js";
|
|
4
|
+
export type { Argon2idKdfMetadata };
|
|
5
|
+
export declare function serializeArgon2idMetadata(salt: Uint8Array, params?: Pick<typeof DEFAULT_ARGON2ID_PARAMS, "memory" | "iterations" | "parallelism">): Argon2idKdfMetadata;
|
|
6
|
+
export declare function parseArgon2idMetadata(metadata: Argon2idKdfMetadata): {
|
|
7
|
+
salt: Uint8Array;
|
|
8
|
+
memory: number;
|
|
9
|
+
iterations: number;
|
|
10
|
+
parallelism: number;
|
|
11
|
+
};
|
|
12
|
+
export declare function deriveArgon2idAesKey(passwordBytes: Uint8Array, salt: Uint8Array, params?: {
|
|
13
|
+
memory: number;
|
|
14
|
+
iterations: number;
|
|
15
|
+
parallelism: number;
|
|
16
|
+
hashLength?: number;
|
|
17
|
+
}): Promise<CryptoKey>;
|
|
18
|
+
export declare function deriveArgon2idAesKeyFromMetadata(passwordBytes: Uint8Array, metadata: Argon2idKdfMetadata): Promise<CryptoKey>;
|
|
19
|
+
export declare function deriveVaultPasswordKey(vaultPassword: string, salt?: Uint8Array): Promise<{
|
|
20
|
+
key: CryptoKey;
|
|
21
|
+
metadata: Argon2idKdfMetadata;
|
|
22
|
+
}>;
|
|
23
|
+
export declare function deriveVaultPasswordKeyFromMetadata(vaultPassword: string, metadata: Argon2idKdfMetadata): Promise<CryptoKey>;
|
|
24
|
+
//# sourceMappingURL=argon2id.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"argon2id.d.ts","sourceRoot":"","sources":["../../src/kdf/argon2id.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAOpE,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,uBAAuB,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAE3E,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,UAAU,EAChB,MAAM,GAAE,IAAI,CAAC,OAAO,uBAAuB,EAAE,QAAQ,GAAG,YAAY,GAAG,aAAa,CAA2B,GAC9G,mBAAmB,CASrB;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,mBAAmB,GAAG;IACpE,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB,CAOA;AAED,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,UAAU,EACzB,IAAI,EAAE,UAAU,EAChB,MAAM,GAAE;IACN,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACK,GAC1B,OAAO,CAAC,SAAS,CAAC,CAmBpB;AAED,wBAAsB,gCAAgC,CACpD,aAAa,EAAE,UAAU,EACzB,QAAQ,EAAE,mBAAmB,GAC5B,OAAO,CAAC,SAAS,CAAC,CAQpB;AAED,wBAAsB,sBAAsB,CAC1C,aAAa,EAAE,MAAM,EACrB,IAAI,CAAC,EAAE,UAAU,GAChB,OAAO,CAAC;IAAE,GAAG,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAS5D;AAED,wBAAsB,kCAAkC,CACtD,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,mBAAmB,GAC5B,OAAO,CAAC,SAAS,CAAC,CAKpB"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { argon2id } from "hash-wasm";
|
|
2
|
+
import { bytesToBase64Url, base64UrlToBytes, toBufferSource, stringToBytes, } from "../crypto/encoding.js";
|
|
3
|
+
import { DEFAULT_ARGON2ID_PARAMS } from "./params.js";
|
|
4
|
+
export { DEFAULT_ARGON2ID_PARAMS } from "./params.js";
|
|
5
|
+
export function serializeArgon2idMetadata(salt, params = DEFAULT_ARGON2ID_PARAMS) {
|
|
6
|
+
return {
|
|
7
|
+
kdf: "argon2id",
|
|
8
|
+
version: "kdf-v1",
|
|
9
|
+
salt: bytesToBase64Url(salt),
|
|
10
|
+
memory: params.memory,
|
|
11
|
+
iterations: params.iterations,
|
|
12
|
+
parallelism: params.parallelism,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function parseArgon2idMetadata(metadata) {
|
|
16
|
+
return {
|
|
17
|
+
salt: base64UrlToBytes(metadata.salt),
|
|
18
|
+
memory: metadata.memory,
|
|
19
|
+
iterations: metadata.iterations,
|
|
20
|
+
parallelism: metadata.parallelism,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export async function deriveArgon2idAesKey(passwordBytes, salt, params = DEFAULT_ARGON2ID_PARAMS) {
|
|
24
|
+
const hashLength = params.hashLength ?? DEFAULT_ARGON2ID_PARAMS.hashLength;
|
|
25
|
+
const hash = await argon2id({
|
|
26
|
+
password: passwordBytes,
|
|
27
|
+
salt,
|
|
28
|
+
parallelism: params.parallelism,
|
|
29
|
+
iterations: params.iterations,
|
|
30
|
+
memorySize: params.memory,
|
|
31
|
+
hashLength,
|
|
32
|
+
outputType: "binary",
|
|
33
|
+
});
|
|
34
|
+
return crypto.subtle.importKey("raw", toBufferSource(new Uint8Array(hash)), { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
|
|
35
|
+
}
|
|
36
|
+
export async function deriveArgon2idAesKeyFromMetadata(passwordBytes, metadata) {
|
|
37
|
+
const { salt, memory, iterations, parallelism } = parseArgon2idMetadata(metadata);
|
|
38
|
+
return deriveArgon2idAesKey(passwordBytes, salt, {
|
|
39
|
+
memory,
|
|
40
|
+
iterations,
|
|
41
|
+
parallelism,
|
|
42
|
+
hashLength: DEFAULT_ARGON2ID_PARAMS.hashLength,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
export async function deriveVaultPasswordKey(vaultPassword, salt) {
|
|
46
|
+
const saltBytes = salt ?? crypto.getRandomValues(new Uint8Array(DEFAULT_ARGON2ID_PARAMS.saltLength));
|
|
47
|
+
const passwordBytes = stringToBytes(vaultPassword.normalize("NFKC"));
|
|
48
|
+
const key = await deriveArgon2idAesKey(passwordBytes, saltBytes);
|
|
49
|
+
return {
|
|
50
|
+
key,
|
|
51
|
+
metadata: serializeArgon2idMetadata(saltBytes),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export async function deriveVaultPasswordKeyFromMetadata(vaultPassword, metadata) {
|
|
55
|
+
return deriveArgon2idAesKeyFromMetadata(stringToBytes(vaultPassword.normalize("NFKC")), metadata);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=argon2id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"argon2id.js","sourceRoot":"","sources":["../../src/kdf/argon2id.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const DEFAULT_ARGON2ID_PARAMS: {
|
|
2
|
+
readonly memory: 65536;
|
|
3
|
+
readonly iterations: 3;
|
|
4
|
+
readonly parallelism: 1;
|
|
5
|
+
readonly hashLength: 32;
|
|
6
|
+
readonly saltLength: 16;
|
|
7
|
+
};
|
|
8
|
+
export type Argon2idParams = typeof DEFAULT_ARGON2ID_PARAMS;
|
|
9
|
+
//# sourceMappingURL=params.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"params.d.ts","sourceRoot":"","sources":["../../src/kdf/params.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB;;;;;;CAM1B,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,OAAO,uBAAuB,CAAC"}
|