1

Imagine a mobile app that connects to an API server.

Disclaimer

I'm not sure if RSA is the right technique for this, please feel free to recommend alternatives.

The goal

The backend/database super users should not be able to recognize personal data (except email) that the user submits (in this case personal tracker data) while the user should be able to read that data in cleartext. In the case of a lost phone or something, the user should be able to retrieve his old RSA keypair without him even noticing, just by using his email and password. Besides all that we want to be able to verify the user by sending him an email on registration.

My idea

  1. User downloads app, app generates local RSA keys.
  2. User registers on the app, provides strong password and email address for verification and this is sent to the server over https:
    • Hashed Password (Bcrypt, salt is stored inside hash)
    • Encrypted RSA Keys (encrypted with ? using the password)
    • Plaintext email for contacting/verification purpose
  3. Server recieves data, creates new user entry in database and stores the already hashed RSA Keys also with the user entry.
  4. User uses app, sends sensitive data encrypted with RSA to the server, server stores that encrypted gibberish.
  5. User can retrieve old entries in the app by retrieving the gibberish and decrypting it with the local RSA key.
  6. User loses his Smartphone, therefore the unencrypted RSA keys
  7. User buys new phone, installs app and logs in with his credentials
  8. Server first uses hashed password to check if credentials are okay, if yes, sends the user his encrypted rsa keys for him to decrypt them with his password locally.
  9. Voila, user has now recovered his encrypted data while backend has no idea of what is inside the data.
9
  • 1
    What's your question? "What's your opinion?" is not a great question for the site.
    – schroeder
    Commented Apr 18, 2023 at 13:58
  • For the process you described the server does need to store any keys at all. User can encrypt data on the client side with a simmetric cipher, e.g. AES, and sent to the server. When needed, user retrieves encrypted data and decrypts them on the client side.
    – mentallurg
    Commented Apr 18, 2023 at 14:00
  • @schroeder My question is if this is the way to achieve this goal. Or if I completely going in the wrong direction.
    – Laisender
    Commented Apr 18, 2023 at 14:41
  • @mentallurg Thanks for the clarification, that sounds a lot simpler! Can you recommend any method to derive the key from the plain password? I am thinking bcrypt and then some KDF. Is there anything I have to make sure when choosing this key generation method? is there a standard way of doing so?
    – Laisender
    Commented Apr 18, 2023 at 15:03
  • @Laisender: You don't need 2. If you can, use Argon2. If you cannot, e.g. if you use WebCrypto, use PBKDF2.
    – mentallurg
    Commented Apr 18, 2023 at 15:10

1 Answer 1

0

If I understand correctly, two cryptographic values are derived from the user password on the client side:

  1. A salted hash (e.g. bcrypt) that is used to authenticate the user with the server

  2. An encryption key that is used to encrypt the user's secrets on the client side.

My concern is with (1) above. From the discussion in the comments, it seems that when the user registers with the service, the user's password is salted and hashed (by way of bcrypt) on the client side, then this salted hash is sent to the server and stored in the user record. Then later, when the user authenticates with the server, the salted+hashed password is sent to the server, and the server compares the salted+hashed password that it receives from the client with the one that it has stored. This basically amounts to client-side hashing, where the salted+hash password simply 'becomes' the actual password. See this answer for more detail about this, and note in particular where it reads, 'This means that you will be storing the full "plain-text" password (the hash) in the database, and you will have lost all benefit of hashing in the first place'. As you probably know, storing the plaintext password (or the equivalent), is not recommended.

In addition to the above, you also need to address the question of where the salt would be stored. If you store the salt on the user's device, and the user looses his/her device, then the salt is lost. If you store the salt on the server, then you would have to work out some protocol for the client to get the salt from the server; and at this point, this begins to look a lot like SRP.

SRP addresses both of the above problems. With SRP, the client and the server mutually authenticate each other based on a password known to the client (and a derivation of the password known to the server), without the server storing the password (or password equivalent). SRP has a number of other security benefits as well. See Alternatives for sending plaintext password while login for more info.

Once you get your head around SRP, you might want to take a look at https://protonmail.com/blog/encrypted_email_authentication for an interesting read on how Protonmail uses SRP to derive two keys from the user's password - one that is used to authenticate with the server, and another that is used for client-side encryption, which seems very similar to what you are trying to do.

Last but not least, I'm not sure you need (asymmetric) RSA encryption for this. Being that the personal data is being encrypted and decrypted by the same user, symmetric encryption (e.g. AES encryption), where the same key is used for both encryption and decryption, ought to suffice.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .