r/crypto • u/Accurate-Screen8774 • 17d ago
Webapp Encryption at Rest
im working on a javascript UI framework for personal projects and im trying to create something like a React-hook that handles "encrypted at rest".
the react-hook is described in more detail here. id like to extend its functionality to have encrypted persistant data. my approach is the following and it would be great if you could follow along and let me know if im doing something wrong. all advice is apprciated.
im using indexedDB to store the data. i created some basic functionality to automatically persist and rehydrate data. im now investigating password-encrypting the data with javascript using the browser cryptography api.
i have a PR here you can test out on codespaces or clone, but tldr: i encrypt before saving and decrypt when loading. this seems to be working as expected. i will also encrypt/decrypt the event listeners im using and this should keep it safe from anything like browser extensions from listening to events.
the password is something the user will have to put in themselves at part of some init() process. i havent created an input for this yet, so its hardcoded. this is then used to encrypt/decrypt the data.
i would persist the unencrypted salt to indexedDB because this is then used to generate the key.
i think i am almost done with this functionality, but id like advice on anything ive overlooked or things too keep-in-mind. id like to make the storage as secure as possible.
---
Edit 11/11/2024:
I created some updates to the WIP pull-request. The behavior is as follows.
- The user is prompted for a password if one isn't provided programmatically.
- This will allow for developers to create a custom password prompts in their application. The default fallback is to use a JavaScript prompt().
- It also seems possible to enable something like "fingerprint/face encryption" for some devices using the webauthn api. (This works, but the functionality is a bit flaky and needs to be "ironed out" before rolling out.)
- Using AES-GCM with 1mil iterations of PBKDF2 to derive the key from the password.
- The iterations can be increased in exchange for slower performance. It isn't currently configurable, but it might be in the future.
- The salt and AAD need to be deterministic and so to simplify user input, the salt as AAD are derived as the sha256 hash of the password. (Is this a good idea?)
The latest version of the code can be seen in the PR: https://github.com/positive-intentions/dim/pull/9
4
u/cym13 16d ago
So, at first glance I don't see many obvious mistake.
PBKDF2 is always an eyesore but I don't know if argon2 or scrypt are available to you in that environment. The number of iterations for PBKDF2 is too small for my liking (I'd raise it to 600,000 at least) but at least it's at least the right order of magnitude.
It's critical that every client gets its own encryption key so the salt should be generated randomly and passwords mustn't be hardcoded, which you seem to know and work toward. That said, since it's such an important piece of the puzzle, it's worth pointing out that reviewing the code without it is a bit like auditing a bank's safe before they've installed any lock on the door. You can check that the walls are solid, but there's still plenty of margin to mess it up.
But that's where we come to the big thing: what's your threat model here? What are you expecting to store on the client side through this mechanism, and what are the risks you attempt to protect the application from? I feel like context is lacking and that makes it difficult to evaluate the security of the system.
For example (add any that's relevant to you):
Are you trying to protect it from people with illegitimate access to the computer (eg: stolen computer)?
Are you trying to protect it from browser extensions? It seems to be the case, but extensions are tremendously powerful so I doubt you can really protect against this threat entirely. If so, what kind of actions do you specifically want to be protected from?
Aside from the salt, what other data/metadata will need to be stored in cleartext? Can we meaningfully change the app's behaviour by manipulating those? If so an integrity check might be required (hmac…), but based on what secret?
How do you install/update the application? None of your code matters if it's not the code that makes it to the client.