为何JWT签名需使用SHA-256这类哈希算法?
首先得明确:JWT里的签名算法(比如RS256、ES256)本质是带哈希的数字签名方案,不是直接对Base64编码的头部+载荷做签名,这种设计是密码学实践和工程效率的双重要求,核心作用有这几点:
性能优化:降低签名计算成本
非对称加密(比如RSA)的签名/验签操作,计算量和输入数据长度正相关。如果直接对可能很长的Base64编码内容(比如载荷包含大量用户信息)做签名,速度会很慢,高并发场景下会成为瓶颈。而哈希算法(比如SHA-256)能把任意长度输入压缩成固定长度的摘要(SHA-256是32字节),用这个短摘要做签名,计算效率会提升几个数量级,工程上更实用。适配数字签名算法的设计要求
绝大多数现代数字签名算法(RSA、ECDSA等)的原生设计就是针对固定长度的短数据,而非任意长度的长文本。直接对长文本做非对称签名,不仅不符合算法规范,还可能引入额外安全风险(比如某些实现对超长输入的处理存在漏洞)。哈希步骤相当于把长数据“转换”成签名算法能安全、高效处理的格式。强化抗篡改与抗碰撞能力
哈希算法的雪崩效应(输入微小变化会导致哈希值完全不同)和抗碰撞性(几乎不可能找到两个不同输入生成相同哈希),让篡改检测更可靠。哪怕攻击者只修改载荷里一个字符,哈希值都会彻底改变,对应的签名验证必然失败。如果直接签原Base64内容,虽然篡改也会失败,但哈希的特性让这种验证的安全性更有保障——攻击者无法通过构造不同的头部/载荷来生成和原签名匹配的结果,因为哈希的抗碰撞性堵死了这条路。遵循密码学标准实践
数字签名的标准流程就是“哈希+非对称加密”,这是密码学界经过多年验证的安全方案。直接对长文本签名并非主流做法,因为哈希算法已经解决了长数据签名的效率和安全问题,没必要另起炉灶。JWT作为标准化的令牌格式,自然会遵循这套成熟的方案。
举个简单例子:如果你的JWT载荷有1KB的Base64内容,直接用RSA签名要处理1024字节数据;用SHA-256哈希后只需要处理32字节,速度差非常明显,而且安全性丝毫不打折扣。
内容的提问来源于stack exchange,提问作者Naga Sudhir

