NodeJS Crypto RS-SHA256 和 JWT 承载

Posted

技术标签:

【中文标题】NodeJS Crypto RS-SHA256 和 JWT 承载【英文标题】:NodeJS Crypto RS-SHA256 and JWT Bearer 【发布时间】:2014-01-14 11:06:35 【问题描述】:

在使用护照和 oauth2orize 实现 oauth2 堆栈时,在这种情况下,问题具体在于使用 oauth2orize jwt 承载。 oauth2orize jwt 承载器非常适合让一切顺利进行,但是它具有标记为要执行的 RSA SHA 片段。

在尝试为 RSA SHA 加密处理添加片段时,我无法获得要验证的签名,因为 verifier.verify 似乎总是返回 false。如果有人已经清除了这个障碍,那么一点帮助将是超级的。

我做了什么: 创建了私钥/公钥:

openssl genrsa -out private.pem 1024
//extract public key
openssl rsa -in private.pem -out public.pem -outform PEM -pubout

现在要签名的数据:

"alg":"RS256","typ":"JWT""iss": "myclient"

我已经尝试了多种方法来签名,这里列出的太多了,但我对正确签名的理解是对这些项目的 bas64 编码进行签名,所以我在 "alg":" 上运行了 base64 "iss": "myclient" 上的 RS256","typ":"JWT" 和 base64 然后在这些编码上运行 base64。所以结果是: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9 eyJpc3MiOiAibXljbGllbnQifQ 然后编码:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiAibXljbGllbnQifQ

这给了我: e2V5SmhiR2NpT2lKU1V6STFOaUlzSW5SNWNDSTZJa3BYVkNKOX0ue2V5SnBjM01pT2lBaWJYbGpiR2xsYm5RaWZRfQ

此时我通过以下方式签署上述base64:

openssl sha -sha256 -sign priv.pem < signThis > signedData

然后我在其上运行 base64 以获取数据以传递到断言的签名部分。 然后我传入对象:


"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion":  "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiAibXljbGllbnQifQ.signedData"

现在在我的代码库中:

var crypto = require('crypto')
   , fs = require('fs')
   , pub = fs.readFileSync('/path/to/pub.pem')
   , verifier = crypto.createVerify("RSA-SHA256");

verifier.update(JSON.stringify(data));

var result = verifier.verify(pub, signature, 'base64');
console.log('vf: ', result);

但是,结果总是错误的。

我确实正确接收了数据,代码中的签名变量与我传入的内容相匹配,我总是收到 false 并且已经用尽了所有我能想到的关于如何调整它以获取验证者的选项。验证返回真。感谢您的时间和帮助!

【问题讨论】:

您能否向我们指出您要计算的规格?我没有看到很多文档提到 OAuth 2.0 的 RSA/SHA-1(但这可能是我对标准的无知)。 签名生成之前编码为 base 64 对我来说似乎不合适。通常,您在通过文本生成签名之前使用 字符编码,如果协议需要,则使用 base 64 将生成的签名转换为文本。 您似乎没有回答,我们可以将此帖子标记为已放弃吗? 抱歉耽搁了,我已经出去度假了。谢谢您的回复!我在base64之前和之后都尝试过编码,但无济于事。我也对标准有点无知,并且正在尽我所能尝试破译我在这里做错了什么。我将 rsa/sha256 基于 oauth2orize jwt 示例中的示例代码以及 google oauth2 服务器到服务器文档。 developers.google.com/accounts/docs/OAuth2ServiceAccount 我也在做一些非常相似的事情。我一直在尝试使用 jwt-simple,它似乎确实简化了过程:jwt-simple。如果我完全找到解决方案,我会通知您。 【参考方案1】:

我不确定这是否正是您要寻找的,但这将使用 jwt-simple(使用加密等)以 google api 方式成功创建 JWT:

var fs       = require('fs')
  , jwt      = require('jwt-simple')
  , keypath  = '/path/to/your.pem'
  , secret   = fs.readFileSync( keypath,  encoding: 'ascii' )
  , now      = Date.now()
  , payload  = 
        scope: 'https://www.googleapis.com/auth/<service>',
        iss  : '<iss_id>@developer.gserviceaccount.com',
        aud  : 'https://accounts.google.com/o/oauth2/token',
        iat  : now,
        exp  : now+3600
    
  , token    = jwt.encode( payload, secret, 'RS256' )
  , decoded  = jwt.decode( token, secret, 'RS256' );

console.log( token );
console.log( decoded );

【讨论】:

【参考方案2】:

我认为此代码示例完全不安全。如果您查看最新的 JWT 代码,它不会在您的解码调用中使用密钥。

https://github.com/hokaccha/node-jwt-simple/blob/master/lib/jwt.js

它基本上只是解码第二段并返回它,这意味着任何人都可以更改该值并且它没有经过验证。

【讨论】:

以上是关于NodeJS Crypto RS-SHA256 和 JWT 承载的主要内容,如果未能解决你的问题,请参考以下文章

nodejs实现md5和SHA256加密

Nodejs Crypto ECDH PublicKey Hex as X.509

来自 nodejs 加密的 SHA256 不正确

尝试使用 crypto-js 和 nodejs 解密

nodejs -- crypto MD5签名

使用 Crypto++ 生成 SHA256 哈希,使用字符串作为输入和输出?