diff --git a/sshcrypt b/sshcrypt new file mode 100755 index 0000000..fe2f2d9 --- /dev/null +++ b/sshcrypt @@ -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 +# 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 <