]>
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 | ||
ecbdad2f SW |
50 | function keyline() { |
51 | awk -vline="$1" 'NR == line' "$keyfile" | |
52 | } | |
53 | ||
54 | function keyfield() { | |
55 | awk -vline="$1" -vfield="$2" 'NR == line { print $field }' "$keyfile" | |
56 | } | |
57 | ||
c5ab018d SW |
58 | function go() { |
59 | layer=$1 | |
60 | if (( layer == 0 || layer > num_layers ));then | |
61 | cat | |
62 | else | |
ecbdad2f | 63 | operation=$(keyfield "$layer" 1) |
fa1362a5 | 64 | if [[ "$operation" == openssl-enc ]];then |
ecbdad2f SW |
65 | openssl enc $openssl_decrypt "-$(keyfield "$layer" 2)" \ |
66 | -nosalt -pass fd:37 37< <(keyfield "$layer" 3) | |
5ed90197 | 67 | elif [[ "$operation" == reverse ]];then |
ecbdad2f | 68 | "$(dirname "$0")/reverse" |
dc38dd97 | 69 | elif [[ "$operation" == openssl-dgst ]];then |
ecbdad2f | 70 | tee >(echo "$(keyline "$layer") $( |
a4f74913 | 71 | { |
ecbdad2f | 72 | keyfield "$layer" 3 | base64 -d |
a4f74913 | 73 | cat |
ecbdad2f | 74 | keyfield "$layer" 4 | base64 -d |
a4f74913 | 75 | } | |
ecbdad2f | 76 | openssl dgst -binary "-$(keyfield "$layer" 2)" | |
a4f74913 | 77 | base64 --wrap=0)" > "$hash_dir/$layer") |
fa1362a5 SW |
78 | else |
79 | die "Unknown operation" | |
80 | fi | | |
81 | go $(( layer + next_layer )) | |
c5ab018d SW |
82 | fi |
83 | } | |
84 | ||
f5a8e270 SW |
85 | go "$first_layer" |
86 | ||
87 | for hash_result in "$hash_dir"/*;do | |
88 | layer=$(basename "$hash_result") | |
89 | if [[ "$mode" == e ]];then | |
90 | # Add the hashes to keyfile | |
91 | key_aside_dir=$(mktemp -d "$keyfile.XXXXXXXXXX") | |
92 | key_aside="$key_aside_dir/key.orig" | |
93 | mv "$keyfile" "$key_aside" | |
94 | sed "${layer}s,.*,$(< "$hash_result")," "$key_aside" > "$keyfile" | |
95 | shred -u "$key_aside" | |
96 | rmdir "$key_aside_dir" | |
dc38dd97 | 97 | else |
f5a8e270 | 98 | # Verify the hashes |
a4f74913 | 99 | if [[ "$(awk '{ print $5 == $6 ? "hash ok" : "mismatch" }' "$hash_result")" != "hash ok" ]];then |
f5a8e270 SW |
100 | die "Hash check $layer failed" |
101 | fi | |
dc38dd97 | 102 | fi |
f5a8e270 | 103 | done |
dc38dd97 SW |
104 | |
105 | rm -r "$hash_dir" |