After a day long of a research (lol), this is the architecture I found for encrypting files (simplified).
Account creation
- Upon account creation, Client create Key Encryption Key (KEK) using salt + password with Argon2.
- Client generate asymmetric Public Key(PK), Master Encryption Key (MEK).
- Client encrypt MEK using AES-256-GCM, and use KEK generated in 1 as encryption key. (we will call Encrypted MEK as EMEK).
- Server store EMEK, PK, salt.
Server only see encrypted MEK here and there are no ways for server to roll back EMEK to MEK. Server would have to know KEK. But server only knows salt not the plaintext password since password is hashed using bcrypt (one way hash function),
For Client, when they want to retrieve MEK, they would just have to re-derive KEK since they put their password when they log in.
File upload
- Generate 256 bits Data Encryption Key (DEK).
- For each chunk in the file, encrypt the chunk using AES_256_GCM with that DEK.
- Fetch PK from the server.
- Use PK to encrypt DEK using Eliptic-Curve Cryptography (ECC).
- Save Encrypted DEK to server
As a result, server will only see encrypted blob of files and only way for server to know the content of files would be when all DEKs of files get compromised. But then that requires MEK to be compromised but we previously have established that is computationally infeasible.
Footnote
For asymmetric/symmetric encryption, you can use any other encryption method as long as they’re reasonably safe (RSA, bcrypt). The reason why I chose ECC/Argon2, is because
ECC: can achieve the same level of security with taking less storage space compare to RSA.
Argon2: resist against GPU attack since Argon2 requires fixed-size memory space for hashing.
Disclaimer
I have a bare minimum knowledge when it comes to cryptography. So take my word with a grain of salt.
Leave a comment