GPG with a keybase user's public key
#!/bin/bash | |
set -Eeu -o pipefail | |
# Runs `gpg` with a keybase user's public key as the recipient. | |
# First argument is keybase username. Remaining arguments are passed to gpg -r xxx … | |
die() { | |
echo "$@" >&2 | |
exit 127 | |
} | |
# Prints the GPG public key(s) of a keybase username | |
get_keybase_gpgkey() { | |
set -Eeu -o pipefail | |
curl --silent -L "https://keybase.io/_/api/1.0/user/lookup.json?usernames=${1}&fields=public_keys" \ | |
| jq -er '.them[] | .public_keys.primary.bundle' \ | |
; | |
} | |
# Prints each UID in a GPG keyfile, one per line | |
list_keyfile_uids() { | |
set -Eeu -o pipefail | |
gpg --list-packets "${1}" \ | |
| sed -n -E 's/^:user ID packet: "(.*)"$/\1/p' \ | |
; | |
} | |
[ $# -ge 1 ] || die "This script requires exactly one argument: a keybase username" | |
_kbun="${1}" | |
shift | |
_to_delete=() | |
cleanup() { | |
[ ${#_to_delete[@]} -eq 0 ] || rm -rf "${_to_delete[@]}" | |
} | |
trap cleanup EXIT | |
_key_asc="$(mktemp -t key.XXX.asc)" | |
_to_delete+=("${_key_asc}") | |
get_keybase_gpgkey "${_kbun}" > "${_key_asc}" || die "Failed to get GPG key for ${_kbun}" | |
_user_id="$(list_keyfile_uids "${_key_asc}" | head -n 1)" | |
[ -n "${_user_id}" ] || echo "Invalid user IDs for GPG key of keybase user ${_kbun}" | |
echo "Encrypting for ${_user_id}" >&2 | |
_keyring="$(mktemp -t keyring.XXX)" | |
_to_delete+=("${_keyring}") | |
gpgt() { | |
# Runs GPG with temp keyring, suppressing stderr unless an actual error occurs. | |
set -Eeu -o pipefail | |
local _stat _err | |
exec 3>&1 | |
set +Ee | |
_err="$(gpg --no-default-keyring --keyring "${_keyring}" --trust-model always "$@" 2>&1 1>&3)" | |
_stat=$? | |
set -Ee | |
exec 3>&- | |
[ ${_stat} -eq 0 ] || printf %s "${_err}" >&2 | |
return ${_stat} | |
} | |
gpgt --import "${_key_asc}" || die "Failed to import GPG key of keybase user ${_kbun}" | |
gpgt -r "${_user_id}" "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment