2. 常见算法介绍:RSA签名、ECDSA签名、SM2签名、HMAC与签名的区别
做签名验签调试,第一关就是搞清楚你手里拿的是什么算法。我见过太多人把RSA和HMAC混为一谈,或者拿着SM2的签名结果去用ECDSA验签——结果当然是失败。这一章咱们就把这几个主流算法掰开揉碎,讲清楚它们的核心逻辑和适用场景。
一句话总结:RSA靠大数分解,ECDSA靠椭圆曲线离散对数,SM2是国密版的ECDSA,HMAC则是带密钥的哈希——它根本不是签名算法。
2.1 RSA签名
RSA签名,说白了就是“私钥加密,公钥解密”的逆用。不过这里有个坑:RSA实际做签名时并不是直接加密原文,而是先对原文做哈希,再对哈希值做私钥操作。
我个人习惯把RSA签名流程拆成三步:
- 哈希摘要:对原文做SHA-256(或其它哈希),得到固定长度的摘要
- 填充:把摘要塞进一个标准格式的块里(PKCS#1 v1.5或PSS)
- 私钥加密:用私钥对填充后的块做模幂运算,输出签名
验签就是反过来:公钥解密签名得到填充块,拆出摘要,再和原文的哈希比对。
避坑指南:我曾经在调试一个支付接口时,发现RSA签名总是验不过。查了两天才发现——对方用的是PSS填充,我默认用了PKCS#1 v1.5。两种填充模式产生的签名完全不同,验签时必须严格匹配。
RSA签名的特点:
- 签名长度固定,等于密钥长度(1024位密钥产生128字节签名)
- 验签速度比签名快(公钥指数通常很小,比如65537)
- 密钥越长越安全,但签名和验签都越慢
| 密钥长度 | 签名长度 | 安全等级(近似) |
|---|---|---|
| 2048位 | 256字节 | 112位 |
| 3072位 | 384字节 | 128位 |
| 4096位 | 512字节 | 152位 |
2.2 ECDSA签名
ECDSA(椭圆曲线数字签名算法)是RSA的替代方案。它用更短的密钥达到同等安全强度——256位的ECDSA和3072位的RSA安全性差不多。
ECDSA的核心思想:利用椭圆曲线上的点加法运算,把私钥(一个大整数)映射到曲线上的一个点(公钥)。签名过程会生成两个整数(r, s),验签时通过公钥和原文哈希验证这对值是否匹配。
嗯,这里要注意:ECDSA每次签名都会引入一个随机数k。这意味着同一份原文、同一个私钥,每次签名结果都不一样。这不是bug,是特性。
重要警告:随机数k绝对不能重复使用!我曾经见过一个项目,因为随机数生成器有bug,导致两次签名用了相同的k值。攻击者直接算出了私钥——整个系统的信任瞬间崩塌。如果你用ECDSA,务必确保随机数质量。
ECDSA签名长度取决于曲线参数。以最常用的P-256曲线为例:
- 签名结果:r和s各32字节,总共64字节
- 公钥:一个点坐标(x, y),各32字节,共64字节(未压缩)
- 私钥:32字节
和RSA对比,ECDSA的优势很明显:
- 签名短(64字节 vs RSA 256字节)
- 计算快(尤其是生成密钥对)
- 适合资源受限的设备
2.3 SM2签名
SM2是国家密码管理局发布的椭圆曲线签名算法。说白了,它就是中国版的ECDSA,但细节上有差异。
SM2使用的椭圆曲线参数是国密标准定义的,和NIST的P-256不一样。签名流程和ECDSA类似,但有几个关键区别:
- SM2在签名前会把发送方ID、公钥等信息混入哈希计算(这叫“用户标识参与签名”)
- SM2的签名结果格式是(r, s),但编码方式可能不同
- SM2推荐使用256位素域上的曲线
实战经验:我在对接某政务系统时,对方要求用SM2签名。我直接用ECDSA的库改了曲线参数,结果验签死活不过。后来才发现——SM2的哈希预处理阶段多了一步“用户标识”的拼接。这个细节在国密标准GM/T 0003-2012里有明确说明,但很多人会忽略。
SM2签名长度:
- 签名结果:r和s各32字节,共64字节
- 公钥:65字节(压缩格式33字节)
- 私钥:32字节
2.4 HMAC与签名的区别
这是最容易混淆的地方。HMAC(基于哈希的消息认证码)经常被误称为“签名”,但它俩有本质区别。
HMAC的核心:用共享密钥对消息做带密钥的哈希。签名验签双方持有同一个密钥,一方生成MAC,另一方验证MAC是否一致。
而真正的签名(RSA/ECDSA/SM2)用的是非对称密钥对——私钥签名,公钥验签。
| 特性 | HMAC | 数字签名 |
|---|---|---|
| 密钥类型 | 对称密钥(双方相同) | 非对称密钥(私钥+公钥) |
| 可公开验证 | 否(需要共享密钥) | 是(公钥公开) |
| 抗抵赖性 | 无(双方都能生成) | 有(只有私钥持有者能生成) |
| 性能 | 极快(纯哈希运算) | 较慢(涉及大数运算) |
| 典型场景 | API鉴权、消息完整性校验 | 数字证书、电子合同、代码签名 |
为什么会有这种混淆?因为很多API文档里把HMAC的结果也叫“签名”。但你要记住:HMAC只能证明消息在传输过程中没被篡改,不能证明消息是谁发的——因为双方都有密钥。
一句话区分:HMAC是“我们俩都知道的秘密”,数字签名是“只有我知道的秘密,但大家都能验证”。
2.5 四种机制对比总览
下面这张SVG图把四种机制的核心逻辑画出来了,方便你对照理解:
2.6 选型建议
说了这么多,实际项目里到底选哪个?我个人的经验是:
- 对外接口、需要公开验证:用RSA或ECDSA。RSA兼容性最好,ECDSA签名更短
- 国密合规要求:用SM2。别想着用ECDSA替代,过不了等保测评
- 内部系统间鉴权、消息完整性校验:用HMAC。性能好,实现简单
- 资源受限设备(IoT):优先ECDSA或SM2,签名短、计算快
最后提醒:不管你选哪种算法,一定要在项目初期就确定好参数细节——曲线名称、填充模式、编码格式、哈希算法。我见过太多项目因为“RSA签名”这四个字太笼统,导致联调时才发现双方用的参数不一样,返工成本极高。