3. 签名与验签原理:非对称签名算法(RSA、ECDSA、SM2)概述

讲签名之前,咱们先理清一个概念。签名不是为了保密,而是为了证明“这东西是我发出的,而且没被人改过”。说白了,就是数字世界的盖章画押。非对称签名用的是一对密钥——私钥盖章,公钥验章。你得把私钥藏好,公钥公开就行。

我早年做金融接口时,有个同事把私钥直接配在代码里,结果上线第一天就被测试发现了。嗯,那场面挺尴尬的。后来我们强制要求私钥必须从HSM(硬件安全模块)读取,人不能直接触碰私钥明文。这算是个血泪教训。

今天咱们重点看三种主流非对称签名算法:RSA、ECDSA 和 SM2。它们底子不一样,但业务上都能完成签名验签。下面一个个聊。

3.1 非对称签名怎么工作?

先说个大致的流程——你写了一段数据,用私钥算出一个“签名值”,把数据和签名一起发给对方。对方拿到你的公钥,对签名做校验,通过了就说明数据没有被篡改,也确实是你签的。

画个图会更好理解。我习惯把整个过程拆成三块:准备、签名、验签。

核心三要素:

  • 私钥:只有签名者持有,用来生成签名。
  • 公钥:公开给所有人,用来验证签名。
  • 数字签名:附加在原数据上的密码学凭证。
非对称签名与验签流程图 签名方 原文 M 私钥 SK 哈希函数 H 计算:S = Sign(SK, H(M)) 输出:签名值 S 输出:原文 M + 签名 S 发送 验签方 收到:M' + S' 公钥 PK 哈希函数 H 校验:Verify(PK, H(M'), S') 结果:通过 / 失败 失败则拒绝数据 验签结果 通过 → 数据可信 失败 → 数据被篡改 注意:哈希运算不可逆,防碰撞

你看这个图,左边签名方用私钥,右边验签方用公钥。中间传输的是“原文+签名”,不加密。为什么?因为签名不负责保密,只负责真实性。如果你既要保密又要签名,那就得先加密再签名,或者用签密方案,那是另一回事。

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的主要区别:

维度ECDSASM2
曲线参数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。

小结对比表:

特性RSAECDSASM2
密钥长度(安全等价)3072位256位256位
签名长度384/512字节64字节64字节
签名速度慢快快
验签速度快(公钥指数小)快快
随机数安全要求低高(k必须唯一)高(同上)
合规适用国际通用国际通用中国国密
标准支持PKCS#1, RFC 8017ANSI X9.62, FIPS 186GM/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调用签名验签接口,下一笔章——哦不,后面几节我们再细聊每个接口的参数和示例。

记着,私钥是你最后的防线。硬件保护好,随机数生成好,协议约定好。做到这三好,签名基本不会翻车。