0

I'm automating key generation with ssh-keygen (OpenSSH v8.9), on a headless server. This is straightforward if no password is required, but gets difficult if you do need a password. ssh-keygen needs 3 things on stdin when generating a new key: y, because the keyfile already exists, and the required password, repeated twice.

With some simplification I'm doing this as follows:

$ printf -v input "y\npassword\npassword\n"
$ echo -n "$input"
y
password
password
$ echo -n "$input" | ssh-keygen -t ed25519 -a100 -f tmpkey

When I initially did this I got this output:

Generating public/private ed25519 key pair.
tmpkey already exists.
Overwrite (y/n)? ssh_askpass: exec(/usr/bin/ssh-askpass): No such file or directory

The key pair was created, but the private key wasn't encrypted. So, I installed ssh-askpass, on a test system with X. When I run ssh-keygen now, I get an OpenSSH authentication popup, and stdin is now ignored. Obviously, I can't have a graphical popup on a headless server, even if I wanted it.

So what's going on? Can I persuade ssh-keygen to automate password entry? If not, can I perhaps use openssl to add a password, or even create the file? I do want to get an OpenSSH-format key out of this - I'm already automating PKCS#8 with openssl.

EDIT

I've found the SSH_ASKPASS_REQUIRE envvar for ssh (not ssh-keygen). If I set it to 'never', it does stop the ssh-askpass popup, but ssh-keygen now only reads the first line of stdin, and ignores the password on the next two lines. So, it doesn't get me anywhere.

EML
  • 537
  • 5
  • 15
QF0
  • 225

2 Answers2

1

You can instead generate the key using PuTTYgen, as dave_thompson_085 pointed out in the comments. Spoiler: you probably don't want to do this, as puttygen appears to have incomplete OpenSSH support.

This will get you an OpenSSH private key:

prikey=$(echo "$password" | puttygen -q -t ed25519 -C '' -O private-openssh-new -o /dev/stdout --new-passphrase /dev/stdin)

The passphrase is on stdin, and the key goes to stdout, so there's nothing recorded in your bash history, or in the ps output. You can now get the public key as:

 tmppipe=$(mktemp -u)
 mkfifo -m 600 "$tmppipe"
 echo "$prikey" > "$tmppipe" &
 pubkey=$(echo "$password" | puttygen "$tmppipe" --old-passphrase /dev/stdin -O public-openssh)

So far, this is way better than ssh-keygen. However, the fly in the ointment is -a100. The procedure above generates a key file with the default 16 KDF rounds.

The puttygen docs (actually the man page; there are no written docs, I think) aren't clear on setting the number of KDF rounds, but it looks like you can set this with --ppk-param passes=$rounds. This does appear to work if you're generating a PuTTY PPK file, but doesn't work for an OpenSSH file. puttygen doesn't complain, but the key file still shows 16 rounds, and making rounds a big number makes no difference to the time required to decrypt the key. To find the number of rounds coded in the file, see Gilles' answer here.

Unless I've missed something in the man page, this makes puttygen pretty pointless for generating OpenSSH keys with passphrases. I personally would use ssh-keygen and hope no-one's looking when you're making the keys. As far as I can make out, you also can't use puttygen for changing the comment in the key file.

EML
  • 537
  • 5
  • 15
0

The way to provide the password is using -N:

echo y| ssh-keygen -t ed25519 -a100 -N "$input" -f tmpkey

Of course you should provide the variable input with content like yours:

input=password
Romeo Ninov
  • 6,677