Реализация 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');

У меня есть пара проблем;

  1. По терминологии "MAC-ключ" равен "Секретной парольной фразе", и, следовательно, параметры функции CryptoJS обращаются в обратном порядке по сравнению с примером кода, приведенным на Keybase?

  2. Пример 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);
    }
};
Другие вопросы по тегам