opscape

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 ...

12 of 12 examples run in Debian 13.7 on 2026-10-31 · openssh-client 1:10.0p1-7+deb13u4 · manual: ssh-keygen(1)

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 ''
explain
output
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
output
-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
explain
output
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
explain
output
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
output
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.pub
ssh-keygen -y -f id_demo
explain
output
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'
explain
output
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
output
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
explain
output
# 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_hosts
ssh-keygen -R server -f ./known_hosts
explain
output
# 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
output
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
explain
outputexit 255
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-keygen with the default path when ~/.ssh/id_ed25519 exists 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 plus ssh-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.

OptionWhat it does
-t TYPEKey type: ed25519, rsa, ecdsa, or the -sk hardware-key variants.
-b BITSKey size in bits (for RSA and ECDSA).
-C COMMENTComment stored with the key, usually user@host.
-f FILEKey file to create or operate on (or known_hosts file with -F and -R).
-N PASSPHRASENew passphrase; '' for none.
-P PASSPHRASEOld passphrase, when changing it with -p.
-pChange the passphrase of a private key.
-cChange the comment of a key.
-lShow the fingerprint of a key file.
-E HASHFingerprint hash to show: sha256 (default) or md5.
-vVerbose; with -l, also print the randomart image.
-yPrint the public key derived from a private key.
-qQuiet: no report when generating.
-F HOSTFind HOST in a known_hosts file.
-R HOSTRemove all keys of HOST from a known_hosts file.
-HHash the host names in a known_hosts file.
-AGenerate any missing host keys of all default types (for servers).
-a ROUNDSKey derivation rounds for the passphrase; more is slower to brute-force.
-Y OPERATIONSignature operations: sign, verify, check-novalidate, find-principals.
-n NAMESPACESignature namespace (with -Y), or principals when signing certificates.
-s FILESignature file to verify (with -Y verify), or CA key when signing certificates.
-I IDENTITYSigner identity (with -Y verify), or certificate identity.
-eExport a key in another format (see -m).
-iImport a key from another format (see -m).
-m FORMATKey format for import, export or conversion: RFC4716, PKCS8 or PEM.

Related