个人笔记,不保证正确。
博客已迁移至:https://ryan4yin.space/posts/jwt-algorithm-key-generation/
签名算法介绍具体的 JWT 签名算法前,先解释一下签名、摘要/指纹、加密这几个名词的含义:
数字签名(Digital Signature):就和我们日常办理各种手续时需要在文件上签上自己的名字一样,数字签名的主要用途也是防止伪造签名。
数字摘要(digest)/数字指纹(fingerprint): 指的都是数据的 Hash 值。
加密算法:这个应该不需要解释,就是对数据进行加密。。
数字签名的具体实现,通常是先对数据进行一次 Hash 摘要(SHA1/SHA256/SHA512 等),然后再使用非对称加密算法(RSA/ECDSA 等)的私钥对这个摘要进行加密,这样得到的结果就是原始数据的一个签名。
用户在验证数据时,只需要使用公钥解密出 Hash 摘要,然后自己再对数据进行一次同样的摘要,对比两个摘要是否相同即可。
注意:签名算法是使用私钥加密,确保得到的签名无法被伪造,同时所有人都可以使用公钥解密来验证签名。这和正常的数据加密算法是相反的。
因为数字签名多了非对称加密这一步,就能保证只有拥有私钥的人才能生成出正确的数字签名,达到了防止伪造签名的目的。
而数字摘要(Hash)则谁都可以计算出来,通常由可信方公布数据的 Hash 值,用户下载数据后,可通过 Hash 值对比来判断数据是否损坏,或者被人调包。
重点在于,Hash 摘要必须由可信方公布出来,否则不能保证安全性。而数字签名可以随数据一起提供,不需要担心被伪造。
JWT 是签名和数据一起提供的,因此必须使用签名才能保证安全性。
P.S. 在 Android/IOS 开发中,经常会遇到各类 API 或者 APP 商店要求提供 APP 的签名,还指明需要的是 MD5/SHA1 值。
这个地方需要填的 MD5/SHA1 值,实际上只是你「签名证书(=公钥+证书拥有者信息)」的「数字指纹/摘要」,和 JWT 的签名不是一回事。
JWT 规范的详细说明请见「参考」部分的链接。这里主要说明一下 JWT 最常见的几种签名算法(JWA):HS256(HMAC-SHA256) 、RS256(RSA-SHA256) 还有 ES256(ECDSA-SHA256)。
这三个都是消息签名算法,得到的都只是一段无法还原的签名。区别在于消息签名与签名验证需要的 「key」不同。
HS256 使用同一个「secret_key」进行签名与验证(对称加密)。一旦 secret_key 泄漏,就毫无安全性可言了。
因此 HS256 只适合集中式认证,签名和验证都必须由可信方进行。
传统的单体应用广泛使用这种算法,但是请不要在任何分布式的架构中使用它!
RS256 是使用 RSA 私钥进行签名,使用 RSA 公钥进行验证。公钥即使泄漏也毫无影响,只要确保私钥安全就行。
RS256 可以将验证委托给其他应用,只要将公钥给他们就行。
ES256 和 RS256 一样,都使用私钥签名,公钥验证。算法速度上差距也不大,但是它的签名长度相对短很多(省流量),并且算法强度和 RS256 差不多。
对于单体应用而言,HS256 和 RS256 的安全性没有多大差别。
而对于需要进行多方验证的微服务架构而言,显然只有 RS256/ES256 才能提供足够的安全性。
在使用 RS256 时,只有「身份认证的微服务(auth)」需要用 RSA 私钥生成 JWT,其他微服务使用公开的公钥即可进行签名验证,私钥得到了更好的保护。
更进一步,「JWT 生成」和「JWT 公钥分发」都可以直接委托给第三方的通用工具,比如 hydra。
甚至「JWT 验证」也可以委托给「API 网关」来处理,应用自身可以把认证鉴权完全委托给外部的平台,而应用自身只需要专注于业务。这也是目前的发展趋势。
RFC 7518 - JSON Web Algorithms (JWA) 中给出的 JWT 算法列表如下:
+--------------+-------------------------------+--------------------+ | "alg" Param | Digital Signature or MAC | Implementation | | Value | Algorithm | Requirements | +--------------+-------------------------------+--------------------+ | HS256 | HMAC using SHA-256 | Required | | HS384 | HMAC using SHA-384 | Optional | | HS512 | HMAC using SHA-512 | Optional | | RS256 | RSASSA-PKCS1-v1_5 using | Recommended | | | SHA-256 | | | RS384 | RSASSA-PKCS1-v1_5 using | Optional | | | SHA-384 | | | RS512 | RSASSA-PKCS1-v1_5 using | Optional | | | SHA-512 | | | ES256 | ECDSA using P-256 and SHA-256 | Recommended+ | | ES384 | ECDSA using P-384 and SHA-384 | Optional | | ES512 | ECDSA using P-521 and SHA-512 | Optional | | PS256 | RSASSA-PSS using SHA-256 and | Optional | | | MGF1 with SHA-256 | | | PS384 | RSASSA-PSS using SHA-384 and | Optional | | | MGF1 with SHA-384 | | | PS512 | RSASSA-PSS using SHA-512 and | Optional | | | MGF1 with SHA-512 | | | none | No digital signature or MAC | Optional | | | performed | | +--------------+-------------------------------+--------------------+ The use of "+" in the Implementation Requirements column indicates that the requirement strength is likely to be increased in a future version of the specification.可以看到被标记为 Recommended 的只有 RS256 和 ES256(纠正:最后一列只是对 JWA 具体实现的一些要求,和算法推荐没有任何关系!)。