根据我的理解,验证JWT
签名是一个直接的过程.但是,当我使用一些在线工具为我做这件事时,它并不匹配.如何在JWT
不使用JWT库的情况下手动验证签名?我需要一种快速方法(使用可用的在线工具)来演示如何完成此操作.
我JWT
在https://jwt.io/#debugger-io上创建了我的以下信息:
HS256
hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6
{ "alg": "HS256", "typ": "JWT" }
{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }
智威汤逊:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.wDQ2mU5n89f2HsHm1dluHGNebbXeNr748yJ9kUNDNCA
手动JWT
签名验证尝试:
使用base64UrlEncode计算器(http://www.simplycalc.com/base64url-encode.php或https://www.base64encode.org/)
如果我:( 不是站点上的实际值,修改后显示最终为我构建的工具)
base64UrlEncode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9") + "." + base64UrlEncode("eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ")
我明白了:
ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5.ZXlKemRXSWlPaUl4TWpNME5UWTNPRGt3SWl3aWJtRnRaU0k2SWtwdmFHNGdSRzlsSWl3aWFXRjBJam94TlRFMk1qTTVNREl5ZlE=
注意:如果我应该对已经编码的值进行编码,或者按原样使用已经编码的值,那么我会有一些困惑.
(即使用
base64UrlEncode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9") + "." + base64UrlEncode("eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ")
vs"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ"
).无论我应该做什么,最终结果仍然与签名不符.我倾向于认为我应该不重新编码的编码值,不管是真还是假.
然后使用HMAC Generator计算器(https://codebeautify.org/hmac-generator或https://www.freeformatter.com/hmac-generator.html#ad-output)
(不是网站上的实际价值,经过修改以显示最终为我构建的工具)
HMACSHA256( "ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5.ZXlKemRXSWlPaUl4TWpNME5UWTNPRGt3SWl3aWJtRnRaU0k2SWtwdmFHNGdSRzlsSWl3aWFXRjBJam94TlRFMk1qTTVNREl5ZlE=", "hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6" )
哪个让我:
a2de322575675ba19ec272e83634755d4c3c2cd74e9e23c8e4c45e1683536e01
这与以下标志部分不符JWT
:
wDQ2mU5n89f2HsHm1dluHGNebbXeNr748yJ9kUNDNCAM
!= a2de322575675ba19ec272e83634755d4c3c2cd74e9e23c8e4c45e1683536e01
目的:
我需要确认这一点的原因是为了证明能够验证JWT
没有被篡改,而不解码JWT
.
我的客户端Web界面不需要解码JWT
,所以他们不需要安装jwt包来执行此操作.他们只需要进行简单的验证,以确认在JWT
存储JWT
未来的API调用之前没有被篡改(但不太可能).
这都是格式和编码的问题.
在https://jwt.io上,您可以根据输入值和密码获取此令牌:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M
Run Code Online (Sandbox Code Playgroud)
我们要证明签名:
3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M
Run Code Online (Sandbox Code Playgroud)
是正确的.
签名是Base64url编码的HMAC-SHA256哈希.(如RFC7515中所述)
当您使用在线HMAC生成器计算哈希值时
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
Run Code Online (Sandbox Code Playgroud)
随着秘密
hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6
Run Code Online (Sandbox Code Playgroud)
你得到
de921a2a4b225fd66ff0983e8566eb0f6e1584bdfa84120568da40e1f571dbd3
Run Code Online (Sandbox Code Playgroud)
结果,这是一个HMAC-SHA256值,但不是Base64url编码的.此哈希是十六进制数的ASCII表示.
要将其与https://jwt.io中的值进行比较,您需要转换其ASCII十六进制表示值并对其进行Base64url编码.
以下脚本正在执行此操作,并使用crypto-js来计算它自己的哈希值.这也可以让您在没有JWT库的情况下进行验证.
var CryptoJS = require("crypto-js");
// the input values
var base64Header = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
var base64Payload = "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ";
var secret = "hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6";
// two hashes from different online tools
var signatureJWTIO = "3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M";
var onlineCaluclatedHS256 = "de921a2a4b225fd66ff0983e8566eb0f6e1584bdfa84120568da40e1f571dbd3";
// hash calculation with Crypto-JS.
// The two replace expressions convert Base64 to Base64url format by replacing '+' with '-'
// and stripping the '=' padding
var base64Signature = CryptoJS.HmacSHA256(base64Header + "." + base64Payload , secret).toString(CryptoJS.enc.Base64).replace(/\+/g,'-').replace(/\=+$/m,'');
// converting the online calculated value to Base64 representation
var base64hash = new Buffer(onlineCaluclatedHS256, 'hex').toString('base64').replace(/\+/g,'-').replace(/\=+$/m,'');
// the results:
console.log("Signature from JWT.IO : " + signatureJWTIO);
console.log("NodeJS calculated hash : " + base64Signature);
console.log("online calulated hash (converted) : " + base64hash);
Run Code Online (Sandbox Code Playgroud)
结果是:
Signature from JWT.IO : 3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M
NodeJS calculated hash : 3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M
online calulated hash (converted) : 3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M
Run Code Online (Sandbox Code Playgroud)
相同!
结论:
由不同的格式和编码,由不同的在线工具计算的值都是正确的,但不能直接比较.如上所示的小脚本可能是更好的解决方案.
小智 5
我遇到了同样的问题,直到我发现我使用的是纯base64
编码而不是base64url
。\n之间还有一些小细节。\n这里是分步手册,希望能够使整个过程更加清晰。
注意 1:您必须从 JSON 字符串(标头和负载)中删除所有空格和换行符。\n当您生成 JWT 令牌时,它会在jwt.io上隐式完成。
\n\n注 2:要将 JSON 字符串转换为base64url
cryptii.com 上的字符串,请创建以下配置:
First view: Text\n\nSecond view: Encode\n Encoding: Base64\n Variant: Standard \'base64url\' (RFC 4648 \xc2\xa75)\n\nThird view: Text\n
Run Code Online (Sandbox Code Playgroud)\n\n注 3:要将 HMAC HEX 代码(签名)转换为base64url
cryptii.com 上的字符串,请创建以下配置:
First view: Bytes\n Format: Hexadecimal\n Group by: None\n\nSecond view: Encode\n Encoding: Base64\n Variant: Standard \'base64url\' (RFC 4648 \xc2\xa75)\n\nThird view: Text\n
Run Code Online (Sandbox Code Playgroud)\n\n您只需要两个在线工具:
\n\nbase64url
编码,在cryptii.com上,您既可以进行编码/解码,也可以进行 HMAC 计算,但是对于 HMAC,您需要提供与jwt.iobase64url
上的输入不同的十六进制密钥,因此我使用单独的服务进行 HMAC 计算。
在本手册中我使用了以下数据:
\n\n标题:
\n\n{"alg":"HS256","typ":"JWT"}\n
Run Code Online (Sandbox Code Playgroud)有效负载:
\n\n{"sub":"1234567890","name":"John Doe","iat":1516239022}\n
Run Code Online (Sandbox Code Playgroud)密钥):
\n\nThe Earth is flat!\n
Run Code Online (Sandbox Code Playgroud)秘密没有base64
被编码。
标题(纯文本):
\n\n{"alg":"HS256","typ":"JWT"}\n
Run Code Online (Sandbox Code Playgroud)标头(base64url
编码):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\n
Run Code Online (Sandbox Code Playgroud)有效负载(纯文本):
\n\n{"sub":"1234567890","name":"John Doe","iat":1516239022}\n
Run Code Online (Sandbox Code Playgroud)有效负载(base64url
编码):
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ\n
Run Code Online (Sandbox Code Playgroud)使用算法计算HMAC SHA256
。
输入字符串(base64url
编码的标头和有效负载,用点连接):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ\n
Run Code Online (Sandbox Code Playgroud)计算代码(十六进制数):
\n\nc8a9ae59f3d64564364a864d22490cc666c74c66a3822be04a9a9287a707b352\n
Run Code Online (Sandbox Code Playgroud)计算出的 HMAC 代码是签名的十六进制表示。\n注意:不应将其编码为base64url
纯文本字符串,而应编码为字节序列。
base64url
【工具1】中:签名(字节):
\n\nc8a9ae59f3d64564364a864d22490cc666c74c66a3822be04a9a9287a707b352\n
Run Code Online (Sandbox Code Playgroud)签名(base64url
编码):
yKmuWfPWRWQ2SoZNIkkMxmbHTGajgivgSpqSh6cHs1I\n
Run Code Online (Sandbox Code Playgroud)这是我们的结果(全部base64url
编码):
标题:
\n\neyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\n
Run Code Online (Sandbox Code Playgroud)有效负载:
\n\neyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ\n
Run Code Online (Sandbox Code Playgroud)签名:
\n\nyKmuWfPWRWQ2SoZNIkkMxmbHTGajgivgSpqSh6cHs1I\n
Run Code Online (Sandbox Code Playgroud)jwt.io的结果:
\n\neyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.yKmuWfPWRWQ2SoZNIkkMxmbHTGajgivgSpqSh6cHs1I\n
Run Code Online (Sandbox Code Playgroud)\n\n正如您所看到的,所有三个部分都是相同的。
\n 归档时间: |
|
查看次数: |
2200 次 |
最近记录: |