Реализация HMAC-SHA256 для Keybase в 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 был выведен в двоичном формате из scrypt выше, а login_session декодируется с помощью base64, а затем передается в HMAC в двоичном формате.

Я использую библиотеку CryptoJS, которая дает следующий пример для реализации

 var hash = CryptoJS.HmacSHA256('Message','Secret Passphrase');

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

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

  2. Пример CryptoJS имеет простые входные данные ascii, в то время как инструкции Keybase предназначены для подачи двоичных входных данных. Когда я пытаюсь передать ему параметр uint8array (это то, что я получаю на предыдущем этапе использования API базы ключей), он падает следующим образом;

    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()
    

person anthonyc    schedule 04.04.2015    source источник


Ответы (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);
    }
};
person Artjom B.    schedule 04.04.2015