【问题标题】:HMAC MD5 Validation with Node.js, Express and Trialpay使用 Node.js、Express 和 Trialpay 进行 HMAC MD5 验证
【发布时间】:2015-07-20 12:44:27
【问题描述】:

我正在尝试使用 Node.js 和 Express 验证从 TrialPay 发送的消息。 TrialPay 使用 HMAC-MD5 哈希对请求进行签名,并在验证时提供these instructions

这是我的代码:

app.post('/trialpay', function(req, res) {

    var key = "[MY MERCHANT KEY]";
    var hash = req.header("TrialPay-HMAC-MD5");
    var data = req.body.toString();

    var crypted = require("crypto").createHmac("md5", key)
        .update(data)
        .digest("hex");

    if (hash == crypted) {
        res.writeHead(200, {"Content-Type": "plain/text"});
        res.end("Success!");
    } else {
        throw new Error("Invalid TrialPay Hash");
    }  
});

这显然不起作用(哈希不匹配)。

免责声明:我对 Node.js 非常陌生,并且几乎没有 Javascript 经验。

更新

我没有意识到该链接受到保护。

TrialPay 使用您的通知密钥(在您的帐户信息中设置) 作为签署 HMAC 的密钥。对于 GET 请求,查询字符串 问号后面的(在 URL 中)已签名。对于 POST 请求对整个 POST 正文进行签名。

下面是 TrialPay 如何指导您在 Google App Engine (Python) 中进行验证的示例:

class MyHandler(webapp.RequestHandler):
  def post(self):
  key = '[YOUR MERCHANT KEY]'
  tphash = self.request.headers['TrialPay-HMAC-MD5'] 
  if hmacmd5(key,self.request.body) != tphash:
    logging.info('invalid trialpay hash')
    return 

更新 2

req.body 打印为:

{ 
  oid: 'sample-order-id',
  sid: 'customer-sid',
  order_date: '04/24/2012',
  timestamp: '04/24/2012 16:28:46',
  first_name: 'customer-firstname',
  last_name: 'customer-lastname',
  email: 'customer@trialpay.com',
  revenue: '10.00',
  zip_code: '94041',
  country: 'US' 
}

【问题讨论】:

  • 您的链接不起作用-它不会让我登录。也就是说,您应该远离请求处理程序中的throwing(基本上是节点中的任何位置)。接受第三个参数(回调,next in express lingo)并将错误传递给next。或者更好的是,在此处尽可能处理错误,并在res.send(403, 'Invalid TrialPay Hash') 处处理。此外,您没有提及您发布的数据类型——如果您可以 console.log 的话,看看 req.body 尤其是 req.body.toString() 包含什么会很有趣。
  • 感谢@LinusGThiel 的评论和建议。当我尝试console.log(req.body.toString()); 时,它只打印出“[object Object]”。请原谅我的无知,在这里。
  • 这就是我的怀疑! console.log(req.body) 带给你什么?
  • 您正在用正确的数据填写[MY MERCHANT KEY],对吧?
  • 好的,console.log(req.body) 将 JSON 参数列表返回给我。那么,如何将其传递给crypto.update()?它需要一个字符串或缓冲区。我都尝试了(可能不正确),但都没有成功。

标签: javascript node.js cryptography express


【解决方案1】:

这应该可以解决问题:

var crypto = require('crypto');

function calculateSignature(key) {
    return function(req, res, next) {
        var hash = req.header("TrialPay-HMAC-MD5"),
            hmac = crypto.createHmac("md5", key);

        req.on("data", function(data) {
            hmac.update(data);
        });

        req.on("end", function() {
            var crypted = hmac.digest("hex");

            if(crypted === hash) {
                // Valid request
                return res.send("Success!", { "Content-Type": "text/plain" });
            } else {
                // Invalid request
                return res.send("Invalid TrialPay hash", { "Content-Type": "text/plain" }, 403);
            }
        });

        req.on("error", function(err) {
            return next(err);
        });
    }
}

app.post("/trialpay", calculateSignature("[MY MERCHANT KEY]"));

【讨论】:

  • 这行得通!非常感谢你的帮助。只是一个问题,我在res.end("Success!") 上方添加了res.writeHead(200, {'Content-Type': 'plain/text'});,因为TrialPay 服务器刚刚挂起。我记录了哈希并且它们匹配,所以我不确定发生了什么。
  • 太棒了!它实际上不是res.end,而是res.send——来自Express 的好东西。见res.send documentation。哇,看着那个,我看到字符串总是用Content-Type: text/html 发送。我的错。以上更新。
  • 我只把它改成了end,因为send也挂了。我在res.send("Success!"); 上方的app.post() 中尝试了console.log('Success!');,但没有任何记录。
  • 好的,那么由于某种原因它没有到达路线。唔。好吧,如果您只需要它用于一条路线,则不必将其作为中间件,而可以直接响应。可能会更好。此外,您永远不会希望在异步代码(请求处理程序、中间件等)中使用 require,因为 require 是同步的。而是将其移至顶部范围。
  • 这很容易受到定时攻击。无论有多少字节匹配,您都应该确保比较 crypted === hash 花费恒定的时间。
【解决方案2】:

对于 Parse Cloud Code:(我已经测试过) 重点是 express.bodyParser 将解析用于哈希的 url 编码字符串。

var parseExpressRawBody = require('parse-express-raw-body');
var queryString = require('querystring');
app.post('/trialpay',parseExpressRawBody(),function(req, res) {
var hmac, calculatedSignature,payloadStr=req.body.toString();
hmac = crypto.createHmac('md5', TrialPayMerchentKey);
hmac.update(payloadStr);
calculatedSignature = hmac.digest('hex');

if (req.headers['trialpay-hmac-md5'] === calculatedSignature) {
   ~~~~~~

【讨论】:

  • 请添加一些解释。
  • 你的 sn-p 真的很糟糕。它应该怎么做?在发布之前花点时间查看您的消息。
猜你喜欢
  • 2012-01-13
  • 2017-02-18
  • 1970-01-01
  • 2017-11-16
  • 2016-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多