手动计算JWT签名永远不会输出真实签名

手动计算JWT签名永远不会输出真实签名,jwt,language-agnostic,Jwt,Language Agnostic,我读了很多关于stackOverflow和jwt文档的问题。 据我所知,现在我应该这样做来计算代币: header = { "alg": "HS256", "typ": "JWT" } payload = { "sub": "1234567890", "name": "JohnDoe", "iat": 1516239022 } secret = "test123" 从标头和负载中删除不必要的空格和特征线,然后将两者编码为base64url 与jwt.io上的输出相同,非常

我读了很多关于stackOverflow和jwt文档的问题。 据我所知,现在我应该这样做来计算代币:

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

payload =
{
  "sub": "1234567890",
  "name": "JohnDoe",
  "iat": 1516239022
}
secret = "test123"
  • 从标头和负载中删除不必要的空格和特征线,然后将两者编码为base64url
  • 与jwt.io上的输出相同,非常完美

  • 使用“test123”作为密码计算sha256 hmac
  • 将哈希转换为字符串,然后对其进行base64url编码
  • 我为这个部分使用,然后我使用编码,得到以下输出:
    O1KYQRJCVMOVWPPUNRLBIMOCW43ZDSKVW7JAERTCM3KUVSKWMSKFW7VCLQ

    jwt.io的输出
    O1kyQRi81ZpUNRlBIMLPy3zylfJaeRSbeRRWljKf-5U

    但如果我转到此页面,我会得到正确的输出:
    O1kyQRi81ZpUNRlBIMLPy3zylfJaeRSbeRRWljKf-5U

    那么我做错了什么?为什么要将十六进制转换为字符串,然后对其进行编码以输出不同的结果

    在在线十六进制到字符串转换错误的情况下,如何在没有使用任何库的情况下,将C++的十六进制转换为字符串(这样我就可以对其进行编码)。如果我将每个字节(2个字符,因为十六进制=4位)转换为ASCII字符,然后进行编码,是否正确


    提前感谢。

    您的hmac步骤正确,输出字节正确(如注释所示)。您遇到的转换问题是由临时字符串中的非显示字符引起的(原始字节没有正确地从第一个网页复制粘贴到第二个网页)

    要在每个阶段复制精确的输出,可以使用以下命令

    在C++方面,应该尝试对原始字节进行操作,而不是在十六进制字符串上操作。获取原始字节并通过base64 URL安全编码器运行它们。或者,如下面的示例所示,获取原始字节,通过普通的base64编码器运行它们,然后将生成的base64字符串修复为URL安全的

  • 构造标题
  • 构造有效载荷
  • 原始密码
  • 将机密转换为十六进制(非base64)
  • 执行hmac并捕获原始字节(注意,这是不可打印的字符串)
  • 将原始字节转储为十六进制,仅供说明(与OP输出匹配)
  • 对于JWT签名,将原始字节转换为base64uri编码
  • 创建完整令牌

  • 这里的一般问题是散列是一个大数字,它只表示为一个prinbtable十六进制代码。当您使用您提到的在线工具将其转换回时,基本上会得到不可打印的字符,并将其复制到base64转换器。然后,您依赖于来自两个不同网站的代码页设置。在程序内部处理并将哈希转换为字节数组要容易得多。所有的解释和显示我很抱歉,我不能使用互联网,直到现在。谢谢你的回答,成功了!
    base64urlEncode(header)
    // output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
    base64urlEncode(payload)
    // output: eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG5Eb2UiLCJpYXQiOjE1MTYyMzkwMjJ9
    
    sha256_hmac("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG5Eb2UiLCJpYXQiOjE1MTYyMzkwMjJ9", "test123)
    // output: 3b59324118bcd59a5435194120c2cfcb7cf295f25a79149b79145696329ffb95
    
    jwt_header=$(echo -n '{"alg":"HS256","typ":"JWT"}' | base64 | sed s/\+/-/g | sed 's/\//_/g' | sed -E s/=+$//)
    
    # ans: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
    
    payload=$(echo -n '{"sub":"1234567890","name":"JohnDoe","iat":1516239022}' | base64 | sed s/\+/-/g |sed 's/\//_/g' |  sed -E s/=+$//)
    
    # ans: eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG5Eb2UiLCJpYXQiOjE1MTYyMzkwMjJ9
    
    secret="test123"
    
    hexsecret=$(echo -n "$secret" | xxd -p | tr -d '\n')
    
    # ans: 74657374313233
    
    hmac_signature_rawbytes=$(echo -n "${jwt_header}.${payload}" |  openssl dgst -sha256 -mac HMAC -macopt hexkey:$hexsecret -binary)
    
    echo -n ${hmac_signature_rawbytes} | xxd -p | tr -d '\n'
    
    #ans: 3b59324118bcd59a5435194120c2cfcb7cf295f25a79149b79145696329ffb95
    
    hmac_signature=$(echo -n ${hmac_signature_rawbytes} | base64  | sed s/\+/-/g | sed 's/\//_/g' | sed -E s/=+$//)
    
    #ans: O1kyQRi81ZpUNRlBIMLPy3zylfJaeRSbeRRWljKf-5U
    
    jwt="${jwt_header}.${payload}.${hmac_signature}"
    
    # ans: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG5Eb2UiLCJpYXQiOjE1MTYyMzkwMjJ9.O1kyQRi81ZpUNRlBIMLPy3zylfJaeRSbeRRWljKf-5U