diff --git a/README.md b/README.md index e8fa8f8..fab35d3 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,11 @@ chmod +x sshencdec.sh ./sshencdec.sh -p ~/.ssh/id_rsa.pub < plain-text-file.txt > encrypted.txt ``` +### encrypt a file using multiple recipients (broadcast encryption) +``` +./sshencdec.sh -p ~/.ssh/id_rsa.pub -p id_rsa-alice.pub -p id_rsa-bob.pub < plain-text-file.txt > encrypted.txt +``` + ### encrypt a file using the public key of a github user ``` ./sshencdec.sh -p <(curl -sf "https://github.com/S2-.keys" | head -n1) < plain-text-file.txt diff --git a/sshencdec.sh b/sshencdec.sh index 797f1d6..18ce979 100755 --- a/sshencdec.sh +++ b/sshencdec.sh @@ -1,11 +1,7 @@ #!/bin/bash -# A POSIX variable OPTIND=1 # reset in case getopts has been used previously in the shell. -public_key= #"~/.ssh/id_rsa.pub" -private_key= #"~/.ssh/id_rsa" - me=`basename "$0"` show_help() { @@ -14,68 +10,100 @@ usage: $me [-p | -s ] [-h] examples: - encrypt a file - $me -p ~/.ssh/id_rsa.pub < plain-text-file.txt > encrypted.txt + $me -p ~/.ssh/id_rsa.pub < plain-text-file.txt > encrypted.txt - decrypt a file - $me -s ~/.ssh/id_rsa < encrypted.txt + $me -s ~/.ssh/id_rsa < encrypted.txt $me home page: https://git.e.tern.al/s2/sshencdec EOF } cleanup() { - rm -f "$temp_file" - rm -f "$temp_file_key" - rm -f "$temp_file_key.enc" - rm -f "$temp_file_ppkey" + rm -rf "$temp_dir" } while getopts "h?p:s:" opt; do case "$opt" in h|\?) - show_help - exit 0 - ;; - p) public_key=$OPTARG - ;; + show_help + exit 0 + ;; + p) public_key+=("$OPTARG") + ;; s) private_key=$OPTARG - ;; + ;; esac done -shift $((OPTIND-1)) +shift $((OPTIND -1)) [ "$1" = "--" ] && shift -temp_file="$(mktemp -p . -t "$(basename "$0").XXXXXX.enc")" -temp_file_key="$(mktemp -p . -t "$(basename "$0").XXXXXX.key")" -temp_file_ppkey="$(mktemp -p . -t "$(basename "$0").XXXXXX.ppkey")" +temp_dir="$(mktemp -d -t "$me.XXXXXX")" +temp_file_key="$(mktemp -p $temp_dir -t "$(basename "$0").XXXXXX.key")" +temp_file="$(mktemp -p $temp_dir -t "$(basename "$0").XXXXXX.cypher")" trap cleanup EXIT #encrypt -if [[ -e "$public_key" ]]; then - ssh-keygen -f "$public_key" -e -m PKCS8 > $temp_file_ppkey +if [[ "${#public_key[@]}" > 0 ]]; then openssl rand 32 > $temp_file_key - if openssl rsautl -encrypt -pubin -inkey "$temp_file_ppkey" -in "$temp_file_key" -out "$temp_file_key.enc"; then - if openssl enc -aes-256-cbc -salt -pass file:"$temp_file_key" > "$temp_file"; then - echo "-- encrypted with https://git.e.tern.al/s2/sshencdec" + echo "-- encrypted with https://git.e.tern.al/s2/sshencdec" + echo "-- keys" + for pubkey in "${public_key[@]}" + do + if [[ -e "$pubkey" ]]; then echo "-- key" - echo "$(openssl base64 -in "$temp_file_key.enc")" + convertedpubkey=$temp_dir/$(basename "$pubkey").pem + ssh-keygen -f "$pubkey" -e -m PKCS8 > $convertedpubkey + #encrypt key with oublic keys + openssl rsautl -encrypt -pubin -inkey "$convertedpubkey" -in "$temp_file_key" -out $temp_dir/$(basename "$pubkey").key.enc + openssl base64 -in $temp_dir/$(basename "$pubkey").key.enc echo "-- /key" - openssl base64 < "$temp_file" fi + done + echo "-- /keys" + + if openssl enc -aes-256-cbc -salt -pass file:"$temp_file_key" > "$temp_file"; then + openssl base64 < "$temp_file" fi #decrypt elif [[ -e "$private_key" ]]; then stdin=`cat` - key_enc=$(echo "$stdin" | awk '/-- key/{f=1;next} /-- \/key/{f=0} f') - cypher=$(echo "$stdin" | sed -e '1,/-- \/key/d') - echo "$key_enc" | openssl base64 -d | openssl rsautl -decrypt -ssl -inkey "$private_key" > "$temp_file" - echo "$cypher" | openssl base64 -d | openssl aes-256-cbc -d -pass file:"$temp_file" + keys_enc=$(echo "$stdin" | awk '/-- keys/{f=1;next} /-- \/keys/{f=0} f') + cypher=$(echo "$stdin" | sed -e '1,/-- \/keys/d') + i=0 + while read line ; do \ + if [ "$line" == "-- key" ]; then + i=$(($i + 1)) + elif [ "$line" == "-- /key" ]; then + : + else + keys[i]="${keys[$i]}$line" + fi + done <<< "$keys_enc" + + decrypted=false + for key in "${keys[@]}" + do + if ((echo "$key" | openssl base64 -d | openssl rsautl -decrypt -ssl -inkey "$private_key" > "$temp_file") > /dev/null 2>&1); then + if echo "$cypher" | openssl base64 -d | openssl aes-256-cbc -d -pass file:"$temp_file"; then + decrypted=true + fi; + fi; + done + + if [ $decrypted = false ]; then + >&2 echo "no valid decription key supplied" + exit 1 + fi + +#help else show_help exit 1 fi +