Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

option to only keep pass phrase in memory #372

Closed
tomholub opened this issue Nov 16, 2018 · 33 comments · Fixed by #1249
Closed

option to only keep pass phrase in memory #372

tomholub opened this issue Nov 16, 2018 · 33 comments · Fixed by #1249
Assignees
Labels
architecture Such issues are important for architecture user experience
Milestone

Comments

@tomholub
Copy link
Collaborator

tomholub commented Nov 16, 2018

part of #1298

@tomholub tomholub added this to the later milestone Nov 16, 2018
@tomholub
Copy link
Collaborator Author

tomholub commented Sep 5, 2019

part of #714

@DenBond7
Copy link
Collaborator

DenBond7 commented May 5, 2021

@tomholub Could you share more details? I mean how do you see that. Because due to the difficult lifecycle of the Android app we can have different thoughts about this issue. I need a little more info.

@bilalashraf123
Copy link

When generate key pair in Android, there is an option to associate an authentication mecahism with it. The authentication mechanism could be device fingerprint. For this, fingerprint needs to be registered.

If authentication mechanism is bound to the key, one cannot access the key without providing the fingerprint. If user deletes the fingerprint on Android device, then that particular key cannot be accessed anymore.

When use Android key store provider, the key pair is generated and stored in TEE (Trusted execution environment)/StrongBox and cannot be exported. TEE is available I believe after Andoid 6.

@tomholub
Copy link
Collaborator Author

tomholub commented May 5, 2021

Sorry Bilal - this issue is not about user's fingerprint or TEE or pins or other similar mechanisms. While this is a related concern (how to ensure that user has acceptable UX on a phone, instead of having to always input long pass phrases), this particular issue is purely about not storing pass phrases in long-term storage. Above, Den is asking about how exactly to achieve that, which may involve some of what you mentioned, but that's not the core of the issue.

For this particular issue, I'd like to see something like this:


(consumers) During setup (of new OpenPGP key, or when importing key or when loading from backup - whenever I'm creating or entering pass phrase), the user should see two radio buttons:

o store pass phrase locally
o keep pass phrase in memory

Default is to store, just like now.

If the user switches it to memory-only, then we do not store pass phrase with the key (or at all). We only keep the pass phrase in memory for up to 4 hours from the moment it was stored - then it needs to be forgotten. During those 4 hours, the key will be used for actions (eg decrypt messages). After those 4 hours, the user will be prompted for a pass phrase with a modal / alert to re-enter it, at which point it will be again remembered for 4 hours.

If app gets killed, pass phrase gets forgotten.

For now, there will be no way for user to switch this anywhere in settings. They would have to log out and re-setup.


(enterprise users with appropriate OrgRule as described in #1168 - don't ask user, automatically only store in memory)


@DenBond7 with this in mind - is this achievable purely using standard Java code? Just keep some information in background process in memory for up to 4 hours, then wipe it?

@DenBond7
Copy link
Collaborator

DenBond7 commented May 5, 2021

@tomholub Thanks! That's what I meant.

with this in mind - is this achievable purely using standard Java code?

It's ok in the Java world. But... It can be a little difficult on Android. Let me explain. We can have any data in the RAM while the app process is alive. But you can easy reproduce a situation that kills our process due to memory optimization. And it will a regular Android system behavior. For example, please run FlowCrypt then move it to the background. After that try to open 10-20 different apps. After that try to open FlowCrypt and you will that the app starts from the fresh state. It depends on different things: manufacturer, RAM and etc. I can't control that.

So only the following can be true:

  1. Keep passphrase up to 4 hours in the RAM
  2. While 1 is true keep passphrase in the RAM if the app process is alive.(it can be from 0 up to 4 hours as I described in 1.)

@bilalashraf123
Copy link

Can we do something like this?

  • store pass phrase locally
  • keep pass phrase temprarily - In this case, store passphrase for 4 hours in local storage securely

When keep pass phrase temprarily, we can apply same security mesaures as we are are for option store pass phrase locally, only difference is the prompt of passphrase after 4 hours or not.

After 4 hours, clear the passpharse and store again securely after taking input from the user.

@DenBond7
Copy link
Collaborator

DenBond7 commented May 5, 2021

@bilalashraf123 of course we can do that. We can have a task for Work manager that will check and clear temporary passphrases.

@tomholub
I'm thinking about one more way. We can use for example https://developer.android.com/guide/components/foreground-services. In that case we can have our passphrases in RAM. But we will have to show a notification in the status bar always.

@DenBond7
Copy link
Collaborator

DenBond7 commented May 5, 2021

For example like Mi Fit, Google Translate

Screenshot_2021-05-05-18-24-22-33

@bilalashraf123
Copy link

please correct me If I am wrong. The actual requirement could be not to ask for passphrase for 4 hours. It does not matter where to store the password temporarily.

@tomholub
Copy link
Collaborator Author

tomholub commented May 5, 2021

please correct me If I am wrong. The actual requirement could be not to ask for passphrase for 4 hours. It does not matter where to store the password temporarily.

We didn't discuss this in detail on mobile apps, just a note that "eventually would be good to use fingerprint or pin to protect the pass phrase".

We did discuss it on the browser extension, where we could use session storage (that browser may store to file system) that we manually empty after 4 hours, and this was rejected - saving it locally is a hazard that the customer does not want.

On Android the situation is a bit different due to the abundance of options to address this further (pin/fingerprint/secure keychain and so on) but I don't want to get into it yet, because it's an implementation and design rabbit hole (plus so many types of devices, etc).

@tomholub
Copy link
Collaborator Author

tomholub commented May 5, 2021

So only the following can be true:

1. Keep passphrase up to 4 hours in the RAM

2. While 1 is true keep passphrase in the RAM if the app process is alive.(it can be from 0 up to 4 hours as I described in 1.)

We can store in memory as you say, and consider it expected behavior that the pass phrase may last less than 4 hours if the OS kills the process for memory management.

@tomholub
Copy link
Collaborator Author

tomholub commented May 5, 2021

@tomholub
I'm thinking about one more way. We can use for example https://developer.android.com/guide/components/foreground-services. In that case we can have our passphrases in RAM. But we will have to show a notification in the status bar always.

This is an excellent option! That way, there could also be a button "forget now" on the notification.

@DenBond7 DenBond7 modified the milestones: soon, 1.1.8 May 6, 2021
@DenBond7 DenBond7 added architecture Such issues are important for architecture user experience labels May 6, 2021
@DenBond7
Copy link
Collaborator

DenBond7 commented May 6, 2021

@tomholub By the way, what about operations like changing passphrase? As for me if a user chooses the option keep pass phrase in memory it should be a read-only prv key. Maybe in the future, we will improve that.

@tomholub
Copy link
Collaborator Author

tomholub commented May 6, 2021

@tomholub By the way, what about operations like changing passphrase? As for me if a user chooses the option keep pass phrase in memory it should be a read-only prv key. Maybe in the future, we will improve that.

Initially, you can do that.

@DenBond7
Copy link
Collaborator

@tomholub I'm thinking about the current issue. It isn't a simple and for now I've just added only a base functionality. And it produced a lot of changes in the code (architecture changes). I think we have to divide the current issue to a few smaller to be able to review it comfortable.

What already works:

  • we can import a key with pass phrase in RAM
  • after that the app will run a foreground service that will erase pass phrases every 4 hours
  • we can go Settings - Keys - Select some key. There we can erase or add a pass phrase. It was added to be able to test a situation when we have or haven't a pass phrase in RAM.

I propose too accept the current changes for this issue and open new issues for the following:

  • decrypt a message
  • creat an encrypted message
  • make a backup
  • change passphrase of imported keys
  • decrypt an attachment

All of those cases is not handled properly now. App doesn't crash but a user will see some sort of errors.

@tomholub It would be great if you test the current changes with described cases to see what exactly happens

One more thing. We can't release the current changes while we don't cover all cases that I've described. For now I propose to make available use pass phrase in RAM only for the debug builds. The release builds should work as before.

@tomholub
Copy link
Collaborator Author

You can still render both ram and storage radio buttons during setup, but in production builds make the ram option grayed out. Then we can release even before we fix all of these.

@DenBond7
Copy link
Collaborator

You can still render both ram and storage radio buttons during setup, but in production builds make the ram option grayed out. Then we can release even before we fix all of these.

Agree. Good idea 👍

@DenBond7
Copy link
Collaborator

@tomholub Please share your opinion - would you like to have a sound when we show a notification or I have to show it silently?

image

@tomholub
Copy link
Collaborator Author

silently please

@tomholub
Copy link
Collaborator Author

Even better if the notification didn't really "show up", and only be visible when we go to notifications

DenBond7 added a commit that referenced this issue May 26, 2021
DenBond7 added a commit that referenced this issue May 26, 2021
DenBond7 added a commit that referenced this issue May 27, 2021
DenBond7 added a commit that referenced this issue May 27, 2021
DenBond7 added a commit that referenced this issue May 27, 2021
* Added PassPhrasesInRAMService. Refactored code.| #372

* Dropped using 'longId'. Migrated to use only 'fingerprint'. Updated the database version to 25. Refactored code.| #372

* Fixed bugs in tests.| #372

* Modified KeysStorage. Moved to use Passphrase instead of String where it is possible. Refactored code.| #372

* Moved NodeKeyDetails to 'security.model'.| #372

* Renamed KeyDetails.Type to KeyDetails.SourceType.| #372

* Renamed KeyDetails to KeyImportDetails.| #372

* Renamed NodeKeyDetails to PgpKeyDetails.| #372

* Refactored code.| #372

* Fixed refactoring errors.| #372

* Refactored code.| #372

* Refactored code.| #372

* Fixed PrivateKeysManager.| #372

* Refactored code.| #372

* Replaced KeyEntity with PgpKeyDetails where it is possible.| #372

* Modified the database schema to store different passphrase types.| #372

* Modified KeysDao to prevent saving passphrase if passphraseType == KeyEntity.PassphraseType.RAM.| #372

* Modified UI in CheckKeysActivity. Added some logic to CheckPrivateKeysViewModel. Refactored code.| #372

* Fixed conflicts after merge.| #372

* Modified PrivateKeysViewModel to be able to store passphrase in RAM. Refactored code in KeysStorageImpl.| #372

* Added auto manage of PassPhrasesInRAMService.| #372

* Improved KeysStorageImpl.updatePassPhrasesCache().| #372

* Modified PrivateKeyDetailsFragment to be able to update(set or erase) a pass phrase for passphraseType == KeyEntity.PassphraseType.RAM.| #372

* Updated a notification in PassPhrasesInRAMService.| #372

* Fixed a bug in CheckKeysActivity. Refactored code.| #372

* Fixed the database migration.| #372

* Fixed a bug in KeysStorageImpl.getPGPSecretKeyRingByFingerprint().| #372

* Added some logic to KeysStorageImpl.| #372

* Fixed a bug in AttachmentDownloadManagerService.| #372

* Fixed some tests.| #372

* Fixed lint warnings.| #372

* Marked some code as deprecated.| #372

* Renamed some strings.| #372

* Disabled "Keep pass phrase in memory" for release builds.| #372

* Made notifications for PassPhrasesInRAMService silent.| #372

* Removed unused code.| #372

* Fixed method names.| #372
@DenBond7
Copy link
Collaborator

For the history. Here I've added only a base realization without error handling.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
architecture Such issues are important for architecture user experience
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants