Hash 我的JWT签名实现有什么问题

Hash 我的JWT签名实现有什么问题,hash,jwt,rsa,Hash,Jwt,Rsa,我试图通过实现我自己的签名函数来更好地理解JWT,这些函数接收有效负载和报头并输出签名,但是当我尝试使用经验证的工具验证结果时遇到了问题。下面是我的实现,任何帮助将不胜感激 const createSignatureSingBaseLibrary=(输入:字符串)=>{ const hash=crypto.createHash(“sha256”); hash.write(输入); const hashedM=hash.digest(); const encryptedM=加密 私人加密( { 钥

我试图通过实现我自己的签名函数来更好地理解JWT,这些函数接收有效负载和报头并输出签名,但是当我尝试使用经验证的工具验证结果时遇到了问题。下面是我的实现,任何帮助将不胜感激

const createSignatureSingBaseLibrary=(输入:字符串)=>{
const hash=crypto.createHash(“sha256”);
hash.write(输入);
const hashedM=hash.digest();
const encryptedM=加密
私人加密(
{
钥匙:私钥,
填充:crypto.constants.RSA_PKCS1_padding,
},
哈希姆
)
.toString(“base64”);
返回加密EDM;
};
我真的不知道会出现什么问题,但我认为这与我编码消息的方式有关,或者可能与加密选项不同于“JWT标准”有关

是一个低级函数,它隐式地既不进行哈希运算,也不设置摘要ID(在PKCS#1 v1.5 padding(RSASSA-PKCS1-v1_5)的情况下)。一个典型的用例是当只有数据的哈希而不是实际数据可用时

在发布的代码中未设置摘要ID,这就是生成的签名不符合PKCS#1 v1.5且验证失败的原因

对于符合PKCS#1 v1.5的签名,摘要ID(用于SHA256)必须设置如下:

const digestID = Buffer.from('3031300d060960864801650304020105000420', 'hex');
const hashedM = Buffer.concat([digestID, hash.digest()]);
PKCS#1 v1.5填充在中有详细描述


此外,JWT应用Base64url而不是Base64编码,即需要以下附加转换:

return encryptedM.toString('base64').replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
当然,您也可以使用支持Base64url的库


但是,由于根据发布的代码,数据可用(而不仅仅是散列),因此可以应用crypto创建签名的标准函数,隐式散列并设置摘要ID,这使其更易于使用,即(自v0.1.92起):

或(自v12.0.0起):

默认情况下,这两个变体都应用PKCS#1 v1.5填充

const sign = crypto.createSign('SHA256');
sign.update(Buffer.from(input, 'utf8'));
const signatureB64 = sign.sign(privateKey, 'base64');
const signatureB64 = crypto.sign('sha256', Buffer.from(input, 'utf8'), privateKey);