我在使用PBKDF2和Webcrypto时遇到了问题。我想在SHA-1算法中使用PBKDF2 .目前,我有
const ENCODING = "utf-8";
const HMACSHA1 = {name: "HMAC", "hash" : "SHA-1"};
const PBKDF2SHA1 = {name: "PBKDF2", "hash": "SHA-1"};
// str2binb takes a string and outputs an ArrayBuffer
async function pbkdf2_generate_key_from_string(string) { // Working
return crypto.subtle.importKey(
"raw",
str2binb(string),
PBKDF2SHA1,
false,
["deriveKey", "deriveBits"],
);
}
async function pbkdf2_derive_salted_key(key, salt, iterations) { // Not working
return crypto.subtle.deriveKey(
{
"name": "PBKDF2",
"salt": salt,
"iterations": iterations,
"hash": "SHA-1",
"length": 160
},
key,
{
"name": "HMAC"
"hash": "SHA-1",
"length": 160
},
true,
[ "encrypt", "decrypt"]
);
}不过,我知道我一定使用错了,因为它是一个受支持的密钥派生算法,并且根据Mozilla的奇妙的文档,在derivedKeyAlgorithm下,HMAC和HMAC-SHA1 1一样受支持。我还让它非常直接地与AES-GCM一起工作。
当我尝试时,我得到的错误信息,
salt = b64binb("QSXCR+Q6sek8bf92"); // ArrayBuffer
key = await pbkdf2_generate_key_from_string("pencil");
x = await pbkdf2_derive_salted_key(key, salt, 4096)是Uncaught DOMException: Cannot create a key using the specified key usages.
注意:据我所知,不再推荐SHA1,这是用于遗留支持的。
注2:当我将上面的内容替换为,
async function pbkdf2_derive_salted_key(key, data, salt, iterations) { // Not working
return crypto.subtle.deriveKey(
{
"name": "PBKDF2",
salt: salt,
"iterations": iterations,
"hash": "SHA-1",
},
key,
{
"name": "AES-GCM",
"length": 256
},
true,
[ "encrypt", "decrypt"]
);
}谢谢。
发布于 2020-05-09 11:45:26
在deriveKey中,参数keyUsages必须更改为["sign", "verify"]。然后代码工作(因为b64binb、str2binb没有发布,下面的代码使用适当的替代品):
const b64binb = base64String => Uint8Array.from(atob(base64String), c => c.charCodeAt(0));
const str2binb = str => new TextEncoder().encode(str);
const buf2hex = buffer => Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
async function pbkdf2_generate_key_from_string(string) {
return crypto.subtle.importKey(
"raw",
str2binb(string),
{
name: "PBKDF2",
},
false,
["deriveKey", "deriveBits"],
);
}
async function pbkdf2_derive_salted_key(key, salt, iterations) {
return crypto.subtle.deriveKey(
{
name: "PBKDF2",
salt: salt,
iterations: iterations,
hash: {name: "SHA-1"}
},
key,
{
name: "HMAC",
hash: "SHA-1",
length: 160
},
true,
["sign", "verify"] // <--------------------- Fix!
);
}
async function test(){
salt = b64binb("QSXCR+Q6sek8bf92"); // ArrayBuffer
key = await pbkdf2_generate_key_from_string("pencil");
x = await pbkdf2_derive_salted_key(key, salt, 4096)
console.log(buf2hex(await window.crypto.subtle.exportKey("raw", x)));
}
test();
使用此密钥,window.crypto.subtle.sign使用HMAC-SHA1 1创建签名。
更新:
由于在https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto中通常指定密钥的使用,因此必须将["encrypt", "decrypt"]作为AES-GCM的keyUsages参数和HMAC-SHA的["sign", "verify"]参数。
为什么["encrypt", "decrypt"]为AES-GCM?AES-GCM用于加密/解密消息:AES描述分组密码 (允许对单个块进行加密)和GCM 操作方式 (允许对多个块进行加密)。GCM提供机密性、真实性和完整性。
为什么["sign", "verify"]为HMAC?HMAC用于签名/验证消息:某些操作模式(如CBC )只提供机密性。另外,为了提供真实性和完整性,可以使用MAC (例如,基于密码散列函数的特定类型的HMAC,例如SHA家族中的一个)对消息进行签名。MAC通常是根据密文而不是明文(https://crypto.stackexchange.com/q/202)计算的。关于SHA1漏洞,请参见HMAC-SHA1 1和HMAC-SHA1 256 这里和这里的比较。
https://stackoverflow.com/questions/61691214
复制相似问题