【问题标题】:How to get HMAC with Crypto Web API如何使用 Crypto Web API 获取 HMAC
【发布时间】:2018-04-29 23:03:01
【问题描述】:

如何使用 Crypto Web API (window.crypto) 在浏览器中获取 HMAC-SHA512(key, data)?

目前我正在使用 CryptoJS 库,它非常简单:

CryptoJS.HmacSHA512("myawesomedata", "mysecretkey").toString();

结果是91c14b8d3bcd48be0488bfb8d96d52db6e5f07e5fc677ced2c12916dc87580961f422f9543c786eebfb5797bc3febf796b929efac5c83b4ec69228927f21a03a

我想摆脱额外的依赖并开始使用 Crypto Web API。我怎样才能得到相同的结果?

【问题讨论】:

标签: javascript cryptography window.crypto


【解决方案1】:

回答我自己的问题。下面的代码返回与CryptoJS.HmacSHA512("myawesomedata", "mysecretkey").toString();相同的结果

因为 WebCrypto 是异步的,所以到处都有承诺:

// encoder to convert string to Uint8Array
var enc = new TextEncoder("utf-8");

window.crypto.subtle.importKey(
    "raw", // raw format of the key - should be Uint8Array
    enc.encode("mysecretkey"),
    { // algorithm details
        name: "HMAC",
        hash: {name: "SHA-512"}
    },
    false, // export = false
    ["sign", "verify"] // what this key can do
).then( key => {
    window.crypto.subtle.sign(
        "HMAC",
        key,
        enc.encode("myawesomedata")
    ).then(signature => {
        var b = new Uint8Array(signature);
        var str = Array.prototype.map.call(b, x => ('00'+x.toString(16)).slice(-2)).join("")
        console.log(str);
    });
});

【讨论】:

  • 代码对我来说是可以理解的,直到您将 ArrayBuffer 转换为字符串的最后一点。为什么TextDecoder 不适合我?
【解决方案2】:

Async/Await Crypto Subtle HMAC SHA-256/512 with Base64 Digest

以下是✅答案的副本。这次我们使用async/await 来获得简洁的语法。这种方法还提供了 base64 编码的摘要。

  • secret 是用于签署body 的密钥。
  • body 是要签名的字符串。
  • enc 是一种将 UTF-8 转换为 JavaScript 字节数组的文本编码器。
  • algorithm是一个JS对象,用于标识签名方法。
  • keyCryptoKey
  • signature 是字节数组哈希。
  • digest 是 base64 编码的签名。

JavaScript 代码如下:

(async ()=>{
'use strict';

let secret = "sec-demo"; // the secret key
let enc = new TextEncoder("utf-8");
let body = "GET\npub-demo\n/v2/auth/grant/sub-key/sub-demo\nauth=myAuthKey&g=1&target-uuid=user-1&timestamp=1595619509&ttl=300";
let algorithm = { name: "HMAC", hash: "SHA-256" };

let key = await crypto.subtle.importKey("raw", enc.encode(secret), algorithm, false, ["sign", "verify"]);
let signature = await crypto.subtle.sign(algorithm.name, key, enc.encode(body));
let digest = btoa(String.fromCharCode(...new Uint8Array(signature)));

console.log(digest);

})();

此页面上的原始答案对今天早些时候的调试工作很有帮助。我们使用它来帮助识别我们创建 signatures for granting access tokens to use APIs with read/write permissions 的文档中的错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-20
    • 1970-01-01
    • 1970-01-01
    • 2022-10-18
    • 2017-04-13
    • 2017-01-11
    • 2018-11-22
    • 1970-01-01
    相关资源
    最近更新 更多