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位起步。别图省那点性能,安全底线不能碰。

好了,签名的基础概念就这些。搞懂了数字签名是什么、有什么用、和加密有什么区别、常见算法有哪些——后面排查签名校验失败问题的时候,你就能快速定位到底是哪个环节出了岔子。