import { HDKey } from '@scure/bip32'; import { Mnemonic, Password, Seed, type AddressIndex, type Brand } from './types'; /** * Strongly-typed aliases for cryptographic primitives */ export type Secp256k1PrivateKeyBytes = Brand; export type EntropyLength = Brand; export type AppNumber = Brand; export type PasswordRequirementId = 'asciiOnly' | 'minLength' | 'uppercase' | 'lowercase' | 'digit' | 'specialChar'; export type PasswordValidationResult = { valid: boolean; requirements: Record; failedRequirements: PasswordRequirementId[]; }; /** * Type alias for secp256k1 signer (compatible with ZeroDev's Signer type) */ export type { Signer as Secp256k1Signer } from '@zerodev/sdk/types'; /** * LibQC base application number for BIP-85 derivation * First 4 digits of sha256("PROJECTELEVEN") hex digest */ export declare const LIBQC_APP_NO_BASE: AppNumber; /** * Application number for secp256k1 private key derivations * Derived from LibQC base + 1 to distinguish from other key types */ export declare const LIBQC_SECP256K1_APP_NO: AppNumber; /** * Application number for Bitcoin private key derivations * Derived from LibQC base + 2 to distinguish from EVM keys */ export declare const LIBQC_BITCOIN_APP_NO: AppNumber; /** * Validate that a mnemonic is properly formatted for LibQC import and derivation * @param mnemonic The mnemonic bytes to validate * @returns The validated mnemonic in canonical single-spaced form * @throws Error if the mnemonic is invalid */ export declare function validateMnemonic(mnemonic: Uint8Array): Mnemonic; /** * Converts a mnemonic phrase to its raw entropy bytes * @param mnemonic The mnemonic bytes (UTF-8 encoded words) * @returns 32 bytes of entropy */ export declare function mnemonicToEntropyBytes(mnemonic: Uint8Array): Uint8Array; /** * Converts raw entropy bytes to a mnemonic phrase * @param entropy 32 bytes of entropy * @returns The mnemonic bytes (UTF-8 encoded words) */ export declare function entropyToMnemonicBytes(entropy: Uint8Array): Mnemonic; /** * Validates a password against the Project Eleven password policy. * * Password policy (ASCII-only by design — non-ASCII characters are rejected): * - asciiOnly: Printable ASCII characters only (U+0020–U+007E) * - minLength: At least 8 characters * - uppercase: At least one uppercase letter (A–Z) * - lowercase: At least one lowercase letter (a–z) * - digit: At least one digit (0–9) * - specialChar: At least one non-alphanumeric ASCII character * * This function never throws. Use it to get per-requirement pass/fail state * for live UI indicators. The `valid` field is `true` only when all six * requirements are met simultaneously. * * @param input The password bytes to evaluate * @returns A PasswordValidationResult with a `valid` boolean and a * per-requirement breakdown */ export declare function validatePassword(input: Uint8Array): PasswordValidationResult; /** * Derive raw entropy via BIP-85 from an HDKey master node * * BIP-85 derivation path: m/83696968'/'/' * * P11TODO add Brand types for BIP-85 parameters * * @param root HDKey master node * @param addressIndex Address index for derivation * @param entropyLength Number of bytes of entropy needed * @param appNo Application number for BIP-85 derivation * @returns Sliced HMAC-SHA512 output as Uint8Array */ export declare function deriveBip85Entropy(root: HDKey, addressIndex: AddressIndex, entropyLength: EntropyLength, appNo: AppNumber): Uint8Array; /** * Internal helper function to derive BIP-85 entropy from a seed. * * This function handles: * 1. Master HDKey creation from the 64-byte seed * 2. BIP-85 path-based entropy derivation * 3. Aggressive memory zeroing of master HDKey private data * * It avoids all intermediate string conversions to minimize JS heap exposure. * * @param seed The 64-byte BIP-39 seed (Uint8Array) * @param addressIndex The address index (0-based) * @param entropyLength Number of bytes of entropy needed (typically 32) * @param appNo Application number for BIP-85 derivation (vault-specific) * @returns The derived entropy as a Uint8Array * * @internal */ export declare function deriveBip85EntropyFromSeed(seed: Seed, addressIndex: AddressIndex, entropyLength: EntropyLength, appNo: AppNumber): Uint8Array; /** * Derive a secp256k1 private key from a seed and address index using BIP-85 * Same private key is used across all chains for the same address index * * @param seed The BIP-39 seed (64 bytes) * @param addressIndex The address index (0-based) * @returns The derived private key as a hex string */ export declare function deriveSecp256k1PrivateKey(seed: Seed, addressIndex: AddressIndex): Secp256k1PrivateKeyBytes; /** * Derive a Bitcoin private key from a seed and address index using BIP-85 * * Uses the same BIP-85 derivation as EVM keys but with a dedicated Bitcoin app number. * Same seed + index produces a related but different key for Bitcoin vs EVM. * * @param seed The BIP-39 seed (64 bytes) * @param addressIndex The address index (0-based) * @returns The derived 32-byte private key (for use with bitcoinjs-lib, ecpair, etc.) */ export declare function deriveBitcoinPrivateKey(seed: Seed, addressIndex: AddressIndex): Uint8Array; /** Key derivation function identifier, stored in vault metadata for forward compatibility */ export declare const KDF_ALGORITHM: "scrypt"; /** * Current encrypted vault schema version (V1): key-commitment padding + CBOR payload */ export declare const ENCRYPTED_VAULT_VERSION_V1: EncryptedVaultVersion; /** * Branded types for cryptographic parameters to prevent accidental misuse */ export type ScryptCostParameter = Brand; export type ScryptBlockSize = Brand; export type ScryptParallelism = Brand; export type EncryptedVaultVersion = Brand; export type ScryptSalt = Brand; export type AesGcmIv = Brand; export type Base64Ciphertext = Brand; export type Base64Iv = Brand; export type Base64ScryptSalt = Brand; /** * Default scrypt parameters. * N=131072 (2^17) requires ~128MB of memory, making GPU/ASIC attacks expensive. * r=8 and p=1 are standard recommendations, e.g. the OWASP Password Storage Cheat Sheet. */ export declare const DEFAULT_SCRYPT_PARAMS: ScryptParams; /** * Scrypt key derivation parameters stored alongside the vault for forward compatibility */ export interface ScryptParams { /** CPU/memory cost parameter (power of 2) */ N: ScryptCostParameter; /** Block size parameter */ r: ScryptBlockSize; /** Parallelism parameter */ p: ScryptParallelism; } /** * Metadata describing how the encryption key was derived */ export interface KeyDerivationOptions { algorithm: typeof KDF_ALGORITHM; params: ScryptParams; } /** * A vault encryption key derived from a user password via scrypt, * bundled with the derivation metadata and salt needed to re-derive it. */ export interface VaultEncryptionKeyWithMetadata { /** Non-extractable AES-256-GCM CryptoKey */ aes256GcmKey: CryptoKey; /** How the key was derived (algorithm + params) */ derivationOptions: KeyDerivationOptions; /** Raw salt bytes used during scrypt key derivation */ scryptSalt: ScryptSalt; } /** * The encrypted vault blob persisted to storage */ export interface EncryptedVault { /** Encrypted vault schema version */ version: EncryptedVaultVersion; /** Base64-encoded AES-GCM ciphertext */ data: Base64Ciphertext; /** Base64-encoded 12-byte initialization vector */ iv: Base64Iv; /** Base64-encoded scrypt salt used for key derivation */ scryptSalt: Base64ScryptSalt; /** Key derivation metadata for forward compatibility */ keyMetadata: KeyDerivationOptions; } /** * Metadata fields serialized into AES-GCM additionalData for authentication */ interface MetadataForAAD { version: EncryptedVaultVersion; scryptSalt: string; keyMetadata: KeyDerivationOptions; } /** * Serializes vault metadata to a canonical byte representation for use as AES-GCM * additionalData. Ensures deterministic output via fixed key ordering. Exported for * use in tests that construct vaults manually. * * @param meta - The metadata to serialize * @returns UTF-8 encoded bytes for the additionalData parameter */ export declare function serializeMetadataForAAD(meta: MetadataForAAD): Uint8Array; /** * Returns cryptographically secure random bytes from the Web Crypto CSPRNG * * This is the single approved entry point for all random byte generation * in LibQC. All cryptographic operations that need randomness must call * this function rather than globalThis.crypto.getRandomValues directly. * * @remarks Entropy sourced from Web Crypto CSPRNG * (globalThis.crypto.getRandomValues). * * @param length - Number of random bytes to generate (must be a positive integer) * @returns A Uint8Array filled with secure random bytes * @throws {RangeError} If length is not a positive integer * @throws {CsprngUnavailableError} If globalThis.crypto.getRandomValues is * not available */ export declare function getSecureRandomBytes(length: number): Uint8Array; /** * Generates a cryptographically random 32-byte salt for scrypt key derivation * * @remarks Entropy sourced from Web Crypto CSPRNG via getSecureRandomBytes. * * @returns 32 random bytes suitable for use as a scrypt salt * @throws {CsprngUnavailableError} If secure randomness is unavailable */ export declare function generateScryptSalt(): ScryptSalt; /** * Derives an AES-256-GCM CryptoKey from a password and salt using scrypt * * Uses scrypt from @noble/hashes to derive 32 bytes of key material, * then imports into Web Crypto API as a non-extractable AES-GCM key. * The raw scrypt output bytes are zeroed immediately after import. * * @param password - The user's password * @param scryptSalt - Raw salt bytes for scrypt key derivation * @param params - Scrypt parameters (defaults to N=2^17, r=8, p=1) * @returns A VaultEncryptionKeyWithMetadata containing the CryptoKey, derivation options, and salt * @throws {KeyDerivationError} If the Web Crypto key import fails */ export declare function deriveEncryptionKey(password: Password, scryptSalt: ScryptSalt, params?: ScryptParams): Promise; /** * Encrypts a plaintext string using AES-256-GCM with the provided encryption key * * Generates a fresh random 12-byte IV for each encryption (NIST-recommended size). * Appends 32 zero bytes (key-commitment padding) to the plaintext before encryption; * this makes the scheme key-committing and prevents password reset without knowing * the correct password. Vault metadata (version, scryptSalt, keyMetadata) is * authenticated via the AES-GCM additionalData (AAD) field but not encrypted. * * @remarks IV entropy sourced from Web Crypto CSPRNG via getSecureRandomBytes. * * @param key - The encryption key to encrypt with * @param plaintext - The plaintext string to encrypt (must be non-empty) * @returns An EncryptedVault object ready for storage * @throws {EmptyPlaintextError} If plaintext is an empty string * @throws {CsprngUnavailableError} If secure randomness is unavailable */ export declare function encryptData(key: VaultEncryptionKeyWithMetadata, plaintextBytes: Uint8Array): Promise; /** * Decrypts an EncryptedVault using AES-256-GCM with the provided encryption key * * Vault metadata (version, scryptSalt, keyMetadata) must match the authenticated * additionalData used during encryption. If metadata was tampered, decryption fails. * * Only the current V1 vault schema is supported. After AES-GCM decryption, * the 32-byte key-commitment padding is verified and stripped. * * @param key - The encryption key to decrypt with * @param vault - The encrypted vault payload * @returns The decrypted plaintext bytes * @throws {VaultCorruptedError} If vault data is structurally invalid (bad base64, wrong IV length) * @throws {IncorrectPasswordError} If decryption fails due to wrong password, tampered ciphertext, tampered metadata, or invalid key-commitment padding */ export declare function decryptData(key: VaultEncryptionKeyWithMetadata, vault: EncryptedVault): Promise;