Nodejs 与 OpenSSL 不同的 HMAC 签名
Nodejs different HMAC signature from OpenSSL
我一直在努力在 Node 中创建正确的 HMAC 签名。
用例
我目前正在为 Node 使用 Jointspace API 客户端来控制飞利浦智能电视。但是为了让它工作,我需要为配对请求签名一个字符串。
现状
我的 nodejs 代码如下所示:
const crypto = require('crypto');
let secret = Buffer.from('ZmVay1EQVFOaZhwQ4Kv81ypLAZNczV9sG4KkseXWn1NEk6cXmPKO/MCa9sryslvLCFMnNe4Z4CPXzToowvhHvA==', 'base64');
let text = '12345';
let algorithm = 'sha1';
let hmac = crypto.createHmac(algorithm, secret);
hmac.write(text);
hmac.end();
console.log(hmac.read('binary').toString('base64'));
当我运行它时,结果是这样的:
~ $ node test.js
DURLMkx7YdrIlWdUKo3iNDC3cp0=
预期
当我通过命令行使用 openssl
命令执行完全相同的操作时,我得到了不同的结果。 (正确结果)
~ $ echo -n "ZmVay1EQVFOaZhwQ4Kv81ypLAZNczV9sG4KkseXWn1NEk6cXmPKO/MCa9sryslvLCFMnNe4Z4CPXzToowvhHvA==" | base64 -d | openssl dgst -sha1 -hmac "12345" -binary | base64
GvbRLlBSY8r/jPqUGox8zZHxOew=
参考资料
an issue on the node Github page 解决了 Node 和 openssl 之间的差异问题。在那个问题上,他们基本上说节点中的加密只是 C++ openssl 库的包装器。为了使其正常工作,由于转换问题,您需要将秘密作为缓冲区而不是字符串提供。
例如
crypto.createHmac('sha1', new Buffer('secret_key', 'utf8'));
但这并不能解决我的问题。
输出差异
~ $ echo "DURLMkx7YdrIlWdUKo3iNDC3cp0=" | base64 -d | hexdump -C
00000000 0d 44 4b 32 4c 7b 61 da c8 95 67 54 2a 8d e2 34 |.DK2L{a...gT*..4|
00000010 30 b7 72 9d |0.r.|
00000014
~ $ echo "GvbRLlBSY8r/jPqUGox8zZHxOew=" | base64 -d | hexdump -C
00000000 1a f6 d1 2e 50 52 63 ca ff 8c fa 94 1a 8c 7c cd |....PRc.......|.|
00000010 91 f1 39 ec |..9.|
00000014
在您的命令中,您将 12345
用作 HMAC 密钥,但在您的代码中,您将其用作数据!所以这是代码的更新
const crypto = require('crypto');
let secret = 'ZmVay1EQVFOaZhwQ4Kv81ypLAZNczV9sG4KkseXWn1NEk6cXmPKO/MCa9sryslvLCFMnNe4Z4CPXzToowvhHvA=='
let key = '12345';
let algorithm = 'sha1';
let hmac = crypto.createHmac(algorithm, key);
hmac.write(secret);
hmac.end();
console.log(hmac.read('binary').toString('base64'));
这是命令
echo -n "ZmVay1EQVFOaZhwQ4Kv81ypLAZNczV9sG4KkseXWn1NEk6cXmPKO/MCa9sryslvLCFMnNe4Z4CPXzToowvhHvA==" | openssl dgst -sha1 -hmac "12345" -binary | base64
它们都 return 相同的哈希值。
我一直在努力在 Node 中创建正确的 HMAC 签名。
用例
我目前正在为 Node 使用 Jointspace API 客户端来控制飞利浦智能电视。但是为了让它工作,我需要为配对请求签名一个字符串。
现状
我的 nodejs 代码如下所示:
const crypto = require('crypto');
let secret = Buffer.from('ZmVay1EQVFOaZhwQ4Kv81ypLAZNczV9sG4KkseXWn1NEk6cXmPKO/MCa9sryslvLCFMnNe4Z4CPXzToowvhHvA==', 'base64');
let text = '12345';
let algorithm = 'sha1';
let hmac = crypto.createHmac(algorithm, secret);
hmac.write(text);
hmac.end();
console.log(hmac.read('binary').toString('base64'));
当我运行它时,结果是这样的:
~ $ node test.js
DURLMkx7YdrIlWdUKo3iNDC3cp0=
预期
当我通过命令行使用 openssl
命令执行完全相同的操作时,我得到了不同的结果。 (正确结果)
~ $ echo -n "ZmVay1EQVFOaZhwQ4Kv81ypLAZNczV9sG4KkseXWn1NEk6cXmPKO/MCa9sryslvLCFMnNe4Z4CPXzToowvhHvA==" | base64 -d | openssl dgst -sha1 -hmac "12345" -binary | base64
GvbRLlBSY8r/jPqUGox8zZHxOew=
参考资料
an issue on the node Github page 解决了 Node 和 openssl 之间的差异问题。在那个问题上,他们基本上说节点中的加密只是 C++ openssl 库的包装器。为了使其正常工作,由于转换问题,您需要将秘密作为缓冲区而不是字符串提供。
例如
crypto.createHmac('sha1', new Buffer('secret_key', 'utf8'));
但这并不能解决我的问题。
输出差异
~ $ echo "DURLMkx7YdrIlWdUKo3iNDC3cp0=" | base64 -d | hexdump -C
00000000 0d 44 4b 32 4c 7b 61 da c8 95 67 54 2a 8d e2 34 |.DK2L{a...gT*..4|
00000010 30 b7 72 9d |0.r.|
00000014
~ $ echo "GvbRLlBSY8r/jPqUGox8zZHxOew=" | base64 -d | hexdump -C
00000000 1a f6 d1 2e 50 52 63 ca ff 8c fa 94 1a 8c 7c cd |....PRc.......|.|
00000010 91 f1 39 ec |..9.|
00000014
在您的命令中,您将 12345
用作 HMAC 密钥,但在您的代码中,您将其用作数据!所以这是代码的更新
const crypto = require('crypto');
let secret = 'ZmVay1EQVFOaZhwQ4Kv81ypLAZNczV9sG4KkseXWn1NEk6cXmPKO/MCa9sryslvLCFMnNe4Z4CPXzToowvhHvA=='
let key = '12345';
let algorithm = 'sha1';
let hmac = crypto.createHmac(algorithm, key);
hmac.write(secret);
hmac.end();
console.log(hmac.read('binary').toString('base64'));
这是命令
echo -n "ZmVay1EQVFOaZhwQ4Kv81ypLAZNczV9sG4KkseXWn1NEk6cXmPKO/MCa9sryslvLCFMnNe4Z4CPXzToowvhHvA==" | openssl dgst -sha1 -hmac "12345" -binary | base64
它们都 return 相同的哈希值。