]>
Commit | Line | Data |
---|---|---|
c5ab018d SW |
1 | #!/bin/bash |
2 | ||
dc38dd97 SW |
3 | umask 077 |
4 | ||
dc38dd97 SW |
5 | hash_dir=$(mktemp -d) |
6 | ||
291948a5 SW |
7 | function die() { |
8 | echo "$*" >&2 | |
c5ab018d | 9 | exit 1 |
291948a5 SW |
10 | } |
11 | ||
12 | if (( $# != 2));then | |
13 | die "usage: overonion e|d keyfile" | |
c5ab018d SW |
14 | fi |
15 | mode=$1 | |
16 | if [[ "$mode" != e && "$mode" != d ]];then | |
291948a5 | 17 | die "Use 'e' for encrypt or 'd' for decrypt" |
c5ab018d SW |
18 | fi |
19 | keyfile=$2 | |
20 | if [[ ! -e "$keyfile" ]];then | |
291948a5 | 21 | die "Keyfile not found" |
c5ab018d SW |
22 | fi |
23 | if [[ ! -r "$keyfile" ]];then | |
291948a5 | 24 | die "Cannot read keyfile" |
c5ab018d SW |
25 | fi |
26 | ||
27 | num_layers=$(wc -l < "$keyfile") | |
28 | if (( num_layers < 20 ));then | |
291948a5 | 29 | die "Keyfile doesn't have enough layers to be an onion" |
c5ab018d SW |
30 | fi |
31 | ||
4c2e9bc9 SW |
32 | hash_fields=$(awk '/^openssl-dgst / { print NF }' "$keyfile" | uniq ) |
33 | ||
c5ab018d SW |
34 | if [[ "$mode" == e ]];then |
35 | first_layer=$num_layers | |
36 | next_layer=-1 | |
37 | openssl_decrypt="" | |
4c2e9bc9 SW |
38 | if [[ "$hash_fields" != 4 ]];then |
39 | die "Refusing to encrypt with already-used key" | |
40 | fi | |
c5ab018d SW |
41 | else |
42 | first_layer=1 | |
43 | next_layer=1 | |
44 | openssl_decrypt="-d" | |
4c2e9bc9 SW |
45 | if [[ "$hash_fields" != 5 ]];then |
46 | die "Key does not appear to have been used for encryption (it has no embedded hashes). Refusing to decrypt." | |
47 | fi | |
c5ab018d SW |
48 | fi |
49 | ||
50 | function go() { | |
51 | layer=$1 | |
52 | if (( layer == 0 || layer > num_layers ));then | |
53 | cat | |
54 | else | |
5ed90197 | 55 | operation=$(sed -n "${layer}{;s/ .*//;p;}" "$keyfile") |
fa1362a5 SW |
56 | if [[ "$operation" == openssl-enc ]];then |
57 | openssl enc $openssl_decrypt "-$(sed -rn "${layer}s/[^ ]+ ([^ ]+) .*/\\1/p" "$keyfile")" \ | |
4a5d2fe4 | 58 | -nosalt -pass fd:37 37< <(sed -rn "${layer}s/^[^ ]+ [^ ]+ //p" "$keyfile") |
5ed90197 SW |
59 | elif [[ "$operation" == reverse ]];then |
60 | reverse | |
dc38dd97 | 61 | elif [[ "$operation" == openssl-dgst ]];then |
a4f74913 SW |
62 | tee >(echo "$(sed -n "${layer}p" "$keyfile") $( |
63 | { | |
64 | awk -vlayer="$layer" 'NR == layer { print $3 }' "$keyfile" | base64 -d | |
65 | cat | |
66 | awk -vlayer="$layer" 'NR == layer { print $4 }' "$keyfile" | base64 -d | |
67 | } | | |
68 | openssl dgst -binary "-$(sed -rn "${layer}s/^[^ ]+ ([^ ]+).*/\\1/p" "$keyfile")" | | |
69 | base64 --wrap=0)" > "$hash_dir/$layer") | |
fa1362a5 SW |
70 | else |
71 | die "Unknown operation" | |
72 | fi | | |
73 | go $(( layer + next_layer )) | |
c5ab018d SW |
74 | fi |
75 | } | |
76 | ||
f5a8e270 SW |
77 | go "$first_layer" |
78 | ||
79 | for hash_result in "$hash_dir"/*;do | |
80 | layer=$(basename "$hash_result") | |
81 | if [[ "$mode" == e ]];then | |
82 | # Add the hashes to keyfile | |
83 | key_aside_dir=$(mktemp -d "$keyfile.XXXXXXXXXX") | |
84 | key_aside="$key_aside_dir/key.orig" | |
85 | mv "$keyfile" "$key_aside" | |
86 | sed "${layer}s,.*,$(< "$hash_result")," "$key_aside" > "$keyfile" | |
87 | shred -u "$key_aside" | |
88 | rmdir "$key_aside_dir" | |
dc38dd97 | 89 | else |
f5a8e270 | 90 | # Verify the hashes |
a4f74913 | 91 | if [[ "$(awk '{ print $5 == $6 ? "hash ok" : "mismatch" }' "$hash_result")" != "hash ok" ]];then |
f5a8e270 SW |
92 | die "Hash check $layer failed" |
93 | fi | |
dc38dd97 | 94 | fi |
f5a8e270 | 95 | done |
dc38dd97 SW |
96 | |
97 | rm -r "$hash_dir" |