使用JavaScript使用HmacSHA256

时间:2016-02-05 15:45:33

标签: javascript sign postman houndify

在用于身份验证的Houndify API文档中,您有以下内容块:

验证请求的示例

我们假设我们有以下信息:

UserID: ae06fcd3-6447-4356-afaa-813aa4f2ba41
    RequestID: 70aa7c25-c74f-48be-8ca8-cbf73627c05f
    Timestamp: 1418068667   
    ClientID: KFvH6Rpy3tUimL-pCUFpPg==
    ClientKey: KgMLuq-k1oCUv5bzTlKAJf_mGo0T07jTogbi6apcqLa114CCPH3rlK4c0RktY30xLEQ49MZ-C2bMyFOVQO4PyA==
  1. 以下列格式连接UserID字符串,RequestID字符串和TimeStamp字符串:{user_id};{request_id}{timestamp}

  2. 使用示例中的值,预期输出将是这种情况:ae06fcd3-6447-4356-afaa-813aa4f2ba41;70aa7c25-c74f-48be-8ca8-cbf73627c05f1418068667

  3. 使用已解码的ClientKey对消息进行签名。结果是一个32字节的二进制字符串(我们无法直观地表示)。但是,在base-64编码之后,签名为:myWdEfHJ7AV8OP23v8pCH1PILL_gxH4uDOAXMi06akk=

  4. 然后,客户端会生成两个身份验证标头 Hound-Request-Authentication Hound-Client-Authentication

  5. Hound-Request-Authentication标头是通过以下列格式连接UserID和RequestID组成的:{user-id};{request-id}。继续上面的示例,此标头的值将是: 猎犬请求身份验证:ae06fcd3-6447-4356-afaa-813aa4f2ba41;70aa7c25-c74f-48be-8ca8-cbf73627c05f

  6. Hound-Client-Authentication标头是通过以下格式连接ClientID,TimeStamp字符串和签名组成的:{client-id};{timestamp};{signature}。继续上面的示例,此标头的值为:Hound-Client-Authentication: KFvH6Rpy3tUimL-pCUFpPg==;1418068667;myWdEfHJ7AV8OP23v8pCH1PILL_gxH4uDOAXMi06akk=

  7. 对于Number 3,它表示"使用解码的ClientKey"对消息进行签名。 "消息"和" ClientKey"是两个不同的字符串。

    我的问题:你如何用另一个字符串签署一个字符串,即这究竟是什么意思?你会如何在JavaScript中做到这一点?

    var message = 'my_message';
    var key = 'signing_key';
    
    //??what next??
    

    我试图弄清楚所有这些,所以我可以在Postman中创建一个预先请求脚本来执行正确的HmacSHA256哈希。

2 个答案:

答案 0 :(得分:7)

根据文档,如果您使用其中一个SDK,它会自动验证您的请求:

  

SDK已经为您处理身份验证。你只需要提供   SDK包含为您生成的客户端ID和客户端密钥   客户端何时创建。如果您不使用SDK,请使用该代码   右边的示例,用于生成您自己的HTTP标头以进行身份​​验证   你的要求。

但是,如果您想手动执行此操作,我相信您需要计算他们在您的问题中的链接中描述的字符串的HMAC值,然后将其作为{{1的一部分您的请求中的标头。他们提供example for node.js

Hound-Client-Authentication

答案 1 :(得分:2)

所以基本上,签署[在这个特定情况下]只是意味着除了 key 之外还使用哈希算法创建字符串的哈希值,而不是 keyless 哈希[像MD5]。例如:

var message = 'my_message';
var key = 'signing_key';
var hashed_message = hash_func(message, key);

其中hash_func是一个散列算法,如HmacSHA256(有问题的散列算法)。

我试图解决这个问题的原因是使用Postman测试Houndify API的身份验证。幸运的是,Postman有一个很好的功能,称为预请求脚本 [完成哈希算法],如果您需要预先生成需要与请求一起发送的值,这将有所帮助。

经过多次摆弄后,我设法创建了一个预先请求的脚本,可以正确地对此API进行身份验证(请参阅下面的代码)。

var unescapeBase64Url = function (key) {
            return key.replace(/-/g, '+').replace(/_/g, '/');
        },

        escapeBase64Url = function (key) {
            return key.replace(/\+/g, '-').replace(/\//g, '_');
        },
        guid = function() {
    function s4() {
        return Math.floor((1 + Math.random()) * 0x10000)
        .toString(16)
        .substring(1);
    }
    return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
        s4() + '-' + s4() + s4() + s4();
    };

var client_id_str = environment["client-id"];
var client_key_str = environment["client-key"];
var user_id_str = environment["user-id"];
var request_id_str = guid();
var timestamp_str = Math.floor(Date.now() / 1000);

var client_key_dec_str = CryptoJS.enc.Base64.parse(unescapeBase64Url(client_key_str));

var message_str = user_id_str+";"+request_id_str+timestamp_str;
var signature_hash_obj = CryptoJS.HmacSHA256(message_str, client_key_dec_str);
var signature_str = signature_hash_obj.toString(CryptoJS.enc.Base64);

var hound_request_str = user_id_str+";"+request_id_str;
var hound_client_str = client_id_str+";"+timestamp_str+";"+escapeBase64Url(signature_str);

postman.setEnvironmentVariable("hound-request-authentication", hound_request_str);
postman.setEnvironmentVariable("hound-client-authentication", hound_client_str);

请注意,您必须在Postman中为 client-id client-key user-id 创建环境变量,以及标头变量 hound-request-authentication hound-client-authentication ,以保存定义标题时将引用的最终值。

希望它有所帮助。