Webcrypto PBKDF2-SHA1
Webcrypto PBKDF2-SHA1
我在将 PBKDF2 与 Webcrypto 结合使用时遇到问题。我想将 PBKDF2 与 SHA-1 算法一起使用。目前,我有,
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。我也很直接地使用它 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"]
);
}
谢谢。
在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 创建签名。
更新:
由于在 SubtleCrypto 中通常指定了密钥的使用,因此必须将 ["encrypt", "decrypt"]
应用为 AES-GCM 的 keyUsages
参数和 HMAC-SHA 的 ["sign", "verify"]
.
为什么 ["encrypt", "decrypt"]
用于 AES-GCM? AES-GCM 用于加密/解密 消息:AES describes a block cipher (allowing the encryption of a single block) and GCM the mode of operation(允许加密 更多 比一个块)。 GCM 提供机密性、真实性和完整性。
为什么 ["sign", "verify"]
用于 HMAC-SHA? HMAC 用于 签名/验证 消息:某些操作模式,例如 CBC only provide confidentiality. To additionally supply authenticity and integrity, the message can be signed with a MAC (e.g. an HMAC which is a specific type of MAC based on a cryptographic hash function e.g. one of the SHA family). The MAC is typically calculated from the ciphertext and not the plaintext (Encrypt-then-MAC). With regard to the SHA1 vulnerabilities, see for a comparison of HMAC-SHA1 and HMAC-SHA256 here and here.
我在将 PBKDF2 与 Webcrypto 结合使用时遇到问题。我想将 PBKDF2 与 SHA-1 算法一起使用。目前,我有,
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。我也很直接地使用它 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"]
);
}
谢谢。
在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 创建签名。
更新:
由于在 SubtleCrypto 中通常指定了密钥的使用,因此必须将 ["encrypt", "decrypt"]
应用为 AES-GCM 的 keyUsages
参数和 HMAC-SHA 的 ["sign", "verify"]
.
为什么 ["encrypt", "decrypt"]
用于 AES-GCM? AES-GCM 用于加密/解密 消息:AES describes a block cipher (allowing the encryption of a single block) and GCM the mode of operation(允许加密 更多 比一个块)。 GCM 提供机密性、真实性和完整性。
为什么 ["sign", "verify"]
用于 HMAC-SHA? HMAC 用于 签名/验证 消息:某些操作模式,例如 CBC only provide confidentiality. To additionally supply authenticity and integrity, the message can be signed with a MAC (e.g. an HMAC which is a specific type of MAC based on a cryptographic hash function e.g. one of the SHA family). The MAC is typically calculated from the ciphertext and not the plaintext (Encrypt-then-MAC). With regard to the SHA1 vulnerabilities, see for a comparison of HMAC-SHA1 and HMAC-SHA256 here and here.