我目前正在尝试实现我们正在使用的库的身份验证部分,但我偶然发现了一个奇怪的数据签名问题,NodeJS 中 crypto.createHmac 的输出大约是 PHP 中 hash_hmac 的一半大小,这是 PHP 和 NodeJS 之间唯一不同的数据部分(我们需要在这里使用 NodeJS)
用于在 NodeJS 中创建签名的确切代码是,
authorization["oauth_signature"] = crypto.createHmac('SHA256', process.env.SECRET).update(toSign).digest('base64');
对于PHP来说,它是
$authorization["oauth_signature"] = base64_encode(hash_hmac("SHA256", $signatureString . $signingKey, $secret));
但是,NodeJS 版本的输出是
7LkQP+qKR1gSdPq/AgH/3No3ps7EtZXnqwjivMixvM8=
对于PHP来说,它是
NmQ0MWIzYmJiMjI2YzFlMDhiYzY3NzVmMWY0MzEwNDlhNDU3NDI0ZGJlMzU3NjJhYmMwYjgwYzZjMDE4NDM4OA==
哪个数据是原来的两倍多
我是否必须为 NodeJS 版本使用不同的库而不是内置库?顺便说一句,我们将 NodeJS 后端托管在 Azure Microsoft上,不确定这是否相关,但似乎至少值得一提。
编辑:
我发现了这个问题,hash_hmac PHP 会自动将其数据导出为十六进制数据,crypto.createHmac 将其数据导出为原始二进制数据,我直接将其转换为 base64,我需要做的就是首先将数据导出为 hex,然后将其转换为 base64。
试试这个;
var crypto = require('crypto');
var s = 'The quick brown fox jumps over the lazy dog';
console.log(
new Buffer(
crypto.createHmac('SHA256', 'SECRET').update(s).digest('hex')
).toString('base64')
);
演示
PHP等效;
base64_encode(hash_hmac("SHA256",'The quick brown fox jumps over the lazy dog', 'SECRET'))
在 Azure 的情况下,你提到的密钥以 Base64 格式提供。使用节点的cryto库,我发现当我将密钥作为缓冲区传入时它可以工作。Azure 授权签名标头节点代码示例如下:
const util = require('util');
const crypto = require('crypto');
var accountName = "YOUR_ACCOUNT_NAME";
var key = Buffer("YOUR_BASE64_KEY",'base64');
var hash = crypto.createHmac('sha256',key).update(stringToSign,'utf8').digest('base64');
var signature = util.format("%s:%s", accountName, hash);
var authorization = util.format("SharedKey %s", signature);