JWT、JWE、JWS 、JWK 都是什么鬼?还傻傻分不清?
共 9495字,需浏览 19分钟
·
2022-01-14 08:59
阅读本文大概需要 10 分钟。
作者:NinthDevilHunster
来源:www.freebuf.com/articles/web/180874.html
JWT
什么是 JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
JWT 解决什么问题?
认证 Authentication; 授权 Authorization // 注意这两个单词的区别; 联合识别; 客户端会话(无状态的会话); 客户端机密。
JWT 的一些名词解释
JWS:Signed JWT签名过的jwt JWE:Encrypted JWT部分payload经过加密的jwt;目前加密payload的操作不是很普及; JWK:JWT的密钥,也就是我们常说的 scret; JWKset:JWT key set在非对称加密中,需要的是密钥对而非单独的密钥,在后文中会阐释; JWA:当前JWT所用到的密码学算法; nonsecure JWT:当头部的签名算法被设定为none的时候,该JWT是不安全的;因为签名的部分空缺,所有人都可以修改。
JWT的组成
header:主要声明了JWT的签名算法; payload:主要承载了各种声明并传递明文数据; signture:拥有该部分的JWT被称为JWS,也就是签了名的JWS;没有该部分的JWT被称为nonsecure JWT 也就是不安全的JWT,此时header中声明的签名算法为none。
JWT header
{
"typ": "JWT",
"alg": "none",
"jti": "4f1g23a12aa"
}
base64UrlEncode(header)
>> eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIiwianRpIjoiNGYxZzIzYTEyYWEifQ
{
"iss": "http://shaobaobaoer.cn",
"aud": "http://shaobaobaoer.cn/webtest/jwt_auth/",
"jti": "4f1g23a12aa",
"iat": 1534070547,
"nbf": 1534070607,
"exp": 1534074147,
"uid": 1,
"data": {
"uname": "shaobao",
"uEmail": "shaobaobaoer@126.com",
"uID": "0xA0",
"uGroup": "guest"
}
}
iss 【issuer】发布者的url地址 sub 【subject】该JWT所面向的用户,用于处理特定应用,不是常用的字段 aud 【audience】接受者的url地址 exp 【expiration】 该jwt销毁的时间;unix时间戳 nbf 【not before】 该jwt的使用时间不能早于该时间;unix时间戳 iat 【issued at】 该jwt的发布时间;unix 时间戳 jti 【JWT ID】 该jwt的唯一ID编号
base64UrlEncode(payload)
>>eyJpc3MiOiJodHRwOi8vc2hhb2Jhb2Jhb2VyLmNuIiwiYXVkIjoiaHR0cDovL3NoYW9iYW9iYW9lci5jbi93ZWJ0ZXN0L2p3dF9hdXRoLyIsImp0aSI6IjRmMWcyM2ExMmFhIiwiaWF0IjoxNTM0MDcwNTQ3LCJuYmYiOjE1MzQwNzA2MDcsImV4cCI6MTUzNDA3NDE0NywidWlkIjoxLCJkYXRhIjp7InVuYW1lIjoic2hhb2JhbyIsInVFbWFpbCI6InNoYW9iYW9iYW9lckAxMjYuY29tIiwidUlEIjoiMHhBMCIsInVHcm91cCI6Imd1ZXN0In19
JWS
JWS 的概念
RSASSA || ECDSA || HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
>>GQPGEpixjPZSZ7CmqXB-KIGNzNl4Y86d3XOaRsfiXmQ
>># 上面这个是用 HMAC SHA256生成的
对称加密HMAC【哈希消息验证码】:HS256/HS384/HS512 非对称加密RSASSA【RSA签名算法】(RS256/RS384/RS512) ECDSA【椭圆曲线数据签名算法】(ES256/ES384/ES512)
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImp0aSI6IjRmMWcyM2ExMmFhIn0.eyJpc3MiOiJodHRwOi8vc2hhb2Jhb2Jhb2VyLmNuIiwiYXVkIjoiaHR0cDovL3NoYW9iYW9iYW9lci5jbi93ZWJ0ZXN0L2p3dF9hdXRoLyIsImp0aSI6IjRmMWcyM2ExMmFhIiwiaWF0IjoxNTM0MDcwNTQ3LCJuYmYiOjE1MzQwNzA2MDcsImV4cCI6MTUzNDA3NDE0NywidWlkIjoxLCJkYXRhIjp7InVuYW1lIjoic2hhb2JhbyIsInVFbWFpbCI6InNoYW9iYW9iYW9lckAxMjYuY29tIiwidUlEIjoiMHhBMCIsInVHcm91cCI6Imd1ZXN0In19.GQPGEpixjPZSZ7CmqXB-KIGNzNl4Y86d3XOaRsfiXmQ
JWS 的额外头部声明
jku: 发送JWK的地址;最好用HTTPS来传输 jwk: 就是之前说的JWK kid: jwk的ID编号 x5u: 指向一组X509公共证书的URL x5c: X509证书链 x5t:X509证书的SHA-1指纹 x5t#S256: X509证书的SHA-256指纹 typ: 在原本未加密的JWT的基础上增加了 JOSE 和 JOSE+ JSON。JOSE序列化后文会说及。适用于JOSE标头的对象与此JWT混合的情况。 crit: 字符串数组,包含声明的名称,用作实现定义的扩展,必须由 this->JWT的解析器处理。不常见。
多重验证与JWS序列化
{
"payload": "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ",
"signatures":
[
{
"protected": "eyJhbGciOiJSUzI1NiJ9",
"header": { "kid": "2010-12-29" },
"signature":"signature1"
},
{
"protected": "eyJhbGciOiJSUzI1NiJ9",
"header": { "kid": "e9bc097a-ce51-4036-9562-d2ade882db0d" },
"signature":"signature2"
},
...
]
}
protected:之前的头部声明,利用b64uri加密; header:JWS的额外声明,这段内容不会放在签名之中,无需验证; signature:也就是对当前header+payload的签名。
JWE
JWE 相关概念
JWE 的构成
eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.
UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-kFm1NJn8LE9XShH59_
i8J0PH5ZZyNfGy2xGdULU7sHNF6Gp2vPLgNZ__deLKxGHZ7PcHALUzoOegEI-8E66jX2E4zyJKxYxzZIItRzC5hlRirb6Y5Cl_p-ko3YvkkysZIFNPccxRU7qve1WYPxqbb2Yw8kZqa2rMWI5ng8Otv
zlV7elprCbuPhcCdZ6XDP0_F8rkXds2vE4X-ncOIM8hAYHHi29NX0mcKiRaD0-D-ljQTPcFPgwCp6X-nZZd9OHBv-B3oWh2TbqmScqXMR4gp_A.
AxY8DCtDaGlsbGljb3RoZQ.
KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.
9hH0vgRfYgPnAHOd8stkvw
The protected header,类似于JWS的头部; The encrypted key,用于加密密文和其他加密数据的对称密钥; The initialization vector,初始IV值,有些加密方式需要额外的或者随机的数据; The encrypted data (cipher text),密文数据; The authentication tag,由算法产生的附加数据,来防止密文被篡改。
JWE 密钥加密算法
Key Encryption Key Wrapping Direct Key Agreement Key Agreement with Key Wrapping Direct Encryption
https://github.com/Spomky-Labs/jose/blob/master/doc/operation/Encrypt.md
JWE Header
type:一般是 jwt alg:算法名称,和JWS相同,该算法用于加密稍后用于加密内容的实际密钥 enc:算法名称,用上一步生成的密钥加密内容的算法。 zip:加密前压缩数据的算法。该参数可选,如果不存在则不执行压缩,通常的值为 DEF,也就是deflate算法 jku/jkw/kid/x5u/x5c/x5t/x5t#S256/typ/cty/crit:和JWS额额外声明一样。
JWE 的加密过程
根据头部alg的声明,生成一定大小的随机数; 根据密钥管理模式确定加密密钥; 根据密钥管理模式确定JWE加密密钥,得到CEK; 计算初始IV,如果不需要,跳过此步骤; 如果ZIP头申明了,则压缩明文; 使用CEK,IV和附加认证数据,通过enc头声明的算法来加密内容,结果为加密数据和认证标记; 压缩内容,返回token。
base64(header) + '.' +base64(encryptedKey) + '.' + // Steps 2 and 3base64(initializationVector) + '.' + // Step 4base64(ciphertext) + '.' + // Step 6base64(authenticationTag) // Step 6
多重验证与JWE序列化
{
"protected": "eyJlbmMiOiJBMTI4Q0JDLUhTMjU2In0",
"unprotected": { "jku":"https://server.example.com/keys.jwks" },
"recipients":[
{
"header": { "alg":"RSA1_5","kid":"2011-04-29" },
"encrypted_key":
"UGhIOguC7Iu...cqXMR4gp_A"
},
{
"header": { "alg":"A128KW","kid":"7" },
"encrypted_key": "6KB707dM9YTIgH...9locizkDTHzBC2IlrT1oOQ"
}
],
"iv": "AxY8DCtDaGlsbGljb3RoZQ",
"ciphertext": "KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY",
"tag": "Mz-VPPyU4RlcuYv1IwIvzw"
}
protected:之前的头部声明,利用b64uri加密; unprotected:一般放JWS的额外声明,这段内容不会被b64加密; iv:64加密后的iv参数; add:额外认证数据; ciphertext:b64加密后的加密数据; recipients:b64加密后的认证标志-加密链,这是一个数组,每个数组中包含了两个信息; header:主要是声明当前密钥的算法; encrypted_key:JWE加密密钥。
JWT 的工作原理
Authorization: Bearer
ECDSA|RSASSA or HMAC ?应该选用哪个?
https://stackoverflow.com/questions/38588319/understanding-rsa-signing-for-jwt。
推荐阅读:
内容包含Java基础、JavaWeb、MySQL性能优化、JVM、锁、百万并发、消息队列、高性能缓存、反射、Spring全家桶原理、微服务、Zookeeper、数据结构、限流熔断降级......等技术栈!
⬇戳阅读原文领取! 朕已阅