赵志浩
Published on 2025-08-09 / 10 Visits
2
0

摘要、加密与签名

摘要

我们从 JWT 令牌的一小段“题外话”来引出现代密码学算法的三种主要用途:摘要、加密与签名。JWT 令牌携带信息的可信度源自于它是被签名过的信息,因此是不可篡改的,是令牌签发者真实意图的体现。然而,你是否了解过签名具体做了什么?为什么有签名就能够让负载中的信息变得不可篡改和不可抵赖呢?要解释数字签名(Digital Signature),必须先从密码学算法的另外两种基础应用“摘要”和“加密”说起。

摘要也称之为数字摘要(Digital Digest)或数字指纹(Digital Fingerprint)。JWT 令牌中默认的签名信息是对令牌头、负载和密钥三者通过令牌头中指定的哈希算法(HMAC SHA256)计算出来的摘要值,如下所示:

signature = SHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload) , secret)

理想的哈希算法都具备两个特性:一是易变性,这是指算法的输入端发生了任何一点细微变动,都会引发雪崩效应(Avalanche Effect),使得输出端的结果产生极大的变化。这个特性常被用来做校验,保护信息未被篡改。

二是不可逆性,摘要的过程是单向的,不可能从摘要的结果中逆向还原出输入值来。

世间的信息有无穷多种,而摘要的结果无论其位数是 32、128、512 Bits,再大也总归是个有限的数字,因此输入数据与输出的摘要结果必然不是一一对应的关系,如果我把一部电影做摘要形成 256 Bits 的哈希值,应该没有人会指望能从这个哈希值中还原出一部电影的。

偶尔能听到 MD5、SHA1 或其他哈希算法被破解了的新闻,这里的“破解”并不是“解密”的意思,而是指找到了该算法的高效率碰撞方法,能够在合理的时间内生成两个摘要结果相同的输入比特流,但并不能指定这两个输入流中的某一个,更不代表碰撞产生的比特流就会是原来的输入源。

由这两个特点可见,摘要的意义是在源信息不泄漏的前提下辨别其真伪。易变性保证了从公开的特征上可以甄别出是否来自于源信息,不可逆性保证了从公开的特征并不会暴露出源信息,这与今天用做身份甄别的指纹、面容和虹膜的生物特征是具有高度可比性的。

在一些场合中,摘要也会被借用来做加密(如保密中介绍的慢哈希 Bcrypt 算法)和签名(如 JWT 签名中的 HMAC SHA256 算法),但在严格意义上看,摘要与这两者是有本质的区别。

加密与摘要的本质区别在于加密是可逆的,逆过程就是解密。
而摘要本身是不可逆的,不能被解密。

加密

根据加密与解密是否采用同一个密钥,现代密码学算法可分为对称加密算法和非对称加密两大类型,这两类算法各自有很明确的优劣势与应用场景。

对称加密的缺点显而易见,加密和解密使用相同的密钥,当通信的成员数量增加时,为保证两两通信都采用独立的密钥,密钥数量就与成员数量的平方成正比,这必然面临密钥管理的难题。

而更尴尬的难题是当通信双方原本就不存在安全的信道时,如何才能将一个只能让通信双方才能知道的密钥传输给对方?如果有通道可以安全地传输密钥,那为何不使用现有的通道传输信息?这个“蛋鸡悖论”曾在很长的时间里严重阻碍了密码学在真实世界中推广应用。

20 世纪 70 年代中后期出现的非对称加密算法从根本上解决了密钥分发的难题,它将密钥分成公钥和私钥,公钥可以完全公开,无须安全传输的保证。私钥由用户自行保管,不参与任何通信传输。根据这两个密钥加解密方式的不同,使得算法可以提供两种不同的功能:

公钥加密,私钥解密,这种就是加密: 用于向私钥所有者发送信息,这个信息可能被他人篡改,但是无法被他人得知。如果甲想给乙发一个安全保密的数据,那么应该甲乙各自有一个私钥,甲先用乙的公钥加密这段数据,再用自己的私钥加密这段加密后的数据。最后再发给乙,这样确保了内容即不会被读取,也不能被篡改。

私钥加密,公钥解密,这种就是签名: 用于让所有公钥所有者验证私钥所有者的身份,并且用来防止私钥所有者发布的内容被篡改。但是不用来保证内容不被他人获得。

不论是加密还是解密,非对称加密算法的计算复杂度都相当高,性能比对称加密要差上好几个数量级(不是好几倍),所以主流的非对称加密算法都只能加密不超过密钥长度的数据,这决定了非对称加密不能直接用于大量数据的加密。

在加密方面,现在一般会结合对称与非对称加密的优点,以混合加密来保护信道安全,具体做法是用非对称加密来安全地传递少量数据给通信的另一方,然后再以这些数据为密钥,采用对称加密来安全高效地大量加密传输数据,这种由多种加密算法组合的应用形式被称为“密码学套件”。非对称加密在这个场景中发挥的作用称为“密钥协商”。

摘要和签名的区别

这里可能会有一个疑问,摘要和签名有区别吗?尤其是针对 "JWT 凭证(HMACSHA256签名算法)" 这个里面提到使用 HMACSHA256 算法基于原始请求内容 + 密钥,生成后的凭证,到底是摘要,还是签名?

在问 DeepSeek 之前,我们先搞清楚一个问题:HMACSHA256 实际是两个算法,SHA256 和 MD5 等一样是一个哈希摘要算法。

而 HMAC 实际是一个对称加解密算法,它和 AES,DES 是平级,都是基于密钥来进行加解密的算法。

我们再看一下 JWT 生成签名时的算法:可以看到 secret 实际是一个单独的传参,最终传递给HMACSHA256函数的参数分别是:原始内容 和 密钥。而不是把密钥拼接给原始内容做的 HASH。

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload) , secret)

所以摘要本身实际是仅保证数据完整性,不涉及身份认证。

而签名:则是对摘要进行加密处理的结果。生成后的摘要,此时使用密钥对该摘要进行加密最终得到的结果中,包含了身份绑定。

即:用私钥加密该摘要证明了发送者的身份。且具备了不可否认性:只有私钥持有者能生成有效签名。并且间接保证数据未被篡改。

这个问题,我问了下 DeepSeek 给的答案也是类似的:

https://chat.deepseek.com/a/chat/s/9ee82e38-2459-471a-a29e-9c8ca2910d88

这里可能接着还是会有一个疑问,使用 HMAC 这类对称加解密算法对摘要进行加密,这属于数字签名吗?还是说必须使用非对称加解密中的私钥进行加密,才算是数字签名?

这里 DS 给的结果是,从工程语境中:常被称为“签名”,但是在密码学的概念中,签名必须是通过非对称加解密中的私钥来生成的,才算是签名。

原因是因为:对称加解密中的密钥是双方共享的,所以不能提供不可否认性。而私钥由于是独一无二的(仅私钥持有者持有的),所以通过私钥持有者生成的签名,才算是真正的数字签名。


那么为什么防重放设计中用 HMAC,而非 非对称加解密来生成签名?

  1. 性能考量:HMAC 比 RSA/ECDSA 快 100-1000 倍

  2. 简单密钥管理:Client/Server 共享密钥即可

  3. 适用场景:只需验证请求来自合法客户端(不要求不可否认)

这里我觉得核心是适用场景,因为此处的场景是:A 云 调用 B 云的接口。由于是云云对接,所以两边云端最开始就线下配置好对应的密钥。这是相对安全的。

至于性能考量,这里不是非常核心,因为可以采用 SHA256 先将原始数据生成摘要,然后再将摘要 使用对应的私钥进行加密,生成签名即可。

只要不是直接将 AES 加密大量的文本即可,只是加密摘要,性能还好。比 HMAC 这类对称加解密慢一些,还能接受。

最后截图一下常见的算法实现:来自凤凰架构。


Comment