Most SSH implementations include a program for creating key pairs. We cover ssh-keygen from OpenSSH and Tectia.
OpenSSH uses the program ssh-keygen to create key pairs. [2.4.2] Let's go into more detail about this program for creating new keys or modifying existing keys.
When creating a new key, you must indicate the key type (DSA or RSA) using the -t flag:
$ ssh-keygen -t dsa
You may also specify these options for creating keys:
The number of bits in the key, using -b; the default is 1024 bits:
$ ssh-keygen -t dsa -b 2048
The name of the private-key file to be generated, using -f. The name is relative to your current directory. Recall that the public-key file is named after the private one with .pub appended.
$ ssh-keygen -t dsa -f mykey Creates mykey and mykey.pub
If you omit the -f option, you are prompted for the information:
$ ssh-keygen -t dsa
...
Enter file in which to save the key (/home/barrett/.ssh/id_dsa): mykey
The default filename for DSA keys is ~/.ssh/id_dsa, and for RSA keys it's ~/.ssh/id_rsa.
The passphrase to decode the key, using -N:
$ ssh-keygen -t dsa -N secretword
If you omit this option, you'll be prompted for the information:
$ ssh-keygen -t dsa ... Enter passphrase: [nothing is echoed] Enter the same passphrase again: [nothing is echoed]
A textual comment associated with the key, using
-C. If you omit this option, the comment is
username
@host
,
where username
is your username and
host
is the local hostname:
$ ssh-keygen ... -C "my favorite key"
Before using any option that places your passphrase on the shell command line, such as the -N or -P options of ssh-keygen, carefully consider the security implications. Because the passphrase appears on your screen, it may be visible to onlookers, and while running, it may be visible to other users viewing the machine's process list via the ps command. In addition, if your shell creates history files of the commands you type, the passphrase is inserted into a history file where it can be read by a third party.
Also, if you think you have a good reason just to type Return and give your key no passphrase, think again. That is essentially equivalent to putting your password in a file in your home directory named MY-PASSWORD.PLEASE-STEAL-ME. If you don't want to have to type a passphrase, the right thing to do is to use ssh-agent, hostbased authentication, or Kerberos. There are very limited circumstances having to do with unattended usage (e.g., cron jobs) where a plaintext, passphrase-less client key might be acceptable. [11.1]
If you use both -f (specify output file) and -N (specify passphrase), ssh-keygen issues no prompts. Therefore, you can automate key generation using these options (and perhaps redirecting output to /dev/null):
$ ssh-keygen -f mykey -N secretword
You might use this technique to automate generation of a large number of keys for some purpose. Use it carefully, though, and always on a secure machine. The password on the command line is probably visible to other users on the same machine via ps or similar programs; and if you're scripting with this technique, obviously the passphrases shouldn't be kept in files for long.
In addition to creating keys, ssh-keygen can manipulate existing keys in the following ways:
Changing the passphrase of an existing key, using
-
p. You can specify the
filename with -f and the old and new
passphrases with -P and
-N, respectively:
$ ssh-keygen -t dsa -p -f mykey -P secretword -N newword Your identification has been saved with the new passphrase.
But if you omit them, you are prompted:
$ ssh-keygen -t dsa -p
Enter file in which the key is (/home/barrett/.ssh/id_rsa): mykey
Enter old passphrase: [nothing is echoed]
Key has comment 'my favorite key'
Enter new passphrase (empty for no passphrase): [nothing is echoed]
Enter the same passphrase again:
Your identification has been saved with the new passphrase.
Note that this changes the passphrase but doesn't change the key, it just re-encrypts the key with the new passphrase. So, the corresponding public-key file on remote machines doesn't change or need to be replaced.
Printing the fingerprint of a given key file, with -l. See the sidebar "Key Fingerprints" for more information. The fingerprint can be calculated from the public key:
$ ssh-keygen -l -f stevekey.pub 1024 5c:f6:e2:15:39:14:1a:8b:4c:93:44:57:6b:c6:f4:17 steve@snailbook.com $ ssh-keygen -B -f stevekey.pub 1024 xitot-larit-gumet-fyfim-sozev-vyned-cigeb-sariv-tekuk-badus-bexax Steve@snailbook.com
Printing a DNS resource record with -r, and using DNS resource record format with -g. These options produce key fingerprints in a format suitable for a BIND nameserver, for the purposes of verifying SSH host keys via the DNS. [7.4.3.2]
Converting between SECSH (Tectia) and OpenSSH key-storage formats, with -e, -i, and -y.
Option | Extract/convert from... | To... |
---|---|---|
-e | OpenSSH private-key file ("export") | SECSH public key (Tectia format) |
-i | SECSH public-key file ("import") | OpenSSH public key |
-y | OpenSSH private-key file | OpenSSH public key |
An OpenSSH "private" key file actually contains both the
public and private keys of a pair, so the
-e and -y options
simply extract the public key and print it out in the desired
format. Use -e to convert an OpenSSH public
key for your ~/.ssh2/authorization file on a
Tectia server host, and -i
to do the opposite.
The -y option is useful if you accidentally
delete your OpenSSH public-key file and need to restore it.
Tectia keys are in a format called SECSH Public Key File Format
or SSH2 format, also used by other SSH implementations whose
keys you may import and export.
A function that's missing is converting the private keys as well. This is useful if you have an OpenSSH server host on which you also want to run Tectia, and you want the two SSH servers to share a host key.
When you make changes to a key, such as its passphrase or comment, the changes are applied to the key file only. If you have keys loaded in an SSH agent, the copies in the agent don't get changed. For instance, if you list the keys in the agent with ssh-add -l (lowercase L) after changing the comment, you still see the old comment in the agent. To make the changes take effect in the agent, unload and reload the affected keys.
Tectia also uses a program named ssh-keygen to create key pairs and manipulate existing keys.
When creating a new key, you may choose the name of the private-key file to be generated, by specifying the name at the end of the command line:
$ ssh-keygen mykey creates mykey and mykey.pub
The name is relative to your current directory, and as usual, the public key file is named after the private one with .pub appended. The key is saved in the directory ~/.ssh2 in a file whose name indicates the key type and number of bits. An example is id_dsa_2048_a, which was generated by the DSA algorithm with 2048 bits.
You also may indicate the following with command-line options:
The number of bits in the key, using -b; the default is 2048 bits:
$ ssh-keygen -b 4096
The key type, such as DSA or RSA, using -t:
$ ssh-keygen -t dsa
A textual comment associated with the key, using -c:
$ ssh-keygen -c "my favorite Tectia key"
If you omit this option, the generated comment describes how and by whom the key was generated. For example:
"2048-bit dsa, barrett@server.example.com, Tue Feb 22 2000 02:03:36"
The passphrase to decode the key, using -p. If you omit this option, you are prompted after generation.
$ ssh-keygen -p secretword
You can also designate an empty password using -P. This shouldn't be done in general but is appropriate in some special cases: [11.1.2.2]
$ ssh-keygen -P
Whether or not to overwrite the key file, if it already
exists, with --overwrite
and the value yes
(the default) or no
:
$ ssh-keygen --overwrite no mykeyfile
In addition to creating keys, ssh-keygen can operate on keys in the following ways:
By changing the passphrase and comment of an existing key, using -e. This option causes ssh-keygen to become interactive, prompting for the new information. This interactive mode is primitive and annoying, requiring nearly 10 user responses to change the passphrase and comment, but it does the job:
$ ssh-keygen -e mykey Passphrase needed for key "my favorite Tectia key" Passphrase : [nothing is echoed] Do you want to edit key "my favorite Tectia key" (yes or no)?yes
Your key comment is "my favorite Tectia key". Do you want to edit it (yes or no)?yes
New key comment:this is tedious
Do you want to edit passphrase (yes or no)?yes
New passphrase : [nothing is echoed] Again : [nothing is echoed] Do you want to continue editing key "this is tedious" (yes or no)?god no
(yes or no)?no
Do you want to save key "this is tedious" to file mykey (yes or no)?yes
Changes are applied to the key files but not propagated to any copies currently loaded in an agent. (So, if you run ssh-add -l to list the keys in your agent, for example, you still see the old comment.)
By converting between various key-storage formats, with the following options:
Option | Extract/convert from... | To... |
---|---|---|
a Handy if you ever lose your public-key file. | ||
-1 | SSH1 key | SECSH key |
| OpenSSH public key | SECSH public key |
| OpenSSH private key, unencrypted only | SECSH private key |
| An OpenSSH or SSH1 authorized_keys file | Tectia authorization file, plus an individual file for each referenced public key |
-D | SECSH private key | SECSH public key a |
-x | X.509 private key | SECSH private key |
-k | PKCS 12 file | SECSH certificate and private key |
-7 | PKCS 7 file | Certificates from that file |
ssh-keygen also gives you some control over input, output, and diagnostics:
By printing the fingerprint of a given key file, with -F. See the sidebar "Key Fingerprints" for more information. [6.2] The fingerprint is calculated from the public key:
$ ssh-keygen -F stevekey.pub Fingerprint for key: xitot-larit-gumet-fyfim-sozev-vyned-cigeb-sariv-tekuk-badus-bexax
By printing cryptographic information about a key, with -i:
$ ssh-keygen -i stevekey.pub DSA Public Key [Strength estimation as of July, 2000 considering NFS and Pollard rho: Attack requires O(2^80) steps, which is roughly equivalent to 6.7 * 10^7 years of effort with 1GHz machine.] p = [Large prime, characteristic of the finite field] 18257155510680634708091813901445079313554557329637337413272033369505053693222548 32994959179095338002184212706407725165597654255005411958024968996544803955496850. ...
You can display this information in different bases with -B; the default is base 10:
$ ssh-keygen -i -B 16 stevekey.pub Base 16, hexadecimal
...
0x909fe130f9fa7192dc2a28591a53c0687...
By printing the program version number, with -V:
$ ssh-keygen -V ssh-keygen: SSH Tectia Server 4.2.1 on i686-pc-linux-gnu Build: 1 Crypto library version: SSH Cryptographic Library, version 1.2.4
By printing a help message, with -h or -?; most Unix shells require you to escape the question mark to prevent the shell from interpreting it as a wildcard:
$ ssh-keygen -h
$ ssh-keygen -\? escaping the question mark
By printing debug information, with -d, as for Tectia's sshd. [5.9]
By suppressing the progress indicator, using
-q. The progress indicator is a sequence of
O's and periods that displays while
ssh-keygen runs, like this: .oOo.oOo.oOo.oOo
:
$ ssh-keygen Generating 2048-bit dsa key pair .oOo.oOo.oOo.oOo Key generated. $ ssh-keygen -q Generating 2048-bit dsa key pair Key generated.
Finally, ssh-keygen has one guru-level
advanced option, -r, for affecting the random
numbers used for key generation. It causes
ssh-keygen to modify ~/.ssh2/random_seed using data you enter
on standard input. [3.6.4] The Tectia manpages
call this "stirring data into the random pool." Note that the
program doesn't prompt you to enter data, it just sits there looking
like it's hung. When this occurs, type as much data as you like and
press the EOF character (Control-D
in most shells):
$ ssh-keygen -rI am stirring the random pool.
blah blah blah
^D Stirred in 46 bytes.
See Table 6-1 for a description of ssh-keygen options.
Table 6-1. ssh-keygen options
ssh-keygen feature | OpenSSH | Tectia |
---|---|---|
a Any illegal argument, such as -h, causes a help message to print. | ||
b You might need to escape the question mark in your shell, e.g., -\?. | ||
c The key file format used by SSH Tectia and several other implementations, but not OpenSSH. | ||
Set number of bits | -b | -b |
Set output file | -f | final argument of the command |
Overwrite output file if present | --overwrite
| |
Set comment string | -C
| -c
|
Change comment string | -c | -e |
Set (new) passphrase | -N
| -p
|
Set empty passphrase | -N `' | -P |
Specify current passphrase | -P | |
Change passphrase | -p | -e |
Set encryption algorithm | -t
| -t
|
Change encryption algorithm | -u | |
Derive public key from private | -D | |
Quieter output | -q | -q |
Describe key | -i | |
Set numeric base for printing key information | -B | |
Print version number | -V | -V |
Print help message | -h a | -h, -? b |
Print debugging information | -d
| |
Use data from stdin for randomness | -r | |
Print a key's fingerprint | - l or -B | -F file |
Convert from SSH-1 to SSH-2 format | -1 file | |
Convert OpenSSH private to Tectia public | -e | |
Convert OpenSSH private to Tectia private | | |
Convert Tectia public to OpenSSH public | -i | |
Extract OpenSSH private to public | -y | |
Convert authorized_keys to authorization file | | |
Convert X.509 key to SECSH format c | -x file | |
Convert PKCS 12 file to SECSH format | -k file | |
Convert PKCS 7 file to SECSH format | -7 file |
Choose your passphrases carefully. Make them at least 10 characters long, containing a mix of uppercase and lowercase letters, digits, and nonalphanumeric symbols. At the same time, you want the passphrase to be easy to remember, but hard for others to guess. Don't use your name, username, phone number, or other easily guessed information in the passphrase. Coming up with an effective passphrase can be a chore, but the added security is worth it.
If you forget a passphrase, you are out of luck: the corresponding SSH private key becomes unusable because you can't decrypt it. The same encryption that makes SSH so secure also makes passphrases impossible to recover. You have to abandon your SSH key, generate a new one, and choose a new passphrase for it. You must also install the new public key on every machine that holds the original one.
As we saw in Chapter 3, the SSH Transport Protocol uses the Diffie-Hellman key-agreement algorithm to generate cryptographic session keys for the SSH connection. [3.8.1.3] One parameter to this algorithm is a mathematical structure from algebra known as a "group"; specifically, a finite integer group with respect to multiplication modulo a prime. In the initial SSH protocol, a single fixed group was used for the key exchange. Due to concern over possible future attacks against this fixed parameter, an extension was created to allow the group to be negotiated, and this extension is now widely implemented.
The OpenSSH server selects the groups to be offered the client from the file /etc/moduli. OpenSSH comes with a moduli file defining a set of suitable groups, and for most people this is sufficient; there is no pressing need to regenerate them. On particularly slow systems, you might edit this file to select groups with a smaller prime modulus, to speed up the key exchange.
If you like, you can generate your own set of key-exchange groups using ssh-keygen -G. This usage is quite technical and infrequently used, so we won't delve further into it here; refer to the ssh-keygen manpage, in the section "MODULI GENERATION," for details. You can also see an example in OpenBSD's usr/src/etc/Makefile for OpenSSH, e.g.: