如何使用在线工具手动验证 JWT 签名 [英] How to manually validate a JWT signature using online tools

查看:17
本文介绍了如何使用在线工具手动验证 JWT 签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我所知,验证 JWT 签名是一个简单的过程.但是当我使用一些在线工具为我做这件事时,它不匹配.如何在不使用 JWT 库的情况下手动验证 JWT 签名?我需要一个快速的方法(使用可用的在线工具)来演示这是如何完成的.

我在 https://jwt.io/#debugger- 上创建了我的 JWTio 带有以下信息:

  • 算法: HS256
  • 秘密: hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6
  • 标题:<上一页>{alg":HS256",典型":智威汤逊"}

  • 有效载荷:<上一页>{子":1234567890",名称":约翰·多伊",iat":1516239022}

  • 验证签名(部分):
    • 秘密值改为上面
    • 已检查"的秘密 base64 编码(无论是否检查,仍然得到不同的值)

智威汤逊:

<上一页>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.wDQ2mU5n89f2HsHm1dluHGNebbXeNr748yJ9kUNDA

<小时>

手动JWT签名验证尝试:

使用 base64UrlEncode 计算器 (http://www.simplycalc.com/base64url-encode.phphttps://www.base64encode.org/)

如果我: (不是网站的实际价值,已修改以显示工具最终将为我构建的内容)

<上一页>base64UrlEncode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9") + "."+ base64UrlEncode("eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ")

我明白了:

<上一页>ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5.ZXlKemRXSWlPaUl4TWpNME5UWTNPRGt3SWl3aWJtRnRaU0k2SWtwdmFHNGdSRzlsSWl3aWFXRjBJam94TlRFMk1qTTVNREl5ZlE=

<块引用>

注意:如果我应该对已经编码的值进行编码,或者按原样使用已经编码的值,我会感到有些困惑.

(即使用<代码> base64UrlEncode( eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9")+ " + base64UrlEncode( eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ") VS <代码> eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ").

不管我应该做什么,最终结果仍然与签名不匹配.我倾向于我应该重新编码编码值,无论这是否正确.

然后使用 HMAC 生成器计算器 (https://codebeautify.org/hmac-生成器https://www.freeformatter.com/hmac-generator.html#ad-output)

(不是网站的实际价值,已修改以显示工具最终将为我构建的内容)

<上一页>HMACSHA256("ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5.ZXlKemRXSWlPaUl4TWpNME5UWTNPRGt3SWl3aWJtRnRaU0k2SWtwdmFHNGdSRzlsSWl3aWFXRjBJam94TlRFMk1qTTVNREl5ZlE=",hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6")

这让我很感动:

<上一页>a2de322575675ba19ec272e83634755d4c3c2cd74e9e23c8e4c45e1683536e01

这与 JWT 的签名部分不匹配:

wDQ2mU5n89f2HsHm1dluHGNebbXeNr748yJ9kUNDNCAM != a2de322575675ba19ec272e83634755d4c3c2cd74e9e23c8e4c45e1683536e01

<小时>

目的:

我需要确认这一点的原因是为了证明能够验证 JWT 未被篡改,而无需解码 JWT.p>

我的客户端 Web 界面不需要解码 JWT,因此他们无需为此安装 jwt 包.他们只需要在存储 JWT 以供将来的 API 调用之前进行简单的验证,以确认 JWT 没有被篡改(尽管不太可能).

解决方案

都是格式和编码的问题.

https://jwt.io 上,您会根据您的输入值和密码获得此令牌:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFa

我们要证明签名:

3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

是正确的.

签名是经过 Base64url 编码的 HMAC-SHA256 哈希.(如 RFC7515 中所述)

当您使用 在线 HMAC 生成器 计算哈希时对于

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

秘密

hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6

你得到

de921a2a4b225fd66ff0983e8566eb0f6e1584bdfa84120568da40e1f571dbd3

作为结果,这是一个 HMAC-SHA256 值,但不是 Base64url 编码的.这个哈希是一个大数字的十六进制字符串表示.

要将其与 https://jwt.io 中的值进行比较,您需要将值转换为十六进制字符串表示回一个数字,然后 Base64url 对其进行编码.

以下脚本正在执行此操作,并且还使用 crypto-js 来计算它自己的哈希值.这也可以是您在没有 JWT 库的情况下进行验证的一种方式.

var CryptoJS = require("crypto-js");//输入值var base64Header = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";var base64Payload = "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ";var secret = "hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6";//来自不同在线工具的两个哈希var signatureJWTIO = "3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M";var onlineCaluclatedHS256 = "de921a2a4b225fd66ff0983e8566eb0f6e1584bdfa84120568da40e1f571dbd3";//使用 Crypto-JS 进行哈希计算.//两个replace表达式通过replace将Base64转换为Base64url格式//'+' 和 '-','/' 和 '_' 并去除 '=' 填充var base64Signature = CryptoJS.HmacSHA256(base64Header + "." + base64Payload , secret).toString(CryptoJS.enc.Base64).replace(/+/g,'-').replace(///g,'_').replace(/=+$/m,'');//将在线计算的值转换为 Base64 表示var base64hash = new Buffer.from(onlineCaluclatedHS256, 'hex').toString('base64').replace(///g,'_').replace(/+/g,'-').replace(/=+$/m,'')//结果:console.log("来自 JWT.IO 的签名:" + signatureJWTIO);console.log("NodeJS 计算哈希:" + base64Signature);console.log("在线计算哈希(转换):"+base64hash);

结果是:

来自 JWT.IO 的签名:3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29MNodeJS计算哈希:3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M在线计算哈希(转换):3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

一模一样!

结论:

不同在线工具计算的值都是正确的,但由于格式和编码不同,无法直接比较.如上所示的一个小脚本可能是一个更好的解决方案.

From what I can understand, it's a straight forward process to validate a JWT signature. But when I use some online tools to do this for me, it doesn't match. How can I manually validate a JWT signature without using a JWT library? I'm needing a quick method (using available online tools) to demo how this is done.

I created my JWT on https://jwt.io/#debugger-io with the below info:

  • Algorithm: HS256
  • Secret: hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6
  • Header:

    {
      "alg": "HS256",
      "typ": "JWT"
    }
    

  • Payload:

    {
      "sub": "1234567890",
      "name": "John Doe",
      "iat": 1516239022
    }
    

  • Verify Signature (section):
    • Secret value changed to above
    • "Checked" secret base64 encoded (whether this is checked or not, still get a different value)

JWT:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.wDQ2mU5n89f2HsHm1dluHGNebbXeNr748yJ9kUNDNCA


Manual JWT signature verification attempt:

Using a base64UrlEncode calculator (http://www.simplycalc.com/base64url-encode.php or https://www.base64encode.org/)

If I: (Not actual value on sites, modified to show what the tools would ultimately build for me)

base64UrlEncode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9") + "." + base64UrlEncode("eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ")

I get:

ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5.ZXlKemRXSWlPaUl4TWpNME5UWTNPRGt3SWl3aWJtRnRaU0k2SWtwdmFHNGdSRzlsSWl3aWFXRjBJam94TlRFMk1qTTVNREl5ZlE=

NOTE: there's some confusion on my part if I should be encoding the already encoded values, or use the already encoded values as-is.

(i.e. using base64UrlEncode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9") + "." + base64UrlEncode("eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ") vs "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ").

Regardless on which I should do, the end result still doesn't match the signature. I'm leaning towards that I should NOT re-encode the encoded value, whether that's true or not.

Then using a HMAC Generator calculator (https://codebeautify.org/hmac-generator or https://www.freeformatter.com/hmac-generator.html#ad-output)

(Not actual value on sites, modified to show what the tools would ultimately build for me)

HMACSHA256(
 "ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5.ZXlKemRXSWlPaUl4TWpNME5UWTNPRGt3SWl3aWJtRnRaU0k2SWtwdmFHNGdSRzlsSWl3aWFXRjBJam94TlRFMk1qTTVNREl5ZlE=",
  "hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6"
)

Which gets me:

a2de322575675ba19ec272e83634755d4c3c2cd74e9e23c8e4c45e1683536e01

And that doesn't match the signature portion of the JWT:

wDQ2mU5n89f2HsHm1dluHGNebbXeNr748yJ9kUNDNCAM != a2de322575675ba19ec272e83634755d4c3c2cd74e9e23c8e4c45e1683536e01


Purpose:

The reason I'm needing to confirm this is to prove the ability to validate that the JWT hasn't been tampered with, without decoding the JWT.

My clients web interface doesn't need to decode the JWT, so there's no need for them to install a jwt package for doing that. They just need to do a simple validation to confirm the JWT hasn't been tampered with (however unlikely that may be) before they store the JWT for future API calls.

解决方案

It's all a matter of formats and encoding.

On https://jwt.io you get this token based on your input values and secret:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

We want to prove that the signature:

3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

is correct.

The signature is a HMAC-SHA256 hash that is Base64url encoded. (as described in RFC7515)

When you use the online HMAC generator to calculate a hash for

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

with the secret

hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6

you get

de921a2a4b225fd66ff0983e8566eb0f6e1584bdfa84120568da40e1f571dbd3

as result, which is a HMAC-SHA256 value, but not Base64url encoded. This hash is a hexadecimal string representation of a large number.

To compare it with the value from https://jwt.io you need to convert the value from it's hexadecimal string representation back to a number and Base64url encode it.

The following script is doing that and also uses crypto-js to calculate it's own hash. This can also be a way for you to verify without JWT libraries.

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 '-', '/' with '_' and stripping the '=' padding
var base64Signature = CryptoJS.HmacSHA256(base64Header + "." + base64Payload , secret).toString(CryptoJS.enc.Base64).replace(/+/g,'-').replace(///g,'_').replace(/=+$/m,'');

// converting the online calculated value to Base64 representation
var base64hash = new Buffer.from(onlineCaluclatedHS256, 'hex').toString('base64').replace(///g,'_').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);

The results are:

Signature from JWT.IO             : 3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

NodeJS calculated hash            : 3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

online calulated hash (converted) : 3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

identical!

Conclusion:

The values calculated by the different online tools are all correct but not directly comparable due to different formats and encodings. A little script as shown above might be a better solution.

这篇关于如何使用在线工具手动验证 JWT 签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆