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"]
);
}
Спасибо.
1 ответ
In deriveKey
, the parameter keyUsages
must be changed to ["sign", "verify"]
. Then the code works (since b64binb
, str2binb
were not posted, the following code uses appropriate substitutes):
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();
With this key, window.crypto.subtle.sign
creates a signature using HMAC-SHA1.
Update:
Since in SubtleCrypto the use of a key is generally specified, ["encrypt", "decrypt"]
must be applied as keyUsages
parameter for AES-GCM and ["sign", "verify"]
for HMAC-SHA.
Why ["encrypt", "decrypt"]
for AES-GCM? AES-GCM is used for encrypting / decrypting messages: AES describes a block cipher (allowing the encryption of a single block) and GCM the mode of operation (allowing the encryption of more than a single block). GCM provides confidentiality, authenticity and integrity.
And why ["sign", "verify"]
для HMAC-SHA? HMAC используется для подписи / проверки сообщений: некоторые режимы работы, такие как CBC, обеспечивают только конфиденциальность. Чтобы дополнительно обеспечить аутентичность и целостность, сообщение может быть подписано с помощью MAC (например, HMAC, который является конкретным типом MAC, основанным на криптографической хэш-функции, например, одной из семейства SHA). MAC обычно вычисляется из зашифрованного текста, а не из открытого текста (зашифровать, затем MAC). Что касается уязвимостей SHA1, см. Сравнение HMAC-SHA1 и HMAC-SHA256 здесь и здесь.