在 P-256 与 P-384 之间选择,就是在同一家族的两条 NIST 曲线之间选择:算法相同(ECDSA 和 ECDH),编码相同,工具也相同。P-384 把经典安全强度从约 128 位提高到约 192 位;P-256 则快好几倍,支持它的硬件也更多。对大多数系统来说,起决定作用的是策略要求,而不是风险。
概览
| P-256(secp256r1) | P-384(secp384r1) | |
|---|---|---|
| 域大小、群的阶 | 256 位 | 384 位 |
| 经典安全强度 | 约 128 位(相当于 AES-128) | 约 192 位(相当于 AES-192) |
| 常用哈希 | SHA-256 | SHA-384 |
| 私钥 | 32 字节 | 48 字节 |
| 公钥 | 未压缩形式 65 字节,SPKI DER 91 字节 | 未压缩形式 97 字节,SPKI DER 120 字节 |
| 签名 | 原始格式 64 字节,DER 为 70~72 字节 | 原始格式 96 字节,DER 约为 102~104 字节 |
| 每秒签名 / 验证次数(OpenSSL 3.6.5) | 约 87,000 / 29,000 | 约 9,700 / 4,500 |
| JOSE / COSE | ES256 / −7 | ES384 / −35 |
| TLS 1.3 | ecdsa_secp256r1_sha256(0x0403),命名组 23 | ecdsa_secp384r1_sha384(0x0503),命名组 24 |
| 混合 TLS 命名组 | SecP256r1MLKEM768 | SecP384r1MLKEM1024 |
| Secure Enclave、Android Keystore、TPM 2.0 | 支持 | 视平台而定(Secure Enclave 不支持) |
| NIST IR 8547(草案) | 2035年后禁止使用 | 2035年后禁止使用 |
速度用 openssl speed 在 Apple M4 Max 的单个核心上测得;下面测量大小的脚本使用 OpenSSL 3.6.5 运行。
需要多高的安全强度?
NIST SP 800-57 第 1 部分把 256~383 位的曲线归入 128 位安全强度,把 384~511 位的曲线归入 192 位。128 位远远超出任何可预见的经典攻击能力:针对 P-256 的已知最佳攻击需要约 2¹²⁸ 次群运算。P-384 多出的余量防范的是椭圆曲线密码分析出现意外进展,而不是暴力破解;它对 Shor 算法也毫无作用,Shor 算法攻破这两条曲线所需的代价相近。因此,NIST IR 8547(首版公开草案)对两者一视同仁:两者在2030年都不会被弃用(那只针对 RSA-2048、P-224 等 112 位安全强度的算法),并且都在2035年后禁止使用。
真正起决定作用的是策略。NSA 最初的商用国家安全算法套件(Commercial National Security Algorithm Suite,CNSA 1.0)要求 ECDH 和 ECDSA 使用 P-384,因此面向美国国家安全系统及其供应链的产品默认使用它;CNSA 2.0 则改用 ML-KEM-1024 和 ML-DSA-87 来取代它。证书颁发机构常为必须在十年甚至更长时间内保持可信的根密钥和中间密钥选用 P-384;Let's Encrypt 的 ISRG Root X2 及其 ECDSA 中间证书都使用 P-384,而订户证书两条曲线都可以用。
性能与大小开销
OpenSSL 为 P-256 提供了手工优化的汇编实现,所以差距很大:在单个 Apple M4 Max 核心上,P-256 每秒约能完成 87,000 次签名,P-384 约 9,700 次;验证则是约 29,000 次对 4,500 次。对 TLS 服务器而言,证书密钥在每次完整握手中签名一次,因此 P-384 会让握手中这部分开销增加到约九倍;对每秒只签发几张证书的证书颁发机构来说,这点差异无关紧要。
大小增长有限:原始签名多 32 字节,公钥多 32 字节,证书多约 60 字节。
#!/bin/sh
dir=$(mktemp -d)
cd "$dir" || exit 1
printf 'hello' > msg
for curve in P-256 P-384; do
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:$curve -out key.pem 2>/dev/null
openssl req -new -x509 -key key.pem -subj "/CN=example.com" -days 90 -outform DER -out cert.der 2>/dev/null
openssl dgst -sha256 -sign key.pem -out sig.der msg
printf '%s: SPKI %s bytes, DER signature %s bytes, self-signed certificate %s bytes\n' "$curve" \
"$(openssl pkey -in key.pem -pubout -outform DER | wc -c | tr -d ' ')" \
"$(wc -c < sig.der | tr -d ' ')" \
"$(wc -c < cert.der | tr -d ' ')"
done
cd / && rm -rf "$dir"
P-256: SPKI 91 bytes, DER signature 71 bytes, self-signed certificate 388 bytes
P-384: SPKI 120 bytes, DER signature 102 bytes, self-signed certificate 451 bytes
支持情况
两条曲线都收录在 FIPS 186-5 和 SP 800-186 中;所有 TLS 库、WebCrypto、JOSE 和 COSE、PIV 智能卡都支持它们,它们也都在 CA/Browser Forum 允许的证书密钥列表中(P-256、P-384 和 P-521)。差距出在安全硬件和认证器上:Apple 的 Secure Enclave 在经典密钥中只提供 P-256,通行密钥几乎全都使用 ES256,一些物联网安全元件也只实现了 P-256。在服务端,HSM 和云 KMS 服务两者都支持。
如何选择
- 公开信任的 TLS 证书:P-256。它的握手更快,而且到处都被接受;P-384 叶子证书不会带来任何客户端能够验证的收益。
- CA 根密钥和中间密钥:对长期使用的密钥来说,P-384 是常见且合理的选择;它可以为 P-256 叶子证书签名。
- JWT 和 API 令牌:
ES256,除非某个规范要求使用ES384,例如部分政府或金融行业的规范。 - 通行密钥和设备密钥:P-256,因为硬件提供的就是它。
- CNSA 1.0 系统及其供应商:P-384 配 SHA-384,再加上 AES-256;并按照 CNSA 2.0 规划向 ML-KEM-1024 和 ML-DSA-87 迁移。
- 混合后量子 TLS:一般场景用
X25519MLKEM768;如果 CNSA 式的策略要求使用 NIST 曲线和安全类别 5 的参数,则用SecP384r1MLKEM1024。
迁移说明
更换曲线意味着要换新密钥,但工具链保持不变。
- 生成新密钥:在密钥将来存放的 HSM 或 KMS 中,用
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-384(或 P-256)生成。 - 正确搭配哈希。P-384 通常与 SHA-384 搭配使用(
ES384、ecdsa-with-SHA384);ECDSA 会把较长的哈希截断到阶的长度,但不匹配的组合会让策略检查和部分验证器出现误判。 - 更新标识符:JOSE 的
alg和crv、COSE 算法、TLS 签名方案以及证书模板。轮换期间,在 JWKS 中同时发布两个密钥,并为它们分配不同的kid值。 - 调整固定大小的缓冲区:原始签名从 64 字节增至 96 字节,坐标从 32 字节增至 48 字节。
- 先对握手做基准测试,再把繁忙的 TLS 端点切换到 P-384 证书;大多数出于策略原因迁移到 P-384 的部署,在策略不适用的地方仍然保留 P-256。