Реализация HMAC-SHA256 для базы ключей в Javascript
Я работаю с API keybase.io - пытаюсь вытолкнуть его из JavaScript. Вход в систему состоит из двух этапов. Второй шаг подробно описан по адресу https://keybase.io/docs/api/1.0/call/login.
Я застрял на следующем;
Сервер и клиент совместно используют этот секрет, и для успешного входа пользователя в систему клиент должен доказать знание этого секрета серверу. Чтобы защитить от повторных атак, он не передает сам секрет. Скорее, он обрабатывает pwh как ключ MAC, а MAC - временную login_session, полученную на предыдущем шаге:
hmac_pwh = HMAC-SHA512(pwh, base64decode(login_session))
Оба входа в двоичном формате; ключ pwh был выведен в двоичном формате из сценария выше, а login_session декодируется в base64, а затем подается в HMAC в двоичном виде.
Я использую библиотеку CryptoJS, которая дает следующий пример для реализации
var hash = CryptoJS.HmacSHA256('Message','Secret Passphrase');
У меня есть пара проблем;
По терминологии "MAC-ключ" равен "Секретной парольной фразе", и, следовательно, параметры функции CryptoJS обращаются в обратном порядке по сравнению с примером кода, приведенным на Keybase?
Пример CryptoJS имеет простые ascii входы, в то время как инструкции на Keybase предназначены для подачи двоичных входов. Когда я пытаюсь передать ему параметр uint8array (что я и получил на предыдущем шаге использования API keybase), он опрокидывается следующим образом;
TypeError: g.clamp is not a function
e,m=4*h; g.sigBytes>m&&(g=f.finalize(g)); g.clamp(); for(var r=this._oKey=g.clone()
1 ответ
CryptoJS.HmacSHA256()
счастливо берет свое WordArray
в качестве ключа. Так что вам нужно только конвертировать ваши UInt8Array
CryptoJS' WordArray
,
Этот пост предоставляет такой (непроверенный) конвертер, созданный Винченцо Чанча:
CryptoJS.enc.u8array = {
/**
* Converts a word array to a Uint8Array.
*
* @param {WordArray} wordArray The word array.
*
* @return {Uint8Array} The Uint8Array.
*
* @static
*
* @example
*
* var u8arr = CryptoJS.enc.u8array.stringify(wordArray);
*/
stringify: function (wordArray) {
// Shortcuts
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
// Convert
var u8 = new Uint8Array(sigBytes);
for (var i = 0; i < sigBytes; i++) {
var byte = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
u8[i]=byte;
}
return u8;
},
/**
* Converts a Uint8Array to a word array.
*
* @param {string} u8Str The Uint8Array.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.u8array.parse(u8arr);
*/
parse: function (u8arr) {
// Shortcut
var len = u8arr.length;
// Convert
var words = [];
for (var i = 0; i < len; i++) {
words[i >>> 2] |= (u8arr[i] & 0xff) << (24 - (i % 4) * 8);
}
return CryptoJS.lib.WordArray.create(words, len);
}
};