#!/bin/bash
+umask 077
+
+hashes=(sha sha1 mdc2 ripemd160 sha224 sha256 sha384 sha512 md4 md5 dss1)
+hash_dir=$(mktemp -d)
+
function die() {
echo "$*" >&2
exit 1
openssl_decrypt="-d"
fi
+function verify_hash() {
+ (( $(wc -l < "$1") == 2 && $(uniq "$1" | wc -l) == 1 ))
+}
+
function go() {
layer=$1
if (( layer == 0 || layer > num_layers ));then
-pass fd:37 37< <(sed -rn "${layer}s/^[^ ]+ [^ ]+ //p" "$keyfile")
elif [[ "$operation" == reverse ]];then
reverse
+ elif [[ "$operation" == openssl-dgst ]];then
+ tee >(sed -rn "${layer}s/^[^ ]+ [^ ]+ //p" "$keyfile" > "$hash_dir/$layer"
+ openssl dgst -binary "-$(sed -rn "${layer}s/[^ ]+ ([^ ]+) .*/\\1/p" "$keyfile")" |
+ base64 --wrap=0 | sed 's/$/\n/' >> "$hash_dir/$layer"
+ # Dying here doesn't terminate the pipeline. :(
+ verify_hash "$hash_dir/$layer" || die "Hash check $layer failed" )
else
die "Unknown operation"
fi |
fi
}
-go "$first_layer"
+function record_hashes() {
+ if [[ "$mode" == d ]] || (( $# < 2 ));then
+ cat
+ else
+ stage=$1
+ hash=$2
+ shift 2
+ tee >(openssl dgst -binary "-$hash" | base64 --wrap=0 |
+ sed "s/^/openssl-dgst $hash /;s/$/\n/" > "$hash_dir/$stage-$hash") |
+ record_hashes "$stage" "$@"
+ fi
+}
+
+record_hashes inner "${hashes[@]}" | go "$first_layer" | record_hashes outer "${hashes[@]}"
+
+if [[ "$mode" == e ]];then
+ # Add the hashes to keyfile
+ key_aside_dir=$(mktemp -d "$keyfile.XXXXXXXXXX")
+ key_aside="$key_aside_dir/key.orig"
+ mv "$keyfile" "$key_aside"
+ cat "$hash_dir"/outer-* "$key_aside" "$hash_dir"/inner* > "$keyfile"
+ shred -u "$key_aside"
+ rmdir "$key_aside_dir"
+else
+ # Verify the hashes
+ for hash_result in "$hash_dir"/*;do
+ verify_hash "$hash_result" || die "Hash check $(basename "$hash_result") failed"
+ done
+fi
+
+rm -r "$hash_dir"