#!/usr/bin/env bash # # Re-encrypt files to multiple recipients. # # Load functions LIB="`dirname $0`/../functions" source "$LIB" readwrite $* || exit 1 # Recrypt a single secret function keyringer_recrypt { # Get file keyringer_get_file "$1" # Set recipients file keyringer_set_recipients "$FILE" # Verbosity echo "Processing $FILE..." # Recrypt in stages. This approach will fail for secrets that have NULL bytes, since # bash can't hold those as variables. # # In that case, it would lead to the following warning: # # lib/keyringer/actions/recrypt: line 20: warning: command substitution: ignored null byte in input # # See https://stackoverflow.com/a/42493691 # ## Decrypt #decrypted="$($GPG --use-agent -d "$KEYDIR/$FILE")" #if [ "$?" != "0" ]; then # echo "Decryption error on $1." # exit 1 #fi ## Recrypt #recrypted="`echo "$decrypted" | $GPG --use-agent --armor -e -s $(keyringer_recipients "$RECIPIENTS_FILE")`" #if [ "$?" != "0" ]; then # echo "Recryption error on $1." # exit 1 #fi #unset decrypted #echo "$recrypted" > "$KEYDIR/$FILE" # As we can't use variables as the secret material can contain NULL bytes, we # use a temporary file instead set -o pipefail mkdir -p -m 700 "$TMPWORK/`dirname $FILE`" $GPG --use-agent -d "$KEYDIR/$FILE" | $GPG --use-agent --armor -e -s $(keyringer_recipients "$RECIPIENTS_FILE") -o "$TMPWORK/$FILE.recrypted" if [ "$?" != "0" ]; then echo "Recryption error on $1." if [ -e "$TMPWORK/$FILE.recrypted" ]; then keyringer_shred "$TMPWORK/$FILE.recrypted" fi exit 1 fi # Move the re-encrypted secret only if there was no error mv "$TMPWORK/$FILE.recrypted" "$KEYDIR/$FILE" } # Set a tmp file keyringer_set_tmpfile recrypt -d # Syntax check and dispatcher if [ ! -z "$2" ]; then keyringer_recrypt $2 else cd $KEYDIR && find ./ | while read file; do if [ ! -d "$KEYDIR/$file" ]; then keyringer_recrypt "$file" fi done fi # Cleanup rm -rf "$TMPWORK" trap - EXIT