После небольшой игры и сравнения моего кода с этим https://github.com/adalberht/hotp-totp-generator/blob/master/index.js мне удалось заставить его работать.
const crypto = require("crypto");
function generateHOTP(algorithm, secret, count, digits) {
// Convert the string to binary data in the form of a sequence of bytes
secret = Buffer.from(secret);
// Writes value to buf at the specified offset with the specified endianness
let countBuffer = Buffer.alloc(8, 0);
countBuffer.writeUInt32BE(count, 4);
// Creates and returns an Hmac object that uses the given algorithm and key
const hmac_result = crypto.createHmac(algorithm, secret)
.update(countBuffer)
.digest("hex");
// Chose the last byte of the hmac to do the dynamic truncation
const offset = parseInt(hmac_result.charAt(hmac_result.length - 1), 16);
// Dynamic truncation
let hotp = parseInt(hmac_result.substr(offset * 2, 2 * 4), 16);
hotp = hotp & 0x7fffffff;
hotp = hotp.toString().padStart(digits, "0");
return hotp;
}
for (let i = 0; i <= 9; i++) {
console.log(i, generateHOTP("sha1", "12345678901234567890", i, 6));
}
Вывод соответствует усеченным десятичным значениям в таблице в вопрос:
0 '1284755224'
1 '1094287082'
2 '137359152'
3 '1726969429'
4 '1640338314'
5 '868254676'
6 '1918287922'
7 '82162583'
8 '673399871'
9 '645520489'