1
0
mirror of https://github.com/5im-0n/sshenc.sh.git synced 2025-08-03 20:00:04 +02:00

Compare commits

...

22 Commits

Author SHA1 Message Date
s2
2546ebca16 update urls 2023-03-17 12:42:15 +01:00
s2
079641675e fix readme link 2023-01-08 15:57:02 +01:00
s2
1ae9f9ed50 update link 2023-01-08 15:54:53 +01:00
s2
4bc407213b Revert "update sshenc.sh url"
This reverts commit b2df05b763.
2023-01-08 15:54:06 +01:00
s2
b2df05b763 update sshenc.sh url 2023-01-08 15:53:21 +01:00
Bernard Martis
bae0175dce Comment code and update user documentation
- Group code into sections by functionality
- Explain the use of multiple public keys
2020-09-07 19:28:04 -04:00
Bernard Martis
c97265aa00 Use LibreSSL on MacOS
- Use the LibreSSL library that comes preinstalled on MacOS
- Disable the OpenSSL options that LibreSSL does not support
- Explain how to install OpenSSl if the LibreSSL version is too old
2020-09-07 19:24:28 -04:00
Pete Woods
b7c0dad242 Remove mapfile use
- This makes it compatible with the version of BASH shipped with macOS
2020-08-28 12:48:54 +01:00
gustavo panizzo
c3467c9760 warn macos users about the need to install openssl 2020-04-07 11:15:05 +02:00
gustavo panizzo
41c8369e8d use whatever bash is first on the $PATH
this is for macos users
2020-04-07 11:15:05 +02:00
s2
0722e8d355 remove debug output 2020-02-29 17:22:09 +01:00
s2
817fc44da7 silence ssh-keygen 2020-02-29 16:43:42 +01:00
s2
1424021a2e fix readme newlines 2020-02-29 15:08:00 +01:00
gustavo panizzo
b79df269c8 fix shell redirection bug 2020-02-27 01:53:42 +01:00
gustavo panizzo
f28a78ff82 change the padding to oaep 2020-02-27 01:53:42 +01:00
gustavo panizzo
845ad71fc4 convert newer ssh keys to a format that openssl can understand 2020-02-27 01:46:33 +01:00
gustavo panizzo
53d26c4163 update the README.md with the new functionality 2020-02-26 23:21:33 +01:00
gustavo panizzo
c56978f9fb add support to automatically pull ssh keys from github handles 2020-02-26 23:16:11 +01:00
s2
c3ebbbfa06 add sshenc-pre1.1.1.sh to tests 2019-11-27 15:57:36 +01:00
s2
eed415d7b2 add more tests 2019-11-26 16:53:44 +01:00
s2
6de058b2da openssl 1.1.1 - this introduces not backward compatible changes :( 2019-11-26 16:39:26 +01:00
s2
63ac438831 use pbkdf2 since it is available in new versions of openssl 2019-11-25 16:28:35 +01:00
4 changed files with 230 additions and 33 deletions

View File

@@ -4,13 +4,13 @@
If you received a message from someone that was encrypted with this script, you can decrypt it with your ssh private key using the following command without installing anything: If you received a message from someone that was encrypted with this script, you can decrypt it with your ssh private key using the following command without installing anything:
``` ```
bash <(curl -s https://sshenc.sh/sshenc.sh) -s ~/.ssh/id_rsa < file-containing-the-encrypted-text.txt bash <(curl -s https://raw.githubusercontent.com/5im-0n/sshenc.sh/master/sshenc.sh) -s ~/.ssh/id_rsa < file-containing-the-encrypted-text.txt
``` ```
sshenc.sh uses openssl under the hood, so you need to have that installed in your path to make it work. sshenc.sh uses openssl under the hood, so you need to have that installed in your path to make it work.
## Install ## Install
``` ```
curl -O https://sshenc.sh/sshenc.sh curl -O https://raw.githubusercontent.com/5im-0n/sshenc.sh/master/sshenc.sh
chmod +x sshenc.sh chmod +x sshenc.sh
``` ```
@@ -28,14 +28,21 @@ sshenc.sh -p ~/.ssh/id_rsa.pub -p id_rsa-alice.pub -p id_rsa-bob.pub < plain-tex
### encrypt a file using the public key of a github user ### encrypt a file using the public key of a github user
``` ```
sshenc.sh -p <(curl -sf "https://github.com/S2-.keys" | grep ssh-rsa | tail -n1) < plain-text-file.txt sshenc.sh -g S2- < plain-text-file.txt
``` ```
this line fetches the first public key for the github user S2- and encrypts the file plain-text-file.txt using this key. this line fetches the public keys for the github user S2- and encrypts the file plain-text-file.txt using its key(s).
### decrypt a file ### decrypt a file
``` ```
sshenc.sh -s ~/.ssh/id_rsa < encrypted.txt sshenc.sh -s ~/.ssh/id_rsa < encrypted.txt
``` ```
## Notes
[OpenSSL 1.1.1](https://www.openssl.org/docs/man1.1.1/man1/openssl-enc.html) introduced a not backwards compatible change: the default digest to create a key from the passphrase changed from md5 to sha-256.
Also, a new `-iter` parameter to explicitly specify a given number of iterations on the password in deriving the encryption key was added.
Before OpenSSL 1.1.1 this option was not available.
Since the new parameters are more secure, `sshenc.sh` changed to adopt them, so since 2019-11-26, files encrypted with a previous version of `sshenc.sh` will not decrypt.
To do so, use the prevous `sshenc.sh` script, located at [https://raw.githubusercontent.com/5im-0n/sshenc.sh/master/sshenc-pre1.1.1.sh](https://raw.githubusercontent.com/5im-0n/sshenc.sh/master/sshenc-pre1.1.1.sh).
## License ## License
[MIT](https://opensource.org/licenses/MIT) [MIT](https://opensource.org/licenses/MIT)

109
sshenc-pre1.1.1.sh Executable file
View File

@@ -0,0 +1,109 @@
#!/bin/bash
OPTIND=1 # reset in case getopts has been used previously in the shell.
me=sshenc.sh
show_help() {
cat << EOF
usage: $me [-p <public ssh key> | -s <private ssh key>] [-h]
examples:
- encrypt a file
$me -p ~/.ssh/id_rsa.pub < plain-text-file.txt > encrypted.txt
- decrypt a file
$me -s ~/.ssh/id_rsa < encrypted.txt
$me home page: https://github.com/5im-0n/sshenc.sh/
EOF
}
cleanup() {
rm -rf "$temp_dir"
}
while getopts "h?p:s:" opt; do
case "$opt" in
h|\?)
show_help
exit 0
;;
p) public_key+=("$OPTARG")
;;
s) private_key=$OPTARG
;;
esac
done
shift $((OPTIND -1))
[ "$1" = "--" ] && shift
temp_dir="$(mktemp -d -t "$me.XXXXXX")"
temp_file_key="$(mktemp "$temp_dir/$me.XXXXXX.key")"
temp_file="$(mktemp "$temp_dir/$me.XXXXXX.cypher")"
trap cleanup EXIT
#encrypt
if [[ "${#public_key[@]}" > 0 ]]; then
openssl rand 32 > $temp_file_key
echo "-- encrypted with https://github.com/5im-0n/sshenc.sh/"
echo "-- keys"
for pubkey in "${public_key[@]}"
do
if [[ -e "$pubkey" ]]; then
convertedpubkey=$temp_dir/$(basename "$pubkey").pem
ssh-keygen -f "$pubkey" -e -m PKCS8 > $convertedpubkey
#encrypt key with public keys
if openssl rsautl -encrypt -pubin -inkey "$convertedpubkey" -in "$temp_file_key" -out $temp_dir/$(basename "$pubkey").key.enc; then
echo "-- key"
openssl base64 -in $temp_dir/$(basename "$pubkey").key.enc
echo "-- /key"
fi
fi
done
echo "-- /keys"
if cat | openssl enc -aes-256-cbc -salt -pass file:"$temp_file_key" > "$temp_file"; then
openssl base64 -A < "$temp_file"
fi
#decrypt
elif [[ -e "$private_key" ]]; then
stdin=`cat`
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 -A | openssl rsautl -decrypt -ssl -inkey "$private_key" > "$temp_file") > /dev/null 2>&1); then
if echo "$cypher" | openssl base64 -d -A | openssl aes-256-cbc -d -pass file:"$temp_file"; then
decrypted=true
fi
fi
done
if [ $decrypted = false ]; then
>&2 echo "no valid decryption key supplied"
exit 1
fi
#help
else
show_help
exit 1
fi

102
sshenc.sh
View File

@@ -1,29 +1,33 @@
#!/bin/bash #!/usr/bin/env bash
OPTIND=1 # reset in case getopts has been used previously in the shell.
# --- constants
me=sshenc.sh me=sshenc.sh
show_help() { show_help() {
cat << EOF cat << EOF
usage: $me [-p <public ssh key> | -s <private ssh key>] [-h] usage: $me [[-p <public ssh key> | -g <github handle>]| -s <private ssh key>] [-h]
examples: examples:
- encrypt a file
$me -p ~/.ssh/id_rsa.pub < plain-text-file.txt > encrypted.txt
- decrypt a file - decrypt a file
$me -s ~/.ssh/id_rsa < encrypted.txt $me -s ~/.ssh/id_rsa < encrypted.txt
$me home page: https://sshenc.sh/ - encrypt a file
$me -p ~/.ssh/id_rsa.pub < plain-text-file.txt > encrypted.txt
- encrypt using a GitHub users public SSH key (requires curl and bash 3.2)
$me -g foo < plain-text-file.txt > encrypted.txt
- encrypt using multiple public keys (file can be read by any associated private key)
$me -g foo -g bar -p baz -p ~/.ssh/id_rsa.pub < plain-text-file.txt > encrypted.txt
$me home page: https://github.com/5im-0n/sshenc.sh/
EOF EOF
} }
cleanup() { # --- process option parameters
rm -rf "$temp_dir" OPTIND=1 # reset in case getopts has been used previously in the shell
} while getopts "h?p:s:g:" opt; do
while getopts "h?p:s:" opt; do
case "$opt" in case "$opt" in
h|\?) h|\?)
show_help show_help
@@ -33,23 +37,72 @@ while getopts "h?p:s:" opt; do
;; ;;
s) private_key=$OPTARG s) private_key=$OPTARG
;; ;;
g) github_handle+=("$OPTARG")
esac esac
done done
shift $((OPTIND -1)) shift $((OPTIND -1)) # pop the processed options off the stack
[ "$1" = "--" ] && shift [ "$1" = "--" ] && shift
# --- setup environment
# data cache files
temp_dir="$(mktemp -d -t "$me.XXXXXX")" temp_dir="$(mktemp -d -t "$me.XXXXXX")"
temp_file_key="$(mktemp "$temp_dir/$me.XXXXXX.key")" temp_file_key="$(mktemp "$temp_dir/$me.XXXXXX.key")"
temp_file="$(mktemp "$temp_dir/$me.XXXXXX.cypher")" temp_file="$(mktemp "$temp_dir/$me.XXXXXX.cypher")"
cleanup() {
rm -rf "$temp_dir"
}
trap cleanup EXIT trap cleanup EXIT
#encrypt # os specific configuration
case "$(uname -s 2>/dev/null)" in
Darwin)
if [[ -n $(openssl version | grep -Eo "LibreSSL [2-9]") ]]; then
openssl_params=''
else
echo >&2 "Install openssl 1.1.1 or higher and add it to your \$PATH"
echo ''
echo ' brew install openssl'
echo ' echo 'export PATH="/usr/local/opt/openssl/bin:$PATH"' >> ~/.bash_profile'
echo ' source ~/.bash_profile'
echo ''
exit 1
fi
;;
*)
openssl_params='-pbkdf2 -iter 100000'
esac
# --- retrieve ssh keys from github
if [[ "${#github_handle[@]}" -gt 0 ]]; then
if ! which curl >/dev/null ; then
>&2 echo "curl command not found"
exit 1
fi
OLDMASK=$(umask); umask 0266
for handle in "${github_handle[@]}"
do
curl -s "https://github.com/$handle.keys" | grep ssh-rsa > "$temp_dir/$handle"
if [ -s "$temp_dir/$handle" ]; then
key_index=0
while IFS= read -r key; do
printf "%s" "${key}" > "$temp_dir/$handle.$key_index"
public_key+=("$temp_dir/$handle.$key_index")
key_index=$((key_index+1))
done < "$temp_dir/$handle"
fi
done
umask "$OLDMASK"
fi
# --- encrypt stdin
if [[ "${#public_key[@]}" > 0 ]]; then if [[ "${#public_key[@]}" > 0 ]]; then
openssl rand 32 > $temp_file_key openssl rand 32 > $temp_file_key
echo "-- encrypted with https://sshenc.sh/" echo "-- encrypted with https://github.com/5im-0n/sshenc.sh/"
echo "-- keys" echo "-- keys"
for pubkey in "${public_key[@]}" for pubkey in "${public_key[@]}"
do do
@@ -57,7 +110,7 @@ if [[ "${#public_key[@]}" > 0 ]]; then
convertedpubkey=$temp_dir/$(basename "$pubkey").pem convertedpubkey=$temp_dir/$(basename "$pubkey").pem
ssh-keygen -f "$pubkey" -e -m PKCS8 > $convertedpubkey ssh-keygen -f "$pubkey" -e -m PKCS8 > $convertedpubkey
#encrypt key with public keys #encrypt key with public keys
if openssl rsautl -encrypt -pubin -inkey "$convertedpubkey" -in "$temp_file_key" -out $temp_dir/$(basename "$pubkey").key.enc; then if openssl rsautl -encrypt -oaep -pubin -inkey "$convertedpubkey" -in "$temp_file_key" -out $temp_dir/$(basename "$pubkey").key.enc; then
echo "-- key" echo "-- key"
openssl base64 -in $temp_dir/$(basename "$pubkey").key.enc openssl base64 -in $temp_dir/$(basename "$pubkey").key.enc
echo "-- /key" echo "-- /key"
@@ -66,15 +119,17 @@ if [[ "${#public_key[@]}" > 0 ]]; then
done done
echo "-- /keys" echo "-- /keys"
if cat | openssl enc -aes-256-cbc -salt -pass file:"$temp_file_key" > "$temp_file"; then if cat | openssl enc -aes-256-cbc -salt $openssl_params -pass file:"$temp_file_key" > "$temp_file"; then
openssl base64 -A < "$temp_file" openssl base64 -A < "$temp_file"
fi fi
#decrypt # --- decrypt stdin
elif [[ -e "$private_key" ]]; then elif [[ -e "$private_key" ]]; then
stdin=`cat` stdin=`cat`
keys_enc=$(echo "$stdin" | awk '/-- keys/{f=1;next} /-- \/keys/{f=0} f') keys_enc=$(echo "$stdin" | awk '/-- keys/{f=1;next} /-- \/keys/{f=0} f')
cypher=$(echo "$stdin" | sed -e '1,/-- \/keys/d') cypher=$(echo "$stdin" | sed -e '1,/-- \/keys/d')
install -m 0600 "$private_key" "$temp_dir/private_key"
ssh-keygen -p -m PEM -N '' -f "$temp_dir/private_key" >/dev/null
i=0 i=0
while read line ; do \ while read line ; do \
@@ -88,10 +143,9 @@ elif [[ -e "$private_key" ]]; then
done <<< "$keys_enc" done <<< "$keys_enc"
decrypted=false decrypted=false
for key in "${keys[@]}" for key in "${keys[@]}"; do
do if $(echo "$key" | openssl base64 -d -A | openssl rsautl -decrypt -oaep -inkey "$temp_dir/private_key" >"$temp_file_key" 2>/dev/null); then
if ((echo "$key" | openssl base64 -d -A | openssl rsautl -decrypt -ssl -inkey "$private_key" > "$temp_file") > /dev/null 2>&1); then if echo "$cypher" | openssl base64 -d -A | openssl aes-256-cbc -d $openssl_params -pass file:"$temp_file_key"; then
if echo "$cypher" | openssl base64 -d -A | openssl aes-256-cbc -d -pass file:"$temp_file"; then
decrypted=true decrypted=true
fi fi
fi fi
@@ -102,7 +156,7 @@ elif [[ -e "$private_key" ]]; then
exit 1 exit 1
fi fi
#help # --- help
else else
show_help show_help
exit 1 exit 1

View File

@@ -1,24 +1,51 @@
sshenc=../sshenc.sh
#to test the pre OpenSSL 1.1.1 script, uncomment the line below:
#sshenc=../sshenc-pre1.1.1.sh
cleanup() { cleanup() {
rm -rf "$tempfile" rm -rf "$temp_dir"
} }
trap cleanup EXIT trap cleanup EXIT
temp_dir="$(mktemp -d -t "sshenc.sh.XXXXXX")"
tempfile=$(tempfile) tempfile="$(mktemp "$temp_dir/sshenc.sh.XXXXXX.cypher")"
plaintext=$(cat sometext) plaintext=$(cat sometext)
echo -n 'testing multiple pubkeys: ' echo -n 'testing multiple pubkeys: '
../sshenc.sh -p id_rsa-1.pub -p id_rsa-2.pub -p id_rsa-3.pub < sometext > $tempfile $sshenc -p id_rsa-1.pub -p id_rsa-2.pub -p id_rsa-3.pub < sometext > $tempfile
for i in {1..3}; do for i in {1..3}; do
cyph=$(../sshenc.sh -s id_rsa-$i < $tempfile) cyph=$($sshenc -s id_rsa-$i < $tempfile)
if [ "$cyph" == "$plaintext" ]; then if [ "$cyph" == "$plaintext" ]; then
echo -n "key$i: ✓ " echo -n "key$i: ✓ "
else else
echo -n "key$i: ⛝ " echo -n "key$i: ⛝ "
fi fi
done done
echo
echo -n 'testing encryption with a single key: '
$sshenc -p id_rsa-1.pub < sometext > $tempfile
cyph=$($sshenc -s id_rsa-1 < $tempfile)
if [ "$cyph" == "$plaintext" ]; then
echo -n "✓"
else
echo -n "⛝"
fi
echo
echo -n 'testing encryption of a binary file: '
$sshenc -p id_rsa-1.pub < ../logo.png > $tempfile
$sshenc -s id_rsa-1 < $tempfile > $temp_dir/binary
diff ../logo.png $temp_dir/binary
retval=$?
if [ $retval -eq 0 ]; then
echo -n "✓"
else
echo -n "⛝"
fi
echo
echo echo
echo done. echo done.