【问题标题】:node.js hmac.digest() output seems wrongnode.js hmac.digest() 输出似乎错误
【发布时间】:2011-12-18 03:59:53
【问题描述】:

我正在尝试使用 node.js 实现 Facebook 库,但请求签名不起作用。我将 PHP 示例 seen here 翻译成节点。我正在使用那里给出的示例进行尝试,其中秘密是字符串“秘密”。我的代码如下所示:

var signedRequest = request.signed_request.split('.');

var sig = b64url.decode(signedRequest[0]);

var expected = crypto.createHmac('sha256', 'secret').update(signedRequest[1]).digest();

console.log(sig == expected); // false

我不能 console.log 解码的字符串本身,因为它们具有导致控制台清除的特殊字符(如果您有解决此问题的建议,请告诉我)但我可以输出它们的 b64url 编码.

正如您在 FB 文档中看到的,预期的编码信号是

vlXgu64BQGFSQrY0ZcJBZASMvYvTHu9GQ0YM9rjPSso

我的expected 值在编码后是

wr5Vw6DCu8KuAUBhUkLCtjRlw4JBZATCjMK9wovDkx7Dr0ZDRgzDtsK4w49Kw4o

那么为什么我认为digest 是错误的呢?也许错误在我这边?好吧,如果我执行文档中给出的 PHP 中的确切示例,就会得到正确的结果。但是如果我改变hash_hmac调用所以最后一个参数是假的,输出十六进制,我得到

YmU1NWUwYmJhZTAxNDA2MTUyNDJiNjM0NjVjMjQxNjQwNDhjYmQ4YmQzMWVlZjQ2NDM0NjBjZjZiOGNmNGFjYQ==

现在,如果我回到我的 javascript 代码,并将我的 hmac 代码更改为 .digest("hex") 而不是默认的 "binary" 并记录结果的 base64 编码,我会得到......惊喜!

YmU1NWUwYmJhZTAxNDA2MTUyNDJiNjM0NjVjMjQxNjQwNDhjYmQ4YmQzMWVlZjQ2NDM0NjBjZjZiOGNmNGFjYQ

同样,除了末尾缺少 == 符号,但我认为这是控制台的问题。我无法想象这是问题所在,没有它们,它甚至不是有效的 base64 字符串长度。

那么,为什么摘要方法在使用十六进制时输出正确结果,但在使用二进制时输出错误答案?二进制文件与 PHP 等价物的“原始”输出不完全相同吗?如果是这样的话,正确的称呼方式是什么?

【问题讨论】:

    标签: php facebook authentication node.js facebook-graph-api


    【解决方案1】:

    我们发现这确实是加密库中的一个错误,并且是在 github 上记录的一个已知问题。我们将不得不升级并得到修复。

    【讨论】:

      【解决方案2】:

      我是 Tesserex 的合伙人。我相信答案可能是 Tesserex 自己发布的答案和 Juicy Scripter 的答案的结合。我们仍在使用 Node 版本。 0.4.7。提到的错误 Tesserex 可以在这里找到:https://github.com/joyent/node/issues/324。我不完全确定这个错误是否影响了我们,但这似乎是一个很好的可能性。我们将 Node 更新到 0.6.5 版并应用了 Juicy Scripter 的解决方案,现在一切正常。谢谢。

      作为关于使用现有库的建议的说明。大多数现有的库都需要 express,这是我们试图避免对我们应用程序的某些细节做的事情。此外,现有的库倾向于假设您使用 node.js 就像一个 Web 服务器并一次回答单个用户的请求。我们正在使用与 websockets 的持久连接,我们的 facebook 客户端将同时为多个用户处理会话数据。最终,我希望将我们的 Facebook 客户端开源,以便与我们这样的应用程序一起使用。

      【讨论】:

      • 刚刚检查过,我提供的代码与v0.4.7完美配合...
      【解决方案3】:

      其实digest没有问题,如果使用b64url.decode的结果默认是utf8编码的(可以通过第二个参数指定):

      var sig = b64url.decode(signedRequest[0], 'binary');
      var expected = crypto.createHmac('sha256', 'secret').update(signedRequest[1]).digest();
      // sig === expected
      

      签名和摘要结果相同。

      您也可以通过将digest 结果转换为utf8 编码字符串来检查:

      var sig = b64url.decode(signedRequest[0]);
      var expected = crypto.createHmac('sha256', 'secret').update(signedRequest[1]).digest();
      var expected_buffer = new Buffer(expected_sig.digest(), 'binary');
      // sig === expected_buffer.toString()
      

      您也可以考虑使用现有的库来完成此类工作(可能更多),仅举几例:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-09-21
        • 2020-07-25
        • 1970-01-01
        • 1970-01-01
        • 2022-06-13
        • 2021-08-16
        • 2018-08-22
        相关资源
        最近更新 更多