@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/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# @vaultkeepr/core
|
|
2
|
+
|
|
3
|
+
Vault cryptography for VaultKeepR: XChaCha20-Poly1305 AEAD encryption, Argon2id key derivation, ECIES wallet envelopes, TOTP, passkeys, BIP-39, password tooling, and import/export for 10+ password manager formats.
|
|
4
|
+
|
|
5
|
+
Zero-knowledge by design: the master password never leaves the user's device, and plaintext never crosses a network boundary.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @vaultkeepr/core
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import {
|
|
17
|
+
addEntry,
|
|
18
|
+
createEmptyVault,
|
|
19
|
+
decryptVault,
|
|
20
|
+
deriveKeyFromPasswordArgon2,
|
|
21
|
+
encryptVault,
|
|
22
|
+
generatePassword,
|
|
23
|
+
generateSaltArgon2,
|
|
24
|
+
serializeVault,
|
|
25
|
+
} from "@vaultkeepr/core";
|
|
26
|
+
|
|
27
|
+
// Build a vault
|
|
28
|
+
const vault = addEntry(createEmptyVault(), {
|
|
29
|
+
title: "GitHub",
|
|
30
|
+
url: "https://github.com",
|
|
31
|
+
username: "octocat",
|
|
32
|
+
password: generatePassword(),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Encrypt locally — Argon2id (t=3, m=64 MiB, p=4) + XChaCha20-Poly1305
|
|
36
|
+
const salt = generateSaltArgon2();
|
|
37
|
+
const key = deriveKeyFromPasswordArgon2("correct horse battery staple", salt);
|
|
38
|
+
const encrypted = encryptVault(serializeVault(vault), key);
|
|
39
|
+
|
|
40
|
+
// Decrypt (the key is wiped after each use — re-derive it)
|
|
41
|
+
const plaintext = decryptVault(encrypted, deriveKeyFromPasswordArgon2("correct horse battery staple", salt));
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Other surfaces: TOTP (`getTOTPCode`, `parseTOTPUri`), importers (`importFromPgp`, `importVaultText`, LastPass, Keeper, Dashlane, Enpass, KeePass XML, RoboForm, Bitwarden/1Password exports), passkey/NFC/MRZ crypto, password health and entropy, BIP-39/EFF wordlists, three-way merge, pairing.
|
|
45
|
+
|
|
46
|
+
## Security notes
|
|
47
|
+
|
|
48
|
+
- Crypto primitives come from `@noble/ciphers`, `@noble/curves`, `@noble/hashes`.
|
|
49
|
+
- `encryptVault`/`decryptVault` wipe the master key after use by default (`wipeKeyAfterUse`).
|
|
50
|
+
- Vault integrity is enforced via an HMAC-SHA256 commitment — tampering throws.
|
|
51
|
+
|
|
52
|
+
## Related packages
|
|
53
|
+
|
|
54
|
+
- [`@vaultkeepr/sync`](https://www.npmjs.com/package/@vaultkeepr/sync) — CRDT synchronization
|
|
55
|
+
- [`@vaultkeepr/ipfs`](https://www.npmjs.com/package/@vaultkeepr/ipfs) — CID storage and gateway fetch
|
|
56
|
+
- [`@vaultkeepr/recovery`](https://www.npmjs.com/package/@vaultkeepr/recovery) — fragmented recovery
|
|
57
|
+
|
|
58
|
+
Repository: [VaultKeepR/vaultkeepr-public](https://github.com/VaultKeepR/vaultkeepr-public) · Site: [vaultkeepr.xyz](https://vaultkeepr.xyz) · Threat model: [`docs/THREAT_MODEL.md`](https://github.com/VaultKeepR/vaultkeepr-public/blob/main/docs/THREAT_MODEL.md)
|
|
59
|
+
|
|
60
|
+
MIT licensed.
|
package/dist/index.d.mts
CHANGED
|
@@ -149,6 +149,7 @@ interface Vault {
|
|
|
149
149
|
legacyContacts?: LegacyContact[];
|
|
150
150
|
prfCredentials?: PrfCredentialRecord[];
|
|
151
151
|
monitoredEmails?: string[];
|
|
152
|
+
secretKey?: string;
|
|
152
153
|
}
|
|
153
154
|
interface PrfCredentialRecord {
|
|
154
155
|
credentialId: string;
|
|
@@ -227,6 +228,8 @@ declare const DEFAULT_ENTRY_GROUP: EntryGroupId;
|
|
|
227
228
|
declare const BUILTIN_FOLDER_IDS: Record<EntryGroupId | "passkeys", string>;
|
|
228
229
|
declare const BUILTIN_FOLDER_NODES: FolderNode[];
|
|
229
230
|
declare function getEntryGroupLabel(folder: string | undefined): string;
|
|
231
|
+
declare function cleanEntryTitle(rawTitle: string, url?: string): string;
|
|
232
|
+
declare function getEntryDisplayName(entry: VaultEntry, primaryUrl?: string): string;
|
|
230
233
|
declare function resolveFolderName(folderId: string | undefined, folderTree: FolderNode[] | undefined): string;
|
|
231
234
|
|
|
232
235
|
declare function generateMasterKey(): Uint8Array;
|
|
@@ -364,7 +367,10 @@ interface EncryptedImportResult {
|
|
|
364
367
|
vault: Vault;
|
|
365
368
|
secretKey?: string;
|
|
366
369
|
}
|
|
367
|
-
declare function importEncryptedVault(encryptedJson: string, password: string, argon2Opts?: Argon2Options
|
|
370
|
+
declare function importEncryptedVault(encryptedJson: string, password: string, argon2Opts?: Argon2Options, precomputed?: {
|
|
371
|
+
key: Uint8Array;
|
|
372
|
+
salt?: Uint8Array;
|
|
373
|
+
}): Promise<EncryptedImportResult>;
|
|
368
374
|
|
|
369
375
|
interface SkippedExport {
|
|
370
376
|
id: string;
|
|
@@ -412,6 +418,7 @@ type PwnedPasswordFetchOptions = {
|
|
|
412
418
|
signal?: AbortSignal;
|
|
413
419
|
fetchFn?: typeof fetch;
|
|
414
420
|
};
|
|
421
|
+
declare function getPwnedCountForHash(sha1Hex: string, options?: PwnedPasswordFetchOptions): Promise<number>;
|
|
415
422
|
declare function getPwnedPasswordCount(password: string, options?: PwnedPasswordFetchOptions): Promise<number>;
|
|
416
423
|
|
|
417
424
|
declare function uniformRandom(max: number): number;
|
|
@@ -582,6 +589,8 @@ declare function setArgon2Provider(fn: Argon2ProviderFn): void;
|
|
|
582
589
|
declare function getHiddenWalletLegacy(masterPassword: string, secretKey?: string): LocalAccount;
|
|
583
590
|
declare function getHiddenWalletPrivateKey(masterPassword: string, secretKey?: string): Promise<`0x${string}`>;
|
|
584
591
|
declare function getHiddenWalletFromPassword(masterPassword: string, secretKey?: string): Promise<LocalAccount>;
|
|
592
|
+
declare function getHiddenWalletFromSecretKey(secretKey: string): Promise<LocalAccount>;
|
|
593
|
+
declare function getHiddenWalletPrivateKeyFromSecretKey(secretKey: string): Promise<`0x${string}`>;
|
|
585
594
|
declare function clearHiddenWalletCache(): void;
|
|
586
595
|
declare const FRAGMENT_DOMAIN: {
|
|
587
596
|
readonly name: "VaultKeeperFragments";
|
|
@@ -685,7 +694,14 @@ interface ShareOptions {
|
|
|
685
694
|
senderLabel?: string;
|
|
686
695
|
}
|
|
687
696
|
declare function generateSharePin(): string;
|
|
688
|
-
|
|
697
|
+
/**
|
|
698
|
+
* PIN proof stored by the server as `pinHash`. It is keyed by the share's URL key,
|
|
699
|
+
* which the server never receives, so the server cannot test a 6-digit PIN offline
|
|
700
|
+
* against what it stores. (An unkeyed SHA-256 of the PIN was invertible in ~10^6 steps.)
|
|
701
|
+
* Pass the key exactly as the recipient reads it in the URL fragment: `privateKeyHex`
|
|
702
|
+
* at creation time.
|
|
703
|
+
*/
|
|
704
|
+
declare function computeApiPinHash(pin: string, keyHex: string): string;
|
|
689
705
|
declare function createSecureShare(payload: Omit<SharePayload, "version" | "createdAt">, pin?: string): ShareCreationResult;
|
|
690
706
|
declare function decryptSecureShare(blobHex: string, keyHex: string, pin: string): SharePayload;
|
|
691
707
|
declare function buildShareUrl(baseUrl: string, shareId: string, keyHex: string): string;
|
|
@@ -790,4 +806,131 @@ declare class VaultKeepR_SLM {
|
|
|
790
806
|
summarizeBreach(breachCount: number, siteUrl: string, lang?: string): Promise<BreachSummaryResult>;
|
|
791
807
|
}
|
|
792
808
|
|
|
793
|
-
|
|
809
|
+
/**
|
|
810
|
+
* Account key rules shared by every client (extension, iOS, Android).
|
|
811
|
+
*
|
|
812
|
+
* One secret key per account, not per device. The unlock method (password, PRF, passkey,
|
|
813
|
+
* biometrics) only releases that key on the device: it never creates an identity.
|
|
814
|
+
* A device without the key must not write to a pointer.
|
|
815
|
+
*/
|
|
816
|
+
interface RemotePointer {
|
|
817
|
+
exists: boolean;
|
|
818
|
+
moved: boolean;
|
|
819
|
+
}
|
|
820
|
+
type KeyAccountState = {
|
|
821
|
+
kind: "ready";
|
|
822
|
+
} | {
|
|
823
|
+
kind: "passage";
|
|
824
|
+
} | {
|
|
825
|
+
kind: "read_only_pair";
|
|
826
|
+
} | {
|
|
827
|
+
kind: "choose";
|
|
828
|
+
};
|
|
829
|
+
declare function accountKeyState(input: {
|
|
830
|
+
hasSecretKey: boolean;
|
|
831
|
+
hasLocalVault: boolean;
|
|
832
|
+
remote: RemotePointer | null;
|
|
833
|
+
}): KeyAccountState;
|
|
834
|
+
/** Address a device writes pointers under: the Smart Account only once moved and the key is here. */
|
|
835
|
+
declare function pointerWalletFor(input: {
|
|
836
|
+
hasSecretKey: boolean;
|
|
837
|
+
remoteMoved: boolean;
|
|
838
|
+
eoa: string;
|
|
839
|
+
smartAccount: string;
|
|
840
|
+
}): string;
|
|
841
|
+
type PassageStep = "idle" | "key_pending" | "copied" | "moved" | "done";
|
|
842
|
+
type PassageEvent = "key_generated" | "copy_ok" | "copy_failed" | "move_ok" | "move_failed" | "move_conflict" | "promote_ok";
|
|
843
|
+
type PassageTransition = {
|
|
844
|
+
step: PassageStep;
|
|
845
|
+
discardPendingKey: boolean;
|
|
846
|
+
} | {
|
|
847
|
+
error: string;
|
|
848
|
+
};
|
|
849
|
+
/**
|
|
850
|
+
* Passage of a legacy account to a key. The pending key is never the identity before "done":
|
|
851
|
+
* a failed copy discards it, a failed move keeps the copy and retries, a move conflict discards it.
|
|
852
|
+
*/
|
|
853
|
+
declare function passageNext(step: PassageStep, event: PassageEvent): PassageTransition;
|
|
854
|
+
/** Identity used for writes during the passage. The key only takes over at "done". */
|
|
855
|
+
declare function passageIdentity(step: PassageStep): "legacy" | "smart_account";
|
|
856
|
+
|
|
857
|
+
declare const RECOVERY_CODE_LENGTH = 20;
|
|
858
|
+
/**
|
|
859
|
+
* An account key is the standard 64-hex key, or any other text of 32 to 4096 characters, kept exactly as
|
|
860
|
+
* given: the account identity is derived from the exact string. The extension's envelope shape {v, iv, ct}
|
|
861
|
+
* and PGP armour are never account keys.
|
|
862
|
+
*/
|
|
863
|
+
declare function isAccountKeyText(value: string): boolean;
|
|
864
|
+
/** Argon2id over the canonical code bytes. Mobile injects a WebView-backed implementation. */
|
|
865
|
+
type RecoveryKdf = (codeBytes: Uint8Array, salt: Uint8Array) => Promise<Uint8Array> | Uint8Array;
|
|
866
|
+
declare const argon2RecoveryKdf: RecoveryKdf;
|
|
867
|
+
interface RecoveryBlob {
|
|
868
|
+
version: 1;
|
|
869
|
+
salt: string;
|
|
870
|
+
encrypted: EncryptedVault;
|
|
871
|
+
}
|
|
872
|
+
declare function generateRecoveryCode(): string;
|
|
873
|
+
/** Canonical form: uppercase, no spaces or hyphens, O -> 0, I and L -> 1. */
|
|
874
|
+
declare function normalizeRecoveryCode(input: string): string;
|
|
875
|
+
declare function isValidRecoveryCode(input: string): boolean;
|
|
876
|
+
/** Display form, in groups of five: XXXXX-XXXXX-XXXXX-XXXXX. */
|
|
877
|
+
declare function formatRecoveryCode(code: string): string;
|
|
878
|
+
/** Lookup key for the server. Only someone holding the code can compute it. */
|
|
879
|
+
declare function deriveRecoveryId(code: string, kdf?: RecoveryKdf): Promise<string>;
|
|
880
|
+
/** Encrypts the account's secret key under a key derived from the recovery code. */
|
|
881
|
+
declare function createRecoveryBlob(secretKeyHex: string, code: string, kdf?: RecoveryKdf): Promise<RecoveryBlob>;
|
|
882
|
+
/** Recovers the secret key. A wrong code and a damaged blob give the same error. */
|
|
883
|
+
declare function openRecoveryBlob(blob: RecoveryBlob, code: string, kdf?: RecoveryKdf): Promise<string>;
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
* Joining an account with its secret key, through a 100-bit code (recovery-code.ts).
|
|
887
|
+
*
|
|
888
|
+
* The sending device seals its secret key under a key derived from the code, and posts only the blob,
|
|
889
|
+
* under an ID derived from the code. The server never sees the code or the key. The receiving device
|
|
890
|
+
* types the code, derives the same ID, fetches the blob (the server forgets it after one read), and opens it.
|
|
891
|
+
*
|
|
892
|
+
* Transport is injected (post / fetchBlob), so each client uses its own HTTP stack.
|
|
893
|
+
*/
|
|
894
|
+
|
|
895
|
+
type JoinPost = (id: string, blob: RecoveryBlob) => Promise<void>;
|
|
896
|
+
type JoinFetch = (id: string) => Promise<RecoveryBlob | null>;
|
|
897
|
+
declare class KeyJoinError extends Error {
|
|
898
|
+
readonly code: "invalid_code" | "not_found";
|
|
899
|
+
constructor(code: "invalid_code" | "not_found");
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* Sending device: creates a code, seals the secret key under it, and posts the blob.
|
|
903
|
+
* Returns the code to show to the user (grouped, for reading). Nothing is sent before the blob exists.
|
|
904
|
+
*/
|
|
905
|
+
declare function prepareKeyJoin(secretKeyHex: string, post: JoinPost, kdf?: RecoveryKdf): Promise<{
|
|
906
|
+
code: string;
|
|
907
|
+
}>;
|
|
908
|
+
/**
|
|
909
|
+
* Receiving device: turns the typed code into the account's secret key. A malformed code fails before any
|
|
910
|
+
* request. A code with no blob (wrong, expired, or already used) fails with "not_found".
|
|
911
|
+
*/
|
|
912
|
+
declare function joinWithKeyCode(input: string, fetchBlob: JoinFetch, kdf?: RecoveryKdf): Promise<string>;
|
|
913
|
+
|
|
914
|
+
/**
|
|
915
|
+
* What a device may do with an encrypted export (.vkenc) when it is imported.
|
|
916
|
+
*
|
|
917
|
+
* An export carries the account's secret key only if it was made with one. The import must never
|
|
918
|
+
* change which account a device belongs to, and must never mix a keyless file into a keyed device.
|
|
919
|
+
* Pure decision: the caller applies it, and a refusal changes nothing.
|
|
920
|
+
*/
|
|
921
|
+
type EncryptedImportDecision = {
|
|
922
|
+
action: "import_keyless";
|
|
923
|
+
} | {
|
|
924
|
+
action: "join_with_file_key";
|
|
925
|
+
} | {
|
|
926
|
+
action: "keep_device_key";
|
|
927
|
+
} | {
|
|
928
|
+
action: "refuse";
|
|
929
|
+
reason: "keyless_file_on_keyed_device" | "other_account";
|
|
930
|
+
};
|
|
931
|
+
declare function decideEncryptedImport(input: {
|
|
932
|
+
deviceKey: string | null;
|
|
933
|
+
fileKey: string | null;
|
|
934
|
+
}): EncryptedImportDecision;
|
|
935
|
+
|
|
936
|
+
export { type AutoTagResult, BIP39_WORDLIST, BUILTIN_FOLDER_IDS, BUILTIN_FOLDER_NODES, type BreachReport, type BreachResult, type BreachSummaryResult, CARD_BRAND_LABELS, type CardBrand, type CloudFile, type CloudFileCategory, type CustomField, DEFAULT_ENTRY_GROUP, DEFAULT_FRAGMENT_COUNT, type DocumentOcrData, EFF_WORDLIST, ENTRY_GROUP_IDS, ENTRY_GROUP_LABELS, EXTENSION_MAX_PAYLOAD_VERSION, EXTENSION_MIN_PAYLOAD_VERSION, type EmailBreach, type EmailBreachReport, type EmailBreachResult, type EncryptedExportPayload, type EncryptedFragmentPayload, type EncryptedImportDecision, type EncryptedImportResult, type EncryptedVault, type EntryGroupId, type ErrorReport, type ExportResult, FRAGMENTED_DEFAULT_THRESHOLD, FRAGMENTED_DEFAULT_TOTAL, type FolderNode, type FragmentDestination, type FragmentedConfig, type FragmentedManifest, type FragmentedPayload, type GeneratePassphraseOptions, type GeneratePasswordOptions, type ImportVaultTextResult, type JoinFetch, type JoinPost, type KeyAccountState, type KeyEnvelope, KeyJoinError, type LegacyContact, MOBILE_MAX_PAYLOAD_VERSION, MOBILE_MIN_PAYLOAD_VERSION, type MRZResult, type MergeImportResult, type MergeImportStats, P256_SPKI_HEADER, PAIR_SEND_URI_SCHEME, PAIR_URI_SCHEME, PAYLOAD_VERSION_CURRENT, PAYLOAD_VERSION_V1, PAYLOAD_VERSION_V2, PAYLOAD_VERSION_V3, PAYLOAD_VERSION_V4, type PairKeypair, type PairPayload, type ParsedPairUri, type PassageEvent, type PassageStep, type PassageTransition, type PasskeyEntry, type PasskeyKeyPair, type PasskeyPrfCredential, type PasswordHealthEntry, type PasswordHealthReport, type PasswordStrength, type PasswordStrengthLevel, type PasswordStrengthResult, type PayloadVersion, type PgpImportResult, type PrfCredentialRecord, type PwnedPasswordFetchOptions, RECOVERY_CODE_LENGTH, type RecoveryBlob, type RecoveryKdf, type RemotePointer, type SecureDocument, type SecureDocumentType, type SeedPhraseEntry, type ShareCreationResult, type ShareOptions, type SharePayload, type SkippedExport, type SkippedItem, TAG_COLORS, type TOTPAlgorithm, VALID_TAGS, type ValidTag, type Vault, type VaultEntry, type VaultEntryUri, type VaultEntryUriMatchType, VaultKeepR_SLM, type VaultPayload, accountKeyState, addEntry, analyzeVaultHealth, argon2RecoveryKdf, buildAttestationObject, buildAuthDataForCreate, buildAuthDataForGet, buildMutualAuthData, buildPairPayload, buildPairSendUri, buildPairUri, buildShareUrl, calculateMrzChecksum, calculatePasswordStrength, captureError, checkEmailBreaches, checkVaultBreaches, cleanEntryTitle, cleanMrzField, clearErrorBuffer, clearHiddenWalletCache, compressVault, computeApiPinHash, createEmptyVault, createEntry, createExportPayload, createFolder, createKeyEnvelope, createRecoveryBlob, createSecureShare, createVaultPayload, decideEncryptedImport, decompressVault, decryptFromPair, decryptKeyEnvelope, decryptNfcPayload, decryptPasskeyPrivateKey, decryptPgpContent, decryptSecureShare, decryptVault, deduplicateEntries, deleteCloudFolder, deleteFolder, deleteUserFolder, deleteVaultEntry, deriveKeyFromPasskeyPrf, deriveKeyFromPasswordAndSignatureArgon2, deriveKeyFromPasswordAndSignatureLegacy, deriveKeyFromPasswordArgon2, deriveKeyFromPrfResult, deriveMrzKseed, deriveNfcKey, derivePairSecret, deriveRecoveryId, digitsOnly, encryptAndFragmentDocument, encryptForPair, encryptNfcPayload, encryptPasskeyPrivateKey, encryptPgpContent, encryptVault, enrollPasskeyForPrf, entryFingerprint, estimatePasswordEntropy, exportBitwardenJson, exportCsv, exportEncryptedVault, exportProtonPassJson, formatCardDisplayMasked, formatCardNumber, formatErrorReport, formatRecoveryCode, fromBase64Url, generateBlurredThumbnailCanvas, generateCredentialId, generateDocumentId, generateMasterKey, generateNfcDeviceSecret, generatePairKeypair, generatePasskeyKeyPair, generatePassphrase, generatePassword, generatePrfSalt, generateRecoveryCode, generateSaltArgon2, generateSharePin, getCardBrand, getChecksumAddress, getEntryDisplayName, getEntryGroupLabel, getErrorBuffer, getHiddenWalletFromPassword, getHiddenWalletFromSecretKey, getHiddenWalletLegacy, getHiddenWalletPrivateKey, getHiddenWalletPrivateKeyFromSecretKey, getLast4, getMostUsedEntries, getPwnedCountForHash, getPwnedPasswordCount, getTOTPCode, getTOTPRemainingSeconds, getTagColor, import1PasswordPif, importBitwardenJson, importCsv, importEncryptedVault, importFromPgp, importProtonPassJson, importVaultText, isAcceptablePayloadVersion, isAccountKeyText, isCurrentPayloadVersion, isEncryptedExport, isNfcPayloadV1, isNfcPayloadV2, isNfcPayloadV3, isOnePasswordPif, isPairSendUri, isPairUri, isPasskeyPrivateKeyEncrypted, isPrfSupported, isProtonPassExport, isValidRecoveryCode, isWebAuthnSupported, joinWithKeyCode, maskCardNumber, mergeFolderTrees, mergeFolders, mergeFragments, mergeImportedEntries, moveFolder, normalizeRecoveryCode, normalizeSignatureForKdf, normalizeUrl, openRecoveryBlob, parseMRZ, parseMrzDate, parsePairPayload, parsePairSendUri, parsePairUri, parseShareUrl, parseTOTPUri, parseVault, parseVaultPayload, passageIdentity, passageNext, pointerWalletFor, prepareKeyJoin, publicKeyToCose, publicKeyToSpki, reassembleAndDecryptDocument, removeEntry, renameFolder, resolveFolderName, rpIdHash, scorePassword, secureCompare, secureWipe, sendErrorReport, serializeVault, setArgon2Provider, signPasskeyAssertion, signStoreFragmentMeta, signStoreFragmentMetaWithSigner, splitBuffer, suggestBip39Words, threeWayMerge, toBase64Url, ttlToMs, uniformRandom, updateEntry, updateEntryUseCount, verifyPasskeyAssertion };
|
package/dist/index.d.ts
CHANGED
|
@@ -149,6 +149,7 @@ interface Vault {
|
|
|
149
149
|
legacyContacts?: LegacyContact[];
|
|
150
150
|
prfCredentials?: PrfCredentialRecord[];
|
|
151
151
|
monitoredEmails?: string[];
|
|
152
|
+
secretKey?: string;
|
|
152
153
|
}
|
|
153
154
|
interface PrfCredentialRecord {
|
|
154
155
|
credentialId: string;
|
|
@@ -227,6 +228,8 @@ declare const DEFAULT_ENTRY_GROUP: EntryGroupId;
|
|
|
227
228
|
declare const BUILTIN_FOLDER_IDS: Record<EntryGroupId | "passkeys", string>;
|
|
228
229
|
declare const BUILTIN_FOLDER_NODES: FolderNode[];
|
|
229
230
|
declare function getEntryGroupLabel(folder: string | undefined): string;
|
|
231
|
+
declare function cleanEntryTitle(rawTitle: string, url?: string): string;
|
|
232
|
+
declare function getEntryDisplayName(entry: VaultEntry, primaryUrl?: string): string;
|
|
230
233
|
declare function resolveFolderName(folderId: string | undefined, folderTree: FolderNode[] | undefined): string;
|
|
231
234
|
|
|
232
235
|
declare function generateMasterKey(): Uint8Array;
|
|
@@ -364,7 +367,10 @@ interface EncryptedImportResult {
|
|
|
364
367
|
vault: Vault;
|
|
365
368
|
secretKey?: string;
|
|
366
369
|
}
|
|
367
|
-
declare function importEncryptedVault(encryptedJson: string, password: string, argon2Opts?: Argon2Options
|
|
370
|
+
declare function importEncryptedVault(encryptedJson: string, password: string, argon2Opts?: Argon2Options, precomputed?: {
|
|
371
|
+
key: Uint8Array;
|
|
372
|
+
salt?: Uint8Array;
|
|
373
|
+
}): Promise<EncryptedImportResult>;
|
|
368
374
|
|
|
369
375
|
interface SkippedExport {
|
|
370
376
|
id: string;
|
|
@@ -412,6 +418,7 @@ type PwnedPasswordFetchOptions = {
|
|
|
412
418
|
signal?: AbortSignal;
|
|
413
419
|
fetchFn?: typeof fetch;
|
|
414
420
|
};
|
|
421
|
+
declare function getPwnedCountForHash(sha1Hex: string, options?: PwnedPasswordFetchOptions): Promise<number>;
|
|
415
422
|
declare function getPwnedPasswordCount(password: string, options?: PwnedPasswordFetchOptions): Promise<number>;
|
|
416
423
|
|
|
417
424
|
declare function uniformRandom(max: number): number;
|
|
@@ -582,6 +589,8 @@ declare function setArgon2Provider(fn: Argon2ProviderFn): void;
|
|
|
582
589
|
declare function getHiddenWalletLegacy(masterPassword: string, secretKey?: string): LocalAccount;
|
|
583
590
|
declare function getHiddenWalletPrivateKey(masterPassword: string, secretKey?: string): Promise<`0x${string}`>;
|
|
584
591
|
declare function getHiddenWalletFromPassword(masterPassword: string, secretKey?: string): Promise<LocalAccount>;
|
|
592
|
+
declare function getHiddenWalletFromSecretKey(secretKey: string): Promise<LocalAccount>;
|
|
593
|
+
declare function getHiddenWalletPrivateKeyFromSecretKey(secretKey: string): Promise<`0x${string}`>;
|
|
585
594
|
declare function clearHiddenWalletCache(): void;
|
|
586
595
|
declare const FRAGMENT_DOMAIN: {
|
|
587
596
|
readonly name: "VaultKeeperFragments";
|
|
@@ -685,7 +694,14 @@ interface ShareOptions {
|
|
|
685
694
|
senderLabel?: string;
|
|
686
695
|
}
|
|
687
696
|
declare function generateSharePin(): string;
|
|
688
|
-
|
|
697
|
+
/**
|
|
698
|
+
* PIN proof stored by the server as `pinHash`. It is keyed by the share's URL key,
|
|
699
|
+
* which the server never receives, so the server cannot test a 6-digit PIN offline
|
|
700
|
+
* against what it stores. (An unkeyed SHA-256 of the PIN was invertible in ~10^6 steps.)
|
|
701
|
+
* Pass the key exactly as the recipient reads it in the URL fragment: `privateKeyHex`
|
|
702
|
+
* at creation time.
|
|
703
|
+
*/
|
|
704
|
+
declare function computeApiPinHash(pin: string, keyHex: string): string;
|
|
689
705
|
declare function createSecureShare(payload: Omit<SharePayload, "version" | "createdAt">, pin?: string): ShareCreationResult;
|
|
690
706
|
declare function decryptSecureShare(blobHex: string, keyHex: string, pin: string): SharePayload;
|
|
691
707
|
declare function buildShareUrl(baseUrl: string, shareId: string, keyHex: string): string;
|
|
@@ -790,4 +806,131 @@ declare class VaultKeepR_SLM {
|
|
|
790
806
|
summarizeBreach(breachCount: number, siteUrl: string, lang?: string): Promise<BreachSummaryResult>;
|
|
791
807
|
}
|
|
792
808
|
|
|
793
|
-
|
|
809
|
+
/**
|
|
810
|
+
* Account key rules shared by every client (extension, iOS, Android).
|
|
811
|
+
*
|
|
812
|
+
* One secret key per account, not per device. The unlock method (password, PRF, passkey,
|
|
813
|
+
* biometrics) only releases that key on the device: it never creates an identity.
|
|
814
|
+
* A device without the key must not write to a pointer.
|
|
815
|
+
*/
|
|
816
|
+
interface RemotePointer {
|
|
817
|
+
exists: boolean;
|
|
818
|
+
moved: boolean;
|
|
819
|
+
}
|
|
820
|
+
type KeyAccountState = {
|
|
821
|
+
kind: "ready";
|
|
822
|
+
} | {
|
|
823
|
+
kind: "passage";
|
|
824
|
+
} | {
|
|
825
|
+
kind: "read_only_pair";
|
|
826
|
+
} | {
|
|
827
|
+
kind: "choose";
|
|
828
|
+
};
|
|
829
|
+
declare function accountKeyState(input: {
|
|
830
|
+
hasSecretKey: boolean;
|
|
831
|
+
hasLocalVault: boolean;
|
|
832
|
+
remote: RemotePointer | null;
|
|
833
|
+
}): KeyAccountState;
|
|
834
|
+
/** Address a device writes pointers under: the Smart Account only once moved and the key is here. */
|
|
835
|
+
declare function pointerWalletFor(input: {
|
|
836
|
+
hasSecretKey: boolean;
|
|
837
|
+
remoteMoved: boolean;
|
|
838
|
+
eoa: string;
|
|
839
|
+
smartAccount: string;
|
|
840
|
+
}): string;
|
|
841
|
+
type PassageStep = "idle" | "key_pending" | "copied" | "moved" | "done";
|
|
842
|
+
type PassageEvent = "key_generated" | "copy_ok" | "copy_failed" | "move_ok" | "move_failed" | "move_conflict" | "promote_ok";
|
|
843
|
+
type PassageTransition = {
|
|
844
|
+
step: PassageStep;
|
|
845
|
+
discardPendingKey: boolean;
|
|
846
|
+
} | {
|
|
847
|
+
error: string;
|
|
848
|
+
};
|
|
849
|
+
/**
|
|
850
|
+
* Passage of a legacy account to a key. The pending key is never the identity before "done":
|
|
851
|
+
* a failed copy discards it, a failed move keeps the copy and retries, a move conflict discards it.
|
|
852
|
+
*/
|
|
853
|
+
declare function passageNext(step: PassageStep, event: PassageEvent): PassageTransition;
|
|
854
|
+
/** Identity used for writes during the passage. The key only takes over at "done". */
|
|
855
|
+
declare function passageIdentity(step: PassageStep): "legacy" | "smart_account";
|
|
856
|
+
|
|
857
|
+
declare const RECOVERY_CODE_LENGTH = 20;
|
|
858
|
+
/**
|
|
859
|
+
* An account key is the standard 64-hex key, or any other text of 32 to 4096 characters, kept exactly as
|
|
860
|
+
* given: the account identity is derived from the exact string. The extension's envelope shape {v, iv, ct}
|
|
861
|
+
* and PGP armour are never account keys.
|
|
862
|
+
*/
|
|
863
|
+
declare function isAccountKeyText(value: string): boolean;
|
|
864
|
+
/** Argon2id over the canonical code bytes. Mobile injects a WebView-backed implementation. */
|
|
865
|
+
type RecoveryKdf = (codeBytes: Uint8Array, salt: Uint8Array) => Promise<Uint8Array> | Uint8Array;
|
|
866
|
+
declare const argon2RecoveryKdf: RecoveryKdf;
|
|
867
|
+
interface RecoveryBlob {
|
|
868
|
+
version: 1;
|
|
869
|
+
salt: string;
|
|
870
|
+
encrypted: EncryptedVault;
|
|
871
|
+
}
|
|
872
|
+
declare function generateRecoveryCode(): string;
|
|
873
|
+
/** Canonical form: uppercase, no spaces or hyphens, O -> 0, I and L -> 1. */
|
|
874
|
+
declare function normalizeRecoveryCode(input: string): string;
|
|
875
|
+
declare function isValidRecoveryCode(input: string): boolean;
|
|
876
|
+
/** Display form, in groups of five: XXXXX-XXXXX-XXXXX-XXXXX. */
|
|
877
|
+
declare function formatRecoveryCode(code: string): string;
|
|
878
|
+
/** Lookup key for the server. Only someone holding the code can compute it. */
|
|
879
|
+
declare function deriveRecoveryId(code: string, kdf?: RecoveryKdf): Promise<string>;
|
|
880
|
+
/** Encrypts the account's secret key under a key derived from the recovery code. */
|
|
881
|
+
declare function createRecoveryBlob(secretKeyHex: string, code: string, kdf?: RecoveryKdf): Promise<RecoveryBlob>;
|
|
882
|
+
/** Recovers the secret key. A wrong code and a damaged blob give the same error. */
|
|
883
|
+
declare function openRecoveryBlob(blob: RecoveryBlob, code: string, kdf?: RecoveryKdf): Promise<string>;
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
* Joining an account with its secret key, through a 100-bit code (recovery-code.ts).
|
|
887
|
+
*
|
|
888
|
+
* The sending device seals its secret key under a key derived from the code, and posts only the blob,
|
|
889
|
+
* under an ID derived from the code. The server never sees the code or the key. The receiving device
|
|
890
|
+
* types the code, derives the same ID, fetches the blob (the server forgets it after one read), and opens it.
|
|
891
|
+
*
|
|
892
|
+
* Transport is injected (post / fetchBlob), so each client uses its own HTTP stack.
|
|
893
|
+
*/
|
|
894
|
+
|
|
895
|
+
type JoinPost = (id: string, blob: RecoveryBlob) => Promise<void>;
|
|
896
|
+
type JoinFetch = (id: string) => Promise<RecoveryBlob | null>;
|
|
897
|
+
declare class KeyJoinError extends Error {
|
|
898
|
+
readonly code: "invalid_code" | "not_found";
|
|
899
|
+
constructor(code: "invalid_code" | "not_found");
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* Sending device: creates a code, seals the secret key under it, and posts the blob.
|
|
903
|
+
* Returns the code to show to the user (grouped, for reading). Nothing is sent before the blob exists.
|
|
904
|
+
*/
|
|
905
|
+
declare function prepareKeyJoin(secretKeyHex: string, post: JoinPost, kdf?: RecoveryKdf): Promise<{
|
|
906
|
+
code: string;
|
|
907
|
+
}>;
|
|
908
|
+
/**
|
|
909
|
+
* Receiving device: turns the typed code into the account's secret key. A malformed code fails before any
|
|
910
|
+
* request. A code with no blob (wrong, expired, or already used) fails with "not_found".
|
|
911
|
+
*/
|
|
912
|
+
declare function joinWithKeyCode(input: string, fetchBlob: JoinFetch, kdf?: RecoveryKdf): Promise<string>;
|
|
913
|
+
|
|
914
|
+
/**
|
|
915
|
+
* What a device may do with an encrypted export (.vkenc) when it is imported.
|
|
916
|
+
*
|
|
917
|
+
* An export carries the account's secret key only if it was made with one. The import must never
|
|
918
|
+
* change which account a device belongs to, and must never mix a keyless file into a keyed device.
|
|
919
|
+
* Pure decision: the caller applies it, and a refusal changes nothing.
|
|
920
|
+
*/
|
|
921
|
+
type EncryptedImportDecision = {
|
|
922
|
+
action: "import_keyless";
|
|
923
|
+
} | {
|
|
924
|
+
action: "join_with_file_key";
|
|
925
|
+
} | {
|
|
926
|
+
action: "keep_device_key";
|
|
927
|
+
} | {
|
|
928
|
+
action: "refuse";
|
|
929
|
+
reason: "keyless_file_on_keyed_device" | "other_account";
|
|
930
|
+
};
|
|
931
|
+
declare function decideEncryptedImport(input: {
|
|
932
|
+
deviceKey: string | null;
|
|
933
|
+
fileKey: string | null;
|
|
934
|
+
}): EncryptedImportDecision;
|
|
935
|
+
|
|
936
|
+
export { type AutoTagResult, BIP39_WORDLIST, BUILTIN_FOLDER_IDS, BUILTIN_FOLDER_NODES, type BreachReport, type BreachResult, type BreachSummaryResult, CARD_BRAND_LABELS, type CardBrand, type CloudFile, type CloudFileCategory, type CustomField, DEFAULT_ENTRY_GROUP, DEFAULT_FRAGMENT_COUNT, type DocumentOcrData, EFF_WORDLIST, ENTRY_GROUP_IDS, ENTRY_GROUP_LABELS, EXTENSION_MAX_PAYLOAD_VERSION, EXTENSION_MIN_PAYLOAD_VERSION, type EmailBreach, type EmailBreachReport, type EmailBreachResult, type EncryptedExportPayload, type EncryptedFragmentPayload, type EncryptedImportDecision, type EncryptedImportResult, type EncryptedVault, type EntryGroupId, type ErrorReport, type ExportResult, FRAGMENTED_DEFAULT_THRESHOLD, FRAGMENTED_DEFAULT_TOTAL, type FolderNode, type FragmentDestination, type FragmentedConfig, type FragmentedManifest, type FragmentedPayload, type GeneratePassphraseOptions, type GeneratePasswordOptions, type ImportVaultTextResult, type JoinFetch, type JoinPost, type KeyAccountState, type KeyEnvelope, KeyJoinError, type LegacyContact, MOBILE_MAX_PAYLOAD_VERSION, MOBILE_MIN_PAYLOAD_VERSION, type MRZResult, type MergeImportResult, type MergeImportStats, P256_SPKI_HEADER, PAIR_SEND_URI_SCHEME, PAIR_URI_SCHEME, PAYLOAD_VERSION_CURRENT, PAYLOAD_VERSION_V1, PAYLOAD_VERSION_V2, PAYLOAD_VERSION_V3, PAYLOAD_VERSION_V4, type PairKeypair, type PairPayload, type ParsedPairUri, type PassageEvent, type PassageStep, type PassageTransition, type PasskeyEntry, type PasskeyKeyPair, type PasskeyPrfCredential, type PasswordHealthEntry, type PasswordHealthReport, type PasswordStrength, type PasswordStrengthLevel, type PasswordStrengthResult, type PayloadVersion, type PgpImportResult, type PrfCredentialRecord, type PwnedPasswordFetchOptions, RECOVERY_CODE_LENGTH, type RecoveryBlob, type RecoveryKdf, type RemotePointer, type SecureDocument, type SecureDocumentType, type SeedPhraseEntry, type ShareCreationResult, type ShareOptions, type SharePayload, type SkippedExport, type SkippedItem, TAG_COLORS, type TOTPAlgorithm, VALID_TAGS, type ValidTag, type Vault, type VaultEntry, type VaultEntryUri, type VaultEntryUriMatchType, VaultKeepR_SLM, type VaultPayload, accountKeyState, addEntry, analyzeVaultHealth, argon2RecoveryKdf, buildAttestationObject, buildAuthDataForCreate, buildAuthDataForGet, buildMutualAuthData, buildPairPayload, buildPairSendUri, buildPairUri, buildShareUrl, calculateMrzChecksum, calculatePasswordStrength, captureError, checkEmailBreaches, checkVaultBreaches, cleanEntryTitle, cleanMrzField, clearErrorBuffer, clearHiddenWalletCache, compressVault, computeApiPinHash, createEmptyVault, createEntry, createExportPayload, createFolder, createKeyEnvelope, createRecoveryBlob, createSecureShare, createVaultPayload, decideEncryptedImport, decompressVault, decryptFromPair, decryptKeyEnvelope, decryptNfcPayload, decryptPasskeyPrivateKey, decryptPgpContent, decryptSecureShare, decryptVault, deduplicateEntries, deleteCloudFolder, deleteFolder, deleteUserFolder, deleteVaultEntry, deriveKeyFromPasskeyPrf, deriveKeyFromPasswordAndSignatureArgon2, deriveKeyFromPasswordAndSignatureLegacy, deriveKeyFromPasswordArgon2, deriveKeyFromPrfResult, deriveMrzKseed, deriveNfcKey, derivePairSecret, deriveRecoveryId, digitsOnly, encryptAndFragmentDocument, encryptForPair, encryptNfcPayload, encryptPasskeyPrivateKey, encryptPgpContent, encryptVault, enrollPasskeyForPrf, entryFingerprint, estimatePasswordEntropy, exportBitwardenJson, exportCsv, exportEncryptedVault, exportProtonPassJson, formatCardDisplayMasked, formatCardNumber, formatErrorReport, formatRecoveryCode, fromBase64Url, generateBlurredThumbnailCanvas, generateCredentialId, generateDocumentId, generateMasterKey, generateNfcDeviceSecret, generatePairKeypair, generatePasskeyKeyPair, generatePassphrase, generatePassword, generatePrfSalt, generateRecoveryCode, generateSaltArgon2, generateSharePin, getCardBrand, getChecksumAddress, getEntryDisplayName, getEntryGroupLabel, getErrorBuffer, getHiddenWalletFromPassword, getHiddenWalletFromSecretKey, getHiddenWalletLegacy, getHiddenWalletPrivateKey, getHiddenWalletPrivateKeyFromSecretKey, getLast4, getMostUsedEntries, getPwnedCountForHash, getPwnedPasswordCount, getTOTPCode, getTOTPRemainingSeconds, getTagColor, import1PasswordPif, importBitwardenJson, importCsv, importEncryptedVault, importFromPgp, importProtonPassJson, importVaultText, isAcceptablePayloadVersion, isAccountKeyText, isCurrentPayloadVersion, isEncryptedExport, isNfcPayloadV1, isNfcPayloadV2, isNfcPayloadV3, isOnePasswordPif, isPairSendUri, isPairUri, isPasskeyPrivateKeyEncrypted, isPrfSupported, isProtonPassExport, isValidRecoveryCode, isWebAuthnSupported, joinWithKeyCode, maskCardNumber, mergeFolderTrees, mergeFolders, mergeFragments, mergeImportedEntries, moveFolder, normalizeRecoveryCode, normalizeSignatureForKdf, normalizeUrl, openRecoveryBlob, parseMRZ, parseMrzDate, parsePairPayload, parsePairSendUri, parsePairUri, parseShareUrl, parseTOTPUri, parseVault, parseVaultPayload, passageIdentity, passageNext, pointerWalletFor, prepareKeyJoin, publicKeyToCose, publicKeyToSpki, reassembleAndDecryptDocument, removeEntry, renameFolder, resolveFolderName, rpIdHash, scorePassword, secureCompare, secureWipe, sendErrorReport, serializeVault, setArgon2Provider, signPasskeyAssertion, signStoreFragmentMeta, signStoreFragmentMetaWithSigner, splitBuffer, suggestBip39Words, threeWayMerge, toBase64Url, ttlToMs, uniformRandom, updateEntry, updateEntryUseCount, verifyPasskeyAssertion };
|