I am implementing a web-based system which has the following goals:
Users are able to store secrets (could be password, or an entire file) on the server.
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.
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.
HTTPS is used for all client/server communication. Users require accounts, there is already an authentication system in place.
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.
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.
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?