Last active
August 29, 2015 14:08
-
-
Save thsutton/00b3a92e7fafbb7f2c64 to your computer and use it in GitHub Desktop.
Edit a GPG encrypted file, maintaining (and extending) multiple recipients
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
#!/bin/sh | |
# | |
# Access a shared secret file. | |
set -eu | |
error() { | |
echo $1 | |
exit 1 | |
} | |
[ 0 -lt $# ] || { | |
cat << EOF | |
Usage: $0 FILE [KEYID] [KEYID] [...] | |
Decrypt and edit FILE, encrypting for the existing recipients and also any new | |
recipients mentioned on the command line. | |
EOF | |
exit 1 ; | |
} | |
SECRET="$1" | |
SHRED=$(which shred) | |
GPG=$(which gpg) | |
MKTEMP=$(which mktemp) | |
VI=$(which vi) | |
[ -z "$EDITOR" ] && EDITOR=$VI | |
# Check the programs we need are available. | |
[ -n "$MKTEMP" ] || error "The mktemp(1) program is missing." | |
[ -n "$GPG" ] || error "The gpg(1) program is missing." | |
[ -n "$SHRED" ] || error "The shred(1) program is missing." | |
[ -n "$EDITOR" ] || error "There is no editor configured." | |
# Check that the secret file exists and is encrypted in the format we expect. | |
[ -f "$SECRET" ] || error "The secret file '$SECRET' does not exist." | |
grep -q -- "^-----BEGIN PGP MESSAGE-----" "$SECRET" || \ | |
error "The secret file is not encrypted." | |
# Extract the header and footer so we can put them back later. | |
HEADER=$(cat "$SECRET" | sed -e '/^-----BEGIN PGP MESSAGE-----$/,$d') | |
FOOTER=$(cat "$SECRET" | sed -e '1,/^-----END PGP MESSAGE-----$/d') | |
# List the recipients | |
RECIPIENTS=$(cat "$SECRET" \ | |
| $GPG --batch --armor --decrypt --list-only --status-fd 1 2> /dev/null \ | |
| awk '/^\[GNUPG:\] ENC_TO / { print "-r",$3 }' \ | |
) | |
# Check there actually are some recipients. | |
[ -n "$RECIPIENTS" ] || \ | |
error "There are no recipients." | |
# Add any new recipients from the command line. | |
shift | |
for addition in $*; do | |
RECIPIENTS="$RECIPIENTS -r $addition" | |
done | |
# TODO: Check that public keys for all recipients are available in the | |
# keychain. | |
# TODO: Check that public keys for all recipients are signed by a trusted key. | |
# Do something really shitty. | |
PLAIN=$($MKTEMP /tmp/secret.XXXXXXXXXX) | |
trap 'echo "Removing decrypted $PLAIN file." && rm -f "$PLAIN"' INT TERM EXIT | |
$GPG --armor --decrypt "$SECRET" > "$PLAIN" | |
# Let the user edit the file. | |
echo "Editing $PLAIN; in case of error shred(1) and rm(1) this yourself!" > /dev/stderr | |
$EDITOR "$PLAIN" | |
# Now re-encrypt for the same recipients it already had. | |
cp "${SECRET}" "${SECRET}.bak" | |
echo "$HEADER" > "${SECRET}" | |
$GPG --armor --encrypt $RECIPIENTS < "$PLAIN" >> "${SECRET}" | |
echo "$FOOTER" >> "${SECRET}" | |
# Shred and delete the temporary file. | |
$SHRED "$PLAIN" | |
rm -f "$PLAIN" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment