0

I have already finished a web app with a secure backend and hashed passwords and now I'm working on an Android version. I store all of the crucial data in an encrypted database using SQLCipher and use the user's password to encrypt it. And I'll try to show you where my problem is:

  1. User logs onto the web app
  2. User changes password
  3. USer logs onto Android app
  4. Now that the password has been changed, I have no way to decrypt my database because I no longer have access to the password which was used to encrypt it.

I don't want to store the user's password in plaintext anywhere and sending it from the server is also not an option. How do I solve this problem?

  • The local SQLCipher DB should still be encrypted with the old password right? So why not prompt the user to fill in the old one and ask for the new one to reencrypt it with the new one? – Black Magic Mar 24 '17 at 8:53
  • I thought about it but it's not very seamless experience. I'm not going to do that unless I'm sure there is no other way. – Ernest Zamelczyk Mar 24 '17 at 9:09
  • Yes it might not be seamless, but how many times are users actually going to change their password – Black Magic Mar 24 '17 at 9:13
0

Would it work to have the user select a list of devices to update when they change the password on the website?

If so, the app could generate a key pair, and post the public key to the server once they have connected/authenticated (they only need to do this once/rarely). When changing the password, you would encrypt the new password with the public key and store it somewhere for the Android app to check on next boot. Nobody will be able to decrypt the new password apart from that particular device.

(If the Android device is compromised and the private keys are read, then presumably the same thing would happen to any rotated password. Maybe this is why the user is changing their password, at which point "select devices to update" is an important step.)

  • But what if selected device doesn't have connection to the internet in that moment? I would be forced to store not hashed password on the server side until the device gets available. – Ernest Zamelczyk Mar 24 '17 at 11:32
  • Not hashed, but public-key encrypted - and nobody has the private key to decrypt it except that particular device. – cloudfeet Mar 24 '17 at 11:33
  • So you mean that we should send the public key first time when device gets connected to the server. Well that seems like a good idea. I'll try and see how this works. – Ernest Zamelczyk Mar 24 '17 at 11:53
  • This one turned out to be a great solution. Sorry for the late followup, but I just simply forgot about that question in the process. – Ernest Zamelczyk Jun 23 '17 at 7:59
0

You should use a web API to allow a password change on the server and trigger that API from the app. That way, the user should only be able to change its password from the app and while connected to the server. But the user's password should not be used to directly encrypt the database but only to encrypt a (large and random) key. The general workflow could be:

  • user asks for a password change on the app
  • app asks the old and new password
  • app confirms the old password with the server through a secure (SSL encrypted) connection - optional
  • app asks the server to change the password by giving the old and new ones over a secure connection
  • app decode the database key with the old password
  • app encode the database key with the new password and saves it in permanent storage

That way the user experience is correct because he only declared his password change once and the app and the server are still in sync after that.

Unfortunately, this is only a general workflow, because even if it is immune to an early connection failure (simply keep old password if server could not change it), the worst case would be if the server could change its password but lose the connection before acknowledging it to the app. As usual, the devil is hidden in the details of worst case failure and the actual protocol should ensure that both sides returns to previous state if a problem occurs before the end.

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.