Webcrypto PBKDF2-SHA1 - PullRequest
       89

Webcrypto PBKDF2-SHA1

1 голос
/ 09 мая 2020

У меня проблема с использованием 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 fantasti c, под derivedKeyAlgorithm HMA C поддерживается также как HMA C -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 Ответ

0 голосов
/ 09 мая 2020

В 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 создает подпись с использованием HMA C -SHA1.

Обновление:

Поскольку в SubtleCrypto обычно указывается использование ключа, необходимо применять ["encrypt", "decrypt"] как параметр keyUsages для AES-GCM и ["sign", "verify"] для HMA C -SHA.

Почему ["encrypt", "decrypt"] для AES-GCM? AES-GCM используется для шифрования / дешифрования сообщений: AES описывает блочный шифр (позволяет шифрование одиночного блок) и GCM режим работы (позволяющий зашифровать больше , чем один блок). GCM обеспечивает конфиденциальность, подлинность и целостность.

А почему ["sign", "verify"] для HMA C -SHA? HMA C используется для подписи / проверки сообщений: некоторые режимы работы, такие как CB C, обеспечивают только конфиденциальность. Чтобы дополнительно подтвердил подлинность и целостность, сообщение может быть подписано MA C (например, HMA C, которое является спецификацией c тип MA C на основе криптографа c ha sh функции например, один из семейства SHA). MA C обычно вычисляется из зашифрованного текста, а не из открытого текста ( Encrypt-then-MA C). Что касается уязвимостей SHA1, см. Сравнение HMA C -SHA1 и HMA C -SHA256 здесь и здесь .

...