How to make ssh-add read passphrase from a file?

Depending on your distribution and on the version of ssh-add you may be able or not to use the -p option of ssh-add that reads the passphrase from stdin in this way:

cat passfile | ssh-add -p keyfile

If this is not working you can use Expect, a Unix tool to make interactive applications non-interactive. You'll have to install it from your package manager.

I have written a tool for you in expect. Just copy the content in a file named ssh-add-pass and set executable permissions on it (chmod +x ssh-add-pass). You can also copy it to /usr/bin or /usr/local/bin to be accessible from the $PATH search.

#!/bin/bash

if [ $# -ne 2 ] ; then
  echo "Usage: ssh-add-pass keyfile passfile"
  exit 1
fi

eval $(ssh-agent)
pass=$(cat $2)

expect << EOF
  spawn ssh-add $1
  expect "Enter passphrase"
  send "$pass\r"
  expect eof
EOF

The usage is simply: ssh-add-pass keyfile passfile


Here is some workaround for systems not supporting -p:

$ PASS="my_passphrase"
$ install -vm700 <(echo "echo $PASS") "$PWD/ps.sh"
$ cat id_rsa | SSH_ASKPASS="$PWD/ps.sh" ssh-add - && rm -v "$PWD/ps.sh"

where ps.sh is basically your script printing your passphrase. See: man ssh-add.

To make it more secure (to not keep it in the same file), use mktemp to generate a random private file, make it executable (chmod) and make sure it prints the passphrase to standard output once executed.


Similar to the answer by kenorb, but doesn't save the secret in a file:

$ SSH_ASKPASS=/path/to/ssh_give_pass.sh ssh-add $KEYFILE <<< "$KEYPASS"

where ssh_give_pass.sh is:

#!/bin/bash
# Parameter $1 passed to the script is the prompt text
# READ Secret from STDIN and echo it
read SECRET
echo $SECRET

If you have you secret in a $KEYPASSFILE, read it into a variable first with

KEYPASS=`cat $KEYPASSFILE`

Also make sure that ssh_give_pass.sh is not editable by unauthorized users - it will be easy to log all secrets passed through the script.

Tags:

Ssh

Ssh Agent