Fwd: Re: Encrypt /decrypta file with ssh keys.

Colin Leavett-Brown crlb at uvic.ca
Sat Aug 6 02:47:38 AEST 2016


As per Alex's suggestion, attached is the proof of concept "sfile" 
script. If there is anyone out there with great C skills who can 
recreate this functionality "out of the box", I think there would be a 
few happy campers (at least two, anyways).



-------- Forwarded Message --------
Subject: 	Re: Encrypt /decrypta file with ssh keys.
Date: 	Fri, 5 Aug 2016 17:24:35 +0100
From: 	Alex Bligh <alex at alex.org.uk>
To: 	Colin Leavett-Brown <crlb at uvic.ca>
CC: 	Alex Bligh <alex at alex.org.uk>



Colin,

> On 5 Aug 2016, at 17:03, Colin Leavett-Brown <crlb at uvic.ca> wrote:
>
> Hi Alex, I think this should be part of Openssh. Do you want to try the wrapper? I've attached the code and it does exactly what you want. Let us know what you think. "sfile" without any parms will tell you how to use it. Colin.

I read the code. Interesting. I suspect you will need to rewrite it in C (without relying on distro specific things like readlink -f) and paying close attention to e.g. minimising temporary files, ensuring they are created with the right modes and deleted on signals etc. in order to get it submitted. I think I might make the magic code longer so it can be more easily detected by 'file' etc. But it's an interesting proof of concept - TBH I'd just post it to the list as such.

Alex

>
>
> On 16-08-05 08:50 AM, Alex Bligh wrote:
>>> On 5 Aug 2016, at 16:30, Colin Leavett-Brown <crlb at uvic.ca> wrote:
>>>
>>> Hello,  I needed to share some secret info with one or two specific individuals and wrote a short wrapper script to encrypt/decrypt files using ssh keys (everyone has at least one pair). In searching, I found others wanting this functionality and borrowed heavily from this doc "http://www.czeskis.com/random/openssl-encrypt-file.html" in writing the script. I am willing to share the code if anyone is interested.
>> I was asking for this functionality only yesterday. My particular use was to encrypt a file with someone else's public key, to send to them so they could decrypt with their private key.
>>
>> If ssh (or some accompanying binary) could do this out the box, it would be great.
>>
>
> --
> Colin Leavett-Brown
> Physics and Astronomy
> University of Victoria
> 250-472-4085
>
> <sfile.txt>

-- 
Alex Bligh





-- 
Colin Leavett-Brown
Physics and Astronomy
University of Victoria
250-472-4085

-------------- next part --------------
#!/bin/bash
  # this is the proof of concept for secure file command.
  # usage: sfile [-e|-d] [-k <pub_private_key>] <file_path>
  # result is written to stdout.
  subcommand='decrypt'
  user_key=''
  user_file=''

  ignore_next='0'
  BASH_ARGV_LEN=$((${#BASH_ARGV}-1))
  for i in `seq $BASH_ARGV_LEN -1 0 `; do
    if [ $ignore_next == '0' ]; then
      if [ "X${BASH_ARGV[$i]}" == 'X-d' ]; then
        subcommand='decrypt'
      elif [ "X${BASH_ARGV[$i]}" == 'X-e' ]; then
        subcommand='encrypt'
      elif [ "X${BASH_ARGV[$i]}" == 'X-h' ]; then
        subcommand='help'
      elif [ "X${BASH_ARGV[$i]}" == 'X-k' ] && [ $i -gt 0 ]; then
        v=$(($i - 1))
        user_key=`readlink -f ${BASH_ARGV[$v]} 2>/dev/null`
        ignore_next='1'
      else
        user_file=`readlink -f ${BASH_ARGV[$i]} 2>/dev/null`
      fi
    else
      ignore_next='0'
    fi
  done
  
  if [ $subcommand == 'help' ] || [ "X$user_file" == 'X' ]; then
    echo 'Usage: sfile [-d|-e|-h] [-k <path_to_key_file>] <path_to_file>'
    echo ''
    echo 'Encrypt a file using an ssh public key and decrypt using the corresponding private'
    echo 'key. The default is to decrypt the specified file using your private key.'
    echo ''
    echo 'Options:'
    echo '  -d - Decrypt specified file. This is the default option.'
    echo '  -e - Encrypt specified file.'
    echo '  -h - Print help messages.'
    echo "  -k <path_to_key_file> - Defaults to '~/.ssh/id_rsa.pub' for encrypt and"
    echo "       '~/.ssh/id_rsa for decrypt'."
    echo ''
    echo 'Note: Result is written to STDOUT.'
    exit 0
  fi

  if [ ! -e $user_file ]; then
    >&2 echo "File '$user_file' does not exist."
    exit 1
  fi

  #
  # Encrypt the specified file.
  #
  if [ $subcommand == 'encrypt' ]; then
    if [ "X$user_key" == 'X' ]; then
      user_key=`readlink -f ~/.ssh/id_rsa.pub`
    fi

    if [ ! -e $user_key ]; then
      >&2 echo "User key file '$user_key' does not exist."
      exit 1
    fi

    key_file=`tempfile`
    openssl rand 64 >$key_file

    pem_file=`tempfile`
    ssh-keygen -f $user_key -e -m PKCS8 >$pem_file

    crypt_key_file=`tempfile`
    openssl rsautl -encrypt -pubin -inkey $pem_file -in $key_file -out $crypt_key_file
    crypt_key_len=`cat $crypt_key_file | wc -c`
    crypt_key_length=$((10000 + $crypt_key_len))

    echo -n `printf '%x%x' 95 $crypt_key_length`
    cat $crypt_key_file
    echo -n `printf '%x' 95`
    openssl enc -aes-256-cbc -salt -pass file:$key_file -in $user_file 

    rm -f $key_file $pem_file $crypt_key_file

  #
  # Decrypt the specified file.
  #
  elif [ $subcommand == 'decrypt' ]; then
    if [ "X$user_key" == 'X' ]; then
      user_key=`readlink -f ~/.ssh/id_rsa`
    fi

    if [ ! -e $user_key ]; then
      >&2 echo "User key file '$user_key' does not exist."
      exit 1
    fi

    hex_data=`dd bs=1 if=$user_file skip=0 count=6 2>/dev/null`
    magic_number=${hex_data:0:2}

    if [ "$magic_number" != '5f' ]; then
      >&2 echo "File '$user_file' is not an ssh public key encrypted file."
      exit 1
    fi

    crypt_key_len=$((16#${hex_data:2:4}-10000))

    skip=$((2+4+$crypt_key_len))
    magic_number=`dd bs=1 if=$user_file skip=$skip count=2 2>/dev/null`
    if [ "$magic_number" != '5f' ]; then
      >&2 echo "File '$user_file' is not an ssh public key encrypted file."
      exit 1
    fi

    crypt_key_file=`tempfile`
    `dd bs=1 if=$user_file of=$crypt_key_file skip=6 count=$crypt_key_len 2>/dev/null`

    key_file=`tempfile`
    `openssl rsautl -decrypt -inkey $user_key -in $crypt_key_file -out $key_file`

    crypt_user_file=`tempfile`
    skip=$((2+4+$crypt_key_len+2+1))
    `tail -c +$skip $user_file >$crypt_user_file 2>/dev/null`

    openssl enc -d -aes-256-cbc -pass file:$key_file -in $crypt_user_file

    rm -f $crypt_key_file $key_file $crypt_user_file
  fi


More information about the openssh-unix-dev mailing list