git signing signify

down with GPG!

SEAN K.H. LIAO

git signing signify

down with GPG!

git signing

Ah, git, well known for its not very friendly ux, integrates with another piece of software that is also often derided for having bad ux, namely gpg.

So you can sign tags, sign commits, and verify them. But who wants to use GPG? Why not use something else like minisign or signify or SSH keys?

Well you can, sort of. Git right now hardcodes some GPG stuff so you need to work around it. Specifically it expects an out of band communication channel --status-fd=X for getting notified of [GNUPG:] SIG_CREATED, [GNUPG:] GOODSIG, [GNUPG:] BADSIG and while you can return any text as the signature for the signing operations, the verifying operations will look for a -----BEGIN/END PGP SIGNATURE----- block that it can extract before the verifying program is called.

Note: if you do this, it is unlikely that anyone else will be able to parse/verify your signatures and forget about it working in Github/etc.

So what you can do is smuggle your signature in the block and write to the status fd as appropriate. This is an ugly hack because you will need those fake PGP lines, but you can put whatever inside. This is demonstrated in a script by Leah Neukirchen replicated below.

 1#!/bin/sh
 2# git-signify [GIT COMMAND] - use git with signify(1)
 3#
 4# First, you need to set the signing key for the repo, e.g.
 5#   git config --local user.signingKey ~/.signify/cwm
 6# This will use cwm.sec and cwm.pub.
 7#
 8# Then you can use
 9#   gpg signify commit -S
10#   gpg signify verify-commit
11#
12#   gpg signify tag -s
13#   gpg signify verify-tag
14#
15# You also can set this script as "gpg.program" to use signify
16# automatically.
17#
18# To the extent possible under law, Leah Neukirchen has waived
19# all copyright and related or neighboring rights to this work.
20# http://creativecommons.org/publicdomain/zero/1.0/
21
22getkey() {
23    key=$(git config user.signingKey)
24    if [ -z "$key" ]; then
25        echo "git-signify: no user.signingKey defined!" 1>&2
26        exit 7
27    fi
28}
29
30while :; do
31case "$1" in
32-bsau)
33    getkey
34    echo "-----BEGIN PGP SIGNATURE----- (really git-signify)"
35    {
36        signify -S -s "$key.sec" -m - -x -
37        if [ $? -eq 0 ] && [ -n "$statusfd" ]; then
38            printf '\n[GNUPG:] SIG_CREATED ' >/dev/fd/$statusfd
39        fi
40    } | sed "s/: .*/: verify with git-signify and ${key##*/}.pub/"
41    echo "-----END PGP SIGNATURE-----"
42    exit 0
43    ;;
44--verify)
45    getkey
46    sed -i '/-----.* PGP SIGNATURE-----/d' "$2"
47    if signify -V -p "$key.pub" -m - -x "$2" 1>&2; then
48        echo "[GNUPG:] GOODSIG "
49        exit 0
50    else
51        r=$?
52        echo "[GNUPG:] BADSIG "
53        exit $r
54    fi
55    ;;
56--status-fd=*)
57    statusfd=${1#--status-fd=}
58    shift
59    ;;
60--*)
61    # ignore all other arguments
62    shift
63    ;;
64*)
65    exec git -c "gpg.program=$0" "$@"
66    ;;
67esac
68done