gpt4 book ai didi

javascript - 签署 JWT - 我做错了吗?

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:56:28 24 4
gpt4 key购买 nike

出于教育目的,我正在尝试使用 JavaScript 制作 JWT 生成器。有一个 jwt.io创建和/或验证 JWT 的工具。

我正在努力让我的结果与验证器的结果相匹配。问题是签名。

这是我的代码:

function base64url(input) {
return btoa(typeof input === 'string' ? input : JSON.stringify(input))
.replace(/=+$/, '')
.replace(/\+/g, '-')
.replace(/\//g, '_');
}

const JWT = {
encode(header, payload, secret) {
const unsigned = [base64url(header), base64url(payload)].join('.');

return [unsigned, base64url(sha256.hmac(secret, unsigned))].join('.');
}
};

为了加密 HMAC SHA256,我正在使用 js-sha256具有 sha256.hmac(key, value) 原型(prototype)的库。我将其与在线工具进行了比较,效果很好。

现在,我使用以下代码对其进行测试:

const jwt = JWT.encode(
{
alg: 'HS256',
typ: 'JWT'
},
123,
'xxx'
);

我得到的结果是:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.MTIz.NzhlNTFmYzUxOGQ2YjNlZDFiOTM0ZGRhOTUwNDFmMzEwMzdlNmZkZWRhNGFlMjdlNDU3ZTZhNWRhYjQ1YzFiMQ

另一方面,jwt.io 的结果是:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.MTIz.eOUfxRjWs-0bk03alQQfMQN-b97aSuJ-RX5qXatFwbE

如您所见,我的结果和 jwt.io 中的 JWT 三个 block 中的两个是相同的结果。签名不同,如果你问我,它生成的签名出奇地短。该工具还将我自己的 JWT 标记为无效。

我检查了在线 HMAC SHA256 生成器,看起来我的代码创建了一个有效的签名,所以:

base64url(sha256.hmac('xxx', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.MTIz')) ===
'NzhlNTFmYzUxOGQ2YjNlZDFiOTM0ZGRhOTUwNDFmMzEwMzdlNmZkZWRhNGFlMjdlNDU3ZTZhNWRhYjQ1YzFiMQ'

jwt.io只是损坏了还是以其他方式损坏?

最佳答案

我不会说你做错了,但你错过了一个小而重要的细节。结果来自 jwt.io是正确的,您计算的散列也是正确的。但是您使用哈希创建的签名不正确。

您使用 sha256.hmac(secret, unsigned) 计算的散列是一个很大的数字,但该函数的返回值是该大数字的十六进制字符串表示形式。对于签名,您需要对原始数字进行 base64url 编码,而不是它的字符串表示形式。

我修改了你的代码,让它直接将哈希值编码为base64url(node.js版本):

const JWT = {
encode(header, payload, secret) {
const unsigned = [base64url(header), base64url(payload)].join('.');
const hash = sha256.hmac(secret, unsigned);
console.log(hash);
var signature = new Buffer.from(hash, 'hex').toString('base64').replace(/\+/g,'-').replace(/\=+$/m,'');

return [unsigned, signature].join('.');
}
};

或者,如果您不使用 node.js,则可以改用它(如 Robo Robok 所建议):

const JWT = {
encode(header, payload, secret) {
const unsigned = [base64url(header), base64url(payload)].join('.');

return [unsigned, base64url(sha256.hmac(secret, unsigned).replace(/\w{2}/g, byte => String.fromCharCode(parseInt(byte, 16))))].join('.');
}
};

结果是一个 token ,与使用 jwt.io 创建的 token 相同:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.MTIz.eOUfxRjWs-0bk03alQQfMQN-b97aSuJ-RX5qXatFwbE

另见 my answer here ,其中我解释了比较不同工具的结果的步骤。

关于javascript - 签署 JWT - 我做错了吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57403050/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com