adur1990 / Pass-for-macOS

macOS wrapper for pass, the standard UNIX password manager
BSD 3-Clause "New" or "Revised" License
111 stars 8 forks source link

Implement passphrase prompt #46

Closed AnotherProksY closed 3 years ago

AnotherProksY commented 3 years ago

Summary

Implement passphrase prompt for Safari and Status Bar.

Motivation

When Pass for MacOS need unlocked and passphrase free gpg session for decrypting local storage, instead of manual passphrase entering inside terminal, prompt user for passphrase in the same pop-up window. It will be a good option to implement Safari Session based ttl cache. After entering passphrase inside Safari, cache passphrase for this session and use without prompt. When user quits Safari, local passphrase cache clears out.

Is your feature request related to a problem? Please describe.

It seems that Pass for MacOS only works when you entered passphrase in actual pass inside terminal. After entering passphrase inside terminal i'v got some time, which is defined in gpg-agent.conf, to use Pass for MacOS. By default it's only 10 minutes. When time expires I need to re-enter my passphrase again. It's ok for CLI use, but not for Safari/Status Bar. Extending ttl time isn't an option.

Describe alternatives you've considered

As I described above, increasing ttl in gpg config isn't an option, but it might be an option for Pass for MacOS. Implement local passphrase cache storage and add option for custom ttl in App Preferences. And of course, you need to encrypt/decrypt this local storage with symmetric encryption algorithm.

Additional context

Nothing to add here :(

adur1990 commented 3 years ago

Thank you for the suggestion, but I'm afraid this won't be possible (or desirable). A little explanation. How Pass for macOS works is that it uses the shell command to directly interact with pass using Swift's Process() class. So, when the user selects a password to decrypt, Pass for macOS literally calls sh -l -c "pass -c <path>". An here, I am not able to handle the passphrase and give it to GnuPG's pin entry.

That was a deliberate decision to do it that way. Otherwise I would have to handle the user's passphrase. The only secure way I can think of to do this is to use macOS' keychain to securely cache the password. Alternatively, I would have to either keep it in RAM or write it to disk, which would require the use of some kind of crypto, which would again be an unnecessary security risk. Additionally, there is no way to enter the passphrase in GnuPG's pin entry from the Process() class.

Anyway, I would propose the following: First, users could use a GUI-based pin entry tool like pinentry-mac (can be installed with brew install pinentry-mac. This will prompt the GUI every time the gpg-agent clears its cache. Additionally, users can decide whether they want to store the passphrase in the macOS keychain. This is probably the most secure way.

Second, I could find a way to check if the passphrase is still cached and if not notify the user that they have to enter the passphrase. But I'm not sure if this makes any sense as I would not be able to do this within Pass for macOS unless the user started the gpg-agent with the --allow-preset-passphrase option.

Third, I could stop using pass but instead use gpg directly to decrypt the password files and provide the passphrase every time. But again, this would require that Pass for macOS handles the gpg passphrase, which is a security risk in my opinion.

These are the ideas that currently come to my mind spontaneously. But I appreciate any other suggestions. Maybe there is a feasible way that I just don't see at the moment.

AnotherProksY commented 3 years ago

Thank you for the reply!

Yeah, second and third solutions are not trivial + risky and it breaks "Unix way" philosophy:

The first solution is fine, but it needs to be documented :)

adur1990 commented 3 years ago

I added a GUI-based pinentry as a requirement to the README. I hope this is an acceptable solution. I noticed that Browserpass does the same, so I decided to follow their example.