]>
Commit | Line | Data |
---|---|---|
1 | #!/bin/bash | |
2 | ||
3 | umask 077 | |
4 | ||
5 | hash_dir=$(mktemp -d) | |
6 | ||
7 | function die() { | |
8 | echo "$*" >&2 | |
9 | exit 1 | |
10 | } | |
11 | ||
12 | if (( $# != 2));then | |
13 | die "usage: overonion e|d keyfile" | |
14 | fi | |
15 | mode=$1 | |
16 | if [[ "$mode" != e && "$mode" != d ]];then | |
17 | die "Use 'e' for encrypt or 'd' for decrypt" | |
18 | fi | |
19 | keyfile=$2 | |
20 | if [[ ! -e "$keyfile" ]];then | |
21 | die "Keyfile not found" | |
22 | fi | |
23 | if [[ ! -r "$keyfile" ]];then | |
24 | die "Cannot read keyfile" | |
25 | fi | |
26 | ||
27 | num_layers=$(wc -l < "$keyfile") | |
28 | if (( num_layers < 20 ));then | |
29 | die "Keyfile doesn't have enough layers to be an onion" | |
30 | fi | |
31 | ||
32 | hash_fields=$(awk '/^openssl-dgst / { print NF }' "$keyfile" | uniq ) | |
33 | ||
34 | if [[ "$mode" == e ]];then | |
35 | first_layer=$num_layers | |
36 | next_layer=-1 | |
37 | openssl_decrypt="" | |
38 | if [[ "$hash_fields" != 4 ]];then | |
39 | die "Refusing to encrypt with already-used key" | |
40 | fi | |
41 | else | |
42 | first_layer=1 | |
43 | next_layer=1 | |
44 | openssl_decrypt="-d" | |
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 | |
48 | fi | |
49 | ||
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 | ||
58 | function go() { | |
59 | layer=$1 | |
60 | if (( layer == 0 || layer > num_layers ));then | |
61 | cat | |
62 | else | |
63 | operation=$(keyfield "$layer" 1) | |
64 | if [[ "$operation" == openssl-enc ]];then | |
65 | openssl enc $openssl_decrypt "-$(keyfield "$layer" 2)" \ | |
66 | -nosalt -pass fd:37 37< <(keyfield "$layer" 3) | |
67 | elif [[ "$operation" == reverse ]];then | |
68 | "$(dirname "$0")/reverse" | |
69 | elif [[ "$operation" == openssl-dgst ]];then | |
70 | tee >(echo "$(keyline "$layer") $( | |
71 | { | |
72 | keyfield "$layer" 3 | base64 -d | |
73 | cat | |
74 | keyfield "$layer" 4 | base64 -d | |
75 | } | | |
76 | openssl dgst -binary "-$(keyfield "$layer" 2)" | | |
77 | base64 --wrap=0)" > "$hash_dir/$layer") | |
78 | else | |
79 | die "Unknown operation" | |
80 | fi | | |
81 | go $(( layer + next_layer )) | |
82 | fi | |
83 | } | |
84 | ||
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" | |
97 | else | |
98 | # Verify the hashes | |
99 | if [[ "$(awk '{ print $5 == $6 ? "hash ok" : "mismatch" }' "$hash_result")" != "hash ok" ]];then | |
100 | die "Hash check $layer failed" | |
101 | fi | |
102 | fi | |
103 | done | |
104 | ||
105 | rm -r "$hash_dir" |