Skip to content

Instantly share code, notes, and snippets.

@mdaniel
Created December 19, 2022 20:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mdaniel/05d50578841fef94b1511148656da0e2 to your computer and use it in GitHub Desktop.
Save mdaniel/05d50578841fef94b1511148656da0e2 to your computer and use it in GitHub Desktop.
Implement the pinentry Assuan protocol backed by the 1Password op binary
#!/usr/bin/env bash
__log=$HOME/op-pinentry.$$.txt
# { set; printenv; echo "ARGV=$*"; } &>"$__log"
# exec 2>>"$__log"
# set -x
# if we are not running under gpg-agent, that is fatal
if [[ -z "$_assuan_pipe_connect_pid" ]]; then
exit 143
fi
# tell them we're here
printf 'OK\n'
# this will be set by the SETKEYINFO command and is the SETKEYINFO _without_ the leading "n/"
GPG_KEY_ID=''
# one will want to be aware of the printf format fed into "op read"
# and either adjust to your setup or rename your Password entry to that scheme
# -r = backslashes mean nothing
while read -r ASSUAN
do
# printf 'READ<<%s>>\n' "$ASSUAN" &>>"$__log"
if [[ "$ASSUAN" == BYE ]]; then
printf 'OK\n'
break
fi
if [[ "$ASSUAN" == SETKEYINFO* ]]; then
GPG_KEY_ID=$(expr "$ASSUAN" : 'SETKEYINFO n/\(.*\)')
if [[ -z "$GPG_KEY_ID" ]]; then
printf 'ERR malformed SETKEYINFO\n'
continue
elif [[ "x$GPG_KEY_ID" == x0 ]]; then
printf 'ERR expected SETKEYINFO to lead with n/\n'
continue
fi
printf 'OK\n'
continue
fi
if [[ "$ASSUAN" == "GETPIN" ]]; then
if [[ -z "$GPG_KEY_ID" ]]; then
printf 'ERR not without SETKEYINFO\n'
continue
fi
printf 'D '
# there won't be any CR or LF but could be %
# op read has an implicit "\n" on its output
op read "$(printf 'op://Private/gpg key %s/password' "$GPG_KEY_ID")" | sed 's,%,%25,g'
printf 'END\n'
printf 'OK\n'
continue
fi
# shrug
printf 'OK\n'
done
exit 0
# https://gnupg.org/documentation/manuals/assuan/Server-responses.html#Server-responses
# https://gnupg.org/documentation/manuals/assuan/Client-requests.html#Client-requests
# https://github.com/gpg/pinentry/blob/pinentry-1.1.1/doc/pinentry.texi#L494-L503
: <<'EXAMPLE'
ARGV=--display :1
READ<<OPTION no-grab>>
READ<<OPTION ttyname=/dev/pts/3>>
READ<<OPTION ttytype=xterm-256color>>
READ<<OPTION lc-ctype=en_US.UTF-8>>
READ<<OPTION lc-messages=en_US.UTF-8>>
READ<<OPTION allow-external-password-cache>>
READ<<OPTION default-ok=_OK>>
READ<<OPTION default-cancel=_Cancel>>
READ<<OPTION default-yes=_Yes>>
READ<<OPTION default-no=_No>>
READ<<OPTION default-prompt=PIN:>>
READ<<OPTION default-pwmngr=_Save in password manager>>
READ<<OPTION default-cf-visi=Do you really want to make your passphrase visible on the screen?>>
READ<<OPTION default-tt-visi=Make passphrase visible>>
READ<<OPTION default-tt-hide=Hide passphrase>>
READ<<OPTION touch-file=/run/user/1000/gnupg/S.gpg-agent>>
READ<<OPTION owner=1122334 alice>>
READ<<GETINFO flavor>>
READ<<GETINFO version>>
READ<<GETINFO ttyinfo>>
READ<<GETINFO pid>>
READ<<SETKEYINFO n/CAFEBABEDEADBEEF000011112222333344445555>>
READ<<SETDESC Please enter the passphrase to unlock the OpenPGP secret key:%0A%22Alice Cryptographer <alice@example.com>%22%0A>>
READ<<SETPROMPT Passphrase:>>
READ<<GETPIN>>
READ<<BYE>>
EXAMPLE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment