ssh-keygen 命令详解与参数实测(Ubuntu 22.04)
以 Ubuntu 22.04(openssh-client 8.9p1)实测逐参数讲解 ssh-keygen 命令:-t rsa/ecdsa/ed25519/dsa、-b 位长、-C 注释、-f 路径、-N 口令与空口令、-q 静默、-l 指纹、-y 导出公钥、-p 改口令、-c 改注释、-F/-R 管理 known_hosts,以及密钥文件 600 权限语义,全部选项与真实回显实测通过。
ssh-keygen 命令详解与参数实测(Ubuntu 22.04)
目标:全面掌握 ssh-keygen 的常用参数——
-t选择 RSA/ECDSA/Ed25519/DSA 算法、-b位长、-C注释、-f输出路径、-N口令(含空口令-N '')、-q静默、-l指纹校验、-y从私钥导出公钥、-p改口令、-c改注释、-F/-R管理 known_hosts,以及私钥文件 600 权限的强制语义,全部命令与回显已在 Ubuntu 22.04(OpenSSH 8.9p1)实测通过。
一、环境信息
本文所有命令均在以下真实服务器环境逐条执行并记录回显,读者可按相同条件复现:
- 操作系统:Ubuntu 22.04.5 LTS,架构 x86_64,root 用户执行;
- OpenSSH 版本:
OpenSSH_8.9p1 Ubuntu-3ubuntu0.18, OpenSSL 3.0.2 15 Mar 2022(实测ssh -V原文); - ssh-keygen 属于
openssh-client软件包(版本1:8.9p1-3ubuntu0.18); - 演示目录:
/root/demo/ssh/(本文所有生成密钥均存放在此,避免污染~/.ssh默认目录;~/.ssh保留 known_hosts 与历史文件不动); - 演示口令:
Test12345(第一代口令)/NewPass456(-p修改后的第二代口令),均为演示用途; - 配套环境:本机 openssh-server 已启动并监听 22/2222 端口(配合《ssh-copy-id 命令详解与参数实测》一文的联机实验;
-F/-R的 known_hosts 操作针对127.0.0.1的连接记录)。
💡 说明:私钥文件一旦生成即等价于身份凭证,本文所有演示密钥均在受控测试环境生成、只用于本机回环实验,不涉及任何生产凭证;读者复现后应及时清理演示密钥。
二、命令概览
2.1 语法与测试数据
ssh-keygen 用于生成、管理 SSH 认证密钥(RSA/ECDSA/Ed25519/DSA),也承担指纹计算、公钥导出、known_hosts 维护等任务。它是多形态工具:生成、改密、导公钥、查指纹分别对应不同的参数组合(见 2.2 usage 里的分形态语法)。常用生成语法:
ssh-keygen -t 类型 -b 位长 -C 注释 -f 输出路径 -N 口令
-t:密钥类型(rsa / ecdsa / ed25519 / dsa,以及硬件密钥 ecdsa-sk / ed25519-sk);-b:位长(RSA 默认 3072;ECDSA 只能取 256/384/521;ed25519 固定 256,-b无意义);-C:注释(默认用户@主机名,写入公钥行尾,方便识别用途);-f:输出文件路径(生成路径私钥与路径.pub公钥一对);-N:新口令(-N ''即无口令;口令用于加密私钥文件本身,与登录无关)。
本文测试数据约定:四类算法各生成一对演示密钥(id_rsa2048/id_rsa4096/id_ecdsa/id_ed25519/id_dsa),口令演示用 id_ed25519_pw;known_hosts 操作以 127.0.0.1 为对象。每个参数小节均可独立执行复现。
2.2 usage 全量输出(--help 形态,逐行照抄)
ssh-keygen 不识别 --help 长选项:报 unknown option -- - 后打印完整分形态 usage,退出码 1。以下为 ssh-keygen --help 的实测输出全文:
$ ssh-keygen --help
unknown option -- -
usage: ssh-keygen [-q] [-a rounds] [-b bits] [-C comment] [-f output_keyfile]
[-m format] [-N new_passphrase] [-O option]
[-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]
[-w provider] [-Z cipher]
ssh-keygen -p [-a rounds] [-f keyfile] [-m format] [-N new_passphrase]
[-P old_passphrase] [-Z cipher]
ssh-keygen -i [-f input_keyfile] [-m key_format]
ssh-keygen -e [-f input_keyfile] [-m key_format]
ssh-keygen -y [-f input_keyfile]
ssh-keygen -c [-a rounds] [-C comment] [-f keyfile] [-P passphrase]
ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]
ssh-keygen -B [-f input_keyfile]
ssh-keygen -D pkcs11
ssh-keygen -F hostname [-lv] [-f known_hosts_file]
ssh-keygen -H [-f known_hosts_file]
ssh-keygen -K [-a rounds] [-w provider]
ssh-keygen -R hostname [-f known_hosts_file]
ssh-keygen -r hostname [-g] [-f input_keyfile]
ssh-keygen -M generate [-O option] output_file
ssh-keygen -M screen [-f input_file] [-O option] output_file
ssh-keygen -I certificate_identity -s ca_key [-hU] [-D pkcs11_provider]
[-n principals] [-O option] [-V validity_interval]
[-z serial_number] file ...
ssh-keygen -L [-f input_keyfile]
ssh-keygen -A [-a rounds] [-f prefix_path]
ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]
file ...
ssh-keygen -Q [-l] -f krl_file [file ...]
ssh-keygen -Y find-principals -s signature_file -f allowed_signers_file
ssh-keygen -Y match-principals -I signer_identity -f allowed_signers_file
ssh-keygen -Y check-novalidate -n namespace -s signature_file
ssh-keygen -Y sign -f key_file -n namespace file [-O option] ...
ssh-keygen -Y verify -f allowed_signers_file -I signer_identity
-n namespace -s signature_file [-r krl_file] [-O option]
退出码=1
分形态解读(本文实测覆盖加粗部分):生成(首段,-t/-b/-C/-f/-N/-q)、改口令(-p -P -N)、导公钥(-y)、改注释(-c -C -P)、查指纹(-l [-v] [-E])、查/删 known_hosts(-F/-R);其余(证书 -s、KRL -k、签名 -Y 等)属进阶形态,本文不展开。
2.3 版本信息
ssh -V
dpkg -S /usr/bin/ssh-keygen
dpkg -l openssh-client | tail -1
实测回显:
$ ssh -V
OpenSSH_8.9p1 Ubuntu-3ubuntu0.18, OpenSSL 3.0.2 15 Mar 2022
$ dpkg -S /usr/bin/ssh-keygen
openssh-client: /usr/bin/ssh-keygen
$ dpkg -l openssh-client | tail -1
ii openssh-client 1:8.9p1-3ubuntu0.18 amd64 secure shell (SSH) client, for secure access to remote machines
💡 要点:ssh-keygen 随 openssh-client 发行,Ubuntu 22.04 全系预装;ssh -V 输出到 stderr(重定向取版本要 ssh -V 2>&1)。
三、参数逐项实测
3.1 无参数交互生成:默认 RSA 3072
不带参数执行 ssh-keygen 进入交互流程:依次询问保存路径(回车取默认 ~/.ssh/id_rsa)、口令(回车两次即空口令)。实测以回车喂入 stdin 完成:
ssh-keygen # 提示处直接回车 ×3(stdin 喂入换行)
实测回显:
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:4TTrBoTKz+ASv1uUyu02XBbhK10vb5JRCIb0yNbchvI root@f1034b9326b2
The key's randomart image is:
+---[RSA 3072]----+
| ... |
| ..*+o |
| *o*o*. |
| . o =o+o+. |
|. + o.E+So |
| = B. =oo . |
|. =.=+ o= |
| . ++ .o o |
| oo.. o |
+----[SHA256]-----+
退出码=0
输出解读:默认类型 rsa、位长 3072(randomart 首行 [RSA 3072] 可证);注释自动取 用户@主机名(root@f1034b9326b2,主机名即本机名);指纹 SHA256 前缀;randomart 是指纹的可视化「画片」,两台机器屏幕上画片一致即可肉眼确认是同一把钥。
💡 要点:交互形态适合人肉生成;自动化场景一律用 -t/-f/-N/-C 全参数化(见 3.2 起),避免交互阻塞脚本。
3.2 -t rsa -b 2048:生成 RSA-2048(配合 -C/-f/-N '' 全参数化)
ssh-keygen -t rsa -b 2048 -C 'demo-rsa2048@test' -f /root/demo/ssh/id_rsa2048 -N ''
实测回显:
$ ssh-keygen -t rsa -b 2048 -C 'demo-rsa2048@test' -f /root/demo/ssh/id_rsa2048 -N ''
Generating public/private rsa key pair.
Your identification has been saved in /root/demo/ssh/id_rsa2048
Your public key has been saved in /root/demo/ssh/id_rsa2048.pub
The key fingerprint is:
SHA256:gXe/cdPRpZU+Nq1+yCaGLU2MF5WS81pC1yjnBkCDKWQ demo-rsa2048@test
The key's randomart image is:
+---[RSA 2048]----+
| .E ++. . ++|
| ...o .B *++|
| ..o .. @o.o|
| . o .o =*o|
| S oo*+.+|
| . =+.. |
| *.o . |
| o = = .|
| o o . |
+----[SHA256]-----+
退出码=0
💡 要点:-N ''(空参数)= 无口令,全流程零交互一次性完成;注释 demo-rsa2048@test 原样出现在指纹行与 .pub 行尾。这是自动化与 CI 场景的标准写法。
3.3 -b 4096:加大 RSA 位长
ssh-keygen -t rsa -b 4096 -C 'demo-rsa4096@test' -f /root/demo/ssh/id_rsa4096 -N ''
实测回显(关键行):
$ ssh-keygen -t rsa -b 4096 -C 'demo-rsa4096@test' -f /root/demo/ssh/id_rsa4096 -N ''
Generating public/private rsa key pair.
Your identification has been saved in /root/demo/ssh/id_rsa4096
Your public key has been saved in /root/demo/ssh/id_rsa4096.pub
The key fingerprint is:
SHA256:caLerAypKTUsE/TsZci4vVocK7IUNd3KlVN6M2JdxHE demo-rsa4096@test
The key's randomart image is:
+---[RSA 4096]----+
| .o+.E |
| . . . = ... |
|. =o.. Oo=. |
|...=oo+.++o |
| ++.oo. S |
|o.*ooo o |
|.* =+ . o |
|+.o+ o . |
|.o+ o |
+----[SHA256]-----+
退出码=0
💡 要点:RSA 位长只影响安全强度与生成/验签耗时,指纹长度不变(SHA256 摘要固定);公钥体长度随位长增长(对比 3.12 的 .pub 文件大小 399 vs 743 字节)。
3.4 -t ecdsa:生成 ECDSA(默认 nistp256)
ssh-keygen -t ecdsa -C 'demo-ecdsa@test' -f /root/demo/ssh/id_ecdsa -N ''
实测回显:
$ ssh-keygen -t ecdsa -C 'demo-ecdsa@test' -f /root/demo/ssh/id_ecdsa -N ''
Generating public/private ecdsa key pair.
Your identification has been saved in /root/demo/ssh/id_ecdsa
Your public key has been saved in /root/demo/ssh/id_ecdsa.pub
The key fingerprint is:
SHA256:gL9uG9nVDebsrbbG1lMaG3QXVNG8oKmZR9KrbOPqtIg demo-ecdsa@test
The key's randomart image is:
+---[ECDSA 256]---+
| .+=|
| . . .o|
| . . . = . o|
| . . . X o..o|
| . S B =....|
| + = + .o .|
| +.o o....* |
| ..+..= =.= |
| E o+=+..+o. . |
+----[SHA256]-----+
退出码=0
💡 要点:ECDSA 默认曲线 nistp256(randomart [ECDSA 256]),公钥行类型标识 ecdsa-sha2-nistp256(见 3.12);-b 只能取 256/384/521,给其他值会报错。密钥短(.pub 仅 177 字节)是椭圆曲线系的优势。
3.5 -t ed25519:生成 Ed25519(推荐)
ssh-keygen -t ed25519 -C 'demo-ed25519@test' -f /root/demo/ssh/id_ed25519 -N ''
实测回显:
$ ssh-keygen -t ed25519 -C 'demo-ed25519@test' -f /root/demo/ssh/id_ed25519 -N ''
Generating public/private ed25519 key pair.
Your identification has been saved in /root/demo/ssh/id_ed25519
Your public key has been saved in /root/demo/ssh/id_ed25519.pub
The key fingerprint is:
SHA256:5T+jDI0qFoij73lqDN3B1znnFEdyZwk17t5wSFZsvI4 demo-ed25519@test
The key's randomart image is:
+--[ED25519 256]--+
| ..+o=+.|
| .o.+.o+|
| . . ..o +..|
| o . +oo + o |
| o o o S=. * .|
|+ o o o.. E = |
|.+ . o . + . .|
|. o.+ . o . o |
| +=+ .. o |
+----[SHA256]-----+
退出码=0
💡 要点:Ed25519 生成最快、密钥最短(.pub 99 字节)、安全性现代,是新部署的首选类型;对端服务器 OpenSSH ≥ 6.5 即支持。
3.6 -N:带口令生成(私钥文件加密)
ssh-keygen -t ed25519 -C 'demo-passphrase@test' -f /root/demo/ssh/id_ed25519_pw -N 'Test12345'
实测回显(关键行):
$ ssh-keygen -t ed25519 -C 'demo-passphrase@test' -f /root/demo/ssh/id_ed25519_pw -N 'Test12345'
Generating public/private ed25519 key pair.
Your identification has been saved in /root/demo/ssh/id_ed25519_pw
Your public key has been saved in /root/demo/ssh/id_ed25519_pw.pub
The key fingerprint is:
SHA256:gF22i/Y6I5y7TC4l9iDmMbx55xc9/volXdGAQn+7iis demo-passphrase@test
The key's randomart image is:
+--[ED25519 256]--+
| o.. .. |
| o o .... ..|
| . o . .. ...|
| o . . ..|
|. o S .. |
|.=+ .. o o . .. |
|oo=*.. + .. o. |
| +.==.ooE. .o. |
| ..B=oo o*+. |
+----[SHA256]-----+
退出码=0
💡 要点:-N 口令 加密的是私钥文件本身(文件内容变成加密形态);使用该私钥登录时需输入口令解密(或由 ssh-agent 缓存)。私钥泄露时口令是第二道防线。与 -N '' 的取舍见 5 章 Q1。
3.7 -t dsa:老算法 DSA 仍可生成
ssh-keygen -t dsa -C 'demo-dsa@test' -f /root/demo/ssh/id_dsa -N ''
实测回显(关键行):
$ ssh-keygen -t dsa -C 'demo-dsa@test' -f /root/demo/ssh/id_dsa -N ''
Generating public/private dsa key pair.
Your identification has been saved in /root/demo/ssh/id_dsa
Your public key has been saved in /root/demo/ssh/id_dsa.pub
The key fingerprint is:
SHA256:SixiFbDo0BJNX1vf7J45GFTE/uMkPWac4QO9RqHPhhA demo-dsa@test
The key's randomart image is:
+---[DSA 1024]----+
|.oo.. . . oo |
| +.o o o .E+. . |
|+ o o . oooo . |
|o. . . ...+ + |
| .o . o S ...@ + |
| . . o . +oo^ |
| . . =O + |
| .. |
| |
+----[SHA256]-----+
退出码=0
💡 要点:8.9 仍允许生成 DSA(固定 1024 位),但 OpenSSH 8.8+ 默认在登录认证时禁用 ssh-dss 算法(服务端 PubkeyAcceptedAlgorithms 不含它),生成出来也只能配到旧设备或显式开启才可用。新部署不要用 DSA。
3.8 -b 512:位长不足直接报错
ssh-keygen -t rsa -b 512 -f /root/demo/ssh/id_rsa512 -N ''
实测回显:
$ ssh-keygen -t rsa -b 512 -f /root/demo/ssh/id_rsa512 -N ''
Invalid RSA key length: minimum is 1024 bits
退出码=255
💡 要点:RSA 最小 1024 位,低于即拒绝(rc=255),不生成任何文件。安全起见实际使用 ≥ 2048(默认 3072)。
3.9 -q:静默生成
ssh-keygen -q -t ed25519 -C 'demo-quiet@test' -f /root/demo/ssh/id_ed25519_quiet -N ''
实测回显:
$ ssh-keygen -q -t ed25519 -C 'demo-quiet@test' -f /root/demo/ssh/id_ed25519_quiet -N ''
退出码=0
💡 要点:-q 抑制全部进度输出(无 randomart),只剩退出码;脚本里批量造钥的首选形态,密钥是否生成成功用退出码与 -f 文件存在性判断。
3.10 -f:指向已存在文件时先询问不覆盖
ssh-keygen -t ed25519 -f /root/demo/ssh/id_ed25519 -N ''
实测回显(该文件已在 3.5 生成过):
$ ssh-keygen -t ed25519 -f /root/demo/ssh/id_ed25519 -N ''
Generating public/private ed25519 key pair.
/root/demo/ssh/id_ed25519 already exists.
Overwrite (y/n)? 退出码=1
💡 要点:目标已存在时交互询问 Overwrite (y/n)?;stdin 无输入(EOF)直接退出 rc=1,不会覆盖——这是天然防误覆盖保护。脚本里若确定要覆盖,先 rm -f 私钥路径 私钥路径.pub 再生成,避免卡在询问处。
3.11 生成结果清单:私钥 600 / 公钥 644 权限语义
查看 /root/demo/ssh/ 生成结果(输出节选,只保留密钥对相关行;目录里另有无关的历史文件):
ls -l /root/demo/ssh/
实测回显(节选):
$ ls -l /root/demo/ssh/
total 64
-rw------- 1 root root 1381 Oct 16 14:18 id_dsa
-rw-r--r-- 1 root root 603 Oct 16 14:18 id_dsa.pub
-rw------- 1 root root 505 Oct 16 14:18 id_ecdsa
-rw-r--r-- 1 root root 177 Oct 16 14:18 id_ecdsa.pub
-rw------- 1 root root 411 Oct 16 14:18 id_ed25519
-rw-r--r-- 1 root root 99 Oct 16 14:18 id_ed25519.pub
-rw------- 1 root root 464 Oct 16 14:18 id_ed25519_pw
-rw-r--r-- 1 root root 102 Oct 16 14:18 id_ed25519_pw.pub
-rw------- 1 root root 411 Oct 16 14:18 id_ed25519_quiet
-rw-r--r-- 1 root root 97 Oct 16 14:18 id_ed25519_quiet.pub
-rw------- 1 root root 1823 Oct 16 14:18 id_rsa2048
-rw-r--r-- 1 root root 399 Oct 16 14:18 id_rsa2048.pub
-rw------- 1 root root 3381 Oct 16 14:18 id_rsa4096
-rw-r--r-- 1 root root 743 Oct 16 14:18 id_rsa4096.pub
权限规律:私钥一律 -rw-------(600,仅属主可读写),公钥一律 -rw-r--r--(644,可公开)。600 是强制语义:权限过宽的私钥会被 ssh/ssh-keygen 直接拒用(3.16 实测)。文件大小对照:ed25519 私钥 411 字节 < ecdsa 505 < rsa2048 1823 < rsa4096 3381。
💡 要点:.pub 公钥可以随意分发(放进服务器 authorized_keys 的就是它);私钥永不离开可信机器。手工备份/迁移时保持 600(scp 会保留权限,部分工具会放宽)。
3.12 公钥文件结构:三类型一行式对比
cat /root/demo/ssh/id_rsa2048.pub /root/demo/ssh/id_ecdsa.pub /root/demo/ssh/id_ed25519.pub
实测回显:
$ cat /root/demo/ssh/id_rsa2048.pub /root/demo/ssh/id_ecdsa.pub /root/demo/ssh/id_ed25519.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCAoBp+U41J8nSrlirFjO4xJO/N1urXqdhyN0+LMIfSx2Pb6+TCsocDiQjmH1paKm/11ewim17uSZ7kAJxyor5HWBjb8ScfYVLybXw0LuCNrmtcfSwsnkSi6au9NXb9TidcCeVJn/wl8ZcI1stOIBMpNIyYCJT9wZKYFHoQiX5FgZxeBxfZURAT7GHV2VEQ8xYRbwSR4JGYJcA+kb1TAnvN2sgfrtQVj3dMIu3S+8gLCaoxggFPMlP5Cw35RjHlcJ13uwiWO0Wavj9JrxrP9Q/uU6bFFTUKve8p67WPLobjweWv3IuMwS9EpSnSwE+rjKbXslhM5ni+0dKmUDM5ROVL demo-rsa2048@test
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBG5gRTqG3NNjTGqCPJNxjI2k3K8TOp39xKAGxIqm9wkvG71C22Tl0lohGMFOpOnZwI8QqW3+DIskQ9cBUcKWP3M= demo-ecdsa@test
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOLSfhHEnAE0hrdxkNl2eM4qI7jzU6PbMjvcW96aZF9f demo-ed25519@test
💡 要点:.pub 行 = 类型标识 base64公钥体 注释 三字段,可直接追加到远端 ~/.ssh/authorized_keys(每行一把)。类型标识对照:RSA→ssh-rsa、ECDSA→ecdsa-sha2-nistp256、Ed25519→ssh-ed25519。
3.13 -l:计算指纹(默认 SHA256,-E md5,可直读私钥)
ssh-keygen -l -f /root/demo/ssh/id_ed25519.pub
ssh-keygen -l -E md5 -f /root/demo/ssh/id_ed25519.pub
ssh-keygen -l -f /root/demo/ssh/id_ed25519
实测回显:
$ ssh-keygen -l -f /root/demo/ssh/id_ed25519.pub
256 SHA256:5T+jDI0qFoij73lqDN3B1znnFEdyZwk17t5wSFZsvI4 demo-ed25519@test (ED25519)
退出码=0
$ ssh-keygen -l -E md5 -f /root/demo/ssh/id_ed25519.pub
256 MD5:20:1d:61:0b:83:85:b3:5f:b8:59:42:92:1e:4d:c5:50 demo-ed25519@test (ED25519)
退出码=0
$ ssh-keygen -l -f /root/demo/ssh/id_ed25519
256 SHA256:5T+jDI0qFoij73lqDN3B1znnFEdyZwk17t5wSFZsvI4 demo-ed25519@test (ED25519)
退出码=0
💡 要点:指纹行 = 位长 前缀:摘要 注释 (类型);默认 SHA256(base64 形态),-E md5 输出冒号分隔的十六进制形态(与老系统/服务商控制台比对时用);-l 直接喂私钥也能算(自动读其公钥部分),但带口令的私钥会提示输入口令。
3.14 -l -v:指纹附带 randomart
ssh-keygen -lv -f /root/demo/ssh/id_ecdsa.pub
实测回显:
$ ssh-keygen -lv -f /root/demo/ssh/id_ecdsa.pub
256 SHA256:gL9uG9nVDebsrbbG1lMaG3QXVNG8oKmZR9KrbOPqtIg demo-ecdsa@test (ECDSA)
+---[ECDSA 256]---+
| .+=|
| . . .o|
| . . . = . o|
| . . . X o..o|
| . S B =....|
| + = + .o .|
| +.o o....* |
| ..+..= =.= |
| E o+=+..+o. . |
+----[SHA256]-----+
退出码=0
💡 要点:-v 在指纹下方追加 randomart 画片,与生成时的画片一致——用于肉眼比对「第一次生成的钥」和「现在这把钥」是否同一把。
3.15 -y:从私钥导出公钥(可与 .pub 全字段比对)
ssh-keygen -y -f /root/demo/ssh/id_ed25519
ssh-keygen -y -f /root/demo/ssh/id_ed25519 > /tmp/exported2.pub
diff /tmp/exported2.pub /root/demo/ssh/id_ed25519.pub && echo '完全一致'
实测回显:
$ ssh-keygen -y -f /root/demo/ssh/id_ed25519
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOLSfhHEnAE0hrdxkNl2eM4qI7jzU6PbMjvcW96aZF9f demo-ed25519@test
退出码=0
$ ssh-keygen -y -f /root/demo/ssh/id_ed25519 > /tmp/exported2.pub
$ diff /tmp/exported2.pub /root/demo/ssh/id_ed25519.pub && echo '完全一致'
完全一致
退出码=0
💡 要点:-y 从私钥重新推导出公钥行(OpenSSH 8.9 的输出连注释一并还原,实测 diff 全字段一致)。「只剩私钥、丢了 .pub」时靠它重建公钥;反向操作不存在(公钥推不出私钥)。
3.16 权限 600 的强制语义:chmod 644 后私钥被拒用
cp /root/demo/ssh/id_ed25519 /root/demo/ssh/perm/badperm
chmod 644 /root/demo/ssh/perm/badperm
ls -l /root/demo/ssh/perm/badperm
ssh-keygen -y -f /root/demo/ssh/perm/badperm
chmod 600 /root/demo/ssh/perm/badperm
ssh-keygen -y -f /root/demo/ssh/perm/badperm | cut -c1-40
实测回显:
$ chmod 644 /root/demo/ssh/perm/badperm
$ ls -l /root/demo/ssh/perm/badperm
-rw-r--r-- 1 root root 411 Oct 16 14:22 /root/demo/ssh/perm/badperm
$ ssh-keygen -y -f /root/demo/ssh/perm/badperm
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/root/demo/ssh/perm/badperm' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/root/demo/ssh/perm/badperm": bad permissions
退出码=255
$ chmod 600 /root/demo/ssh/perm/badperm
$ ssh-keygen -y -f /root/demo/ssh/perm/badperm | cut -c1-40
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOLS
恢复 600 后退出码=0
💡 要点:同内容同属主的私钥,仅因 644 权限即被拒(bad permissions,rc=255);改回 600 立即可用。这条保护在 ssh/ssh-keygen/ssh-copy-id 全链路一致——「拷私钥到新机器连不上」先查权限是不是 600(5 章 Q2)。
3.17 -p:修改私钥口令(-P 旧口令 -N 新口令)
ssh-keygen -p -P 'Test12345' -N 'NewPass456' -f /root/demo/ssh/id_ed25519_pw
ssh-keygen -p -P 'wrong-pass' -N 'x' -f /root/demo/ssh/id_ed25519_pw
ssh-keygen -p -P 'NewPass456' -N '' -f /root/demo/ssh/id_ed25519_pw
实测回显:
$ ssh-keygen -p -P 'Test12345' -N 'NewPass456' -f /root/demo/ssh/id_ed25519_pw
Key has comment 'demo-passphrase@test'
Your identification has been saved with the new passphrase.
退出码=0
$ ssh-keygen -p -P 'wrong-pass' -N 'x' -f /root/demo/ssh/id_ed25519_pw
Failed to load key /root/demo/ssh/id_ed25519_pw: incorrect passphrase supplied to decrypt private key
退出码=255
$ ssh-keygen -p -P 'NewPass456' -N '' -f /root/demo/ssh/id_ed25519_pw
Key has comment 'demo-passphrase@test'
Your identification has been saved with the new passphrase.
退出码=0
💡 要点:-p 就地改写私钥文件的加密口令(公钥不变、指纹不变);旧口令错误 rc=255 且不做任何修改;-N '' 可把带口令钥改成无口令钥。省略 -P/-N 时进入交互询问(脚本务必带上,避免挂住)。
3.18 -c:修改注释(公私钥同步)
cat /root/demo/ssh/id_ed25519.pub
ssh-keygen -c -C 'renamed-comment@test' -f /root/demo/ssh/id_ed25519 -P ''
cat /root/demo/ssh/id_ed25519.pub
实测回显:
$ cat /root/demo/ssh/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOLSfhHEnAE0hrdxkNl2eM4qI7jzU6PbMjvcW96aZF9f demo-ed25519@test
$ ssh-keygen -c -C 'renamed-comment@test' -f /root/demo/ssh/id_ed25519 -P ''
Old comment: demo-ed25519@test
Comment 'renamed-comment@test' applied
退出码=0
$ cat /root/demo/ssh/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOLSfhHEnAE0hrdxkNl2eM4qI7jzU6PbMjvcW96aZF9f renamed-comment@test
对带口令的私钥不给 -P 时会提示 Enter passphrase:,stdin 已关闭导致解密失败。实测:
$ ssh-keygen -p -P '' -N 'Test12345' -f /root/demo/ssh/id_ed25519_pw # 先设回口令
Key has comment 'demo-passphrase@test'
Your identification has been saved with the new passphrase.
设口令退出码=0
$ ssh-keygen -c -C 'y@test' -f /root/demo/ssh/id_ed25519_pw # 不给 -P
Enter passphrase: Cannot load private key "/root/demo/ssh/id_ed25519_pw": incorrect passphrase supplied to decrypt private key
改注释退出码=255
💡 要点:-c 同步改写公钥与私钥里的注释(公钥体不变,只有行尾注释变,因此指纹不变);带口令钥必须 -P 旧口令 才能改。注释只影响人类可读性,改注释不会使已部署的 authorized_keys 失效。
3.19 -F:在 known_hosts 中查找主机条目
ssh-keygen -F 127.0.0.1
实测回显(known_hosts 中存在该主机指纹时):
$ ssh-keygen -F 127.0.0.1
# Host 127.0.0.1 found: line 1
127.0.0.1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJO+yG1w+ThzGkfIBPDvghHn5Eyhd578pl/dQiiCUQy1
退出码=0
主机无记录时无输出且退出码 1。-F 常用于安装公钥前确认本机是否已记录目标主机指纹(配合 3.20 排查指纹冲突)。
💡 要点:-F 主机名 按主机查找 known_hosts(默认 /root/.ssh/known_hosts,可用 -f 指定他文件);找到时打印所在行号与指纹原文,找不到 rc=1。known_hosts 行被 hashed(匿名化)时也能查到(内部会哈希后比对)。
3.20 -R:从 known_hosts 删除主机条目
ssh-keygen -R 127.0.0.1
ssh-keygen -F 127.0.0.1
实测回显:
$ ssh-keygen -R 127.0.0.1
# Host 127.0.0.1 found: line 1
/root/.ssh/known_hosts updated.
Original contents retained as /root/.ssh/known_hosts.old
$ ssh-keygen -F 127.0.0.1
退出码=1
💡 要点:-R 删除该主机的全部指纹记录并自动备份原文件为 known_hosts.old(可回滚);删除后 -F 查询 rc=1。典型用途见 4.4 与 5 章 Q6:服务器重装导致主机指纹变更,客户端报 REMOTE HOST IDENTIFICATION HAS CHANGED 时用 -R 清旧记录后重连。
3.21 技术拓展:四种密钥算法对比
四类算法在本机的实测生成数据汇总(回显出处 3.2~3.7 与 3.11 的文件大小):
| 算法 | 生成命令 | randomart 头 | 公钥类型标识 | .pub 大小 | 生成速度 | 默认登录可用(8.9) |
|---|---|---|---|---|---|---|
| RSA | ssh-keygen -t rsa -b 2048 | [RSA 2048] | ssh-rsa | 399 B | 慢(位长越大越慢) | ✔(但 ssh-rsa 签名算法 SHA-1 变体被默认禁用,RSA-SHA2 可用) |
| RSA-4096 | ssh-keygen -t rsa -b 4096 | [RSA 4096] | ssh-rsa | 743 B | 最慢 | ✔ |
| ECDSA | ssh-keygen -t ecdsa | [ECDSA 256] | ecdsa-sha2-nistp256 | 177 B | 快 | ✔ |
| Ed25519 | ssh-keygen -t ed25519 | [ED25519 256] | ssh-ed25519 | 99 B | 最快 | ✔(新部署首选) |
| DSA | ssh-keygen -t dsa | [DSA 1024] | ssh-dss | 603 B | 快 | ✘(生成可,登录默认禁用) |
💡 要点:选型结论——新一律 Ed25519;对旧系统兼容再退回 RSA ≥ 2048;ECDSA 适合对密钥长度敏感的嵌入式;DSA 仅存留于兼容场景。
四、实战示例
4.1 场景一:一键生成部署用密钥并校验指纹
自动化部署的标准三步:生成(全参数化零交互)→ 清单确认 → 指纹登记:
ssh-keygen -q -t ed25519 -C 'deploy@2026-10' -f /root/demo/ssh/id_deploy -N ''
ssh-keygen -l -f /root/demo/ssh/id_deploy.pub
ls -l /root/demo/ssh/id_deploy /root/demo/ssh/id_deploy.pub
实测回显:
$ ssh-keygen -q -t ed25519 -C 'deploy@2026-10' -f /root/demo/ssh/id_deploy -N ''
$ ssh-keygen -l -f /root/demo/ssh/id_deploy.pub
256 SHA256:wqTfF1aNjr6CBvgH/xKstfULuQ4O3YSCA7i+70jCtCc deploy@2026-10 (ED25519)
退出码=0
$ ls -l /root/demo/ssh/id_deploy /root/demo/ssh/id_deploy.pub
-rw------- 1 root root 411 Oct 16 14:47 /root/demo/ssh/id_deploy
-rw-r--r-- 1 root root 96 Oct 16 14:47 /root/demo/ssh/id_deploy.pub
退出码=0
要点:-q 静默 + -N '' 免密 + 指纹落库三件事一次完成;权限自动 600/644(3.11)。把指纹记入变更单,后续可用 -l 复核是否被替换。
4.2 场景二:私钥迁移后验证完整性
把私钥拷到新机器后,用 -y 导出公钥与原 .pub 比对(3.15 的方法迁移场景复用):
ssh-keygen -y -f /root/demo/ssh/id_ed25519 > /tmp/exported2.pub
diff /tmp/exported2.pub /root/demo/ssh/id_ed25519.pub && echo '完全一致'
实测回显:
$ ssh-keygen -y -f /root/demo/ssh/id_ed25519 > /tmp/exported2.pub
$ diff /tmp/exported2.pub /root/demo/ssh/id_ed25519.pub && echo '完全一致'
完全一致
退出码=0
要点:diff 为空即「钥没拷坏、没拷错」。拷完若报 bad permissions,是权限问题不是内容问题(3.16),chmod 600 即可。
4.3 场景三:装机前核对主机指纹(-F)
运维换机/重装前,先查本机 known_hosts 里的旧指纹,重装后再核对是否变化。-F 有记录与无记录两种实测形态:
ssh-keygen -F 127.0.0.1
有记录时(3.19 实测,rc=0):
$ ssh-keygen -F 127.0.0.1
# Host 127.0.0.1 found: line 1
127.0.0.1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJO+yG1w+ThzGkfIBPDvghHn5Eyhd578pl/dQiiCUQy1
退出码=0
条目被 -R 清理后(4.4 实测,无输出且 rc=1):
$ ssh-keygen -F 127.0.0.1
删除后再查退出码=1
要点:rc=0 有记录、rc=1 无记录,可直接做 if 判断。核对时把 -F 输出的指纹与「管理员在服务器上执行的 ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub」结果比对,一致才放行重装后的连接。
4.4 场景四:主机重装后的指纹冲突清理(-R 后重连)
服务器重装(host key 变更)后客户端连接会报 REMOTE HOST IDENTIFICATION HAS CHANGED(完整回显见《ssh-copy-id 命令详解与参数实测》一文 Q6 场景),处置三步:确认变更合理性 → -R 删旧指纹 → 重连自动登记新指纹:
ssh-keygen -R 127.0.0.1
ssh -o StrictHostKeyChecking=accept-new sshu1@127.0.0.1 id
ssh-keygen -F 127.0.0.1
实测回显:
$ ssh-keygen -R 127.0.0.1
# Host 127.0.0.1 found: line 1
/root/.ssh/known_hosts updated.
Original contents retained as /root/.ssh/known_hosts.old
$ ssh -o StrictHostKeyChecking=accept-new -o BatchMode=yes sshu1@127.0.0.1 id
Warning: Permanently added '127.0.0.1' (ED25519) to the list of known hosts.
uid=1019(sshu1) gid=3109(sshu1) groups=3109(sshu1)
退出码=0
$ ssh-keygen -F 127.0.0.1
# Host 127.0.0.1 found: line 1
|1|womMKf0bDbaNb2JZje9nT1TZRu4=|8Mokzrbb+dq06GWEY8I4j6J6cHA= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH7Kmu111+y5OcQhflH1ImWs9mjGQQv1dUlub9ZvMVt6
重新登记查询退出码=0
要点:-R 备份旧记录到 known_hosts.old;重连时 accept-new 自动登记新指纹(回显 Permanently added);之后 -F 查到的是新指纹(|1| 开头 = hashed 形态存储)。⚠️ 执行 -R 前务必人工确认主机指纹变更是「合法重装」而非中间人——-R 只是清记录,不负责判断对错。
五、注意事项与常见问题
Q1:密钥口令(-N)和登录密码是什么关系?要不要设?
两码事:口令加密的是本地私钥文件,登录密码是服务端账号认证因子。-N '' 无口令钥适合自动化与个人可信终端;共享/移动设备上的私钥建议设口令(3.6),泄露后仍有缓冲,或配合 ssh-agent 缓存避免反复输入。企业批量主机分发场景一律 -N '' + 权限管控。
Q2:私钥权限为什么必须 600?
OpenSSH 对「其他用户可读」的私钥一律拒用:644 时 ssh-keygen/ssh 直接报 WARNING: UNPROTECTED PRIVATE KEY FILE! + bad permissions,rc=255(3.16 实测)。这是防同机其他用户窃取私钥的强制保护。迁移私钥后 chmod 600 私钥 是标准动作;.pub 保持 644 无碍。
Q3:ssh-keygen -y 导出的公钥为什么连注释一起输出?
实测 8.9 的 -y 会把私钥内存储的注释一并还原,输出与 .pub 文件全字段一致(3.15 diff 完全一致)。老版本部分输出不带注释;写脚本不要假设注释存在,解析公钥只取前两字段(类型 + base64 体)。
Q4:-b 512 为什么报错?最小位长是多少?
RSA 最小 1024 位(实测报文 Invalid RSA key length: minimum is 1024 bits,rc=255,3.8)。1024 位已不安全,实际应 ≥ 2048(默认 3072、推荐 4096);ECDSA 的 -b 只能 256/384/521;ed25519 固定 256,-b 参数对它无意义。
Q5:DSA 钥能生成为什么连不上?
OpenSSH 8.8+ 默认在认证阶段禁用 ssh-dss 算法(SHA-1 签名强度不足)。实测 ssh-keygen -t dsa 可正常生成(3.7),但 ssh 登录认证时不会协商该算法;只有在服务端显式加回 PubkeyAcceptedAlgorithms +ssh-dss(不建议)或对接极老的设备时才用。新部署弃用 DSA。
Q6:ssh 报 REMOTE HOST IDENTIFICATION HAS CHANGED 怎么处理?
流程:① 读报错里的指纹,人工确认服务器确实重装(找管理员核对)→ ② ssh-keygen -R 主机名或IP 清旧记录(自动备份 .old,3.20/4.4)→ ③ 重连并核对新指纹。⚠️ 不确认就 -R 等于无视中间人告警;known_hosts.old 可用于事后审计。
Q7:指纹怎么核对?SHA256 和 MD5 两种格式能互转吗?
同一把钥的两种摘要表示:-l 默认 SHA256(base64,如 SHA256:5T+jD...),-E md5 输出冒号十六进制(如 MD5:20:1d:61:...),3.13 实测两者指向同一把钥。与对方核对指纹时先确认对方要哪种格式,再用对应 -E 参数生成,避免「看起来不一致」的假告警。
六、参考链接
- ssh-keygen(1) 手册(Ubuntu 22.04 jammy):https://manpages.ubuntu.com/manpages/jammy/en/man1/ssh-keygen.1.html
- OpenSSH 官方文档(ssh-keygen 起页):https://www.openssh.com/manual.html
- OpenSSH 8.9 发布说明(8.8 起默认禁用 ssh-dss、RSA SHA-1 签名的背景):https://www.openssh.com/releasenotes.html
- RFC 4253(SSH 传输层协议,主机钥与指纹定义):https://datatracker.ietf.org/doc/html/rfc4253
- RFC 8709(Ed25519 在 SSH 中的算法定义):https://datatracker.ietf.org/doc/html/rfc8709