5

I'm working on an app where I want to provide end to end encryption on files, where multiple users are able to access these folders. I'd like the encryption to be as transparent and frictionless as possible (I don't want users to have to manage their own keys), so I've been considering ways to do this.

The requirements for this protocol are:

  1. Users do not have to manage their own key
  2. Users must be able to use it from multiple devices
  3. On changing device, users must still have access to their old files

My current thoughts are:

  1. When a user signs up, generate a keypair (client side)
  2. Encrypt their private key with a symmetric key derived from salt + password (client side)
  3. Upload public key, encrypted private key, hash(salt + password) and salt to API
  4. Server side, store public key and encrypted private key. As the users password is used for encrypting their private key, it cannot be transmitted in plaintext to the server, ever. If, instead, a hash is transmitted, their password is not revealed but if an attacker were to breach the database, it would be possible to use the hash to login to their account, but not decrypt files. To fix this, the password hash transmitted is rehashed server-side, and stored.
  5. When a user creates a folder, generate a new symmetric key, and encrypt these files using that key (client side)
  6. Encrypt this symmetric key using the users public key (client side)
  7. When user logs in, download their public and encrypted private key
  8. Decrypt private key, store on device
  9. Use private key to decrypt symmetric key, then decrypt files
  10. To grant folder access owned by A to another user B, user A fetches the public key for user B from the API, decrypts the folder symmetric key using their own private key, then encrypts the symmetric key again using B's public key, before transmitting it back to the API. User B can then fetch the encrypted symmetric key, decrypt it using their private key, and decrypt the folder contents

Does such an approach make sense (from a security and usability perspective)? Are there any caveats or potential pitfalls?

I understand that there are N times protocols for multi-party asymmetrical encryption, however as it's files rather than messages being stored it's not realistic from a bandwidth perspective.

  • 3
    You shouldn’t roll your own protocol, the pitfalls are in the details. There are good solutions that already do almost all of this, for example PGP. I cannot see how this would differ, bandwidth-wise; if you need access to the file, you need to download it; if it is big or small is irrelevant in terms of key management, which is the overhead here – Tobi Nary Nov 30 '17 at 11:21
  • "upload public key" where? Where are the folders and files stored? This is not looking like an "end-to-end" scenario if the keys and files are being stored on your server. – schroeder Nov 30 '17 at 11:46
  • You need to explain #9 - you compressed the entire complexity of your problem into one vague point. Whose public key? Which symmetric key? What database? Do you want each other user to have a unique key? Do you want the ability to revoke access to other users? – schroeder Nov 30 '17 at 11:50
  • Note that whatever else you think your core function of your service is, in this design, your core function is to be a key management server (and oh yeah, you offer storage space, too). Look for design patterns for key management services, and you will have a much easier time. – schroeder Nov 30 '17 at 11:55
  • @SmokeDispenser PGP only solves encrypting for one recipient. As multiple users need to access the files, a copy of each file would have to be stored for each user that can access it. As the goal is full end-to-end encryption, not only would it have to be stored, but the uploader would have to upload it for each user too – Benedict Lewis Nov 30 '17 at 15:49
1

Your approach makes sense as far as using one symmetric key to encrypt the files, and sharing that key among authorized users using public keys to keep it secret.

To address concerns with storing private keys on your server (even though they'd be encrypted), you could just issue a new keypair to a user every time they log in from a new device. This would allow your users to disassociate from any given keypair if a device is lost, app is deleted etc. This would also afford you the flexibility remove individual devices in case of theft, although that would necessitate re-encrypting all files associated with that user with a new symmetric key.

  • The issue with that is that it requires the folder owner to be logged in on at least one device at any time. If the folder owner loses or breaks their phone without logging in to another, the private key to decrypt the symmetric key is lost. I suppose you could use other users with access to the folder as brokers for a new key exchange, however you then have issues on folders with only one user – Benedict Lewis Nov 30 '17 at 20:22
  • I'll second what @RubberStamp suggested in taking a look at keybase.io. They have a mechanic (which I don't understand at all) to allow you to provision new devices by using a multi-word (13?) passphrase that you register as a secondary 'device' when you create your account. I'd say it's a reasonable policy that if a user destorys/loses 100% of their devices AND their paper key, that their files are permanently gone. Unfortunately at this point I'm out of my depth and couldn't guess how it actually works. – user8675309 Nov 30 '17 at 20:33
1

Have you looked into the Signal Protocol (wikipedia) and libsignal library for C, Java, and Javascript?

I believe it meets all three of your requirements, plus it has the advantage of being very well built by a team of crypto experts, and unless you're a team of experts, you're going to do crypto wrong.

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.