How can a browser app protect private keys both at runtime and at rest?

0
0
Asked By MellowPine47 On

I'm building a personal end-to-end encrypted chat application and I'm stuck between two imperfect browser storage options. Data in localStorage or IndexedDB may be readable from the browser profile on disk, so storing a private key there appears unsafe at rest. Encrypting the key before storage helps only if the decryption key is protected separately; once the app can decrypt it, malicious or compromised code running in the app's origin may be able to exfiltrate it. Web Crypto lets me create non-extractable CryptoKey objects and store them in IndexedDB, which limits key export at runtime, but I can't wrap a non-extractable key because wrapping requires extracting it first. Is there a practical browser-native way to make a key locally usable, non-portable, and reasonably protected at rest? I'm considering splitting the design across a non-exportable Web Crypto key and a separately passphrase-encrypted key, but that feels unnecessarily complicated. What is the usual approach, and what threats can browser APIs realistically defend against?

2 Answers

Answered By AmberLattice31 On

If you use a passphrase, derive a wrapping key with a memory-hard password KDF such as Argon2id where available, or a carefully configured PBKDF2 implementation, then encrypt the private-key material before putting it in IndexedDB. The passphrase or a credential-derived secret must not be stored alongside it. For a non-extractable Web Crypto key, you can store the key handle and rely on the platform's browser-profile and disk protections, but you cannot also independently encrypt the key material without having an exportable representation. Avoid inventing a split-key or custom PGP construction unless you have a very specific threat model and have had the design reviewed.

Answered By SilverMaple22 On

There isn't a magic storage primitive that solves both problems for arbitrary JavaScript keys. A non-extractable CryptoKey prevents export through the Web Crypto API, but it does not make a compromised origin safe: code running with the same origin can often ask the browser to use that key. It also doesn't guarantee that every browser profile database is encrypted at rest. Conversely, an encrypted blob is only protected while the wrapping secret stays outside the attacker's reach. Common choices are a user passphrase-derived key, a platform credential such as WebAuthn, or relying on OS/device encryption for the browser profile.

CedarOrbit6 -

So the important step is to define the threat model. Protection against someone copying browser files is different from protection against malicious JavaScript or an XSS bug, and the latter cannot be fixed just by choosing IndexedDB over localStorage.

Related Questions

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.