Last active
December 17, 2018 10:14
-
-
Save mafredri/96af39be4fb2977081dfce7989a7c2c7 to your computer and use it in GitHub Desktop.
gpg-yubikey-sign: Sign Git commits with any of your valid GPG subkeys
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env zsh | |
# gpg-yubikey-sign | |
# | |
# This script lets you use any of your unexpired subkeys connected to | |
# your public key (0xDEADBEEFCAFEBAAD) to sign git commits. It will also | |
# display "Waiting for YubiKey touch..." to remind you that an action is | |
# required. | |
# | |
# Add this script to your PATH and configure git to use it for gpg | |
# signing. | |
# | |
# git config --global user.signingkey 0xDEADBEEFCAFEBAAD | |
# git config --global gpg.program gpg-yubikey-sign | |
emulate -R zsh | |
setopt err_exit | |
typeset -a ARGS=("$@") | |
# Only use this script for signing. | |
if [[ $* != *" -bsau"* ]]; then | |
exec gpg $ARGS | |
fi | |
KEYID=$ARGS[-1] | |
EPOCH=$(date +%s) | |
# This creates a string of all your available subkeys | |
# and their expiry dates. | |
typeset -a SUBKEYS | |
typeset -A SUBKEYS_WITH_EXPIRY | |
SUBKEYS_WITH_EXPIRY=($( | |
gpg --with-colons --list-keys $KEYID \ | |
| grep -E "^sub:u:4096:1:[^:]+:[^:]+:[^:]+:"::::s::::::23: \ | |
| cut -d: -f5,7 \ | |
| tr ':' ' ' | |
)) | |
for key expiry in ${(kv)SUBKEYS_WITH_EXPIRY}; do | |
# Only include subkeys that have not expired. | |
if (( expiry > EPOCH )); then | |
SUBKEYS+=($key) | |
fi | |
done | |
if (( $#SUBKEYS == 0 )); then | |
echo "error: no unexpired subkeys available for $KEYID" >>$TTY | |
exit 1 | |
fi | |
SUBKEYS_JOINED="${(j:|:)SUBKEYS}" | |
CARD=$( | |
gpg --with-colons --card-status \ | |
| grep -E "^fpr:[^:]+(${SUBKEYS_JOINED}):" \ | |
| cut -d: -f2 | |
) | |
if [[ $CARD = "" ]]; then | |
echo "error: no card matching subkeys connected for $KEYID" >>$TTY | |
exit 1 | |
fi | |
# Replace key in arguments and force subkey via !. | |
ARGS[-1]="$CARD!" | |
if [[ $GIT_REFLOG_ACTION = rebase* ]]; then | |
# Write a newline to prevent overwriting text (Rebasing (X/Y)). | |
echo -n $'\nWaiting for YubiKey touch...' > $TTY | |
gpg $ARGS | |
RET=$? | |
# Move cursor to position 1, erase line (Waiting...) and move cursor one | |
# line up so that Git can continue where it left of. | |
echo -n $'\e[1G\e[K\e[1A' > $TTY | |
exit $RET | |
fi | |
echo -n $'Waiting for YubiKey touch...' > $TTY | |
gpg $ARGS | |
RET=$? | |
# Move cursor to position 1 and erase the rest of the line. | |
echo -n $'\e[1G\e[K' > $TTY | |
exit $RET |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment