3. 签名与验签原理:非对称签名算法(RSA、ECDSA、SM2)概述
讲签名之前,咱们先理清一个概念。签名不是为了保密,而是为了证明“这东西是我发出的,而且没被人改过”。说白了,就是数字世界的盖章画押。非对称签名用的是一对密钥——私钥盖章,公钥验章。你得把私钥藏好,公钥公开就行。
我早年做金融接口时,有个同事把私钥直接配在代码里,结果上线第一天就被测试发现了。嗯,那场面挺尴尬的。后来我们强制要求私钥必须从HSM(硬件安全模块)读取,人不能直接触碰私钥明文。这算是个血泪教训。
今天咱们重点看三种主流非对称签名算法:RSA、ECDSA 和 SM2。它们底子不一样,但业务上都能完成签名验签。下面一个个聊。
3.1 非对称签名怎么工作?
先说个大致的流程——你写了一段数据,用私钥算出一个“签名值”,把数据和签名一起发给对方。对方拿到你的公钥,对签名做校验,通过了就说明数据没有被篡改,也确实是你签的。
画个图会更好理解。我习惯把整个过程拆成三块:准备、签名、验签。
核心三要素:
- 私钥:只有签名者持有,用来生成签名。
- 公钥:公开给所有人,用来验证签名。
- 数字签名:附加在原数据上的密码学凭证。
你看这个图,左边签名方用私钥,右边验签方用公钥。中间传输的是“原文+签名”,不加密。为什么?因为签名不负责保密,只负责真实性。如果你既要保密又要签名,那就得先加密再签名,或者用签密方案,那是另一回事。
3.2 RSA签名
RSA应该是大家最熟悉的。它基于大整数分解困难问题。私钥(d, n),公钥(e, n)。签名时对哈希值做模幂运算,验签时再用公钥指数算回去,对比哈希。
关键特征:
- 签名长度固定,等于密钥长度(比如2048位RSA签名就是256字节)。
- 计算速度:签名慢,验签快(公钥指数常取65537,计算量小)。
- 安全性:当前推荐至少2048位,很多金融监管要求3072位。
我遇到过一个问题:如果用RSA签名,哈希函数不能太弱。比如用SHA-1做摘要,结果被碰撞攻击。那是2017年,我们有个旧系统还在用SHA-1+RSA,被安全审计直接打了回来。后来全部迁移到SHA-256。
注意:RSA签名存在“同态性质”——如果你拿到一个合法签名,理论上可以对签名做代数变换得到另一个合法签名(在小概率下)。实际应用中通常用PSS(概率签名方案)来避免这个问题。我个人建议能用PSS就别用PKCS#1 v1.5,除非有兼容硬性要求。
3.3 ECDSA签名
ECDSA(椭圆曲线数字签名算法)基于椭圆曲线离散对数困难问题。密钥长度小得多,256位ECDSA安全性约等于3072位RSA。签名长度也短:两个大整数(r, s),共64字节左右。
优势很明显:
- 短签名、短密钥,对带宽和存储友好。
- 签名速度也比RSA快不少。
- 支持曲线很多,但互操作比较麻烦。
但ECDSA有个坑——随机数k必须唯一。如果两次签名用了同一个k,或者k可预测,私钥就会泄漏。2011年索尼PS3就是因为这个被破解,k固定不变,直接算出了私钥。嗯,这就是不敬畏密码学的代价。
实战建议:使用HSM生成k时,确认HSM用了合格的随机数发生器(TRNG)。很多HSM就这个点做得比软件好。我亲自测过一些软件实现的k生成,有循环周期缺陷,后来全换了硬件的。
3.4 SM2签名
SM2是国内密码标准(GM/T 0003-2012),也是椭圆曲线算法,但曲线参数和ECDSA不同。签名格式也特殊——输出是64字节(r, s),但与ECDSA字节序、变换公式有差异。
和ECDSA的主要区别:
| 维度 | ECDSA | SM2 |
|---|---|---|
| 曲线参数 | secp256r1等 | SM2推荐曲线(国密标准) |
| 哈希函数 | SHA-256等 | SM3(256位杂凑) |
| 签名格式 | ASN.1 DER或原始(r,s) | 原始(r,s) 各32字节 |
| 用户标识 | 无 | 签名前需处理用户标识ZA |
| 密钥生成 | 随机数mod曲线阶 | 随机数mod曲线阶(增加校验) |
SM2签名验签之前需要先计算ZA值,它把用户标识、曲线参数、公钥一起哈希,再参与签名输入。这点很特别,ECDSA没有这个步骤。我在对接一个政务平台时,因为没算ZA,验签始终失败,折腾了大半天才找到原因。从那以后我就把SM2的ZA计算写进了内部检查清单。
性能方面:SM2和ECDSA在同等曲线下计算量相当。但是国内很多HSM对SM2做了硬件加速,所以国密设备上SM2反而比ECDSA快一些。
3.5 三种算法对比
选哪个?没有答案。我通常看场景给建议:
- 如果对接海外系统,或者有现成的RSA基础设施(比如PKI体系用RSA证书),用RSA 3072+ SHA-256。
- 如果追求签名短、性能高,且对密钥随机性有把握,用ECDSA P-256。
- 如果必须过国家密码合规(比如等保、金融国密改造),那就用SM2+SM3。
小结对比表:
| 特性 | RSA | ECDSA | SM2 |
|---|---|---|---|
| 密钥长度(安全等价) | 3072位 | 256位 | 256位 |
| 签名长度 | 384/512字节 | 64字节 | 64字节 |
| 签名速度 | 慢 | 快 | 快 |
| 验签速度 | 快(公钥指数小) | 快 | 快 |
| 随机数安全要求 | 低 | 高(k必须唯一) | 高(同上) |
| 合规适用 | 国际通用 | 国际通用 | 中国国密 |
| 标准支持 | PKCS#1, RFC 8017 | ANSI X9.62, FIPS 186 | GM/T 0003 |
3.6 避坑指南
- 哈希选取不能太弱:SHA-1别用了,用SHA-256以上。SM2必须配SM3,不要交叉混用。
- 签名输出编码要约定:ECDSA可以是ASN.1 DER,也可以是原始r||s。HSM接口通常支持多种,但双方必须一致。我遇到过一次,生产环境签名方用DER,验签方用原始字节,结果当天被运维电话叫醒。
- 密钥生命周期:HSM里的私钥可以安全存储,但备份和迁移策略要提前设计。万一HSM坏了,私钥丢了,所有已签名的文件都无法验证。听起来像废话,但真有人没备份。
- 验签时一定要用公钥:有一次我检查代码,发现某人用私钥去验签——没错,他用错了API。结果验签必然失败,还怪算法有问题。
个人习惯:在HSM上签名时,先把待签哈希传入HSM,让HSM内部做签名计算,永远不要从HSM导出私钥。如果需要频繁签名,善用HSM的会话缓存,避免每次重新加载密钥证书。
3.7 一点总结
非对称签名是数字世界的身份证明。RSA稳定可靠,ECDSA短小精悍,SM2符合国情。选型时不必纠结于“哪个最强”,而是看你的系统生态和合规需求。至于具体怎么对接HSM调用签名验签接口,下一笔章——哦不,后面几节我们再细聊每个接口的参数和示例。
记着,私钥是你最后的防线。硬件保护好,随机数生成好,协议约定好。做到这三好,签名基本不会翻车。