Skip to content

Instantly share code, notes, and snippets.

@davidlj95
Created July 2, 2022 03:43
Show Gist options
  • Save davidlj95/62efea859cfd932c7d0dbe2e8ad433b1 to your computer and use it in GitHub Desktop.
Save davidlj95/62efea859cfd932c7d0dbe2e8ad433b1 to your computer and use it in GitHub Desktop.
Helps fixing a GPG paperkey using checksums & vim
#!/bin/bash
#
# So you have backed up your GPG key using paperkey, and have scanned it
# using OCR techniques. However, it's not perfect and some checksums do not match
# Some 8s are Bs, 0s are Os... This script will try to spot errors so you
# can compare those lines and fix them
#
# Given a secret key exported using paperkey, tries to decode it.
#
# In case a CRC checksum wrong is found, a vim editor will be opened
# in the line that requires a fix. When a change is done in the file,
# it will be checked again, and if line being fixed is correct, will
# move automatically to next line until all lines are cleared
#
# The public key is needed too. You can fetch it using:
#
# gpg --recv-keys <id>
# gpg --export > public-key.gpg
#
# After having a proper secret key file, import your secret key using:
# paperkey --pubring public-key.gpg --secrets secret-key.asc | gpg --import
#
# More info:
# https://wiki.archlinux.org/title/Paperkey#Restore_secret_key
# Paperkey tool needed
if ! command -v paperkey > /dev/null 2>&1; then
>&2 echo "❌ paperkey is not installed"
exit 1
fi
# Usage
function print_usage_and_exit() {
>&2 echo "Usage:"
>&2 echo "./fix-paperkey.sh <secret_key_file> <public_key_file>"
>&2 echo "[--no-auto] [--pause]"
>&2 echo ""
>&2 echo "--no-auto: does not save & check the file again after each edit"
>&2 echo "--pause: pause to indicate which line is failing before entering editor"
exit 1
}
# Args
if [ $# -lt 2 ]; then
>&2 echo "❌ Not enough arguments"
print_usage_and_exit
fi
secret_key_file="$1"
if ! [ -r "$secret_key_file" ]; then
>&2 echo "❌ Secret key file '$secret_key_file' not readable"
exit 1
fi
shift
public_key_file="$1"
if ! [ -r "$public_key_file" ]; then
>&2 echo "❌ Public key file '$public_key_file' not readable"
exit 1
fi
shift
auto="true"
pause=""
while [[ $# -gt 0 ]]; do
case "$1" in
--no-auto)
auto=""
shift
;;
--pause)
pause="true"
shift
;;
*)
>&2 echo "❌ Unknown argument '$1'"
print_usage_and_exit
;;
esac
done
# Remove # / empty lines to jump to line
sed -i.bak '/^#/d' "$secret_key_file"
sed -i.bak '/^[[:space:]]*$/d' "$secret_key_file"
rm "$secret_key_file.bak"
last_error_line=0
while ! error=$((\
paperkey --pubring "$public_key_file" --secrets "$secret_key_file" \
) 2>&1); do
# Parse error message and retrieve failing line (or quit if not CRC error)
error_regexp='CRC on line ([0-9]+) does not match \(([A-F0-9]{6}\!\=[A-F0-9]{6})\)'
if [[ $error =~ $error_regexp ]]; then
error_line="${BASH_REMATCH[1]}"
error_crc_mismatch="${BASH_REMATCH[2]}"
>&2 echo "ℹ️ CRC Error detected on line $error_line ($error_crc_mismatch)"
else
>&2 echo "❌ Unknown error:"
>&2 echo "$error"
exit 1
fi
# Open Vim where something needs to be fixed + highlight line being edited + autosave & quit every change
if [ "$pause" = "true" ]; then
>&2 echo "⌨️ Press a key to enter the editor and fix it"
read
fi
vim \
-c 'set cursorline' \
+$error_line \
${auto:+-c 'autocmd TextChanged,TextChangedI *.* wq'} \
"$secret_key_file"
# Transform file to uppercase
# Doing it this way as can't do it with sed in BSD
# https://stackoverflow.com/a/18298422
tmpfile="$(mktemp)"
cat "$secret_key_file" | tr '[:lower:]' '[:upper:]' > "$tmpfile"
mv -f "$tmpfile" "$secret_key_file"
done
echo "✅ All good"
@davidlj95
Copy link
Author

RESERVED

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment