Some preface:
- Our application is killed by mobile OS quite frequently (often this happens while app stays in the background), and this forces users to go through logging form after each crash. This happens to other applications as well, the frequency of such events depends on app’s performance (os might kill the app which consumes too much cpu or ram, etc) and also on the resource restrictions and state of the particular device. For instance, if Status is the only app which is running on the device it might happen that it will not be killed for weeks. But that’s rarely the case.
- The suggested approach to bypass this issue was to restore the last known state of the app on the next run, or at least log in without password prompt. It was partially implemented (only for iOS) here https://github.com/status-im/status-react/pull/5617 . The password is stored as a plain text in the keychain if a user switches on “save password until logout”. When user internationally logs out the password is removed from the keychain.
- There was also a request for implementation of the same functionality on iOS, as it was postponed because of security concerns [Epic] Implement "Save password" functionality for Android · Issue #5793 · status-im/status-mobile · GitHub
- I opened a PR which enables “Save Password” functionality on Android 23+ [ANDROID #5793] enable saving password on android by rasom · Pull Request #6616 · status-im/status-mobile · GitHub, but @cammellos raised the concern that storing a plain password on the device is a wrong way to go
- we decided to close that pull request and continue the discussion here
next steps
- We suggested that “Save Password” functionality should be disabled on iOS until we figure a better approach
- We can stop using a plain password when a user creates/restores account. We can hash it before ever passing to status-go. In this case, there is no need to store a plain password on the device. This change will require migration for realm db (as it will be encrypted with a key derived from the password’s hash but not directly from the password) and also functionality for changing account’s password on status go side (if such doesn’t exist already)
former steps are not that clear - derive time-based token which will be stored on the device and used as a password. Not clear how to implement this, because password (or its derivatives, token in this case) should be used for realm db encryption, which means that the token will be needed on the next run and can’t disappear (expire) because access to can be lost.
- On Android we can temporarily store password (rather its hash) in memory using a service in the background (with no guaranty of persistence, service might be killed at any point in time), which would allow as to reuse password if the app was closed but service hasn’t been killed. Storing time-based or some randomly generated token in the service will not work at least for realm db (same reason as 3)
- We can have a separate PK for whisper and for the funded account. In this case, we can have separate passwords for them and even if whisper key will have all the same problems which a single key has now, the password for the funded account will not be required for logging in, thus no need to store it in any form, funds are safe.
So open questions are:
- Is storing of the password’s hash on device instead of password enough for us? @petty’s quote on this
how that private key is (en/de)crypted shouldn’t also be on the same device, unless stored in a separate key-manager app like lastpass (outside the realm of status development)
- if not, what measures must be taken?
- store keys only on a secure enclave
- time-based token
- seprate keys for whisper and funded account
- something also
- Are there other solutions which were not mentioned?