在 Ed25519 与 Ed448 之间做选择,归根结底是安全余量的问题。两者属于 RFC 8032 中的同一个算法族,都已获 FIPS 186-5 批准,签名也都是确定性的,每次签名都不需要随机性。Ed448 运行在更大的曲线上,经典安全强度约为 224 位,而不是约 128 位,代价则体现在大小、速度和生态系统支持上。
概览
| Ed25519 | Ed448 | |
|---|---|---|
| RFC 8032 章节 | §5.1 | §5.2 |
| 曲线 | Edwards25519(与 Curve25519 双有理等价),p = 2²⁵⁵ − 19 | Edwards448(“Goldilocks”),p = 2⁴⁴⁸ − 2²²⁴ − 1 |
| 余因子 | 8 | 4 |
| 经典安全强度 | 约 128 位 | 约 224 位 |
| 哈希 | SHA-512 | SHAKE256 |
| 私钥(种子) | 32 字节 | 57 字节 |
| 公钥 | 32 字节(SPKI DER 为 44 字节) | 57 字节(SPKI DER 为 69 字节) |
| 签名 | 64 字节 | 114 字节 |
| 上下文字符串 | 仅 Ed25519ctx 和 Ed25519ph 中有 | 始终存在(0~255 字节,默认为空) |
| 每秒签名 / 验证次数(OpenSSL 3.6.5) | 约 60,000 / 25,000 | 约 27,500 / 10,100 |
| X.509 OID | 1.3.101.112 | 1.3.101.113 |
JOSE alg / COSE | Ed25519 / −19(RFC 9864) | Ed448 / −53(RFC 9864) |
| TLS 1.3 | ed25519(0x0807) | ed448(0x0808) |
| OpenSSH | ssh-ed25519 | 不支持 |
| 浏览器 WebCrypto | Firefox 129、Safari 17、Chrome 137 及更高版本 | 不提供 |
速度在 Apple M4 Max 的单个核心上用 openssl speed 测得。
安全余量
两者都是基于 Edwards 曲线的 EdDSA,采用完备加法公式、确定性 nonce 和严格编码,因此在抵御实现错误方面同样稳健。区别在于群的大小。Ed25519 的群约有 2²⁵² 个元素,针对 Pollard rho 算法可提供约 128 位安全强度,与 P-256、AES-128 和 SHA-256 碰撞处于同一级别。Ed448 的群约有 2⁴⁴⁶ 个元素,可提供约 224 位安全强度,高于 P-384(192 位),接近 P-521。
对经典攻击者来说,128 位已远远超出其能力范围,因此额外的余量防范的是椭圆曲线密码分析出人意料的进展,而不是暴力破解。面对大型量子计算机,两条曲线都会被 Shor 算法攻破,攻破更大的那条也只需略高的代价,这也是 NIST 的后量子计划对两者一视同仁的原因。
设计上的差异
Ed448 并不是 Ed25519 的放大版。它用 SHAKE256 而不是 SHA-512 计算哈希,这意味着依赖树中会多出一种哈希算法;它还总会在签名输入前加上一个域字符串,其中包含最长 255 字节的上下文。Ed25519 的纯(pure)形式没有上下文;Ed25519ctx 虽然存在,但很少有实现支持。如果你的协议需要对同一个密钥的不同用途做域分离,Ed448 直接就能提供,而使用 Ed25519 时,你必须把分离信息放进被签名的消息里。
两者都有预哈希变体,即 Ed25519ph 和 Ed448ph(FIPS 186-5 §7.8 中的 HashEdDSA),它们是独立的算法,签名互不兼容;除非你必须签名无法一次性完整传入的数据,否则应使用纯版本。
下面的脚本用 Node.js 26.10(OpenSSL 3.6.5)运行,展示了两者的大小差异。
import { generateKeyPairSync, sign, verify } from "node:crypto";
const message = Buffer.from("release-2026.10.tar.gz digest");
for (const type of ["ed25519", "ed448"]) {
const { privateKey, publicKey } = generateKeyPairSync(type);
const signature = sign(null, message, privateKey);
const raw = publicKey.export({ format: "jwk" }).x;
console.log(
type.padEnd(8),
"public key:", Buffer.from(raw, "base64url").length, "bytes,",
"SPKI DER:", publicKey.export({ type: "spki", format: "der" }).length, "bytes,",
"signature:", signature.length, "bytes,",
"verifies:", verify(null, message, publicKey, signature),
);
}
ed25519 public key: 32 bytes, SPKI DER: 44 bytes, signature: 64 bytes, verifies: true
ed448 public key: 57 bytes, SPKI DER: 69 bytes, signature: 114 bytes, verifies: true
生态系统支持
Ed25519 得到广泛支持:OpenSSH(自 9.5 版起为默认密钥类型)、Go 标准库、libsodium、BoringSSL、Java 15 及更高版本、通过第三方库支持的 .NET、所有主流 JOSE 库、OpenPGP v6 密钥、Apple CryptoKit、所有当前浏览器中的 WebCrypto,以及许多用于 SSH 和 FIDO2 的安全密钥。
Ed448 可以在 OpenSSL、Bouncy Castle、Java 15 及更高版本、Node.js、Python 的 cryptography、部分 RFC 9580 OpenPGP 实现(Ed448 在其中是可选的)以及部分 JOSE 库中使用。OpenSSH、Go 标准库、BoringSSL 和浏览器 WebCrypto 都不支持它(MDN 列出的 sign() 算法中有 Ed25519,但没有 Ed448)。两条曲线都不能用于公开信任的 TLS 证书,这类证书的密钥仅限于 RSA 和 NIST 曲线。
如何选择
- SSH、Git 签名、软件发布、JWT、服务间身份验证:Ed25519。
- 在浏览器端用 WebCrypto 签名:Ed25519(旧版浏览器用 ECDSA P-256);Ed448 不可用。
- 策略要求签名至少具备 192 位经典安全强度:Ed448;如果策略以 NIST 曲线为基础,则选 P-384 或 P-521(例如 CNSA 1.0 指定的是 P-384,而不是 Ed448)。
- 需要内置域分离的协议:Ed448 的强制上下文可以派上用场;使用 Ed25519 时,在被签名的数据中加入固定标签。
- 链路或存储空间非常受限:Ed25519,因为其签名短 50 字节,密钥短 25 字节。
迁移说明
在两者之间迁移意味着要换用新密钥:它们的曲线不同、哈希不同,标识符也不同。
- 先检查所有验证者。Ed448 的支持是瓶颈所在;只要有一个使用方基于 Go 标准库或 OpenSSH,就无法采用 Ed448。
- 显式修改标识符:OID
1.3.101.113;JOSEalgEd448(RFC 9864),较早的库则用EdDSA加crvEd448;COSE −53;v6 密钥中的 OpenPGP 算法 28。 - 按 57 字节的密钥和 114 字节的签名调整缓冲区和 schema 的大小;固定为 32 字节和 64 字节的字段是典型的出错点。
- 确定上下文。如果采用 Ed448,就要规定协议使用的上下文字符串,因为签名者和验证者必须传入相同的上下文。
- 为了长期防护,优先制订后量子计划(ML-DSA,可以与 Ed25519 或 Ed448 组成复合方案),而不是从 Ed25519 迁移到 Ed448。
参考资料
- RFC 8032:EdDSA(§5.1 Ed25519,§5.2 Ed448)
- FIPS 186-5:数字签名标准(§7)
- NIST SP 800-186(§3.2.3.1 Edwards25519,§3.2.3.2 Edwards448)
- RFC 8410:X.509 中的 Ed25519 与 Ed448
- RFC 9864:JOSE 与 COSE 的完全指定算法
- RFC 9580:OpenPGP
- MDN:SubtleCrypto.sign() 支持的算法