3. 公钥密码学基础

说实话,很多搞PKI的人,到最后对底层的密码学还是一知半解。这其实挺危险的。你没法判断一个方案到底安不安全。

我个人习惯,在深入信任模型之前,先把“地基”打牢。这章我们就聊聊RSA、ECC和密钥对。这些东西是后面所有逻辑的起点。

3.1 密钥对:一个锁,一把钥匙,但身份不同

对称加密大家熟,就一把钥匙,开锁锁门都用它。公钥密码学不一样,它天然就生成“一对”钥匙。

  • 私钥:自己藏好。这是你的数字身份。泄露了,等于你这个人可以被冒充。
  • 公钥:可以公开。别人拿它来验证你是不是你,或者给你加密消息。

核心只有两个操作:

  1. 加密:用你的公钥加密,只有你的私钥能解开。
  2. 签名:用你的私钥签名,别人可以用你的公钥验证签名是不是你干的。

这个逻辑一旦搞反,整个PKI就全乱套了。

我曾经见过一个项目:他们把签名用的私钥直接拿去当加密密钥用,结果密钥泄露后,整个系统的历史通信都被解密了。记住,签名是法律效力,加密是隐私保护,用的密码学原语刚好相反。

3.2 RSA:老大哥,至今仍是主力

RSA是1977年发明的,到现在快50年了。之所以还在用,是因为它的数学原理足够牢靠。简单说,它基于一个事实:

两个大质数相乘很容易,但把一个大数分解成两个质数,难如登天。你想想看,一个2048位的数,你要去猜它是哪两个质数的乘积,这计算量,宇宙毁灭都算不完。

嗯,这里要注意,RSA的密钥对生成过程其实很“重”。

# RSA密钥对生成的核心流程(简化)
1. 随机选择两个大质数 p 和 q (需满足特定随机性要求)
2. 计算 n = p * q       // n 就是公钥的一部分
3. 计算欧拉函数 φ(n) = (p-1)(q-1)
4. 选择一个整数 e (通常为 65537), 满足 1 < e < φ(n)
5. 计算 d, 使得 (d * e) % φ(n) == 1 // d 就是私钥

# 公钥: (n, e)
# 私钥: (n, d)

我刚开始做证书库的时候,觉得RSA生成密钥慢无所谓。后来在生产环境压测,发现并发量一大,CPU直接飙红。因为RSA私钥运算(比如签名)非常消耗性能,尤其是在移动设备上。

特性 RSA 优势 RSA 劣势
安全性强度 经过近50年密码分析考验,极其成熟 密钥长度不断增加(2048位起步,现在推荐4096位)
性能 加密与签名验证速度尚可 签名与解密速度非常慢(相较于ECC)
密钥体积 公钥相对较大(2048位),但网络传输不是瓶颈 私钥体积也大,对存储和传输有一定开销
适用场景 CA根证书、代码签名、数字信封(加密对称密钥) 频繁签名的场景(如TLS握手)、资源受限设备

一个小经验:在PKI系统中,根CA和二级CA的私钥,我们通常用RSA-4096。因为这些CA证书有效期长,需要最强的抗量子计算储备(虽然现在还没有量子计算机能攻破4096位RSA,但我们要未雨绸缪)。而终端实体证书(比如SSL证书),为了兼顾兼容性与性能,通常用RSA-2048或ECC。

3.3 ECC:后来居上,轻量战士

ECC,椭圆曲线密码学。它的核心优势就一句话:相同安全强度下,密钥尺寸更小,计算速度更快。

为什么会这样?RSA的数学基础是“因数分解”,而ECC的数学基础是“椭圆曲线离散对数问题”。说白了,攻破ECC需要的计算量是指数级的,比RSA要难得多。所以ECC用256位就能达到RSA-3072位或更高的安全等级。

我遇到过很多客户,一听到用ECC就担心兼容性。其实现在主流的浏览器、操作系统,对ECC的支持已经非常好了。

安全等级(位) RSA 密钥长度(位) ECC 密钥长度(位)
80 1024 160
112 2048 224
128 3072 256
192 7680 384
256 15360 521

上面的表格很直观。想达到相同的安全等级,ECC的密钥长度只有RSA的十分之一左右。这意味着什么?

  • 带宽压力小:TLS握手时,证书传输更快。
  • 计算负荷低:服务器每秒可以处理更多TLS握手。
  • 存储空间省:对IoT设备,这点很关键。

踩坑提醒:ECC虽然好,但你不能随便用一条曲线。NIST P-256(secp256r1)是业界最通用的标准。千万别用一些奇奇怪怪的曲线,尤其是那些声称“自己研发”的私有曲线。我以前有个同事,为了省事儿用了OpenSSL不默认支持的曲线,结果在客户的老系统上完全无法互通,现场排查了整整两天。

3.4 密钥管理与边界设计

技术懂了,但落到工程实践上,核心其实是“边界”。哪部分是硬件?哪部分是软件?哪部分归CA管?哪部分归用户管?

答案是:私钥永远不能离开它被生成的边界。

我个人习惯,把密钥对的生存周期分成三个阶段:

  1. 生成:必须在安全环境中生成。可以是HSM(硬件安全模块)、TPM(可信平台模块),或者签名服务器。
  2. 存储:私钥必须加密存储,而且密码必须高强度、唯一。不要硬编码到代码里。
  3. 使用:私钥只用于签名或解密,不要挪作他用。用完立即从内存中清除。

你看看下图,就知道RSA和ECC在实际PKI中的边界到底划在哪里:

PKI信任模型中的密钥边界设计 CA根(RSA-4096) 硬件安全模块HSM 二级CA(RSA/E) 签名服务器 终端实体(ECC) 软/硬件模组 安全边界 私钥不可导出 公钥可公开 RSA根侧重抗量子计算与长生命周期 ECC终端侧重性能与移动设备兼容性

你看,根CA的私钥,牢牢锁在HSM里,谁也别想把它提取出来私钥。二级CA在签名服务器里,私钥也是加密存储的。到了终端用户(比如你的浏览器),ECC私钥就存在你的操作系统安全存储或硬件TPM里。

3.5 实战中的避坑指南

最后,我给你总结几个我踩过的坑,或者见过别人踩的坑:

  • 不要在代码中硬编码私钥密码:曾经有个安全审计项目,我发现他们把HSM的PIN码直接写在Java类里,而且代码还提交到了Github公共仓库。后果?整个CA被重新颁发所有证书。
  • 不要混用密钥用途:签名密钥和加密密钥必须分开。签名密钥不能用来加密,加密密钥不能用来签名。这是PKI最基本的原则。我见过用SSL证书的私钥去签代码的,出了问题责任说不清。
  • 选择正确的曲线:如果你用ECC,请默认使用NIST P-256。别为了“创新”选P-521(虽然理论上更安全,但性能差,兼容性差)。更不要用SM2(国家商用密码算法)去对接国外系统,反之亦然。
  • 重视密钥生命周期:生成、使用、轮换、销毁,每一步都要有记录,有审计。我以前在一家金融公司,他们规定CA私钥每3年必须轮换一次,而且旧私钥必须物理销毁(用粉碎机粉碎HSM芯片)。听起来很夸张,但这是对用户负责。

一句话总结:公钥是门牌号,私钥是家里的钥匙。RSA是厚重牢固的防盗门,ECC是灵巧坚固的指纹锁。选哪个,取决于你的门框(场景)能承受多重的门,以及你希望开锁有多快。