import { generateRecoveryPhrase } from '../keyManagementBIP39' import type { EncryptedPayload } from '../keyManagementEncryption' import { generateKEK } from './crypto' import { decryptKEK, encryptKEK } from './kekEncryption' import { storeEncryptedKEK, getEncryptedKEK } from './credentials' import { decryptPrivateKeyWithKEK, encryptPrivateKeyWithKEK } from './privateKeyEncryption' export interface CreateAccountResult { recoveryPhrase: string[] npub: string publicKey: string } export interface UnlockAccountResult { privateKey: string publicKey: string npub: string } export async function createAccountTwoLevel( privateKeyHex: string, getPublicKey: (secretKey: Uint8Array) => string, encodeNpub: (publicKey: string) => string ): Promise { const recoveryPhrase = generateRecoveryPhrase() const kek = await generateKEK() const encryptedPrivateKey = await encryptPrivateKeyWithKEK(privateKeyHex, kek) const encryptedKEK = await encryptKEK(kek, recoveryPhrase) await storeEncryptedKEK(encryptedKEK) const { storageService } = await import('../storage/indexedDB') await storageService.set('nostr_encrypted_key', encryptedPrivateKey, 'nostr_key_storage') const { hexToBytes } = await import('nostr-tools/utils') const secretKey = hexToBytes(privateKeyHex) const publicKey = getPublicKey(secretKey) const npub = encodeNpub(publicKey) await storageService.set('nostr_public_key', { publicKey, npub }, 'nostr_key_storage') await storageService.set('nostr_account_exists', true, 'nostr_key_storage') return { recoveryPhrase, npub, publicKey } } export async function unlockAccountTwoLevel( recoveryPhrase: string[], getPublicKey: (secretKey: Uint8Array) => string, encodeNpub: (publicKey: string) => string ): Promise { const encryptedKEK = await getEncryptedKEK() if (!encryptedKEK) { throw new Error('No encrypted KEK found in Credentials API') } const kek = await decryptKEK(encryptedKEK, recoveryPhrase) recoveryPhrase.fill('') const { storageService: indexedDBStorage } = await import('../storage/indexedDB') const encryptedPrivateKey = await indexedDBStorage.get('nostr_encrypted_key', 'nostr_key_storage') if (!encryptedPrivateKey) { throw new Error('No encrypted private key found in IndexedDB') } const privateKeyHex = await decryptPrivateKeyWithKEK(encryptedPrivateKey, kek) const { hexToBytes } = await import('nostr-tools/utils') const secretKey = hexToBytes(privateKeyHex) const publicKey = getPublicKey(secretKey) const npub = encodeNpub(publicKey) return { privateKey: privateKeyHex, publicKey, npub } } export async function accountExistsTwoLevel(): Promise { try { const { storageService: indexedDBStorage } = await import('../storage/indexedDB') const exists = await indexedDBStorage.get('nostr_account_exists', 'nostr_key_storage') return exists === true } catch (e) { console.error('[keyManagementTwoLevel] Error checking account existence:', e) return false } } export async function getPublicKeysTwoLevel(): Promise<{ publicKey: string; npub: string } | null> { try { const { storageService: indexedDBStorage } = await import('../storage/indexedDB') return indexedDBStorage.get<{ publicKey: string; npub: string }>('nostr_public_key', 'nostr_key_storage') } catch (e) { console.error('[keyManagementTwoLevel] Error reading public keys:', e) return null } } export async function deleteAccountTwoLevel(): Promise { const { storageService: indexedDBStorage } = await import('../storage/indexedDB') await indexedDBStorage.delete('nostr_encrypted_key') await indexedDBStorage.delete('nostr_public_key') await indexedDBStorage.delete('nostr_account_exists') if (navigator.credentials?.preventSilentAccess) { void navigator.credentials.preventSilentAccess() } }