]> git.scottworley.com Git - overonion/blobdiff - overonion
keyline() and keyfield() operations
[overonion] / overonion
index a33351a7ece4153b72b765c204c01ac66c37f975..50d1958e5f2c03a85185222d201a53e9bee046f9 100755 (executable)
--- a/overonion
+++ b/overonion
@@ -1,5 +1,9 @@
 #!/bin/bash
 
+umask 077
+
+hash_dir=$(mktemp -d)
+
 function die() {
   echo "$*" >&2
   exit 1
@@ -25,25 +29,77 @@ if (( num_layers < 20 ));then
   die "Keyfile doesn't have enough layers to be an onion"
 fi
 
+hash_fields=$(awk '/^openssl-dgst / { print NF }' "$keyfile" | uniq )
+
 if [[ "$mode" == e ]];then
   first_layer=$num_layers
   next_layer=-1
   openssl_decrypt=""
+  if [[ "$hash_fields" != 4 ]];then
+    die "Refusing to encrypt with already-used key"
+  fi
 else
   first_layer=1
   next_layer=1
   openssl_decrypt="-d"
+  if [[ "$hash_fields" != 5 ]];then
+    die "Key does not appear to have been used for encryption (it has no embedded hashes).  Refusing to decrypt."
+  fi
 fi
 
+function keyline() {
+  awk -vline="$1" 'NR == line' "$keyfile"
+}
+
+function keyfield() {
+  awk -vline="$1" -vfield="$2" 'NR == line { print $field }' "$keyfile"
+}
+
 function go() {
   layer=$1
   if (( layer == 0 || layer > num_layers ));then
     cat
   else
-    openssl enc $openssl_decrypt "-$(sed -n "${layer}s/ .*//p" "$keyfile")" \
-            -pass fd:37 37< <(sed -n "${layer}s/^[^ ]* //p" "$keyfile") |
-    go $(( layer + next_layer ))
+    operation=$(keyfield "$layer" 1)
+    if [[ "$operation" == openssl-enc ]];then
+      openssl enc $openssl_decrypt "-$(keyfield "$layer" 2)" \
+              -nosalt -pass fd:37 37< <(keyfield "$layer" 3)
+    elif [[ "$operation" == reverse ]];then
+      "$(dirname "$0")/reverse"
+    elif [[ "$operation" == openssl-dgst ]];then
+      tee >(echo "$(keyline "$layer") $(
+            {
+              keyfield "$layer" 3 | base64 -d
+              cat
+              keyfield "$layer" 4 | base64 -d
+            } |
+              openssl dgst -binary "-$(keyfield "$layer" 2)" |
+              base64 --wrap=0)" > "$hash_dir/$layer")
+    else
+      die "Unknown operation"
+    fi |
+      go $(( layer + next_layer ))
   fi
 }
 
 go "$first_layer"
+
+for hash_result in "$hash_dir"/*;do
+  layer=$(basename "$hash_result")
+  if [[ "$mode" == e ]];then
+    # Add the hashes to keyfile
+    key_aside_dir=$(mktemp -d "$keyfile.XXXXXXXXXX")
+    key_aside="$key_aside_dir/key.orig"
+    mv "$keyfile" "$key_aside"
+    sed "${layer}s,.*,$(< "$hash_result")," "$key_aside" > "$keyfile"
+    shred -u "$key_aside"
+    rmdir "$key_aside_dir"
+  else
+    # Verify the hashes
+    if [[ "$(awk '{ print $5 == $6 ? "hash ok" : "mismatch" }' "$hash_result")" != "hash ok" ]];then
+      die "Hash check $layer failed"
+    fi
+  fi
+done
+
+rm -r "$hash_dir"