Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 153 additions & 0 deletions sshcrypt
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#!/bin/bash
#
# Uses your SSH keys to perform public key cryptography
#
# Expects openssh-client and openssl to be installed
#
# Author: Greg Retkowski <greg@rage.net>
# License: Apache License Version 2.0
#


# Loosely based on http://unix.stackexchange.com/a/33293

# dd blocksize
BS=512

#set -x
case $1 in
'encrypt')
PUB_KEY=$2
DATA_FILE=$3
FILE_BASENAME=`basename ${DATA_FILE}`
OUT_FILE=${FILE_BASENAME}.enc
if [ -e $OUT_FILE ]; then
echo "Refusing to overwrite $OUT_FILE"
exit 1
fi

KEY_DESC=$(ssh-keygen -l -E md5 -f $PUB_KEY)
# grab the bytes, so we can make our secret key as long as possible
KEYLEN_BYTES=$(echo $KEY_DESC |awk '{printf("%d", ($1 - 96) / 8)}')
SECRET_KEY_FILE=$(mktemp /dev/shm/.${LOGNAME}.skf.XXX)
chmod 0600 $SECRET_KEY_FILE
openssl rand ${KEYLEN_BYTES}>$SECRET_KEY_FILE

PUB_PEM=$(mktemp)
ssh-keygen -f $PUB_KEY -e -m pkcs8 >$PUB_PEM

ENC_SECRET_KEY_FILE=$(mktemp /dev/shm/.${LOGNAME}.eskf.XXX)
chmod 0600 $ENC_SECRET_KEY_FILE
echo $ENC_SECRET_KEY_FILE
cat $SECRET_KEY_FILE| openssl rsautl -encrypt -pubin -inkey $PUB_PEM \
|sed -e 's/\x0\+$//g' > ${ENC_SECRET_KEY_FILE}

rm $PUB_PEM

# We store all the data together in a single file; we store the
# following items in 1K blocks:
# * the basename of the encrypted file
# * A string containing the public key description
# * The key, encryped via the public key
# * A signature block (optional)
# Then starting at the 4K boundry, is the encrypted data.
#
echo -ne "$FILE_BASENAME\0" | dd of=$OUT_FILE bs=$BS seek=0 status=none
echo -ne "$KEY_DESC\0" | dd of=$OUT_FILE bs=$BS seek=2 status=none
cat ${ENC_SECRET_KEY_FILE} | dd of=$OUT_FILE bs=$BS seek=4 status=none
cat ${SECRET_KEY_FILE} | \
openssl enc -aes-256-cbc -pass stdin -in $DATA_FILE | \
dd of=$OUT_FILE bs=$BS seek=8 status=none
rm ${SECRET_KEY_FILE}
rm ${ENC_SECRET_KEY_FILE}
echo "Encrypted for key: $KEY_DESC"
echo "Wroute out $OUT_FILE"
;;
'decrypt')

PRIV_KEY=$2
DATA_FILE=$3
ENC_SECRET_KEY_FILE=$(mktemp /dev/shm/.${LOGNAME}.eskf.XXX)
chmod 0600 $ENC_SECRET_KEY_FILE

# Pull the data out of the three 1K blocks
FILE_NAME=`dd if=$DATA_FILE bs=$BS skip=0 count=2 status=none`
KEY_ID=`dd if=$DATA_FILE bs=$BS skip=2 count=2 status=none`
dd if=$DATA_FILE bs=$BS skip=4 count=2 status=none|sed -e 's/\x0\+$//g' \
>${ENC_SECRET_KEY_FILE}

if [ -e $FILE_NAME ]; then
echo "Refusing to overwrite $FILE_NAME"
exit 1
fi

ENC_DATA_FILE=$(mktemp)
dd if=$DATA_FILE bs=$BS skip=8 status=none >${ENC_DATA_FILE}

# Decrypt the secret key
SECRET_KEY_FILE=$(mktemp /dev/shm/.${LOGNAME}.skf.XXX)
chmod 0600 $SECRET_KEY_FILE
openssl rsautl -decrypt -in ${ENC_SECRET_KEY_FILE} \
-inkey $PRIV_KEY -out ${SECRET_KEY_FILE}
rm ${ENC_SECRET_KEY_FILE}

# And use the secret keyfile to decrypt the rest of the file.
cat ${SECRET_KEY_FILE} | \
openssl enc -aes-256-cbc -pass stdin -d \
-in $ENC_DATA_FILE -out $FILE_NAME
rm ${SECRET_KEY_FILE}
echo "Decrypted to ${FILE_NAME}"
;;
'keyinfo')
# Just pulls the key_id string out of the file.
DATA_FILE=$2
KEY_ID=`dd if=$DATA_FILE bs=$BS skip=2 count=2 status=none`
echo $KEY_ID
;;
'sign')
# http://superuser.com/a/308130
PRIV_KEY=$2
DATA_FILE=$3

ENC_DATA_FILE=$(mktemp)
SIG_FILE=$(mktemp /dev/shm/.${LOGNAME}.sig.XXX)

dd if=$DATA_FILE bs=$BS skip=8 status=none >${ENC_DATA_FILE}
openssl dgst -sign $PRIV_KEY $ENC_DATA_FILE >$SIG_FILE
cat $SIG_FILE|dd bs=$BS count=2 status=none | sed -e 's/\x0\+$//g'| \
dd of=$DATA_FILE bs=$BS seek=6 conv=notrunc status=none
echo Signed $DATA_FILE
;;
'verify')

PUB_KEY=$2
DATA_FILE=$3

ENC_DATA_FILE=$(mktemp)
SIG_FILE=$(mktemp /dev/shm/.${LOGNAME}.sig.XXX)
dd if=$DATA_FILE bs=$BS skip=6 count=2 status=none | \
sed -e 's/\x0\+$//g' >${SIG_FILE}
dd if=$DATA_FILE bs=$BS skip=8 status=none >${ENC_DATA_FILE}

PUB_PEM=$(mktemp)
ssh-keygen -f $PUB_KEY -e -m pkcs8 >$PUB_PEM
openssl dgst -verify $PUB_PEM -signature $SIG_FILE $ENC_DATA_FILE

rm $PUB_PEM $SIG_FILE $ENC_DATA_FILE

;;
*)
cat <<EOF

$0: Use SSH keys to perform public key encryption operations

Encrypting a file : $0 encrypt ssh_pub_key plaintext_file
Descryptiong a file : $0 decrypt ssh_priv_key encrypted_file
Signing a file : $0 sign ssh_priv_key encrypted_file
Verifying a sig : $0 verify ssh_pub_key encrypted_file
Show key info for file: $0 keyinfo encrypted_file

EOF

;;
esac