NodeJS相当于hmac-sha256授权的C#代码

时间:2018-03-26 15:36:04

标签: javascript c# node.js hmac

我试图转换这里找到的C#代码: AMX Authorization Header以便连接到外部API。 C#代码在尝试连接到外部API时起作用,但当我将其转换为nodeJS解决方案时,它不起作用。

我无法访问外部C#API,因此无法更新该方面但希望有人可以查看此内容并查看我遗漏或错误的内容:

我的nodejs解决方案:

var request = require('request');
var uuid = require('node-uuid');
var CryptoJS = require('crypto-js');

var URL = "https://urltoexternalAPI.com";
var itemAPPId = "testAPPId";
var APIKey = "testAPIKey";

var requestUri = encodeURIComponent(URL.toLowerCase());
var requestHttpMethod = "GET";

var requestTimeStamp = Math.floor(new Date().getTime() / 1000).toString();

var nonce = uuid.v1().replace(/-/g, '');

//I excluded the content hashing part as the API Im hitting is a GET request with no body content
var signatureRawData = itemAPPId + requestHttpMethod + requestUri + requestTimeStamp + nonce;

var secretKeyByteArray = CryptoJS.enc.Base64.parse(APIKey);

var signature = CryptoJS.enc.Utf8.parse(signatureRawData);

var signatureBytes = CryptoJS.HmacSHA256(signature, secretKeyByteArray);

var requestSignatureBase64String = signatureBytes.toString(CryptoJS.enc.Base64);

request({
  url: URL,
  headers: {
    'Authorization': "amx "+itemAPPId+":"+requestSignatureBase64String+":"+nonce+":"+requestTimeStamp
  }
}, function (error, response, body) {
  if (response.statusCode != 200) {
    console.log("Fail");
  } else {
    console.log("Success");
  }
});

1 个答案:

答案 0 :(得分:1)

我明白了!如果有人遇到过这个问题,他们可能会发现以下内容:

以下C#代码与nodeJS略有不同:   System.Web.HttpUtility.UrlEncode(request.RequestUri.AbsoluteUri.ToLower());

最初我按原样复制了这个功能,并编写了与之相当的nodejs:

 var requestUri = encodeURIComponent(URL.toLowerCase());

C#中URL的编码将所有内容保持为小写 - 例如: https:// 变为 https%3a%2f%2f - 而nodeJS将其编码大写字符 - https%3A%2F%2F - 这就是导致错误哈希的原因。

解决方案是在对URL进行编码后将小写函数移动到。像这样:

var requestUri = encodeURIComponent(URL).toLowerCase();

看起来相当简单,但在尝试复制C#解决方案时,您可能不会发现两个URL编码器的工作方式不同。

最终解决方案:(由于Yoryo更新为加密)

const fetch = require("node-fetch");
const uuid = require("uuid");
const crypto = require('crypto');

var URL = "https://urltoapi.com";

var itemAPPId = config.itemAPPId;
var APIKey = config.itemAPIKey;

var requestUri = encodeURIComponent(URL).toLowerCase();
var requestHttpMethod = "GET"; //should be dynamic

var requestTimeStamp = Math.floor(new Date().getTime() / 1000).toString();

var nonce = uuid.v1().replace(/-/g, '');
var signatureRawData = itemAPPId + requestHttpMethod + requestUri + requestTimeStamp + nonce;

var key = Buffer.from(APIKey, 'base64');
var requestSignatureBase64String = crypto.createHmac('sha256', key).update(signatureRawData, 'utf8').digest('base64');

const hitExternalAPI = async url => {
  try {
    const res = await fetch(url, { method: 'GET', headers: { "Authorization": "amx "+itemAPPId+":"+requestSignatureBase64String+":"+nonce+":"+requestTimeStamp } })
    .then(res => {
      console.log(res.ok);
    });
  } catch (error) {
    console.log("Error",error);
  }
};
hitExternalAPI(URL);