在Javascript中实现HMAC-SHA256 for Keybase [英] Implementing HMAC-SHA256 for Keybase in Javascript

查看:5278
本文介绍了在Javascript中实现HMAC-SHA256 for Keybase的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用keybase.io API - 尝试从javascript驱动它。登录是一个两步过程。第二步详述为
https://keybase.io/docs/api /1.0/call/login



我遇到了以下情况:


服务器和客户端共享此密钥,并且对于客户端
成功记录用户,它必须向服务器证明这个
秘密的知识。为了防止重放攻击,它做
不发送秘密本身。相反,它将pwh作为MAC密钥,并且
MACs在上一步骤中检索的临时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 key'等于'Secret Passphrase',因此CryptoJS函数参数的顺序与Keybase上给出的代码示例相反?

    / li>
  2. CryptoJS示例具有平滑的ASCII输入,而Keybase上的指令用于提供二进制输入。当我尝试和喂它一个uint8array参数(这是我从使用keybase API的上一步得到的),如下所示:

      TypeError:g.clamp不是函数





      e,m = 4 * h; 
    g.sigBytes> m&&(g = f.finalize(g));
    g.clamp();
    for(var r = this._oKey = g.clone()



解决方案

CryptoJS.HmacSHA256() happily拥有自己的 WordArray 作为键,所以你只需要将你的 UInt8Array 转换为CryptoJS' WordArray p>

帖子提供了由Vincenzo Ciancia创建的(未测试的)转换器: / p>

  CryptoJS.enc.u8array = {
/ **
*将字数组转换为Uint8Array。
*
* @param {WordArray} wordArray字数组。
*
* @return {Uint8Array} Uint8Array。
*
* @static
*
* @example
*
* var u8arr = CryptoJS.enc.u8array.stringify(wordArray);
* /
stringify:function wordArray){
//快捷方式
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;

//转换
var u8 = new Uint8Array(sigBytes);
for(var i = 0; i var byte =(words [i>>> 2]> 4)* 8))& 0xff;
u8 [i] = byte;
}

return u8;
},

/ **
*将Uint8Array转换为字数组。
*
* @param {string} u8Str Uint8Array。
*
* @return {WordArray}字数组。
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.u8array.parse(u8arr);
* /
parse:function(u8arr){
//快捷键
var len = u8arr.length;

//转换
var words = [];
for(var i = 0; i words [i>> 2] | =(u8arr [i]& 0xff)< (24-(i%4)* 8);
}

return CryptoJS.lib.WordArray.create(words,len);
}
};


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

解决方案

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

这篇关于在Javascript中实现HMAC-SHA256 for Keybase的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆