15

I read man ssh-add and I don't see a flag for passing a passphrase like we have in ssh which is -p.

I tried

# the -K is for macOS's ssh-add but it's not relevant
ssh-add -q -K ~/.ssh/id_rsa <<< $passphrase

But I get the following output:

ssh_askpass: exec(/usr/X11R6/bin/ssh-askpass): No such file or directory

How can I pass a password w/o triggering a prompt

Update

Adding more context to what I'm doing, I'm creating a script to create SSH keys for me. It will generate the passphrase, the SSH key using that passphrase, and add it to the agent.

# ...
passphrase=$(generate_password)

ssh-keygen -t rsa -b 4096 -C $email -f $filename -N $passphrase -q
ssh-add -q -K $filename

Following Stephen's answer, I'm not sure how would that work. Seems like I'd had to create a temporal script and save it to disk, in order for SSH_ASKPASS to work. Any ideas?

4
  • FYI wrt temporary files & co: the here-string syntax (<<< $passphrase) will use a temporary file and store the passphrase into it (at least in bash, ksh and zsh)
    – user313992
    Mar 8, 2020 at 8:27
  • Warning: passing data on the command-line, may expose it to other processes on the same machine. Also consider: do you need a passphrase? Mar 8, 2020 at 9:34
  • You could use Homebrew to install ssh-askpass Mar 9, 2020 at 1:05
  • related: unix.stackexchange.com/q/90853
    – djvg
    Oct 6, 2021 at 12:24

2 Answers 2

22

From the ssh-add manpage:

 DISPLAY and SSH_ASKPASS
         If ssh-add needs a passphrase, it will read the passphrase from
         the current terminal if it was run from a terminal.  If ssh-add
         does not have a terminal associated with it but DISPLAY and
         SSH_ASKPASS are set, it will execute the program specified by
         SSH_ASKPASS (by default ``ssh-askpass'') and open an X11 window
         to read the passphrase.  This is particularly useful when calling
         ssh-add from a .xsession or related script.  (Note that on some
         machines it may be necessary to redirect the input from /dev/null
         to make this work.)

So we can use this to cheat a little.

We start with no identities in the agent:

$ ssh-add -l
The agent has no identities.

So now we need a program that will supply the password:

$ cat x
#!/bin/sh
echo test123

And then convince ssh-add to use that script:

$ DISPLAY=1 SSH_ASKPASS="./x" ssh-add test < /dev/null
Identity added: test (sweh@godzilla)

And there it is:

$ ssh-add -l                                          
2048 SHA256:07qZby7TafI10LWAMSvGFreY75L/js94pFuNcbhfSC0 sweh@godzilla (RSA)

Edit to add, based on revised question:

The password could be passed as a variable, and the askpass script use that variable.

For example:

$ cat /usr/local/sbin/auto-add-key
#!/bin/sh
echo $SSH_PASS

$ SSH_PASS=test123 DISPLAY=1 SSH_ASKPASS=/usr/local/sbin/auto-add-key ssh-add test < /dev/null
Identity added: test (sweh@godzilla)

In the workflow presented you would do SSH_PASS=$passphrase to use the newly generated passphrase.

1
  • Possible improvement: ssh-add will endlessly loop calling the SSH_ASKPASS program if password was bad, consider making auto-add-key exit if $1 starts with Bad (full content is "Bad passphrase, try again for /path/to/key" as of OpenSSH_9.3p1)
    – Asmadeus
    Nov 25 at 5:07
6

You can use script(1) as a mini-expect.

On Linux:

{ sleep .1; echo password; } | script -q /dev/null -c 'ssh-add /path/to/identity'

On BSD:

{ sleep .1; echo password; } | script -q /dev/null ssh-add /path/to/identity

You may want to increase the delay (sleep .3 or sleep 1) if the right hand of the pipeline is slow to start. For anything more complex, use expect. Do not use sshpass since it's really no better than script and itself subject to races.

6
  • You're right about the flag, I don't know why that came to mind; maybe it's a different tool that takes -p as password(?) I can't remember. Anyways, you're right Mar 8, 2020 at 6:20
  • Could you break down the first part of the expression, and how the solution works? I'm not sure why the sleep call Mar 8, 2020 at 6:21
  • Yes, sshpass. See the updated answer, I think the BSD syntax works in MacOS, too.
    – user313992
    Mar 8, 2020 at 6:21
  • The sleep is to give time to ssh-add to start, print its prompt and turn echo mode off on the pseudo-terminal created by script. Like with any pipeline, both sides of the pipeline are started in any order, and are run in parallel, at the same time.
    – user313992
    Mar 8, 2020 at 6:23
  • For this kind of timing problems (which also badly affect sshpass), see this Q&A.
    – user313992
    Mar 8, 2020 at 6:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .