I am implementing a web-based system which has the following goals:

  1. Users are able to store secrets (could be password, or an entire file) on the server.

  2. Server has no knowledge of the keys for decryption. So that if the server is compromised, the attacker would not be able to decrypt the secrets.

  3. Secrets can be shared between users.


The main threat I am concerned about for the purposes of this question is server compromise. I want to ensure that if an attacker gains access to the server or database (offline or online), no secrets are exposed. I understand there are other threats, like a compromised user account. Other safeties will be in place to protect against that.

I decided that it is safest for the server to never see a plaintext secret or the key material. Therefore, all encryption is done client-side. I am using asmCrypto.

  1. HTTPS is used for all client/server communication. Users require accounts, there is already an authentication system in place.

  2. Users generate a personal RSA key pair (2048-bit, e=65537). The private key is encrypted with AES-GCM using a PBKDF2-generated key based on the a user-provided passphrase. The AES nonce is generated by the server to guarantee uniqueness. The user's public key and the encrypted private key are sent to the server to be stored.

  3. When a user saves a secret, they generates a random unique key (K) for that secret. They encrypt the secret with AES-GCM using K and a server-provided nonce. Then they encrypt K using their own public key and OAEP padding. Additionally, they may encrypt K with another user's public key. The encrypted copies of K are sent to the server.

  4. To read the secret (possibly from another computer), a user must retrieve their encrypted private key from the server. They decrypt their private key client-side by providing a passphrase, which is fed into PBKDF2 to generate the AES key. Once their RSA private key is decrypted, they can decrypt the secret key (K), and subsequently the secret.


I know there are many pitfalls and potential gotchas with encryption. I've done a lot of reading to try to understand how best to use these algorithms (for instance, the unique nonce for AES-GCM, the value of e for the RSA keys, and the importance of using proper padding). However, I'm not entirely confident this is a sensible design.

What flaws do you see in this design?

Are the choices of algorithms and parameters sound?

Is there any way to judge the quality of the asmCrypto library?

Am I missing a simpler, obvious solution?


Issue with Trusting the Server

If you base the web-app on the server, then when the server is compromised, the base web page or the crypto library can be compromised/bypassed directly without alerting the users.

Your infrastructure is built upon a bed of sand if you cant trust the server.


  • Remove encryption totally and have the content unencrypted, the users still use the software expecting it to be encrypted, but it isnt. (complications being the current encrypted content)
  • Or to just send the 'secret' to the attacker directly.

The whole Javascript Cryptography Considered Harmful issue documents this and other issues. Note: That this article mentions the secure notes use case.

  • A very valid point. So is the best advice to just allow the server to do all the cryptography (including storing keys), harden it as much as possible and hope it never gets compromised? – Nate H Jun 29 '17 at 15:18
  • Also, is the design sound if the client is not Javascript in the web browser, but a native app for instance? – Nate H Jul 10 '17 at 23:05
  • I am not competent to analyse the specifics. But you are not using a high level independently developed solution to this (such as potentially gpg). Notwithstanding that the delivery of this solution does not have a secure path to the users computer. – Andrew Russell Jul 13 '17 at 1:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.