210

I would like to make an automated script that calls ssh-keygen and creates some pub/private keypairs that I will use later on. In principle everything works fine with....
ssh-keygen -b 2048 -t rsa -f /tmp/sshkey -q
...except that it asks me for the passphrase that would encrypt the keys. This make -at present- the automation difficult.

I could provide a passphrase via the command line argument -N thepassphrase, so to keep the prompt from appearing. Still I do not even desire to have the keys -additionally secured by encryption- and want the keypairs to be plaintext.

What is a (the best) solution to this problem?

The -q option which supposedly means "quiet/silent" does still not avoid the passphrase interaction. Also I have not found something like this
ssh-keygen ... -q --no-passphrase

Please do not start preaching about or lecture me to the pro and cons of the "missing passphrase", I am aware of that. In the interactive form (not as a script) the user can simply hit [ENTER] twice and the key will be saved as plaintext. This is what I want to achieve in a script like this:

#!/bin/bash

command1 command2 var=$(command3)

this should not stop the script and ask for password

ssh-keygen -b 2048 -t rsa -f /tmp/sshkey -q

Joe Holloway
  • 103
  • 4

8 Answers8

267

This will prevent the passphrase prompt from appearing and set the key-pair to be stored in plaintext (which of course carries all the disadvantages and risks of that):

ssh-keygen -b 2048 -t rsa -f /tmp/sshkey -q -N ""

Using Windows 10 built in SSH

PowerShell:

ssh-keygen -b 2048 -t rsa -f C:/temp/sshkey -q -N '""'

CMD:

ssh-keygen -b 2048 -t rsa -f C:/temp/sshkey -q -N ""
Will Huang
  • 103
  • 5
  • 8
    This works. In case /tmp/sshkey already exists one gets an overwrite prompt, though. This can be prevented via redirecting/closing stdin - e.g. via adding 0>&-. – maxschlepzig Feb 04 '18 at 19:05
  • 6
    So bad practice to generate a clear pair of keys in /tmp ;) – tisc0 Feb 24 '20 at 16:03
  • 3
    To make it not ask questions it's enough to specify the destination (-f ~/.ssh/id_rsa), and specify a passphrase (-N ''). – x-yuri Apr 01 '21 at 23:06
  • Is it possible to do this as another user? When I try to do this it errors: sudo -i -u $user_name ssh-keygen -b 2048 -t rsa -f /tmp/sshkey -q -N "" option requires an argument -- N – openCivilisation Apr 05 '21 at 05:01
  • Thanks for the PowerShell example! – Cameron Kerr Jun 18 '21 at 11:49
  • 2
    Powershell should be ssh-keygen -t rsa -b 4096 -f "C:/temp/sshkey" -q -N '""' (single quotes around a set of double quotes). While 2 sets of double quotes works in this specific case, it can cause issues when paired with additional arguments (such as empty comment/-C e.g. ssh-keygen -t rsa -b 4096 -f "C:/temp/sshkey" -q -N '""' -C '""' ). – PotatoFarmer Jul 09 '21 at 02:43
  • 1
    This is a variation I came up with, in my case I needed to overwrite any previous ssh keys so mine looks like this HOSTNAME=$(hostname) ; yes | ssh-keygen -t rsa -C "$HOSTNAME" -f "$HOME/.ssh/id_rsa" -P "" && cat ~/.ssh/id_rsa.pub – ruevaughn Jan 10 '22 at 07:28
  • @PotatoFarmer prefixing arguments with --% stops powershell of interpreting arguments as commands or expressions. The stop-parsing token – Janis Veinbergs Nov 24 '22 at 15:12
61

The simplest way I found to do what you want is this (example using default filename)

    < /dev/zero ssh-keygen -q -N ""

If the ~/.ssh/id_rsa file already exists, the command will exit without modifying anything.

If not, you get a brand new key, in that filename.

Either way, you haven't overwritten anything, and you know at the end you have a key.

cmc
  • 174
JoaoCC
  • 771
27

This worked for me:

ssh-keygen -t rsa -f /home/oracle/.ssh/id_rsa -q -P ""

The -P is the passphrase option, and "" is the empty passphrase.

slm
  • 369,824
gowrish
  • 295
7

You can use expect to send the "enter" for you

cat test.sh
#!/bin/bash
set -x
XYZ=$(expect -c "
spawn ssh-keygen -b 2048 -t rsa -f /tmp/sshkey -q
expect \"Enter passphrase (empty for no passphrase):\"
send \"\r\"
expect \"Enter same passphrase again:\"
send \"\r\"
")

But be aware, that if the file /tmp/sshkey already exists it will fail because the output of the command will be different.

BitsOfNix
  • 5,117
  • 1
    thank you for the contribution. the expect seems even a more versatile for problems in the same kind.... well those where scripting and user-interaction would conflict. I will be aware of the potential conflicht that /tmp/sshkey already exists and check for it prior to using your command. – humanityANDpeace Mar 27 '13 at 14:26
3

For another user, tested on Ubuntu 18.04:

sudo -u username bash -c "ssh-keygen -f ~username/.ssh/id_rsa -N ''"
  • What is the relevance of doing it for another user? How does ssh-keygen depend on the user running it? I'm just trying to understand this better. Thanks. – pgr Nov 02 '20 at 16:17
  • 2
    Good point. One benefit is the rights are set correct by ssh-keygen. I have updated the answer to put the file straight in the right place. Now the command does everything in one go: no need to move files or change rights. – Jeroen Vermeulen Nov 02 '20 at 23:31
2

I did a simple echo before ssh-keygen. So su - <user> -c "echo |ssh-keygen -t rsa"

This was tested on Redhat 6

Anthon
  • 79,293
koopsj
  • 21
  • I don't think this is the best answer around, but I think there isn't any reason to downvote either, guys. – cubuspl42 Nov 01 '16 at 15:05
2

ssh key generation function which can be put into .bashrc or .bash_aliases

# Make an ssh key if not exists, and copy ssh key to clipboard
# needs xclip to copy to system clipboard
ssh-key-now () {
    cat /dev/zero | ssh-keygen -t ed25519 -C "made with ssh-key-now" -q -N ""
    xclip -sel clip < ~/.ssh/id_ed25519.pub
    echo "ssh-key copied to clipboard"
}

Saves time when you've reinstalled OS and lost your ssh keys and have to set up gitlab/github again

Ace.C
  • 121
0

The following works:

sudo -u user ssh-keygen -t rsa -N '' <<<''

It is intended to create the directory ~user/.ssh/, so that the file ~user/.ssh/authorized_keys can be created and updated to hold a public key for incoming ssh access.

A key pair is also generated but not needed for this purpose.

For example, one can prepare a boot-time init (kernel) parameter to preseed a live system for ssh access as follows:

ID=$(cat ~/.ssh/id_rsa.pub)
pr1="sudo -u user ssh-keygen -t rsa -N '' <<<''; echo '$ID' | sudo -u user tee -a ~user/.ssh/authorized_keys"

Include "$pr1" in the appropriate kernel parameter as a command which gets run automatically, as in ocs_prerun1="$pr1" for Clonezilla. Also verify that ssh service is enabled, as in ocs_daemonon="ssh".