]> git.scottworley.com Git - overonion/blob - overonion
Add hashing
[overonion] / overonion
1 #!/bin/bash
2
3 umask 077
4
5 hashes=(sha sha1 mdc2 ripemd160 sha224 sha256 sha384 sha512 md4 md5 dss1)
6 hash_dir=$(mktemp -d)
7
8 function die() {
9 echo "$*" >&2
10 exit 1
11 }
12
13 if (( $# != 2));then
14 die "usage: overonion e|d keyfile"
15 fi
16 mode=$1
17 if [[ "$mode" != e && "$mode" != d ]];then
18 die "Use 'e' for encrypt or 'd' for decrypt"
19 fi
20 keyfile=$2
21 if [[ ! -e "$keyfile" ]];then
22 die "Keyfile not found"
23 fi
24 if [[ ! -r "$keyfile" ]];then
25 die "Cannot read keyfile"
26 fi
27
28 num_layers=$(wc -l < "$keyfile")
29 if (( num_layers < 20 ));then
30 die "Keyfile doesn't have enough layers to be an onion"
31 fi
32
33 if [[ "$mode" == e ]];then
34 first_layer=$num_layers
35 next_layer=-1
36 openssl_decrypt=""
37 else
38 first_layer=1
39 next_layer=1
40 openssl_decrypt="-d"
41 fi
42
43 function verify_hash() {
44 (( $(wc -l < "$1") == 2 && $(uniq "$1" | wc -l) == 1 ))
45 }
46
47 function go() {
48 layer=$1
49 if (( layer == 0 || layer > num_layers ));then
50 cat
51 else
52 operation=$(sed -n "${layer}{;s/ .*//;p;}" "$keyfile")
53 if [[ "$operation" == openssl-enc ]];then
54 openssl enc $openssl_decrypt "-$(sed -rn "${layer}s/[^ ]+ ([^ ]+) .*/\\1/p" "$keyfile")" \
55 -pass fd:37 37< <(sed -rn "${layer}s/^[^ ]+ [^ ]+ //p" "$keyfile")
56 elif [[ "$operation" == reverse ]];then
57 reverse
58 elif [[ "$operation" == openssl-dgst ]];then
59 tee >(sed -rn "${layer}s/^[^ ]+ [^ ]+ //p" "$keyfile" > "$hash_dir/$layer"
60 openssl dgst -binary "-$(sed -rn "${layer}s/[^ ]+ ([^ ]+) .*/\\1/p" "$keyfile")" |
61 base64 --wrap=0 | sed 's/$/\n/' >> "$hash_dir/$layer"
62 # Dying here doesn't terminate the pipeline. :(
63 verify_hash "$hash_dir/$layer" || die "Hash check $layer failed" )
64 else
65 die "Unknown operation"
66 fi |
67 go $(( layer + next_layer ))
68 fi
69 }
70
71 function record_hashes() {
72 if [[ "$mode" == d ]] || (( $# < 2 ));then
73 cat
74 else
75 stage=$1
76 hash=$2
77 shift 2
78 tee >(openssl dgst -binary "-$hash" | base64 --wrap=0 |
79 sed "s/^/openssl-dgst $hash /;s/$/\n/" > "$hash_dir/$stage-$hash") |
80 record_hashes "$stage" "$@"
81 fi
82 }
83
84 record_hashes inner "${hashes[@]}" | go "$first_layer" | record_hashes outer "${hashes[@]}"
85
86 if [[ "$mode" == e ]];then
87 # Add the hashes to keyfile
88 key_aside_dir=$(mktemp -d "$keyfile.XXXXXXXXXX")
89 key_aside="$key_aside_dir/key.orig"
90 mv "$keyfile" "$key_aside"
91 cat "$hash_dir"/outer-* "$key_aside" "$hash_dir"/inner* > "$keyfile"
92 shred -u "$key_aside"
93 rmdir "$key_aside_dir"
94 else
95 # Verify the hashes
96 for hash_result in "$hash_dir"/*;do
97 verify_hash "$hash_result" || die "Hash check $(basename "$hash_result") failed"
98 done
99 fi
100
101 rm -r "$hash_dir"