如何使用在线工具手动验证JWT签名

时间:2018-05-01 18:24:41

标签: jwt

根据我的理解,这是验证JWT签名的直接过程。但是,当我使用一些在线工具为我做这件事时,它并不匹配。如何在不使用JWT库的情况下手动验证JWT签名?我需要一种快速的方法(使用可用的在线工具)来演示如何完成这项工作。

我使用以下信息在https://jwt.io/#debugger-io上创建了JWT

  • 算法: HS256
  • 秘密: hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6
  • 标题
    {
      "alg": "HS256",
      "typ": "JWT"
    }
    
  • 有效载荷:
    {
      "sub": "1234567890",
      "name": "John Doe",
      "iat": 1516239022
    }
    
  • 验证签名(部分):
    • 秘密值已更改为
    • “已检查”秘密base64编码(无论是否已选中,仍会获得不同的值)

JWT:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.wDQ2mU5n89f2HsHm1dluHGNebbXeNr748yJ9kUNDNCA

手动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 Generator计算器https://codebeautify.org/hmac-generatorhttps://www.freeformatter.com/hmac-generator.html#ad-output

(不是网站上的实际价值,经过修改后会显示最终为我制作的工具)

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

哪个让我:

a2de322575675ba19ec272e83634755d4c3c2cd74e9e23c8e4c45e1683536e01

这与JWT

的签名部分不符

wDQ2mU5n89f2HsHm1dluHGNebbXeNr748yJ9kUNDNCAM != a2de322575675ba19ec272e83634755d4c3c2cd74e9e23c8e4c45e1683536e01

目的:

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

我的客户端网页界面不需要解码JWT,因此他们无需安装 jwt软件包来执行此操作。他们只需要进行简单的验证,以确认JWT在未来API调用存储JWT之前未被篡改(但不太可能)。

2 个答案:

答案 0 :(得分:6)

这完全是格式和编码问题。

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

replace-item n blacklist -1

我们要证明签名:

n

是对的。

签名是Base64url编码的HMAC-SHA256哈希。 (如RFC7515

中所述

使用online HMAC generator计算

的哈希值时
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

秘密

3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

你得到了

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

结果,这是一个HMAC-SHA256值,但不是Base64url编码的。此哈希是十六进制数字的ASCII表示。

要将它与https://jwt.io中的值进行比较,您需要转换它的ASCII十六进制表示值并对其进行Base64url编码。

以下脚本正在这样做,并且还使用crypto-js来计算它自己的哈希值。这也可以让您在没有JWT库的情况下进行验证。

hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6

结果是:

de921a2a4b225fd66ff0983e8566eb0f6e1584bdfa84120568da40e1f571dbd3

相同!

结论:

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

答案 1 :(得分:0)

我遇到了同样的问题,直到我发现我使用的是普通的base64编码而不是base64url。 两者之间也有一些小细节。 这是循序渐进的手册,希望可以使整个过程更加清晰。

注释

注释1:,您必须从JSON字符串(标头和有效负载)中删除所有空格和换行符。 生成JWT令牌时,它是在jwt.io上隐式完成的。

注意2:要将cryptii.com上的JSON字符串转换为base64url字符串,请创建以下配置:

First view: Text

Second view: Encode
    Encoding: Base64
    Variant: Standard 'base64url' (RFC 4648 §5)

Third view: Text

注释3:要将cryptii.com上的HMAC HEX代码(签名)转换为base64url字符串,请创建以下配置:

First view: Bytes
    Format: Hexadecimal
    Group by: None

Second view: Encode
    Encoding: Base64
    Variant: Standard 'base64url' (RFC 4648 §5)

Third view: Text

手册

您将只需要两个在线工具:

  1. [工具1]: cryptii.com-用于base64url编码,
  2. [工具2]: codebeautify.org-用于HMAC计算。

cryptii.com上,您既可以进行base64url编码/解码,也可以进行HMAC计算,但是对于HMAC,您需要提供一个与jwt.io上的输入不同的十六进制密钥,因此我为HMAC计算使用了单独的服务。

输入数据

在本手册中,我使用了以下数据:

  • 标题:

    {"alg":"HS256","typ":"JWT"}
    
  • 有效载荷:

    {"sub":"1234567890","name":"John Doe","iat":1516239022}
    
  • 秘密(密钥):

    The Earth is flat!
    

该机密未经base64编码。

步骤1:转换标题[工具1]

  • 标题(纯文本):

    {"alg":"HS256","typ":"JWT"}
    
  • 标头(已编码base64url):

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
    

步骤2:转换有效载荷[工具1]

  • 有效载荷(纯文本):

    {"sub":"1234567890","name":"John Doe","iat":1516239022}
    
  • 有效负载(base64url编码):

    eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
    

步骤3:计算HMAC代码(签名)[工具2]

使用SHA256算法计算HMAC。

  • 输入字符串(base64url编码的标头和有效负载,用点连接):

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
    
  • 计算代码(十六进制数字):

    c8a9ae59f3d64564364a864d22490cc666c74c66a3822be04a9a9287a707b352
    

计算出的HMAC代码是签名的HEX表示。 注意:它不应被编码为base64url作为纯文本字符串,而应被编码为字节序列。

步骤4:将计算出的HMAC代码编码到base64url [工具1]:

  • 签名(字节):

    c8a9ae59f3d64564364a864d22490cc666c74c66a3822be04a9a9287a707b352
    
  • 签名(已编码base64url):

    yKmuWfPWRWQ2SoZNIkkMxmbHTGajgivgSpqSh6cHs1I
    

摘要

以下是我们的结果(全部base64url编码):

  • 标题:

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
    
  • 有效载荷:

    eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
    
  • 签名:

    yKmuWfPWRWQ2SoZNIkkMxmbHTGajgivgSpqSh6cHs1I
    

来自jwt.io的结果:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.yKmuWfPWRWQ2SoZNIkkMxmbHTGajgivgSpqSh6cHs1I

如您所见,这三个部分都是相同的。