Попытка кодирования строки в Java/NodeJS(Одноразовый пароль)

#java #node.js #one-time-password #code-translation

Вопрос:

Я написал кусок кода в NodeJS, который кодирует секретную строку в ключ otp для использования в другом приложении. Теперь я хочу сделать то же самое на Java для нескольких применений.

Узлы:

 const crypto = require("crypto");
const secret = "3f944b3fea81e35994f9";
const counter = getCounter(); // Value: 00000000033ea377

console.log("Counter:", typeof counter,"-", counter); 
// Returns: Counter: string - 00000000033ea377

const hmac = crypto.createHmac("sha1", Buffer.from(secret, 'hex'));
const digest = hmac.update(Buffer.from(counter, 'hex')).digest();

console.log("Digest:", typeof digest,"-", digest);
console.log("Digest(Hex):", typeof digest.toString("hex"),"-", digest.toString("hex"));
// Returns: Digest: object - <Buffer fb 6b 67 d4 5f ed 05 e8 be 74 44 b4 f9 22 d4 14 5a d1 11 b1>
// Returns: Digest(Hex): string - fb6b67d45fed05e8be7444b4f922d4145ad111b1

// Final Value: fb6b67d45fed05e8be7444b4f922d4145ad111b1
 

Ява:

 String secret = "3f944b3fea81e35994f9";
String counter = "00000000033ea377"; // Same value as in the nodejs code

Mac mac = Mac.getInstance("HmacSHA1");

SecretKeySpec key = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA1");
mac.init(key);
System.out.println(BaseEncoding.base16().lowerCase()
        .encode(mac.doFinal(counter.getBytes(StandardCharsets.UTF_8))));
// BaseEncoding is the class from Google's Guava (My version: 31.0.1-jre)
// Final Value: bccd0b95617b90ff497491e5c554b5e2545f1a4b
 

В Java я не получаю то же значение, что и в NodeJS. Я уверен, что это должно быть как-то связано с кодировками из Buffer.from(var, "hex")
Потому что, если я изменю

 const hmac = crypto.createHmac("sha1", Buffer.from(secret, 'hex'));
const digest = hmac.update(Buffer.from(counter, 'hex')).digest();
 

Для

 const hmac = crypto.createHmac("sha1", Buffer.from(secret, 'utf8')); // Changed from "hex" to "utf8"
const digest = hmac.update(Buffer.from(counter, 'utf8')).digest(); // Changed from "hex" to "utf8"
 

Я получаю то же значение, что и в коде Java, но API, для которого я использую токен, теперь выдает ошибку о том, что токен недействителен. Я попытался преобразовать массив байтов utf8 в массив байтов с шестнадцатеричными значениями, но это не сработало так хорошо.

Я надеюсь, что кто — нибудь сможет мне помочь!

Спасибо, радсн!