跳到主要内容
ecdsa.com

Ed25519 vs RSA 密钥:生成 SSH 密钥该选哪种

多年来,新 SSH 密钥的答案一直是 Ed25519。还需要生成 RSA 的理由只剩兼容性缺口,而且越来越少见。
对比对象Ed25519RSA

Ed25519 与 RSA 之争,最常出现在有人运行 ssh-keygen、不知道 -t 该传什么值的时候。同样的比较也适用于代码签名和文件签名。Ed25519 以极小的密钥提供 128 位安全强度,签名快速且是确定性的;RSA 的兼容性无处不在,但体积大得多,密钥生成也更慢、更容易出问题。

概览

Ed25519RSA-3072
安全强度约 128 位约 128 位(RSA-2048:112 位)
私钥32 字节种子3072 位模数加 CRT 值
公钥(原始)32 字节384 字节模数加指数
OpenSSH .pub 行(实测)86 字节558 字节
签名64 字节384 字节
单个签名的 SSHSIG 文件(实测)294 字节1,211 字节
密钥生成微秒级平均约 100 毫秒,波动很大
每秒签名 / 验证次数(OpenSSL 3.6.5)约 60,000 / 25,000约 1,000 / 54,000
SSH 算法名称ssh-ed25519、sk-ssh-ed25519@openssh.com密钥类型 ssh-rsa;签名 rsa-sha2-256、rsa-sha2-512
OpenSSH 支持自 6.5 版(2014年)起支持;自 9.5 版(2023年)起为默认一直支持
确定性签名是PKCS #1 v1.5 是;PSS 为随机化签名
NIST IR 8547(草案)2035年后禁用RSA-2048 在2030年后弃用;所有 RSA 在2035年后禁用

在 Apple M4 Max 的单个核心上用 OpenSSH 10.3p1 和 OpenSSL 3.6.5 测得。

大小与速度

在同样的 128 位安全强度下,Ed25519 公钥为 32 字节,而 RSA-3072 的模数为 384 字节。在 SSH 中,这一差异体现在 authorized_keys、known_hosts、证书和每一次握手上:Ed25519 公钥行为 86 字节,RSA-3072 为 558 字节;分离式 SSH 签名文件为 294 字节,RSA-3072 为 1,211 字节。

速度上两者并不对称。RSA 验证比 Ed25519 快(在这台机器上约为每秒 54,000 次对 25,000 次),但签名约慢 60 倍;而且密钥生成需要搜索两个大素数,在这台机器上生成一个 RSA-3072 密钥平均约需 100 毫秒,在小型设备上可能要久得多。对于每个连接都要签名一次握手的 SSH 服务器,Ed25519 主机密钥占用的 CPU 更少;对用户而言,两者都是瞬间完成。

表中的大小数据由下面的脚本生成,它只用到了 OpenSSH。

比较 Ed25519 与 RSA-3072 的 SSH 密钥和签名
#!/bin/sh
dir=$(mktemp -d)
cd "$dir" || exit 1
ssh-keygen -q -t ed25519 -N "" -C demo -f id_ed25519
ssh-keygen -q -t rsa -b 3072 -N "" -C demo -f id_rsa
for k in id_ed25519 id_rsa; do
  echo "$k.pub: $(wc -c < $k.pub | tr -d ' ') bytes"
  printf 'hello\n' > "msg-$k"
  ssh-keygen -q -Y sign -f "$k" -n file "msg-$k"
  echo "signature file: $(wc -c < "msg-$k.sig" | tr -d ' ') bytes"
done
cd / && rm -rf "$dir"
OpenSSH 10.3p1 下的输出
id_ed25519.pub: 86 bytes
signature file: 294 bytes
id_rsa.pub: 558 bytes
signature file: 1211 bytes

稳健性与失效模式

Ed25519 几乎没有可调的选项:一条曲线、一种哈希、确定性 nonce、一种签名编码。没有需要选择的填充方式,也不会意外选中弱参数集。

RSA 的历史就是一份参数和填充错误的清单。SSH 最初的 ssh-rsa 签名算法使用 SHA-1 计算哈希,而 SHA-1 已被选择前缀碰撞攻破;OpenSSH 8.8(2021年9月)默认禁用了它,现在 RSA 密钥改用 rsa-sha2-256 或 rsa-sha2-512(RFC 8332)签名,任何当前版本的客户端和服务器都会自动这样做。过短的密钥是另一个陷阱:自2013年起,NIST 就不再允许用 1024 位 RSA 签名;2048 位对应 NIST 的 112 位安全强度,NIST IR 8547 草案提议在2030年后弃用它。薄弱的密钥生成器曾产生共享的或带有特定结构的素数(ROCA 缺陷,以及可用批量 GCD 分解的密钥);只要随机数生成器正常工作,Ed25519 种子就不存在这类故障。

兼容性

Ed25519 可用于 OpenSSH 6.5 及更高版本、PuTTY、Windows 内置的 OpenSSH、GitHub、GitLab、Bitbucket、大多数云控制台、Linux EC2 实例,以及 Git 的 SSH 提交签名。明显的缺口包括:Amazon EC2 Windows 实例,其密钥对必须是 RSA,因为初始 Administrator 密码要用该密钥解密;部分网络设备和嵌入式 SSH 实现;以及非常老旧的企业软件。基于 FIDO 的 ed25519-sk 密钥需要支持 EdDSA 的认证器;ecdsa-sk 是支持更广泛的硬件选项。

凡是能用 SSH 的地方都能用 RSA,这是它唯一真正的优势。TLS 证书的情况则正好相反:公开信任的 CA 签发 RSA 和 ECDSA 证书,但不签发 Ed25519 证书,因此本文比较的是 SSH 和签名场景,而不是 HTTPS。

如何选择

  • 个人 SSH 密钥和 CI 部署密钥:Ed25519,用密码短语保护,或存放在安全密钥上(ssh-keygen -t ed25519-sk)。
  • SSH 主机密钥:优先提供 Ed25519;只要还有旧客户端连接,就保留一个 RSA 主机密钥(只用 rsa-sha2-*),并规划将其移除。
  • 用 SSH 密钥签名提交和文件:Ed25519;签名大小只有五分之一,验证命令完全相同。
  • Windows EC2 实例、旧式专用设备、无法更新的系统:RSA-3072 或 RSA-4096。
  • PIV 模式下的硬件令牌:令牌支持什么就用什么,通常是 RSA 或 ECDSA P-256,而不是 Ed25519。
  • 长期规划:两者都无法抵御量子计算机;OpenSSH 已经用后量子混合密钥交换保护会话密钥,OpenSSH 10.4 还为签名新增了一种实验性的 ML-DSA-44 加 Ed25519 复合密钥类型。

迁移说明

用 Ed25519 替换 RSA 密钥只是一次常规的密钥轮换。

  1. 生成新密钥,可以使用 ssh-keygen -t ed25519 -a 100(为密码短语增加 KDF 轮数),也可以在安全密钥上生成。
  2. 与旧密钥并行安装:把新密钥追加到每台服务器的 authorized_keys 中,添加到 Git 托管平台的账号和配置管理中,并确认可以用 ssh -i ~/.ssh/id_ed25519 登录。
  3. 对于主机密钥,在 sshd_config 中添加 HostKey /etc/ssh/ssh_host_ed25519_key;启用了 UpdateHostKeys 的客户端(当前 OpenSSH 默认开启)会自动获知新密钥,known_hosts 条目也可以在移除 RSA 密钥之前更新。
  4. 移除 RSA 密钥:一旦没有任何东西再依赖它,就将其从 authorized_keys、账号和 ssh-agent 中删除,并检查日志,找出仍在协商 RSA 的客户端。
  5. 如果必须保留 RSA,要确保任何地方都没有重新启用 ssh-rsa(SHA-1):在 HostKeyAlgorithms 或 PubkeyAcceptedAlgorithms 中查找 +ssh-rsa。ssh -Q HostKeyAlgorithms 列出客户端支持的算法,nmap --script ssh2-enum-algos 列出服务器提供的算法,SSH 公钥查看器则显示密钥的类型、长度和指纹。

参考资料

全部对比