英文:
Translate createHmac from crypto to crypto-js with Buffers
问题
我正在尝试将给定的代码使用crypto翻译成使用crypto-js的版本,但迄今为止没有成功。
我甚至无法获得相同的哈希值。
最终目标是生成TOTP令牌,我需要在web浏览器中使用crypto-js来生成它们。
关键部分是"步骤1: 生成HMAC-SHA-1值",我无法获得与crypto-js中的const hmacResult = hmac.digest();
相同的结果...
const crypto = require('crypto');
const cryptojs = require('crypto-js');
const base32 = require('hi-base32');
function generateHOTP(secret, counter) {
const decodedSecret = base32.decode.asBytes(secret);
const buffer = Buffer.alloc(8);
for (let i = 0; i < 8; i++) {
buffer[7 - i] = counter & 0xff;
counter = counter >> 8;
}
// 步骤1: 生成HMAC-SHA-1值
let hmacjs = cryptojs.algo.HMAC.create(cryptojs.algo.SHA1, cryptojs.enc.Utf8.stringify(decodedSecret) );
hmacjs.update(buffer);
console.log(hmacjs.finalize().toString());
const hmac = crypto.createHmac('sha1', Buffer.from(decodedSecret));
hmac.update(buffer);
const hmacResult = hmac.digest();
console.log(hmacResult.toString('hex'));
// 步骤2: 生成4字节字符串 (动态截断)
const code = dynamicTruncationFn(hmacResult);
// 步骤3: 计算HOTP值
return code % 10 ** 6;
}
function dynamicTruncationFn(hmacValue) {
const offset = hmacValue[hmacValue.length - 1] & 0xf;
return (
((hmacValue[offset] & 0x7f) << 24) |
((hmacValue[offset + 1] & 0xff) << 16) |
((hmacValue[offset + 2] & 0xff) << 8) |
(hmacValue[offset + 3] & 0xff)
);
}
function generateTOTP(secret, window = 0) {
const counter = Math.floor(Date.now() / 30000);
return generateHOTP(secret, counter + window);
}
console.log(generateTOTP('GEZDGNBVGY3TQOJQGEZDG', 0));
我尝试了各种变化并查阅了文档,但无法找到解决方案。
英文:
I am trying to translate a given Code using crypto to a version using crypto-js without luck so far.
I am not even able to get the same hash values.
The final goal is to generate TOTP tokens and I need to do it with crypto-js, because I want to generate them in a webbrowser.
The critical part is "Step 1: Generate an HMAC-SHA-1 value", I am not able to get a identical result as in const hmacResult = hmac.digest(); in crypto-js...
const crypto = require('crypto');
const cryptojs = require('crypto-js');
const base32 = require('hi-base32');
function generateHOTP(secret, counter) {
const decodedSecret = base32.decode.asBytes(secret);
const buffer = Buffer.alloc(8);
for (let i = 0; i < 8; i++) {
buffer[7 - i] = counter & 0xff;
counter = counter >> 8;
}
// Step 1: Generate an HMAC-SHA-1 value
let hmacjs = cryptojs.algo.HMAC.create(cryptojs.algo.SHA1, cryptojs.enc.Utf8.stringify(decodedSecret) );
hmacjs.update(buffer);
console.log(hmacjs.finalize().toString());
const hmac = crypto.createHmac('sha1', Buffer.from(decodedSecret));
hmac.update(buffer);
const hmacResult = hmac.digest();
console.log(hmacResult.toString('hex'));
// Step 2: Generate a 4-byte string (Dynamic Truncation)
const code = dynamicTruncationFn(hmacResult);
// Step 3: Compute an HOTP value
return code % 10 ** 6;
}
function dynamicTruncationFn(hmacValue) {
const offset = hmacValue[hmacValue.length - 1] & 0xf;
return (
((hmacValue[offset] & 0x7f) << 24) |
((hmacValue[offset + 1] & 0xff) << 16) |
((hmacValue[offset + 2] & 0xff) << 8) |
(hmacValue[offset + 3] & 0xff)
);
}
function generateTOTP(secret, window = 0) {
const counter = Math.floor(Date.now() / 30000);
return generateHOTP(secret, counter + window);
}
console.log(generateTOTP('GEZDGNBVGY3TQOJQGEZDG', 0));
I tried diverse variation and consulted the documentations, but couldn't figure out a solution.
答案1
得分: 0
CryptoJS内部使用WordArray
数据类型,即您需要将decodedSecret
(JavaScript数组)和buffer
(NodeJS缓冲区)转换为WordArray
,并将生成的HMAC作为WordArray
转换为NodeJS缓冲区。
有几种方法可以实现这一点。一种可能的方法是通过Latin1进行转换:
// 步骤1:生成HMAC-SHA-1值
let decodedSecretWA = cryptojs.enc.Latin1.parse(Buffer.from(decodedSecret).toString('latin1')); // JS数组 -> WordArray
let bufferWA = cryptojs.enc.Latin1.parse(buffer.toString('latin1')); // NodeJS缓冲区 -> WordArray
let hmacjsWA = cryptojs.algo.HMAC.create(cryptojs.algo.SHA1, decodedSecretWA);
hmacjsWA.update(bufferWA);
let hmacResultjsWA = hmacjsWA.finalize();
const hmacResultjs = Buffer.from(hmacResultjsWA.toString(cryptojs.enc.Latin1), 'latin1'); // WordArray -> NodeJS缓冲区
console.log(hmacResultjs);
另一种方法是直接使用cryptojs.lib.WordArray.create()
将其转换为WordArray
,该方法可以处理JavaScript数组(通过类型化数组)和NodeJS缓冲区。没有CryptoJS支持的反向方向,但可以使用这里的CryptJsWordArrayToUint8Array()
进行转换:
// 步骤1:生成HMAC-SHA-1值
let decodedSecretWA = cryptojs.lib.WordArray.create(new Uint8Array(decodedSecret)); // JS数组 -> WordArray
let bufferWA = cryptojs.lib.WordArray.create(buffer); // NodeJS缓冲区 -> WordArray
let hmacjsWA = cryptojs.algo.HMAC.create(cryptojs.algo.SHA1, decodedSecretWA);
hmacjsWA.update(bufferWA);
let hmacResultjsWA = hmacjsWA.finalize();
const hmacResultjs = Buffer.from(CryptJsWordArrayToUint8Array(hmacResultjsWA)); // WordArray -> NodeJS缓冲区
console.log(hmacResultjs);
英文:
CryptoJS uses the WordArray
data type internally, i.e. you have to convert decodedSecret
(JavaScript array) and buffer
(NodeJS buffer) into a WordArray
and the resulting HMAC as WordArray
into a NodeJS buffer.
There are several approaches to this. One possibility is the conversion via latin1:
// Step 1: Generate an HMAC-SHA-1 value
let decodedSecretWA = cryptojs.enc.Latin1.parse(Buffer.from(decodedSecret).toString('latin1')); // JS array -> WordArray
let bufferWA = cryptojs.enc.Latin1.parse(buffer.toString('latin1')); // NodeJS Buffer -> WordArray
let hmacjsWA = cryptojs.algo.HMAC.create(cryptojs.algo.SHA1, decodedSecretWA);
hmacjsWA.update(bufferWA);
let hmacResultjsWA = hmacjsWA.finalize();
const hmacResultjs = Buffer.from(hmacResultjsWA.toString(cryptojs.enc.Latin1), 'latin1'); // WordArray -> NodeJS Buffer
console.log(hmacResultjs);
Another approach is to convert directly to a WordArray
with cryptojs.lib.WordArray.create()
, which can handle JavaScript arrays (via typed arrays) and NodeJS buffers. There is no CryptoJS support for the reverse direction, but e.g. CryptJsWordArrayToUint8Array()
from here can be applied:
// Step 1: Generate an HMAC-SHA-1 value
let decodedSecretWA = cryptojs.lib.WordArray.create(new Uint8Array(decodedSecret)); // JS array -> WordArray
let bufferWA = cryptojs.lib.WordArray.create(buffer); // NodeJS Buffer -> WordArray
let hmacjsWA = cryptojs.algo.HMAC.create(cryptojs.algo.SHA1, decodedSecretWA);
hmacjsWA.update(bufferWA);
let hmacResultjsWA = hmacjsWA.finalize();
const hmacResultjs = Buffer.from(CryptJsWordArrayToUint8Array(hmacResultjsWA)); // WordArray -> NodeJS Buffer
console.log(hmacResultjs);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论