Networking and remote
ssh-keygen
Create, inspect and manage SSH keys, and maintain known_hosts entries.
ssh-keygen [-t TYPE] [-C COMMENT] [-f FILE] [-N PASSPHRASE] | -l -f FILE | -y -f FILE | -R HOST ...
ssh-keygen makes the key pairs used to log in with ssh without a password: a private key
that never leaves your machine (~/.ssh/id_ed25519) and a public key (.pub) that you install
on servers with ssh-copy-id. Today the right default is ssh-keygen -t ed25519: short keys,
fast, and supported by every current server. Use RSA (at least 3072 bits) only for old systems
that lack Ed25519.
The same tool inspects keys (fingerprints with -l, rebuilding a lost .pub with -y),
changes a key's passphrase (-p) or comment (-c), cleans up known_hosts (-F to find a
host, -R to remove it) and signs files (-Y sign).
A passphrase encrypts the private key on disk; ssh's agent lets you type it once per
session. The examples write keys into the current directory with -f and use an empty
passphrase (-N '') so they run unattended; for your own keys, accept the default path and
choose a passphrase at the prompt.
Examples
Generate an Ed25519 key pair
ssh-keygen -t ed25519 -C "dev@laptop" -f ./id_demo -N ''
Generating public/private ed25519 key pair. Your identification has been saved in ./id_demo Your public key has been saved in ./id_demo.pub The key fingerprint is: SHA256:GYwAFwgDVVr9JA1u03ePQNSOa2iZY7mHd8/pqAqQZAI dev@laptop The key's randomart image is: +--[ED25519 256]--+ |Eoo+*o.o .o. | | o.+ oo+o. . | | o o =++ oo. | | + o ..+.o.o | | o S= .. . | | . O o | | .o = | | .o o .o . | | .+.o.o= | +----[SHA256]-----+
Two files are written: id_demo (private) and id_demo.pub (public). The fingerprint is
the short form you compare when verifying a key, and the "randomart" is a picture of the
same fingerprint. Both are random, so they differ every run. -C sets the comment at the
end of the public key, conventionally user@host.
What the key files look like
Setup run before this example
ssh-keygen -q -t ed25519 -C "dev@laptop" -f ./id_demo -N ''ls -l id_demo id_demo.pub
cat id_demo.pub
-rw------- 1 dev dev 399 Oct 31 20:21 id_demo -rw-r--r-- 1 dev dev 92 Oct 31 20:21 id_demo.pub ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILAW2NEgrZJKeuND/0S0TcQIjI9hbkjRInh7R5HQfrGp dev@laptop
The private key is mode 600 (only you can read it), and ssh refuses to use it otherwise.
The public key is one line: type, base64 key data and comment. That line is what goes into
a server's ~/.ssh/authorized_keys.
Show a key's fingerprint
Setup run before this example
ssh-keygen -q -t ed25519 -C "dev@laptop" -f ./id_demo -N ''ssh-keygen -lf id_demo.pub
256 SHA256:U+8H7PqWJgjRRb7yIY9ccrqEqVimEBbgELwOr/ztwvk dev@laptop (ED25519)
-l prints the size in bits, the SHA256 fingerprint, the comment and the type. Compare it
with what a server or a colleague shows to confirm it is the same key.
The old MD5 fingerprint format
Setup run before this example
ssh-keygen -q -t ed25519 -C "dev@laptop" -f ./id_demo -N ''ssh-keygen -E md5 -lf id_demo.pub
256 MD5:94:9b:b7:c1:75:f9:bd:7a:8d:3b:ee:4c:e7:83:06:21 dev@laptop (ED25519)
Some older tools and web consoles still show colon-separated MD5 fingerprints. -E md5
prints that form for comparison.
Generate an RSA key for older systems
ssh-keygen -q -t rsa -b 4096 -C "legacy" -f ./id_rsa_demo -N ''
ssh-keygen -lf id_rsa_demo.pub
4096 SHA256:Fj3qcFpEOI0LErQhDJMJrl5gnyERbpf/cDd0npSAPXo legacy (RSA)
-b 4096 sets the key size and -q silences the report. The fingerprint line shows
4096 and (RSA).
Recreate a lost public key
Setup run before this example
ssh-keygen -q -t ed25519 -C "dev@laptop" -f ./id_demo -N ''
rm id_demo.pubssh-keygen -y -f id_demo
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDLWxB+GJ0QJv9vsMof+sYM65ejDUCB6knDp+XSIUZNK dev@laptop
-y reads the private key (asking for the passphrase if it has one) and prints the public
key. Redirect it to id_demo.pub to restore the file.
Add or change a passphrase
Setup run before this example
ssh-keygen -q -t ed25519 -C "dev@laptop" -f ./id_demo -N ''ssh-keygen -p -f id_demo -P '' -N 'correct horse battery'
Key has comment 'dev@laptop' Your identification has been saved with the new passphrase.
-p rewrites the private key with a new passphrase: -P is the old one (empty here) and
-N the new one. Interactively, leave both out and you are prompted, which keeps the
passphrase out of your shell history.
Change a key's comment
Setup run before this example
ssh-keygen -q -t ed25519 -C "dev@laptop" -f ./id_demo -N ''ssh-keygen -c -C "dev@workstation" -f id_demo
cat id_demo.pub
Old comment: dev@laptop Comment 'dev@workstation' applied ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEylBfA8NI9qys9hUzem6vgIkcHN4M3gg4zVnwToRcRk dev@workstation
-c changes the comment stored in the private key and rewrites the .pub file to match.
Look up a host in known_hosts
ssh-keygen -F server
# Host server found: line 1 server,localhost,127.0.0.1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBrLmL1ZqP7QFVURKaGSZ2CBR+wEZEBFAx7EgM4/l6+K
-F searches ~/.ssh/known_hosts and prints the matching line with its line number. It
also works when the file stores hashed host names, which grep cannot search.
Remove a host's old key from known_hosts
Setup run before this example
cp ~/.ssh/known_hosts ./known_hostsssh-keygen -R server -f ./known_hosts
# Host server found: line 1 ./known_hosts updated. Original contents retained as ./known_hosts.old
-R deletes every key for that host and keeps a backup as known_hosts.old. This is the
fix after a server is legitimately reinstalled; the example works on a copy (-f) so the
real file is untouched. Without -f it edits ~/.ssh/known_hosts.
Sign and verify a file with an SSH key
Setup run before this example
ssh-keygen -q -t ed25519 -C "dev@laptop" -f ./id_demo -N ''ssh-keygen -Y sign -f id_demo -n file todo.txt
echo "dev@laptop $(cat id_demo.pub)" > allowed_signers
ssh-keygen -Y verify -f allowed_signers -I dev@laptop -n file -s todo.txt.sig < todo.txt
Signing file todo.txt Write signature to todo.txt.sig Good "file" signature for dev@laptop with ED25519 key SHA256:gtVdpHfYtQIBgEMRKEAqD2wXvDkDnAEJwTJ5OAA9iJE
-Y sign writes todo.txt.sig; -n file is a namespace that stops a signature made for
one purpose being reused for another. Verification takes a list of trusted keys, the signer
identity and the data on standard input. git can use the same mechanism to sign commits.
Reading something that is not a key
ssh-keygen -lf todo.txt
todo.txt is not a public key file.
ssh-keygen says the file is not a public key file and exits with 255.
Common pitfalls
Running
ssh-keygenwith the default path when~/.ssh/id_ed25519exists asks whether to overwrite it. Answering yes destroys the old key and locks you out of every server that only knows it.Never share or copy the file without
.pub. Only the public key goes to servers, repositories and colleagues.-N ''creates an unencrypted private key. That is fine for automation keys with limited access, but personal keys deserve a passphrase plusssh-agent.OpenSSH 10.0 removed DSA support entirely, and current versions refuse RSA keys shorter than 1024 bits. Replace such keys with Ed25519.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
All platforms use OpenSSH's ssh-keygen; options match. macOS adds keychain integration to
ssh-add(--apple-use-keychain), not to ssh-keygen.
Options worth knowing
A selection, described in our own words. For the full list, see ssh-keygen(1) or ssh-keygen --help.
| Option | What it does |
|---|---|
-t TYPE | Key type: ed25519, rsa, ecdsa, or the -sk hardware-key variants. |
-b BITS | Key size in bits (for RSA and ECDSA). |
-C COMMENT | Comment stored with the key, usually user@host. |
-f FILE | Key file to create or operate on (or known_hosts file with -F and -R). |
-N PASSPHRASE | New passphrase; '' for none. |
-P PASSPHRASE | Old passphrase, when changing it with -p. |
-p | Change the passphrase of a private key. |
-c | Change the comment of a key. |
-l | Show the fingerprint of a key file. |
-E HASH | Fingerprint hash to show: sha256 (default) or md5. |
-v | Verbose; with -l, also print the randomart image. |
-y | Print the public key derived from a private key. |
-q | Quiet: no report when generating. |
-F HOST | Find HOST in a known_hosts file. |
-R HOST | Remove all keys of HOST from a known_hosts file. |
-H | Hash the host names in a known_hosts file. |
-A | Generate any missing host keys of all default types (for servers). |
-a ROUNDS | Key derivation rounds for the passphrase; more is slower to brute-force. |
-Y OPERATION | Signature operations: sign, verify, check-novalidate, find-principals. |
-n NAMESPACE | Signature namespace (with -Y), or principals when signing certificates. |
-s FILE | Signature file to verify (with -Y verify), or CA key when signing certificates. |
-I IDENTITY | Signer identity (with -Y verify), or certificate identity. |
-e | Export a key in another format (see -m). |
-i | Import a key from another format (see -m). |
-m FORMAT | Key format for import, export or conversion: RFC4716, PKCS8 or PEM. |
Related
sshLog in to a remote machine or run a command on it over an encrypted connection; also forwards ports and jumps through hosts.ssh-copy-idInstall your public SSH key in a remote account's authorized_keys so you can log in without a password.scpCopy files between hosts over ssh, with cp-like syntax where a remote path is written HOST:PATH.