1. 签名校验基础:数字签名到底是什么
做签名校验排查,第一步得搞清楚——数字签名到底是个什么东西?
我见过不少开发同学,一遇到签名校验失败就懵了。其实说白了,数字签名就是给数据盖个「防伪章」。你想想看,现实里我们怎么确认一份文件是真的?看公章、看签字。数字世界也一样,只不过这个「章」是一串数学计算出来的结果。
1.1 什么是数字签名
数字签名,是用私钥对数据的哈希值进行加密运算后得到的一串数据。接收方用对应的公钥来验证这串数据是否合法。
举个例子:
- 签名过程:发送方对文件算一个哈希值,然后用私钥加密这个哈希值,得到签名。
- 验证过程:接收方用公钥解密签名,得到哈希值A;再对收到的文件算哈希值B。如果A==B,签名通过。
核心要点:数字签名不是加密整个文件,而是加密文件的「指纹」(哈希值)。这样做效率高,而且能保证文件完整性。
1.2 签名的作用
数字签名主要解决三个问题:
| 作用 | 说明 | 类比现实 |
|---|---|---|
| 身份认证 | 确认数据确实来自声称的发送方 | 身份证上的照片 |
| 数据完整性 | 数据在传输过程中没有被篡改 | 信封的封条 |
| 不可否认性 | 发送方不能事后否认发过该数据 | 合同上的签字 |
我的经验:有一次排查APK安装失败问题,发现签名校验报错。查了半天,原来是渠道方在打包后手动改了AndroidManifest里的一个字段。签名校验直接就把这个篡改给揪出来了——完整性保护就是这么管用。
1.3 签名与加密的区别
很多人把签名和加密搞混。我刚开始学的时候也犯过这个错。其实它们完全是两码事:
| 对比维度 | 数字签名 | 数据加密 |
|---|---|---|
| 目的 | 防篡改、防抵赖 | 防泄露、保机密 |
| 使用密钥 | 私钥签名,公钥验证 | 公钥加密,私钥解密 |
| 处理对象 | 数据的哈希值 | 整个数据 |
| 输出结果 | 签名(固定长度) | 密文(与原文等长或更长) |
| 能否还原原文 | 不能 | 能(用私钥解密) |
简单记法:签名用私钥,加密用公钥。反过来就错了。
注意:签名不保护数据内容本身。签名后的数据仍然是明文传输的。如果有人想偷看你的数据内容,光靠签名是不够的,得配合加密一起用。
1.4 常见签名算法
实际项目中,我接触最多的签名算法有三种。每种都有自己的脾气:
RSA
RSA 是最经典的签名算法。基于大整数分解难题,安全性经过了多年考验。
- 密钥长度:2048位起步,4096位更安全
- 签名速度:较慢(尤其私钥签名时)
- 典型应用:APK签名、SSL证书、代码签名
// RSA签名示例(伪代码)
PrivateKey privateKey = loadPrivateKey("rsa_private.pem");
Signature sign = Signature.getInstance("SHA256withRSA");
sign.initSign(privateKey);
sign.update(data);
byte[] signature = sign.sign();
ECDSA
ECDSA 基于椭圆曲线离散对数问题。同样的安全强度下,密钥比RSA短得多。
- 密钥长度:256位即可达到RSA 3072位的安全等级
- 签名速度:比RSA快
- 典型应用:区块链交易签名、TLS 1.3、移动端签名
我个人偏好:新项目我一般优先选ECDSA。密钥短、性能好,移动端兼容性也越来越好了。不过要注意,ECDSA的随机数生成必须足够随机,否则会泄露私钥——这个坑我在审计代码时见过不止一次。
HMAC
HMAC 不是非对称签名,而是基于共享密钥的消息认证码。它和RSA/ECDSA有本质区别:
| 特性 | RSA/ECDSA | HMAC |
|---|---|---|
| 密钥类型 | 公私钥对 | 共享密钥 |
| 验证方 | 任何持有公钥的人 | 只有持有共享密钥的人 |
| 不可否认性 | 支持 | 不支持 |
| 性能 | 较慢 | 非常快 |
// HMAC-SHA256示例
Mac hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec key = new SecretKeySpec(sharedKey, "HmacSHA256");
hmac.init(key);
byte[] result = hmac.doFinal(data);
什么时候用HMAC:内部系统之间的API签名、微服务之间的通信认证。因为双方共享同一个密钥,性能好、实现简单。但注意——HMAC不能用于公开验证的场景,比如APK签名就不适合用HMAC。
1.5 签名算法对比一览
| 算法 | 安全基础 | 密钥长度 | 签名速度 | 验证速度 | 典型场景 |
|---|---|---|---|---|---|
| RSA | 大整数分解 | 2048-4096位 | 慢 | 快 | APK签名、SSL证书 |
| ECDSA | 椭圆曲线离散对数 | 256-521位 | 快 | 快 | 区块链、TLS 1.3 |
| HMAC | 共享密钥+哈希 | 任意长度 | 极快 | 极快 | API签名、内部认证 |
避坑提醒:我曾经接手过一个项目,对方用RSA 1024位做签名。当时觉得没问题,结果安全审计直接亮了红灯。现在1024位已经被认为不够安全了,至少2048位起步。别图省那点性能,安全底线不能碰。
好了,签名的基础概念就这些。搞懂了数字签名是什么、有什么用、和加密有什么区别、常见算法有哪些——后面排查签名校验失败问题的时候,你就能快速定位到底是哪个环节出了岔子。