Node.js:签名验证(PS256)在Node.js中成功,但在jwt.io调试器中失败

时间:2019-02-21 11:32:15

标签: node.js jwt rsa auth0

我编写了一个测试脚本,用于签名,然后使用PS256算法验证JWT。

我的代码成功验证了JWT,但是在jwt.io调试器中验证失败。

我正在使用jws@3.2.1

仅在使用PS256算法时会发生这种情况,例如在使用RS256时不会发生这种情况。

我做错什么了吗?

我用以下方法生成了密钥:

openssl genpkey -algorithm RSA -out private_key2.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -pubout -in private_key2.pem -out public_key2.pem

您可以在repl.it上尝试我的代码:https://repl.it/@SamArtuso/Nodejs-Signature-verification-PS256-succeeds-in-Nodejs

代码:

const { join } = require('path');
const { readFileSync } = require('fs');
const jws = require('jws');

const ALG = 'PS256';

/**********
 * SIGNING
 **********/

const PRIVATE_KEY_PATH = join(__dirname, './keys/private_key2.pem');

const privateKey = readFileSync(PRIVATE_KEY_PATH).toString();

const payload = {
  foo: 'bar',
};

const token = jws.sign({
  header: { alg: ALG },
  payload,
  privateKey,
})

console.log('Token:');
console.log(token);

/************
 * VERIFYING
 ************/

const PUBLIC_KEY_PATH = join(__dirname, './keys/public_key2.pem');

const publicKey = readFileSync(PUBLIC_KEY_PATH).toString();

const result = jws.verify(token, ALG, publicKey);
if (result) {
  console.log('Verification successful.');
} else {
  console.error('Verification failed.');
}

私钥:

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDPR8CD/9V9fddR
vMk590JtuU4hPT9iPD/mYeWdvUTbkN2iPpg6LDADBntz8I9CzThCkgHmDQhh49Qz
AONiHfyHhKT6HHIBS78wGWfhE9ueFtkv19xisvFJTDO6IllGFMiioj8AkvOJwaY+
5ZKSFG32V0gMaglNSNTOh5KK6DsxgdH2KfMzn6uFwJkvsz1qwPiINu/rqvOQPOIK
JCbNHBOg/SvhPWBSEFDC9AkLm3ajhGAcnSlWi0KgUFz7iHuUR6s4GLdkc40uAooY
ExEWsZyoByT18tXln2hPAvE1Ata2PSbtLHuwvMQt4vzZi80K4BXqOiqvNMo1A1aT
oSQnmOwtAgMBAAECggEAPpHTPEVS5aHCCItrVtMbu1FvkzsQ0g+L3nh4vqfujDTr
olkwzIagK5meVH4uUKTwMbAvYIlYmWwTlx3ShcC1hRb2UgWaKGf8G4HfyKKc7djJ
0NZhUW3gxhZ5mttZhX0qn2VIjVzOpSvOijf0iaIfG3h3aD/t9OViT8G+6610iNmz
Oygmi9kQaBAS2A2sLSSMhdyddIPEpZ8QOHwGCRvBXWO100BCV9ROQzYxW+U9VPaJ
I0tXDL1L1H7y1EbxccPfOsfUPMtF9LQWQZ6ksJuSRwkBAnfKpzexguph29sLDjCQ
X23rQN/NwiU+zRmn+cW7VqkZsbSqucP9t+d19UdWpQKBgQDn9sThxAZvx4OS0noD
AWJX5CliDNlagmLqr4c0QoYI+fPL7FcK9tQYUZ869jnebX7UPHTuDhMoIvWknZbB
QhoogpRoX+XFtxzPwjtBBGc5TYacYnOR4xPSjvDlIrY7FQiH8TgpAGzenSBiD8O0
xW4zSaHLUDHEMFEyPq8tdMmBewKBgQDkwjUnVMPlA9AOD+KQNXgf2kV9z0ZA5idt
9WcsXsxpO2W6S0ntkr29Yr3VuuuJTRH7Fm+bPDJ6C1bfZ746hn3iLMZbMxgGVEf/
cN0nNXjfG5G7EEIU9WFges1I5rec/5W38kIco6soP36Qj5HcUBXt6AHy3k1IbEL2
84Bp1SZ0dwKBgF19mhCcXzPCKAePCVoYvrhJ31wDbb8K+i84m7e2cCtCAr7X/KUQ
op9Clni/MMezPgDwdPhVd+cfX/3+/fnaWIynRIVk0UkE6nnaAOPNkIUJ+A0jqQzN
hvnAXtsbSHM7oPqZgFcWMsrubVTYobpEMIw/SxSUt9oo1zD3Dse1YFntAoGBAIAL
AIuKU7f9gVhNpehINXvGxfzcpxsueEWBBgX87fe9CnzTJYc4CsJV4aIfZTVOEVF0
xnWipTJQ5IhZ3k2N+CpAG6ryl3D7fe1J9E+9C3H+UXzeZc6rZp0FP6Cdm4riOKBk
loLHTcdSevpZkjA6F3w5z9Vsft+Z0YW+2FLkvwiTAoGAdjUYcGTaEhGNtHQszAeY
2VbeVHwgnajKhaZpKMNTVp/AFgeS5k1lSATlT5wQHD3OAhUn+NAEwUOUBBWOpg+i
jML8loplEcVmdHkfGFsrIvzFFIIXQOWy77s/McTCh2jLkLYO8kIOrGy08JBiZnQ/
Ki/HFS/2yaUbG6UdH8FFp2g=
-----END PRIVATE KEY-----

公钥:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz0fAg//VfX3XUbzJOfdC
bblOIT0/Yjw/5mHlnb1E25Ddoj6YOiwwAwZ7c/CPQs04QpIB5g0IYePUMwDjYh38
h4Sk+hxyAUu/MBln4RPbnhbZL9fcYrLxSUwzuiJZRhTIoqI/AJLzicGmPuWSkhRt
9ldIDGoJTUjUzoeSiug7MYHR9inzM5+rhcCZL7M9asD4iDbv66rzkDziCiQmzRwT
oP0r4T1gUhBQwvQJC5t2o4RgHJ0pVotCoFBc+4h7lEerOBi3ZHONLgKKGBMRFrGc
qAck9fLV5Z9oTwLxNQLWtj0m7Sx7sLzELeL82YvNCuAV6joqrzTKNQNWk6EkJ5js
LQIDAQAB
-----END PUBLIC KEY-----

编辑:说明了如何重现我的问题。

  1. 使用以下脚本运行我的脚本:npm init -f && npm install jws && node test.js
  2. 脚本将输出令牌和Verification successful.
  3. 将令牌复制并粘贴到jwt.io的“已编码”字段中
  4. 将公钥复制并粘贴到“公钥或证书”字段中。
  5. 底部显示红色的“无效签名”消息。

以下是我的脚本将生成的令牌的示例。请记住,PS256具有概率而不是确定性签名,因此每次运行脚本时,签名都会有所不同。

eyJhbGciOiJQUzI1NiJ9.eyJmb28iOiJiYXIifQ.Rn6i-94ovuKOVRc2jzLVS40MpMmBkIfkyvF56JK3tM8wvg-DW943NNbXf01bhRdyoUj0A73NSQtz0kB4WfXN1uAH1omzNr0ww-iTfC23AX0OcjbsE7CcDz_ZQWWOzwEGGFVfV9ez5yn1pKRYVdFaKqApk3irP-ej_WGrrJfgeZVs683lNk0WjKOYhj6vsryuz52c0OEJ0UmYy7hSSfL38jgL6bdE0awg2DgiaU6qszZEkMjSnugoMobeAUUyOiXHsR79NryuhCQko-I9P1vKd1dEA3zM1iut5sW5FwB8K9Fi49gaQy0zHk72txJvUWdxW5ns0Svft3qLke5XMuqm2g

2 个答案:

答案 0 :(得分:0)

我试图将您的令牌,您的公共密钥和您的私有密钥复制并粘贴到jwt.io的调试器中。这是我的发现:

  1. 如果仅粘贴令牌,则可以正确解码令牌,但是无法验证签名(显而易见)。
  2. 如果您随后粘贴公钥(应该足以验证签名),则仍然无法验证签名。这很奇怪
  3. 如果再粘贴私钥(验证签名不是必需的),则表明签名有效。

因此,显然,问题归结为一个问题,为什么只有提供了私钥,才能验证令牌的签名……

这使我想到一个假设,即私钥和公钥在某种程度上不匹配。因此,我尝试从您提供的私钥中重新生成(或更好地提取)公钥,并将其与您建议的公钥进行比较。因此,我将您的私钥粘贴到名为privateKey.pem的文件中,并运行以下命令:

$ openssl rsa -in privateKey.pem -pubout

这给了我以下公共密钥:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz0fAg//VfX3XUbzJOfdC
bblOIT0/Yjw/5mHlnb1E25Ddoj6YOiwwAwZ7c/CPQs04QpIB5g0IYePUMwDjYh38
h4Sk+hxyAUu/MBln4RPbnhbZL9fcYrLxSUwzuiJZRhTIoqI/AJLzicGmPuWSkhRt
9ldIDGoJTUjUzoeSiug7MYHR9inzM5+rhcCZL7M9asD4iDbv66rzkDziCiQmzRwT
oP0r4T1gUhBQwvQJC5t2o4RgHJ0pVotCoFBc+4h7lEerOBi3ZHONLgKKGBMRFrGc
qAck9fLV5Z9oTwLxNQLWtj0m7Sx7sLzELeL82YvNCuAV6joqrzTKNQNWk6EkJ5js
LQIDAQAB
-----END PUBLIC KEY-----

不幸的是,这也是您提供的公用密钥,因此我们可以从列表中删除此想法。

因此,我开始在网上搜索并通过Auth0找到this blog post,他们在其中描述了对PS*算法的支持,但是根据文档,一切都会按预期进行。嗯,更奇怪

因此,我接下来要尝试的是使用jwt.io的调试器,使用令牌的解码值,算法PS256和提供的私钥对事物进行加密。这使我有了这个令牌:

eyJhbGciOiJQUzI1NiJ9.eyJmb28iOiJiYXIifQ.wzkD7q5lH_qJw_V6DJLk72TDqpzA05KN3XHfEFOeAQgCriodoOLrgQ-p3ifIzK525puiV1hnXQuJ-6TEZRqiO8dqlPWQJbG1mLdTTx7ZwdUKsDjY6CMsmsskU8eVrzfaSDVmGvbjaWKq1_KGvtk4vMT0Z9m_YhUjD_SDVbCaZReEbzxta4APM7dMQ5mRFzD03JTwe05_AqayrfXdTungeBEJcMB0tY_4FjWiKbBZOpyQLebzPJ69VgpQFGvf6fPuKT6_3LTEHPrRNFL05OYpgRvayh3pEAF297aSCQ_SFi9slqDdVKkor-q8UDO-zM7J952uCkr7NkXV0Loq62_gMg

如果将 this 令牌粘贴到jwt.io的调试器中,并使用 your 公钥,则签名有效。因此,基本上PS256似乎可以与jwt.io一起使用,但是出于某种原因而不是您的令牌…

这最终使我想到也许Node.js和jwt.io确实使用不同的方式来运行PS256算法。当然,由于这是一个标准,因此两者应该以相同的方式工作,但显然它们并非如此。我不知道这两者都是谁做错了,或者我俩都以不同的方式工作是否还好,因为我以前从未处理过PS256

很抱歉,我在这里没有更好的答案,但是我想找出真正原因的唯一方法是调试到Node.js的加密代码,并看看jwt.io的源代码(据我所知,这是不公开的)。

从我的角度来看,您所做的是正确的,我想这是Node.js或jwt.io或两者中的错误

PS:写完这个答案后,我发现this issue,我猜原来的作者是你(不是吗?),那里的回答基本上得出相同的结论,那就是问题所在网站。所以也许这实际上是您可以获得的最佳答案。

答案 1 :(得分:-2)

确保正确复制密钥。

https://jwt.io/要求您复制包含END> ind_sum<-read.csv("Washington_ind.csv",header=FALSE,sep=",") > ind_sum V1 1 229.6161795 2 93.56251442 3 733.6790106 4 0.579372878 5 202.5939352 标签行的行

  

----- BEGIN公钥-----

     

----- END公钥-----

enter image description here