Implementing HMAC-SHA256 for Keybase in Javascript

好久不见. 提交于 2019-12-11 02:00:00

问题


I am working with the keybase.io API - trying to drive it from javascript. Logging in is a two step process. The second step is detailed at https://keybase.io/docs/api/1.0/call/login.

I am stuck on the following;

The server and the client share this secret, and for the client to successfully log the user in, it must prove knowledge of this secret to the server. To protect against replay attacks, it does not send the secret itself. Rather, it treats pwh as MAC key, and MACs the temporary login_session retrieved in the previous step:

hmac_pwh = HMAC-SHA512(pwh, base64decode(login_session)) 

Both inputs are in binary format; the pwh key was output in binary format from scrypt above, and the login_session is base64-decoded and then fed into HMAC in binary.

I am using the CryptoJS library which gives the following example for implementation

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

I have a couple of problems;

  1. as a matter of terminology does 'MAC key' equal 'Secret Passphrase' and hence the CryptoJS function parameters are reversed in their order vs the code example given on Keybase?

  2. The CryptoJS example has plain ascii inputs whilst the instructions on Keybase are to feed binary inputs. When I try and feed it a uint8array parameter (which is what I get from the previous step in using the keybase API) it keels over as follows;

    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() happily takes its own WordArray as a key. So you only need to convert your UInt8Array to CryptoJS' WordArray.

This post provides such an (untested) converter created by 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);
    }
};


来源:https://stackoverflow.com/questions/29448968/implementing-hmac-sha256-for-keybase-in-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!