Skip to content

Instantly share code, notes, and snippets.

@acdvorak
Last active January 8, 2019 21:49
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 acdvorak/cbd28c85b87e2b57f0a9f01f0a016092 to your computer and use it in GitHub Desktop.
Save acdvorak/cbd28c85b87e2b57f0a9f01f0a016092 to your computer and use it in GitHub Desktop.
GPG signing for Git commits and tags
#!/bin/bash
# Set this value to `1` to test the script in a temporary directory
# without making any permanent global changes.
DRY_RUN=1
GLOBAL_GIT_FLAGS=()
if [[ "$DRY_RUN" == 1 ]]; then
export GNUPGHOME="$(mktemp -d)"
cd "$GNUPGHOME"
git init .
else
GLOBAL_GIT_FLAGS+=( --global )
fi
# macOS GPG Suite (https://gpgtools.org/)
# From https://gist.github.com/danieleggert/b029d44d4a54b328c0bac65d46ba4c65
if [[ -f /usr/local/MacGPG2/bin/gpg2 ]]; then
git config "${GLOBAL_GIT_FLAGS[@]}" gpg.program /usr/local/MacGPG2/bin/gpg2
mkdir -p ~/.gnupg
if ! grep 'pinentry-program' ~/.gnupg/gpg-agent.conf > /dev/null 2> /dev/null; then
echo 'pinentry-program /usr/local/MacGPG2/libexec/pinentry-mac.app/Contents/MacOS/pinentry-mac' >> ~/.gnupg/gpg-agent.conf
fi
fi
GIT_GPG_PROGRAM=$(git config gpg.program)
[[ -f "$GIT_GPG_PROGRAM" ]] && GPG_CMD="$GIT_GPG_PROGRAM" || GPG_CMD='gpg'
# NOTE: Name and email must match git config values EXACTLY and have NO comment.
# If the values differ, you will need to run
# `git config --global user.signingkey "$KEY_ID"`
# to avoid getting an error message when you try to commit.
# From https://www.gnupg.org/documentation/manuals/gnupg/Unattended-GPG-key-generation.html
cat > /tmp/gpg-commands.txt <<EOF
%echo Generating a GPG key...
Key-Type: RSA
Key-Length: 4096
Name-Real: $(git config user.name)
Name-Email: $(git config user.email)
Expire-Date: 0
# Do a commit here, so that we can later print "done" :-)
%commit
%echo Done!
EOF
echo
"$GPG_CMD" --batch --generate-key /tmp/gpg-commands.txt
echo
"$GPG_CMD" --list-secret-keys --keyid-format LONG
echo
KEY_ID=$("$GPG_CMD" --list-secret-keys --keyid-format LONG | grep '^sec' | sed -E 's%^sec +[a-z]+[0-9]+/([a-zA-Z0-9]+).*%\1%')
if [[ -z "$KEY_ID" ]]; then
echo 'ERROR: GPG key not generated' >&2
exit 1
fi
"$GPG_CMD" --armor --export "$KEY_ID"
echo
echo 'Copy the ENTIRE public key above, and paste it into https://github.com/settings/gpg/new'
echo
git config "${GLOBAL_GIT_FLAGS[@]}" commit.gpgsign true
git config "${GLOBAL_GIT_FLAGS[@]}" tag.forceSignAnnotated true
git config "${GLOBAL_GIT_FLAGS[@]}" user.signingkey "$KEY_ID"
# I don't think setting GPG_TTY is necessary, but I'm leaving this here
# just in case.
# From https://help.github.com/articles/telling-git-about-your-signing-key/:
#
# ```bash
# test -r ~/.bash_profile && echo 'export GPG_TTY=$(tty)' >> ~/.bash_profile
# echo 'export GPG_TTY=$(tty)' >> ~/.profile
# ```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment