我从this implementation开始在NativeScript应用中使用Google Authenticator实现两要素身份验证。由于Node的加密模块未在NativeScript中运行,因此我试图使其与CryptoJS一起使用。
这是有效的Node代码。该函数返回具有正确值的缓冲区。
const crypto = require('crypto');
function generateHOTP(secret, counter) {
const buffer = Buffer.alloc(8);
for (let i = 0; i < 8; i++) {
buffer[7 - i] = counter & 0xff;
counter = counter >> 8;
}
const hmac = crypto.createHmac('sha1', secret);
hmac.update(buffer);
return hmac.digest();
}
这是CryptoJS等效项。返回的值与先前的函数不同,有时无论输入多少,多次迭代都返回相同的值。
const CryptoJS = require("crypto-js");
function generateHOTP(secret, counter) {
const buffer = Buffer.alloc(8);
for (let i = 0; i < 8; i++) {
buffer[7 - i] = counter & 0xff;
counter = counter >> 8;
}
let result = CryptoJS.HmacSHA1(buffer.toString(), secret); // buffer.toString() is the problem
return Buffer.from(result.toString(), "hex");
}
如果在第一个函数中将hmac.update(buffer)
更改为hmac.update(buffer.toString())
,它将返回与第二个相同的错误值,因此问题出在此字符串转换中。 buffer
是一个UInt8Array。
如何固定CryptoJS.HmacSHA1(message, key)
的第一个参数以返回与第一个函数相同的值?
[您正在为密码模块提供缓冲区,而您正在向CryptoJS提供字符串。可能它们处理的字符串与缓冲区不同。 CryptoJS不支持将Buffer作为输入,仅支持字符串和WordArray,因此窍门是将Buffer转换为WordArray:
更改以下行:
let result = CryptoJS.HmacSHA1(buffer.toString(), secret);
至:
let result = CryptoJS.HmacSHA1(CryptoJS.lib.WordArray.create(buffer), secret);
如果您希望代码更符合加密版本(CryptoJS具有相似的接口):
const CryptoJS = require("crypto-js");
function generateHOTP(secret, counter) {
const buffer = Buffer.alloc(8);
for (let i = 0; i < 8; i++) {
buffer[7 - i] = counter & 0xff;
counter = counter >> 8;
}
const hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA1, secret);
hmac.update(CryptoJS.lib.WordArray.create(buffer))
return Buffer.from(hmac.finalize().toString(), 'hex');
}