]>
Commit | Line | Data |
---|---|---|
c5ab018d SW |
1 | #!/bin/bash |
2 | ||
dc38dd97 SW |
3 | umask 077 |
4 | ||
5 | hashes=(sha sha1 mdc2 ripemd160 sha224 sha256 sha384 sha512 md4 md5 dss1) | |
6 | hash_dir=$(mktemp -d) | |
7 | ||
291948a5 SW |
8 | function die() { |
9 | echo "$*" >&2 | |
c5ab018d | 10 | exit 1 |
291948a5 SW |
11 | } |
12 | ||
13 | if (( $# != 2));then | |
14 | die "usage: overonion e|d keyfile" | |
c5ab018d SW |
15 | fi |
16 | mode=$1 | |
17 | if [[ "$mode" != e && "$mode" != d ]];then | |
291948a5 | 18 | die "Use 'e' for encrypt or 'd' for decrypt" |
c5ab018d SW |
19 | fi |
20 | keyfile=$2 | |
21 | if [[ ! -e "$keyfile" ]];then | |
291948a5 | 22 | die "Keyfile not found" |
c5ab018d SW |
23 | fi |
24 | if [[ ! -r "$keyfile" ]];then | |
291948a5 | 25 | die "Cannot read keyfile" |
c5ab018d SW |
26 | fi |
27 | ||
28 | num_layers=$(wc -l < "$keyfile") | |
29 | if (( num_layers < 20 ));then | |
291948a5 | 30 | die "Keyfile doesn't have enough layers to be an onion" |
c5ab018d SW |
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 | ||
dc38dd97 SW |
43 | function verify_hash() { |
44 | (( $(wc -l < "$1") == 2 && $(uniq "$1" | wc -l) == 1 )) | |
45 | } | |
46 | ||
c5ab018d SW |
47 | function go() { |
48 | layer=$1 | |
49 | if (( layer == 0 || layer > num_layers ));then | |
50 | cat | |
51 | else | |
5ed90197 | 52 | operation=$(sed -n "${layer}{;s/ .*//;p;}" "$keyfile") |
fa1362a5 SW |
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") | |
5ed90197 SW |
56 | elif [[ "$operation" == reverse ]];then |
57 | reverse | |
dc38dd97 SW |
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" ) | |
fa1362a5 SW |
64 | else |
65 | die "Unknown operation" | |
66 | fi | | |
67 | go $(( layer + next_layer )) | |
c5ab018d SW |
68 | fi |
69 | } | |
70 | ||
dc38dd97 SW |
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" |