aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
blob: 9e9e1338bb34f1f54d0314e4a2343e205cdfc41d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# pinentry-rofi

GUI for GPG using [rofi](https://github.com/lbonn/rofi) for passwords, pins, etc.
Optional persistence of passwords into ??? (pass(1)???)

(c) 2018 Dale Phurrough
Licensed under the Mozilla Public License 2.0
(c) 2023 Matěj Cepl
Port to Linux/rofi

## Features

* Allows GnuPG to prompt and read passphrases by the pinentry protocol
  with a GUI when running on Linux
* Works for all keys managed by gpg-agent (GPG, SSH, etc)
* Drop-in replacement GUI to pinentry-curses, pinentry-gtk-2, etc.

## Requirements

* rofi (tested with the Wayland branch 1.7.5+wayland2+git.1690115482.ff2338c)
* GPG v2.1.11 or later. Earlier versions of 2.x (aka GPG2) or 1.x (aka GPG) have not been tested and are not recommended. You can check the version by `gpg2 --version`

## Setup

1. Save the `pinentry-rofi.sh` script and set its permissions to be readable and executable, e.g.
   `chmod ug=rx pinentry-rofi.sh`
2. Configure gpg-agent to use this script for pinentry using
   one of the following methods
    1. Set pinentry-program within ~/.gnupg/gpg-agent.conf to the script's path, e.g.
     `pinentry-program /mnt/c/repos/pinentry-rofi/pinentry-rofi.sh`
    2. Or, set the path to this script when you launch gpg-agent, e.g.
     `gpg-agent --pinentry-program /mnt/c/repos/pinentry-rofi/pinentry-rofi.sh`
[comment]: # 3. Optionally _enable_ persistence of passwords.
[comment]: #     1. Follow instructions <https://github.com/davotronic5000/PowerShell_Credential_Manager>
[comment]: #    to install the needed module from the Powershell Gallery or GitHub.
[comment]: #     2. Note security perspectives like <https://security.stackexchange.com/questions/119765/how-secure-is-the-windows-credential-manager>
[comment]: #     3. Edit the script and near the beginning of the file set `PERSISTENCE` to one of the values:
[comment]: #         * `""` no persistence
[comment]: #         * `"Session"` persists the password only for the current Windows login session
[comment]: #         * `"LocalMachine"` persists the password for the current Windows login on the local Windows computer
[comment]: #         * `"Enterprise"` persists the password for the current Windows login and requests Windows Credential Manager to synchronize it across Windows computers for that same Windows login


## Troubleshooting Ideas

1. Run `gpg2 --version` and `gpg-agent --version`. If you don't have version 2.1.11 or newer for both versions, you may have unknown problems.
2. I recommend you have a fully working GPG2 and GPG-agent setup using the default GPG2 configuration. Try two tests.  If these both don't work, you first need to troubleshoot your install.
    1. `gpg2 --clearsign myfile.zip`. Your entire console window should clear and present you an isolated password entry field in a crudely drawn box. Type in your key's password and it should return to your normal console with no error. You should now have the newly signed `myfile.zip.asc` file.
    2. If you are using the SSH-compatibility feature of GPG-agent, ensure you are not running `ssh-agent`. Try `ssh-add ...` to add your SSH key for your favorite host. Then remove and stash in a protected location this ssh key file from your `~/.ssh` directory to ensure ssh isn't using that file instead of the agent. Now try to ssh to this host. It should automatically retrieve the private host key from gpg-agent.
3. I discovered that there are many ways for gpg-agent to be started silently. The options passed to it are inconsistent across the methods (and across gpg versions). On my computer, I explicitly start gpg-agent.  Below is the method I use in my `.profile`. Please be aware that `.profile` is not always run for all *nix shell scenarios and `.bashrc` may be better for your setup. The details on this are written in the [BASH man page](https://linux.die.net/man/1/bash) in the INVOCATION section.
4. Configuration of GPG can become complicated if you diverge from what the GPG team considers a standard setup. You may need to read the [official GPG documentation](https://gnupg.org/documentation/index.html) to configure it for your specific computer setup.
5. GIT uses `gpg` by default. To instruct GIT to use `gpg2`, you can easily configure it with `git config --global gpg.program gpg2`
6. Enable a gpg-agent log file. Edit your `~/.gnupg/gpg-agent.conf` file and insert the following lines. Your user must have permission to write to this file path. Restart gpg-agent after you save this configuration.
    ```crmsh
    debug 1024
    debug-pinentry
    log-file /home/username/agent.log
    ```
7. Enable a log file specific to this pinentry code. Edit the script, near the top, set `DEBUGLOG` to a file path, e.g. `"$HOME/pintrace.log"`. Your user must have permission to write to this file path. Restart gpg-agent after you save this configuration.

## Example configuration files

Below are some examples from my configuration files. If you have a working GPG2 and gpg-agent setup, the only config change likely needed is the `pinentry-program` line from setup step 2.

#### Part of my ~/.profile

```bash
if [ -z "$(pgrep gpg-agent)" ]; then
    gpgconf --launch gpg-agent
    # I use the above method because the following method
    # doesn't set GPG_AGENT_INFO or GPG_TTY and has a bug
    # setting SSH_AUTH_SOCK if you use socket redirection:
    #   eval $(gpg-agent --homedir $HOME/.gnupg --daemon)
fi
if [ -z "$(pgrep dirmngr)" ]; then
    dirmngr --homedir $HOME/.gnupg --daemon >/dev/null 2>&1
    # I use the above method to consistently set vars in .bashrc
    # rather than the following:
    #   eval $(dirmngr --homedir $HOME/.gnupg --daemon)
fi
```

#### Part of my ~/.bashrc

```bash
export GPGKEY=12345678 # set prefered gpg signing key
PIDFOUND=$(pgrep gpg-agent)
if [ -n "$PIDFOUND" ]; then
    export GPG_AGENT_INFO="$HOME/.gnupg/S.gpg-agent:$PIDFOUND:1"
    export GPG_TTY=$(tty)
    export SSH_AUTH_SOCK="$HOME/.gnupg/S.gpg-agent.ssh"
    unset SSH_AGENT_PID
fi
PIDFOUND=$(pgrep dirmngr)
if [ -n "$PIDFOUND" ]; then
    export DIRMNGR_INFO="$HOME/.gnupg/S.dirmngr:$PIDFOUND:1"
fi
unset PIDFOUND
```

#### My ~/.gnupg/gpg-agent.conf

```
enable-ssh-support
disable-scdaemon
pinentry-program /mnt/c/repos/pinentry-rofi/pinentry-rofi.sh
```

## References

* <https://www.gnupg.org/software/pinentry/index.html>
* <https://www.gnupg.org/documentation/manuals/gnupg/Agent-Options.html>
* <https://github.com/GPGTools/pinentry/blob/master/doc/pinentry.texi>
* <https://gist.github.com/mdeguzis/05d1f284f931223624834788da045c65>
* <https://github.com/GPGTools/pinentry/blob/master/pinentry/pinentry.c>