126

Using gpg from a console-based environment such as ssh sessions fails because the GTK pinentry dialog cannot be shown in a SSH session.

I tried unset DISPLAY but it did not help. The GPG command line options do not include a switch for forcing the pinentry to console-mode.

Older GPG versions offered a text-based prompt that worked fine in SSH sessions but after the upgrade it just fails.

There is the --textmode command line switch but apparently, it does something else.

What would be the proper and clean way of getting plain-text pin entry for remote sessions?

ccpizza
  • 7,456
  • 6
  • 54
  • 56

12 Answers12

139

To change the pinentry permanently, append the following to your ~/.gnupg/gpg-agent.conf:

pinentry-program /usr/bin/pinentry-tty

(In older versions which lack pinentry-tty, use pinentry-curses for a 'full-terminal' dialog window.)

Tell the GPG agent to reload configuration:

gpg-connect-agent reloadagent /bye
u1686_grawity
  • 426,297
  • 64
  • 894
  • 966
  • 14
    It's not completely "sane". Normally, `gpg-agent` should itself detect the presence or lack of `$DISPLAY` and choose the apropriate pinentry... – u1686_grawity Dec 19 '12 at 15:00
  • 13
    The agent is most likely capable of detecting the presence of a running xorg. But having a `DISPLAY` defined does not necessarily mean I can or want to use it, for example, when connected over SSH. – ccpizza Dec 19 '12 at 17:34
  • 1
    You are right - I had X11 forwarding enabled. Never thought of the implications, though. Thanks again. – ccpizza Dec 19 '12 at 21:06
  • 1
    For anyone trying this via SSH where you've su/sudoed to the user: That doesn't seem to work at all. If you SSH to the computer as the user though (eg. `ssh the_user@my.host.com` instead of `su - the_user`) the correct pinentry program shows up without trouble. Hope that helps. – lfxgroove Feb 09 '15 at 16:52
  • Kubuntu 14.04 here. I had to first install pinentry-curses (it is a separate package apparently), then set `DISPLAY=''` before this would work. – Asfand Qazi Aug 19 '15 at 09:25
  • 4
    @lfxgroove: the problem is that `su` does not change the ownership of your TTY, so you need to manually `chown` it. See [this article](https://wiki.archlinux.org/index.php/GnuPG#su). – Rufflewind Oct 09 '15 at 16:22
  • 1
    What to do if there is no `~/.gnupg/gpg-agent.conf`? – Starx Dec 08 '16 at 09:43
  • 2
    @Starx: You create one. – u1686_grawity Dec 08 '16 at 10:39
  • @grawity, haha thanks. I tried that already. And I noticed that it does ask a passphrase in a CLI application but not the TTY itself. Is there a way to set `pinentry-program` to use TTY? – Starx Dec 08 '16 at 10:48
  • Use the (recent) `pinentry-tty`. – u1686_grawity Dec 08 '16 at 10:55
  • 4
    Another tip: to view all the available options, type `ls /usr/bin | grep pinentry`. I see `pinentry`, `pinentry-curses`, `pinentry-emacs`, `pinentry-gnome3`, `pinentry-gtk2`, `pinentry-qt` and `pinentry-tty`. This way you can choose the one that suits you better, if you don't have the lack of `$DISPLAY` issue. – Jeffrey Lebowski Jan 10 '17 at 12:56
  • 1
    For those of you who might be getting errrors, make sure to use the absolute path to the pinentry program. (i.e., include `/usr/bin`) It won't work otherwise. – Avindra Goolcharan Jun 24 '17 at 19:11
  • In Ubuntu 16.04, pinentry-tty was available as a package ready to be installed. – Craig Hicks May 01 '18 at 11:48
  • Having done this, I was still getting an error: `gpg: signing failed: Invalid IPC response`. Appending `pinentry-mode loopback` to the `gpg-agent.conf` file fixed it. – irbanana Jul 13 '18 at 13:16
  • 2
    I had to add `export GPG_TTY=$(tty)` to my `~/.bashrc` to get this to work – jaryaman Sep 19 '19 at 15:47
  • Has anyone managed to get this working on Amazon Linux AMI 2018.03 release? pinentry-tty is not available and adding pinentry-curses to gpg-agent.conf has no effect. – Edward Dec 16 '19 at 01:50
  • On my box gnupg agent does not restart with the command above. You need to issure `gpgconf --kill gpg-agent` – Mark Veltzer Jun 28 '21 at 09:51
  • For Solaris refugees: `pinentry-program /usr/lib/pinentry-curses` . I know this is tagged linux, but I could find virtually nothing Solaris specific, and this issue otherwise matches strongly. – Justin Oct 21 '21 at 20:15
31

On a debian box:

sudo apt install pinentry-tty
sudo update-alternatives --config pinentry

(and set it to pinentry-tty)

John Lawrence Aspden
  • 972
  • 2
  • 13
  • 21
15

On Ubuntu 18.04, with the default installation of gpg 2.2.4, I have

/usr/bin/pinentry
/usr/bin/pinentry-gnome3
/usr/bin/pinentry-gtk-2
/usr/bin/pinentry-x11

I was able to do the following to have a text-based PIN entry:

export GPG_TTY=$(tty)
gpg-connect-agent updatestartuptty /bye >/dev/null
Roc W.
  • 295
  • 2
  • 4
  • 2
    That is the right solution and also the official one from `man gpg-agent`, ``` You should always add the following lines to your .bashrc or whatever initialization file is used for all shell invocations: GPG_TTY=$(tty) export GPG_TTY It is important that this environment variable always reflects the output of the tty command. ``` – whhone Apr 11 '22 at 14:19
  • This is the right answer. – Felipe Aug 13 '23 at 01:58
  • It doesn't cover the case when GPG agent is forwarded via SSH. `gpg-connect-agent: connection to agent is in restricted mode`. Maybe correct, but not full answer :-) – 0andriy Aug 23 '23 at 12:10
  • In my case, I'm connecting to a screen session where there is a desktop session running. gpg-agent will refuse to connect to the tty, so you have to stop it with `systemctl --user stop gpg-agent` (and all the associated sockets), and then restart it from the command line with GPG_TTY set. – David Dombrowsky Aug 29 '23 at 17:57
10

I just had this problem on Ubuntu 16.04.3 when trying to generate/install a private key using gpg2 (2.1.11) on a system account without a password, and on a user account over ssh. Nothing worked giving:

gpg: key FE17AE6D/FE17AE6D: error sending to agent: Permission denied
gpg: error building skey array: Permission denied

I then found this which worked for me, so in brief:

pico ~/.gnupg/gpg-agent.conf
# add: allow-loopback-pinentry
gpg-connect-agent reloadagent /bye
gpg2 --pinentry-mode loopback --import private.key
racitup
  • 201
  • 2
  • 2
10

I'll copy my answer from over here...

Looking at man pinentry-gnome3, I see this:

   pinentry-gnome3  implements  a PIN entry dialog based on GNOME 3, which
   aims to follow the GNOME Human Interface Guidelines as closely as  pos‐
   sible.   If the X Window System is not active then an alternative text-
   mode dialog will be used.  There are other flavors that  implement  PIN
   entry dialogs using other tool kits.

Unfortunately, this text-mode fallback doesn't work for me. It seems others have the same issue. However, this comment spurred my to try a different GUI pin-entry program: pinentry-gtk2. You can switch like this:

> sudo update-alternatives --config pinentry
There are 3 choices for the alternative pinentry (providing /usr/bin/pinentry).

  Selection    Path                      Priority   Status
------------------------------------------------------------
* 0            /usr/bin/pinentry-gnome3   90        auto mode
  1            /usr/bin/pinentry-curses   50        manual mode
  2            /usr/bin/pinentry-gnome3   90        manual mode
  3            /usr/bin/pinentry-gtk-2    85        manual mode

Press <enter> to keep the current choice[*], or type selection number: 3
update-alternatives: using /usr/bin/pinentry-gtk-2 to provide /usr/bin/pinentry (pinentry) in manual mode

Once I switched, it worked perfectly for me! In a terminal on the desktop, it will use the GUI password entry, but when I ssh into my machine, it will use a text-mode password entry.

mblythe
  • 411
  • 4
  • 4
  • This is the right answer. The text fallback in pinentry-gnome3 is completely broken, because it'll open up on X11 if there's an X11 session running on the machine even when $DISPLAY is unset. pinentry-gtk2 behaves correctly: it falls back to pinentry-tty if $DISPLAY is unset. – Laurence Gonsalves Oct 12 '21 at 18:50
7

If you don't have it, install pinentry-curses with yum or apt-get.

Then, run:

sudo update-alternatives --config pinentry

And select pinentry-curses from the list.

Aiden Woodruff
  • 171
  • 1
  • 3
5

Not sure which version of GPG this question was originally about. I am using GPG v2.2.19 in (K)ubuntu 20.04 LTS Focal. All I had to add was just --pinentry-mode loopback and it started to ask for a password in TTY. I didn't have to install anything. For example:

gpg --pinentry-mode loopback --export-secret-keys -a | less
Victor Yarema
  • 378
  • 4
  • 7
  • Thanks a lot, and +1. Worked for me immediately in debian Buster, and probably saved a lot of time and hassle compared to the other solutions. – Binarus Jun 05 '23 at 10:51
2

To prevent the pinentry popup you could ssh localhost. Optionally forcing X11 disabled, -x Disables X11 forwarding. See the full example below.

patrick@patrick-C504:~$ ssh localhost
patrick@localhost's password: 
Welcome to Ubuntu 14.04.3 LTS (GNU/Linux 3.13.0-68-generic x86_64)

 * Documentation:  https://help.ubuntu.com/

Last login: Mon Nov 16 22:48:53 2015 from localhost
patrick@patrick-C504:~$ gpg --gen-key
gpg (GnuPG) 1.4.16; Copyright (C) 2013 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection? 4
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 
Requested keysize is 2048 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 
Key does not expire at all
Is this correct? (y/N) y

You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
    "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

Real name: Foo
Name must be at least 5 characters long
Real name: FooBar
Email address: foorbar@foo.bar
Comment: 
You selected this USER-ID:
    "FooBar <foorbar@foo.bar>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
You need a Passphrase to protect your secret key.

gpg: gpg-agent is not available in this session
Enter passphrase:
PvdL
  • 127
  • 3
  • 3
    Which X11 features specifically should be disabled? I personally know the answer to my question, the author does not, so the answer seems incomplete without this information. – Ramhound Nov 17 '15 at 12:26
  • ssh'ing to local host was enough for me, but optionally `-x Disables X11 forwarding.` should prevent any X11 forwarding. Answer is updated. – PvdL Nov 18 '15 at 09:45
  • I prefer this solution, given that pinentry over -X doesn't show up – I'm normally physically at my laptop, where I want X pinentry (so I don't want to edit a conf file all the time), but if I happen to ssh -X into it I might still want a curses pinentry. Of course, ideally, the gtk pinentry would actually work over ssh -X :-/ – unhammer Jun 05 '16 at 13:29
2

If you do export GPG_TTY=$(tty) and unset DISPLAY it will give a TLI dialog box asking for the passphrase. Typing in the correct passphrase makes it decrypt.

If you do NOT do the above export of GPG_TTY and unset of DISPLAY it expects to use X Windows. If you launched your session (such as PuTTY) from an MS-Windows system with X11 forwarding turned on it wants to send the X-Window dialog to your MS Windows system. You can use an X emulator such as Exceed or Cygwin/X on Windows to allow the X-Window prompt for passphrase to appear on your MS-Windows box.

However, you can eliminate the need to set GPG_TTY and unset DISPLAY and getting either the TLI or GUI by running the command line with --batch option and putting the passphrase in with the --passphrase option:

gpg --batch --passphrase "<passphrase>" -o "<decrypted output file name>" --decrypt "<encrypted input file name>"

All 3 methods worked for me today on RHEL6 running gnupg2.

dmb
  • 1,284
  • 9
  • 14
MensaWater
  • 21
  • 1
  • 2
    According to [Roc White’s answer](https://superuser.com/q/520980/150988#1407685), `export GPG_TTY=$(tty)` is sufficient.  Have you tried that?  Do you have a reference that says that `unset DISPLAY` is *also* necessary? P.S. People don’t like to put passphrases on the command line. – Scott - Слава Україні May 30 '19 at 19:24
  • 3
    -1 Putting a password or passphrase as an argument to a command is *never* a good idea as it can be easily seen by other processes that monitor system activity and will likely get recorded into your command history where it will remain for some time.. – SlySven Jun 06 '20 at 00:38
  • For me export  GPG_TTY=$(tty) only was not enough. System used gpg-agent and popped up a GUI window (pinentry-gtk-2 in my case). – reikred Jan 21 '22 at 19:46
1

I found the "full example" in PvdL's answer a bit confusing, here's what I do:

ssh -X machine
# work hack hack work until I need something from gpg
ssh -x localhost -p$port
gpg2 --decrypt file.gpg
# enter password to pinentry
exit
# now the key is unlocked in gpg-agent, and I can keep decrypting files
# from my X ssh session without being asked for the password
unhammer
  • 202
  • 1
  • 13
0

in CentOS 8 you can try :

yum -y install pinentry

Think Big
  • 101
  • 2
0

Simply uninstall pinentry, it has many issues on cli programs. GPG will ask for password on terminal if pinentry is not installed.