Ste*_*rev 9 javascript cryptography window.crypto
如何使用Crypto Web API(window.crypto
)在浏览器中获取HMAC-SHA512(密钥,数据)?
目前我使用的是CryptoJS库,它非常简单:
CryptoJS.HmacSHA512("myawesomedata", "mysecretkey").toString();
结果是91c14b8d3bcd48be0488bfb8d96d52db6e5f07e5fc677ced2c12916dc87580961f422f9543c786eebfb5797bc3febf796b929efac5c83b4ec69228927f21a03a
.
我想摆脱额外的依赖,并开始使用Crypto Web API.我怎样才能得到相同的结果?
Ste*_*lum 30
以下是 \xe2\x9c\x85 答案的副本。这次我们使用async/await
干净的语法。此方法还提供 Base64 编码的摘要。
secret
是将用于签署 的密钥body
。body
是要签名的字符串。enc
是一个文本编码器,可将 UTF-8 转换为 JavaScript 字节数组。algorithm
是一个JS对象,用于标识签名方法。key
是一个CryptoKey。signature
是字节数组哈希。digest
是base64编码的签名。JavaScript 代码如下:
\n(async ()=>{\n\'use strict\';\n\nlet secret = "sec-demo"; // the secret key\nlet enc = new TextEncoder("utf-8");\nlet body = "GET\\npub-demo\\n/v2/auth/grant/sub-key/sub-demo\\nauth=myAuthKey&g=1&target-uuid=user-1×tamp=1595619509&ttl=300";\nlet algorithm = { name: "HMAC", hash: "SHA-256" };\n\nlet key = await crypto.subtle.importKey("raw", enc.encode(secret), algorithm, false, ["sign", "verify"]);\nlet signature = await crypto.subtle.sign(algorithm.name, key, enc.encode(body));\nlet digest = btoa(String.fromCharCode(...new Uint8Array(signature)));\n\nconsole.log(digest);\n\n})();
Run Code Online (Sandbox Code Playgroud)\r\n此页面上的原始答案对今天早些时候的调试工作很有帮助。我们使用它来帮助识别文档中创建签名以授予访问令牌以使用具有读/写权限的 API 的错误。
\nSte*_*rev 14
回答我自己的问题.下面的代码返回相同的结果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);
});
});
Run Code Online (Sandbox Code Playgroud)
不知怎的,@StephenBlum 的答案对我不起作用。
我将@StepanSnigirev 的答案重写为下面的异步。
"use strict";
(async () => {
const secret = "mysecretkey";
const enc = new TextEncoder();
const body = "myawesomedata";
const algorithm = { name: "HMAC", hash: "SHA-512" };
const key = await crypto.subtle.importKey(
"raw",
enc.encode(secret),
algorithm,
false,
["sign", "verify"]
);
const signature = await crypto.subtle.sign(
algorithm.name,
key,
enc.encode(body)
);
// convert buffer to byte array
const hashArray = Array.from(new Uint8Array(signature));
// convert bytes to hex string
const digest = hashArray
.map((b) => b.toString(16).padStart(2, "0"))
.join("");
console.log(digest);
})();
Run Code Online (Sandbox Code Playgroud)
注意:我们不能使用new Uint8Array(arrayBuffer).map(...)
. 虽然 Uint8Array 实现了 ArrayLike 接口,但它的 map 方法将返回另一个不能包含字符串(在我们的例子中为十六进制八位字节)的 Uint8Array,因此Array.from
hack