diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rwxr-xr-x | lib/keyringer/actions/recrypt | 59 |
2 files changed, 52 insertions, 11 deletions
@@ -1,3 +1,7 @@ +2022-08-19 - unreleased - Silvio Rhatto <rhatto@riseup.net> + + Fix re-encryption when the secret hass NULL bytes + 2022-06-07 - 0.5.7 - Silvio Rhatto <rhatto@riseup.net> New upstream URLs diff --git a/lib/keyringer/actions/recrypt b/lib/keyringer/actions/recrypt index 0e2f6a0..5542bfc 100755 --- a/lib/keyringer/actions/recrypt +++ b/lib/keyringer/actions/recrypt @@ -9,33 +9,66 @@ 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" - # Decrypt - decrypted="$($GPG --use-agent -d "$KEYDIR/$FILE")" + # Verbosity + echo "Processing $FILE..." - if [ "$?" != "0" ]; then - echo "Decryption error on $1." - exit 1 - fi + # 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 - # Recrypt - recrypted="`echo "$decrypted" | $GPG --use-agent --armor -e -s $(keyringer_recipients "$RECIPIENTS_FILE")`" + #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 - unset decrypted - echo "$recrypted" > "$KEYDIR/$FILE" + # 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 @@ -46,3 +79,7 @@ else fi done fi + +# Cleanup +rm -rf "$TMPWORK" +trap - EXIT |