Использование WebCrypto для генерации ключа ECDH из PBKDF2 - PullRequest
0 голосов
/ 30 ноября 2018

ПРЕДУПРЕЖДЕНИЕ Следующее не предназначено для подтверждения преобразования паролей в ключи ECDH.Создание ключей ECDH из высокоэнтропийных, крипто-безопасных PRNG.

Я хочу взять секрет и сгенерировать из него открытый / закрытый ключ ECDH.

В браузереобычным способом было бы использовать PBKDF2 (или другие детерминированные байты) для генерации пары открытого / закрытого ключа ECDH в WebCrypto.

Следующий пример кода должен сделать это, но он генерирует исключение DOM в Chrome:

// Generate a random KDF key.
const priv = new Uint8Array(24)
crypto.getRandomValues(priv)
const kdfKey = await crypto.subtle.importKey(
  'raw', priv, { name: 'PBKDF2' }, false, ['deriveKey'])

// Derive the ECDH key.
const salt = new Uint8Array(16)
const iterations = 2000
const hash = { name: 'SHA-512' }
const curve = { name: 'ECDH', namedCurve: 'P-384' }
const usages = ['deriveKey']

crypto.getRandomValues(salt)

const ecdhKey = await crypto.subtle.deriveKey({
  name: 'PBKDF2', salt, iterations, hash
}, kdfKey, curve, true, usages) // throws.

Выше работает, когда алгоритм AES-GCM (то есть, когда кривая заменяется, например, { name: 'AES-GCM', length: 256 }), но другие алгоритмы также выдают исключения, поэтому я подозреваю, что я что-то упустил ... тонкий.

Я надеялся, что WebCrypto будет подходить для приема случайных битов и генерации пары открытого / секретного ключей ECDH.Похоже, что это может быть не так.

Альтернативой может быть использование PBKDF2 - deriveBits, которое можно использовать для создания пары ключей ECDH вручную.Если это действительно единственный вариант, каков обычный алгоритм для преобразования случайных битов в открытый / закрытый ключ (т. Е. Ссылки и открытые реализации)?Если мне нужно что-то разработать, я, скорее всего, опубликую это здесь: интерес и обзор.

РЕДАКТИРОВАТЬ: Дополнительные подробности сценария использования

Использование PBKDF является попыткой избежать необходимостигенерировать открытый ключ (x и y) пары ключей ECDH, если задан (приватный) параметр d.x и y являются производными и поэтому не требуют хранения, и у нас очень ограниченное хранилище данных - подходит только для закрытого ключа, например, 192 бита, более или менее (PBKDF может сгладить размер битатоже, но это в стороне).

Если WebCrypto вычислил x и y при заданном (псевдо) случайном d параметре, желаемый результат может быть достигнут /проиллюстрировано следующим образом:

>>> curve = { name: 'ECDH', namedCurve: 'P-256' }
>>> k = await crypto.subtle.generateKey(curve, true, ['deriveKey'])
>>> pri = await crypto.subtle.exportKey('jwk', k.privateKey)
>>> delete pri.x
>>> delete pri.y
>>> k2 = await crypto.subtle.importKey('jwk', pri)
    ^^ errors

PBKDF используется для генерации (AES) ключей в многочисленных примерах.Я надеялся, что функциональность для вычисления x и y для эллиптических кривых, уже существующая в WebCrypto, будет доступна через PBKDF2 deriveKey.

Альтернатива "сделай сам" в Javascript - эторазберите JWK / Base64 (вариант URL), затем используйте функцию большого целого с арифметикой по модулю (например, Маленькая теорема Ферма) и, наконец, напишите функции для сложения точек эллиптической кривой, удвоения и умножения.Что я и сделал ( ECC математика здесь ).Но я надеялся, что все это будет излишним, поскольку в WebCrypto существует код для выполнения именно этого, и я просто надеялся использовать либо importKey, либо deriveKey, чтобы использовать его.

Просто дляповторить: нет пользовательских паролей;использование такого ключа для генерации ключа ECDH считается неразумным.

Ответы [ 3 ]

0 голосов
/ 03 декабря 2018

Брайан,

Невозможно детерминистически создать пару ключей из пароля, используя WebCrypto.

Извините.

Вы можете определенно создать пару ключей из пароляв Javascript, а затем импортировать эту пару ключей, пока ее ключ secp256r1 в правильном представлении.

Существует несколько библиотек javascript, которые поддерживают детерминированное создание пары ключей из пароля.Я не могу сделать какие-либо заявления о правильности или безопасности этих библиотек или если есть такие, которые делают это для secp256r1.Конечно, генерация ключей является одним из наиболее важных аспектов, которые следует учитывать при использовании криптографии, и делать это на основе слабого источника энтропии плохо.

Если вы решите пойти дальше с этим подходом, несмотря на то, что импорт ключа заданного типа довольно прост, см .: https://github.com/diafygi/webcrypto-examples#ecdsa---importkey

TL; DR ваши мили будут варьироваться в зависимости от этого подхода, ноэто возможно.

Райан

0 голосов
/ 03 декабря 2018

Из обновления мы до сих пор не можем сказать, каков вариант использования, мы можем сказать (я думаю), что ваша цель - сэкономить место на диске по какой-то причине.Ключи ECC довольно малы, трудно представить, какой будет сценарий использования, особенно в веб-приложении, где такой маленький объем памяти потребует использования более слабого подхода.Тем не менее, предыдущий ответ остается прежним, невозможно напрямую делать то, что вы хотите, с помощью webcrypto.

0 голосов
/ 30 ноября 2018

"тонкий".Хорошо!

SubtleCrypto.generateKey ()

Прочитав инструкции по генерации ключа для SubtleCrypto по ссылке выше, я вставил это в консоль браузера на Chrome иработал нормально.Возможно, вам придется адаптировать его под вашу ситуацию, особенно в части, касающейся ключевых слов:

(async function() {
    const algo = {
        "name": "RSASSA-PKCS1-v1_5",
        "modulusLength": 256,
        "publicExponent": new Uint8Array([0x01, 0x00, 0x01]),
        "hash": {
            "name": "SHA-256"
        }
    };
    const extractable = true;
    const keyUsages = ["sign","verify"];
    const result = await crypto.subtle.generateKey(algo, extractable, keyUsages);
    console.log(result);
})();
...