dotfiles/.bin/gpgfile.sh
2024-12-13 09:10:05 +01:00

138 lines
4.1 KiB
Bash
Executable File

#!/bin/sh
# for shellrc:
# alias encrypt-kasse="gpgfile.sh -k 52BE43BA -k 7A97EAD5 -k 8AFDAD2D -e /path/to/kassenbuch.odt"
# alias decrypt-kasse="gpgfile.sh -d -e /path/to/kassenbuch.odt.gpg"
# alias encrypt-documents="gpgfile.sh -k 7A97EAD5 -e /path/to/documents"
# alias decrypt-documents"gpgfile.sh -d -e /path/to/documents.tar.gpg"
### functions
usage() {
echo "usage: $(basename $0) <options> <files/dirs>"
echo "options:"
echo " -k <key_id> key id (can be supplied multiple times)"
echo " -e encrypt files or directories (requires -k)"
echo " -d decrypt files or directories"
echo "note: directories will be wrapped in tar(1)"
exit 2
}
### main program
# parse arguments
while getopts 'k:edh' arg
do
case ${arg} in
k) keylist="$keylist -r $OPTARG" ;;
e) encrypt=1 ;;
d) encrypt=0 ;;
h) usage ;;
?) usage ;;
esac
done
# shift parsed arguments out of the way $1 starts now with files/dirs
shift $(($OPTIND - 1))
# print usage, if no file/dir argument is provided
[ -z "$1" ] \
&& echo "ERROR: No files/dirs argument provided." \
&& usage
# print usage, if no option argument was provided
[ "$OPTIND" == "1" ] \
&& echo "ERROR: No option provided (needs -d, or -e and -k)" \
&& usage
### handle encryption (set by -e)
if [ "$encrypt" -eq "1" ]
then
# no key?
[ -z "$keylist" ] \
&& echo "ERROR: Encryption mode (-e) needs a key (-k), which was not provided." \
&& exit 1
# loop at provided files
for item in "$@"
do
# Work in a subshell so dir changes won't be persistent.
# Due to this, we "return" instead of "continue".
# This is needed because we don't want to include the
# basedir hierarchy in tar files.
(
# change working directory
cd "$(dirname "$item")"
item="$(basename "$item")"
# don't handle non existant files
readlink -f "$item" > /dev/null 2>&1 \
|| { echo "$item: skipped: file not found" \
&& return; }
# don't re-encrypt gpg files
[ "${item##*.}" == "gpg" ] \
&& echo "$item: skipped: already gpg encrypted" \
&& return
# handle directory: tar + gpg, then remove original dir + tar
[ -d "$item" ] \
&& echo "$item -> $item.tar" \
&& tar -cf "$item.tar" "$item" \
&& rm -rf "$item" \
&& item="$item.tar"
# no return: fallthrough to next handler
# handle files: gpg, then remove original file
[ -f "$item" ] \
&& echo "$item -> $item.gpg" \
&& gpg -q -e $keylist -o "$item.gpg" "$item" \
&& rm -f "$item"
) # exit subshell
done
fi
### handle decryption (set by -d)
if [ $encrypt -eq 0 ]
then
for item in "$@"
do
# Work in a subshell so dir changes won't be persistent.
# Due to this, we "return" instead of "continue".
# This is needed because we don't want to include the
# basedir hierarchy in tar files.
(
# change working directory
cd "$(dirname "$item")"
item="$(basename "$item")"
# don't handle non existant files
readlink -f "$item" > /dev/null 2>&1 \
|| { echo "skipping: $item (reason: file not found)" \
&& return; }
# don't handle files that are not gpg encrypted
[ "${item##*.}" != "gpg" ] \
&& echo "skipping: $item (reason: not a gpg file)" \
&& return
# handle file: decrypt with gpg + delete encrypted version
[ "${item##*.}" == "gpg" ] \
&& echo "$item -> ${item%.*}" \
&& gpg -q -d -o "${item%.*}" "$item" \
&& rm -f "$item" \
&& item="${item%.*}"
# no return: fallthrough to next handler
# handle tar: if file ends in tar after decryption, untar it and delete the tar.
[ "${item##*.}" == "tar" ] \
&& echo "$item -> ${item%.*}" \
&& tar xf "$item" \
&& rm -f "$item"
) # exit subshell
done
fi