2. 非对称加密与数字签名

上一章我们聊了TLS的整体握手流程,你可能会问:为什么非得搞出公钥私钥两把钥匙?一把锁不行吗? 说白了,对称加密虽然快,但密钥分发是个死穴。我在早期做内部PKI项目时,就亲眼见过运维把对称密钥明文贴在服务器机柜上……嗯,从那以后,我对非对称加密有了刻骨铭心的理解。

2.1 非对称加密的两大台柱:RSA与ECC

非对称加密的核心就是公私钥对:公钥随便发,私钥自己藏。加密用公钥,解密用私钥;签名用私钥,验签用公钥。目前业界主要用两种算法:RSA和ECC(椭圆曲线)。

一句话对比:RSA依赖大整数分解的难度,ECC依赖椭圆曲线离散对数问题。同样安全强度下,ECC的密钥长度短得多,计算也更快。

RSA原理(只讲干货)

  • 选两个大素数 p、q,计算 n = p×q
  • 欧拉函数 φ(n) = (p-1)(q-1)
  • 选公钥指数 e(常用65537),满足 gcd(e, φ(n)) = 1
  • 用扩展欧几里得算法求私钥 d ≡ e⁻¹ mod φ(n)
  • 公钥:(n, e);私钥:(n, d)

加密:c = m^e mod n;解密:m = c^d mod n。说白了就是取模运算。但注意:RSA直接把明文当数字加密不安全,必须配合OAEP填充。我曾经见过一个项目用教科书式RSA(无填充),结果被选择明文攻击打穿,教训惨痛。

⚠ 避坑:RSA密钥长度目前推荐至少2048位,建议3072位或以上。1024位已经可以在几天内被破解,别用了。

ECC原理(曲线上的魔法)

ECC基于椭圆曲线方程 y² = x³ + ax + b,加上无穷远点构成群。密钥对就是一个标量乘运算:私钥 k(一个大随机数),公钥 K = k×G,G是曲线的基点。

为什么ECC更香?举个例子:RSA 2048位的安全强度,ECC只要224位密钥;RSA 3072对应ECC 256位。我在做移动端证书签发时,因为手机性能有限,果断选了ECC,TLS握手快了一倍都不止。

💡 常用曲线:主流SSL/TLS推荐使用X25519(更高效)或P‑256(兼容性更好)。国内商密也搞了SM2曲线,基于素数域256位椭圆曲线。

2.2 哈希算法——数字签名的“摘要工兵”

数字签名不会对整个文件加密——文件太大,效率极低。实际做法是对文件的哈希值签名。哈希算法把任意长度数据变成固定长度的摘要(比如256位),而且具备三大特性:

  • 单向性:从摘要反推原文不可能
  • 抗碰撞性:找不到两个不同原文给同一个摘要
  • 抗篡改性:原文改一点点,摘要就面目全非

常见算法:SHA‑256、SHA‑384、SHA‑512(SHA‑1已死,MD5已死)。我曾经在安全检查中发现一家企业的证书签名算法还是SHA‑1withRSA,浏览器直接标红不信任,他们整组人连夜换证书,太折腾了。

2.3 数字签名流程——谁签的?谁验的?

现在我们把RSA/ECC和哈希串起来,看一个完整签名流程:

  1. 生成摘要:对原文用SHA‑256算出哈希值 H
  2. 签名:发信方用自己私钥对 H 加密(或ECC的签名运算),得到签名值 S
  3. 发送:原文 + 签名 S 一起发给接收方
  4. 验签:接收方用发送方公钥解密 S,得到 H',同时自己对原文算一遍哈希 H
  5. 比较:H' == H?相等则签名有效,否则数据被篡改

你想想看,这里面有个关键点:谁持有私钥,谁才能签名。所以数字签名提供了身份认证和完整性,但不加密原文。我在做银行网银系统时,每一笔交易报文都走了签名+验签,后来审计也没出过问题。

2.4 证书中的密钥对——公钥的“身份证”

公钥本身是裸露的——怎么证明这把公钥属于张三而不是李四?这就需要数字证书(X.509,后两章会解剖)。一个证书里至少包含:

  • 持有者信息:CN、OU、O、L、ST、C 等
  • 持有者公钥:算法标识(比如RSA 2048) + 公钥值
  • 签发者信息:CA(证书颁发机构)
  • 签名:CA用自己的私钥对整个证书主体签名
  • 有效期、序列号、扩展项…

所以说白了,证书就是“给公钥盖了个CA的章”。而证书里的密钥对就两个角色:

密钥对 谁持有 用途
证书主体的公钥 所有人可见 验签主体身份、加密对称密钥(RSA)
证书主体的私钥 仅主体自己 签名、解密
CA的公钥 预埋在信任库 验签证书真伪
CA的私钥 CA自己 签发证书

我习惯在HSM(硬件安全模块)里面生成并保存私钥,而不是放在磁盘上。私钥一旦泄露,证书就得立即吊销——我在一家支付公司就遇到过运维把私钥文件拷到Git仓库里……那叫一个刺激。

2.5 一张图看懂本章核心

下面这张SVG把RSA/ECC、哈希、签名流程和证书密钥对串起来了:

非对称加密与数字签名核心逻辑 非对称加密 RSA (大素数分解) ECC (椭圆曲线) 哈希算法 (SHA-256) 数字签名 (签名+验签) 摘要 → 私钥签名 证书中的密钥对 公钥(可见)+ 私钥(保密) 私钥签名 → 公钥验签 CA签发证书 = CA私钥签名 RSA/ECC + 哈希 → 数字签名 → 证书

2.6 本章小结(手账式)

  • RSA:成熟、兼容性好,但密钥长、计算慢;ECC:短密钥、快、趋势,主流用P‑256/X25519
  • 哈希:用SHA‑256以上,别再用SHA‑1;哈希是用来压缩待签名数据的
  • 数字签名 = 哈希 + 私钥运算;能证明身份和防篡改,但不能加密数据
  • 证书就是“CA盖戳的公钥”

个人建议:新项目直接上ECC(比如P‑256或X25519),别再抱着RSA 2048不放了。但要注意ECC的签名算法叫ECDSA,不是直接加密。我去年帮某云厂商迁移证书体系时,把RSA全部换成了ECC,TLS握手速度提升了约30%,而且证书体积小了一半,大厂的CDN节点都很开心。

⚠ 再强调一个坑:不要混淆“签名”和“加密”。RSA既可以加密也可以签名,但ECC只能签名/密钥协商(通过ECDHE),不能直接加密数据。想用ECC加密?得用ECIES混合机制,不要自己瞎造轮子。

好了,这一章的知识框架搭起来了。下回我们再深入看X.509证书的结构——那个才是最常打交道的东西。