]> git.scottworley.com Git - overonion/blame - overonion
Add hashing
[overonion] / overonion
CommitLineData
c5ab018d
SW
1#!/bin/bash
2
dc38dd97
SW
3umask 077
4
5hashes=(sha sha1 mdc2 ripemd160 sha224 sha256 sha384 sha512 md4 md5 dss1)
6hash_dir=$(mktemp -d)
7
291948a5
SW
8function die() {
9 echo "$*" >&2
c5ab018d 10 exit 1
291948a5
SW
11}
12
13if (( $# != 2));then
14 die "usage: overonion e|d keyfile"
c5ab018d
SW
15fi
16mode=$1
17if [[ "$mode" != e && "$mode" != d ]];then
291948a5 18 die "Use 'e' for encrypt or 'd' for decrypt"
c5ab018d
SW
19fi
20keyfile=$2
21if [[ ! -e "$keyfile" ]];then
291948a5 22 die "Keyfile not found"
c5ab018d
SW
23fi
24if [[ ! -r "$keyfile" ]];then
291948a5 25 die "Cannot read keyfile"
c5ab018d
SW
26fi
27
28num_layers=$(wc -l < "$keyfile")
29if (( num_layers < 20 ));then
291948a5 30 die "Keyfile doesn't have enough layers to be an onion"
c5ab018d
SW
31fi
32
33if [[ "$mode" == e ]];then
34 first_layer=$num_layers
35 next_layer=-1
36 openssl_decrypt=""
37else
38 first_layer=1
39 next_layer=1
40 openssl_decrypt="-d"
41fi
42
dc38dd97
SW
43function verify_hash() {
44 (( $(wc -l < "$1") == 2 && $(uniq "$1" | wc -l) == 1 ))
45}
46
c5ab018d
SW
47function 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
71function 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
84record_hashes inner "${hashes[@]}" | go "$first_layer" | record_hashes outer "${hashes[@]}"
85
86if [[ "$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"
94else
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
99fi
100
101rm -r "$hash_dir"