Skip to content

Instantly share code, notes, and snippets.

@kevinoid
Created July 31, 2019 16:31
Show Gist options
  • Save kevinoid/189a0168ef4ceae76ed669cd696eaa37 to your computer and use it in GitHub Desktop.
Save kevinoid/189a0168ef4ceae76ed669cd696eaa37 to your computer and use it in GitHub Desktop.
GnuPG pinentry script for terminal or graphical interface based on $PINENTRY_USER_DATA.
# ~/.bashrc: executed by bash(1) for non-login shells.
# If file exists (likely) copy fragment below into existing script:
# If stdin is a terminal
if [ -t 0 ]; then
# Set GPG_TTY so gpg-agent knows where to prompt. See gpg-agent(1)
export GPG_TTY="$(tty)"
# Set PINENTRY_USER_DATA so pinentry-auto knows to present a text UI.
export PINENTRY_USER_DATA=USE_TTY=1
fi
# gpg-agent configuration. Usually ~/.gnupg/gpg-agent.conf. See gpg-agent(1).
# Use pinentry-auto script as the pinentry program.
pinentry-program /path/to/pinentry-auto
#!/bin/sh
# Choose between pinentry-tty and pinentry-x11 based on whether
# $PINENTRY_USER_DATA contains USE_TTY=1
#
# Based on:
# https://kevinlocke.name/bits/2019/07/31/prefer-terminal-for-gpg-pinentry
#
# Note: Environment detection is difficult.
# - stdin is Assuan pipe, preventing tty checking
# - configuration info (e.g. ttyname) is passed via Assuan pipe, preventing
# parsing or fallback without implementing Assuan protocol.
# - environment is sanitized by atfork_cb in call-pinentry.c (removing $GPG_TTY)
#
# $PINENTRY_USER_DATA is preserved since 2.08 https://dev.gnupg.org/T799
#
# Format of $PINENTRY_USER_DATA not specified (that I can find), pinentry-mac
# assumes comma-separated sequence of NAME=VALUE with no escaping mechanism
# https://github.com/GPGTools/pinentry-mac/blob/v0.9.4/Source/AppDelegate.m#L78
# and recognizes USE_CURSES=1 for curses fallback
# https://github.com/GPGTools/pinentry-mac/pull/2
#
# To the extent possible under law, Kevin Locke <[email protected]> has
# waived all copyright and related or neighboring rights to this work
# under the terms of CC0: https://creativecommons.org/publicdomain/zero/1.0/
set -Ceu
# Use pinentry-tty if $PINENTRY_USER_DATA contains USE_TTY=1
case "${PINENTRY_USER_DATA-}" in
*USE_TTY=1*)
# Note: Change to pinentry-curses if a Curses UI is preferred.
exec pinentry-tty "$@"
;;
esac
# Otherwise, use any X11 UI (configured by Debian Alternatives System)
# Note: Will fall back to curses if $DISPLAY is not available.
exec pinentry-x11 "$@"
@boxofrox
Copy link

Just found your blog post for this method. Many thanks for sharing this!

@salewski
Copy link

salewski commented Feb 9, 2020

Very nice. Thanks for sharing this, and also for the great write-up in your blog post.

@kevsestrella
Copy link

awesome, this worked for my problem of using pinentry-tty in terminal and pinentry from browserpass(chrome browser for pass).

@stacyharper
Copy link

I think I found a bug. For a reason I dunno, using a gpg command from GUI then from bash_profile session work (graphical pinentry then curse pinentry) BUT using a bash_profile session then a GUI one doest not (curse pinentry then curse pinentry). It looks like the PINENTRY_USER_DATA var is conserved on the GUI session (where I dont have the var).

@shanness
Copy link

This seems much simpler

#!/bin/sh
tty -s && exec pinentry-tty "$@" || exec pinentry-x11 "$@"

@kevinoid
Copy link
Author

@shanness Good idea. Unfortunately, it won't work because stdin is the Assuan pipe, not a TTY, so tty -s will always exit non-zero.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment