在Javascript中为Keybase实现HMAC-SHA256

时间:2015-04-04 16:48:10

标签: javascript cryptography hmac cryptojs keybase

我正在使用keybase.io API - 尝试从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()
    

1 个答案:

答案 0 :(得分:2)

CryptoJS.HmacSHA256()愉快地将自己的WordArray作为关键。因此,您只需要将UInt8Array转换为CryptoJS' WordArray

post提供了由Vincenzo Ciancia创建的这种(未经测试的)转换器:

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);
    }
};