SubtleCrypto: метод deriveBits()
Базовая реализация Широко доступна *
Эта функция хорошо отработана и работает на многих устройствах и версиях браузеров. Она доступна в браузерах с июля 2015 года.
* Некоторые части этой функции могут иметь разный уровень поддержки.
Безопасный контекст: Эта функция доступна только в безопасных контекстах (HTTPS), в некоторых или во всех поддерживающих браузерах.
Примечание: Эта функция доступна в Web Workers.
Метод deriveBits() интерфейса SubtleCrypto может использоваться для получения массива битов из базового ключа.
Он принимает в качестве аргументов базовый ключ, алгоритм вывода и длину выводимых битов. Он возвращает Promise, который будет выполнен с ArrayBuffer, содержащим выведенные биты.
Этот метод очень похож на SubtleCrypto.deriveKey(), за исключением того, что deriveKey() возвращает объект CryptoKey, а не ArrayBuffer. По сути, deriveKey() состоит из deriveBits() и importKey().
Эта функция поддерживает те же алгоритмы вывода, что и deriveKey(): ECDH, HKDF, PBKDF2 и X25519. См. Поддерживаемые алгоритмы для более подробной информации об этих алгоритмах.
Синтаксис
deriveBits(algorithm, baseKey, length)
Параметры
algorithm-
Объект, определяющий алгоритм вывода для использования.
- Для использования ECDH передайте объект
EcdhKeyDeriveParams, указав строкуECDHв качестве свойстваname. - Для использования HKDF передайте объект
HkdfParams. - Для использования PBKDF2 передайте объект
Pbkdf2Params. - Для использования X25519 передайте объект
EcdhKeyDeriveParams, указав строкуX25519в качестве свойстваname.
- Для использования ECDH передайте объект
baseKey-
CryptoKey, представляющий входные данные для алгоритма вывода. Еслиalgorithm— ECDH, это будет закрытый ключ ECDH. В противном случае это будет исходный материал ключа для функции вывода: например, для PBKDF2 это может быть пароль, импортированный какCryptoKeyс помощьюSubtleCrypto.importKey(). length-
Число, представляющее количество выводимых битов. Для совместимости со всеми браузерами число должно быть кратно 8.
Возвращаемое значение
Promise, который выполняется с ArrayBuffer, содержащим выведенные биты.
Исключения
Обещание отклоняется, когда возникает одно из следующих исключений:
-
OperationErrorDOMException -
Возникает, если параметр length вызова
deriveBits()равен null, а также в некоторых случаях, если параметр length не кратен 8. -
InvalidAccessErrorDOMException -
Возникает, когда базовый ключ не является ключом для запрошенного алгоритма вывода или если значение
CryptoKey.usagesэтого ключа не содержитderiveBits. -
NotSupportedDOMException -
Возникает при попытке использовать алгоритм, который либо неизвестен, либо не подходит для вывода.
Поддерживаемые алгоритмы
Примеры
Примечание: Вы можете попробовать рабочие примеры на GitHub.
ECDH
В этом примере Алиса и Боб генерируют каждую пару ключей ECDH.
Затем мы используем закрытый ключ Алисы и открытый ключ Боба для вывода общего секрета. Полный код см. на GitHub.
async function deriveSharedSecret(privateKey, publicKey) {
const sharedSecret = await window.crypto.subtle.deriveBits(
{
name: "ECDH",
namedCurve: "P-384",
public: publicKey,
},
privateKey,
128,
);
const buffer = new Uint8Array(sharedSecret, 0, 5);
const sharedSecretValue = document.querySelector(".ecdh .derived-bits-value");
sharedSecretValue.classList.add("fade-in");
sharedSecretValue.addEventListener("animationend", () => {
sharedSecretValue.classList.remove("fade-in");
});
sharedSecretValue.textContent = `${buffer}…[${sharedSecret.byteLength} bytes total]`;
}
// Generate 2 ECDH key pairs: one for Alice and one for Bob
// In more normal usage, they would generate their key pairs
// separately and exchange public keys securely
const generateAliceKeyPair = window.crypto.subtle.generateKey(
{
name: "ECDH",
namedCurve: "P-384",
},
false,
["deriveBits"],
);
const generateBobKeyPair = window.crypto.subtle.generateKey(
{
name: "ECDH",
namedCurve: "P-384",
},
false,
["deriveBits"],
);
Promise.all([generateAliceKeyPair, generateBobKeyPair]).then((values) => {
const aliceKeyPair = values[0];
const bobKeyPair = values[1];
const deriveBitsButton = document.querySelector(".ecdh .derive-bits-button");
deriveBitsButton.addEventListener("click", () => {
// Alice then generates a secret using her private key and Bob's public key.
// Bob could generate the same secret using his private key and Alice's public key.
deriveSharedSecret(aliceKeyPair.privateKey, bobKeyPair.publicKey);
});
});
X25519
В этом примере Алиса и Боб генерируют каждую пару ключей X25519. Затем мы используем закрытый ключ Алисы и открытый ключ Боба для вывода секрета и сравниваем его с секретом, выведенным с использованием закрытого ключа Боба и открытого ключа Алисы, чтобы показать, что они общие/тождественные.
HTML
HTML определяет две кнопки. Кнопка «Изменить ключи» нажимается для генерации новых пар ключей для Алисы и Боба. Кнопка «Вывести биты» нажимается для вывода общего секрета с текущим набором пар ключей.
<input id="buttonDeriveKeys" type="button" value="Derive bits" /> <input id="buttonChangeKeys" type="button" value="Change keys" />
JavaScript
Функция для генерации общего секрета с использованием алгоритма X25519 показана ниже. Она принимает закрытый ключ одной стороны и открытый ключ другой.
async function deriveSharedSecret(privateKey, publicKey) {
return await window.crypto.subtle.deriveBits(
{
name: "X25519",
public: publicKey,
},
privateKey,
128,
);
}
Код ниже добавляет функцию для генерации новых ключей для Алисы и Боба. Это делается в первый раз при загрузке JavaScript и повторяется всякий раз, когда нажимается кнопка «Изменить ключи» (это позволяет увидеть эффект изменения ключей на общем секрете).
let aliceKeyPair;
let bobKeyPair;
async function changeKeys() {
try {
aliceKeyPair = await window.crypto.subtle.generateKey(
{
name: "X25519",
},
false,
["deriveBits"],
);
bobKeyPair = await window.crypto.subtle.generateKey(
{
name: "X25519",
},
false,
["deriveBits"],
);
log("Keys changed");
} catch (e) {
log(e);
}
}
changeKeys();
const changeKeysButton = document.querySelector("#buttonChangeKeys");
// Generate 2 X25519 key pairs: one for Alice and one for Bob
// In more normal usage, they would generate their key pairs
// separately and exchange public keys securely
changeKeysButton.addEventListener("click", changeKeys);
Код ниже добавляет функцию-обработчик, которая вызывается каждый раз при нажатии кнопки «Вывести биты». Обработчик генерирует общие секреты для Алисы и Боба с использованием метода deriveSharedSecret() , определённого выше, и регистрирует их для простоты сравнения.
const deriveBitsButton = document.querySelector("#buttonDeriveKeys");
deriveBitsButton.addEventListener("click", async () => {
// Generate 2 X25519 key pairs: one for Alice and one for Bob
// In more normal usage, they would generate their key pairs
// separately and exchange public keys securely
// Alice then generates a secret using her private key and Bob's public key.
// Bob could generate the same secret using his private key and Alice's public key.
const sharedSecretAlice = await deriveSharedSecret(
aliceKeyPair.privateKey,
bobKeyPair.publicKey,
);
let buffer = new Uint8Array(sharedSecretAlice, 0, 10);
log(`${buffer}…[${sharedSecretAlice.byteLength} bytes total] (Alice secret)`);
const sharedSecretBob = await deriveSharedSecret(
bobKeyPair.privateKey,
aliceKeyPair.publicKey,
);
buffer = new Uint8Array(sharedSecretBob, 0, 10);
log(`${buffer}…[${sharedSecretAlice.byteLength} bytes total] (Bob secret)`);
});
Результат
Нажмите кнопку «Вывести биты», чтобы сгенерировать и вывести общий секрет от Боба и ключей Алисы. Нажмите кнопку «Изменить ключи», чтобы изменить ключи X25519, используемые обеими сторонами.
PBKDF2
В этом примере мы запрашиваем у пользователя пароль, затем используем его для вывода некоторых битов с помощью PBKDF2. Полный код см. на GitHub.
let salt;
/*
Get some key material to use as input to the deriveBits method.
The key material is a password supplied by the user.
*/
function getKeyMaterial() {
const password = window.prompt("Enter your password");
const enc = new TextEncoder();
return window.crypto.subtle.importKey(
"raw",
enc.encode(password),
{ name: "PBKDF2" },
false,
["deriveBits", "deriveKey"],
);
}
/*
Derive some bits from a password supplied by the user.
*/
async function getDerivedBits() {
const keyMaterial = await getKeyMaterial();
salt = window.crypto.getRandomValues(new Uint8Array(16));
const derivedBits = await window.crypto.subtle.deriveBits(
{
name: "PBKDF2",
salt,
iterations: 100000,
hash: "SHA-256",
},
keyMaterial,
256,
);
const buffer = new Uint8Array(derivedBits, 0, 5);
const derivedBitsValue = document.querySelector(
".pbkdf2 .derived-bits-value",
);
derivedBitsValue.classList.add("fade-in");
derivedBitsValue.addEventListener("animationend", () => {
derivedBitsValue.classList.remove("fade-in");
});
derivedBitsValue.textContent = `${buffer}…[${derivedBits.byteLength} bytes total]`;
}
const deriveBitsButton = document.querySelector(".pbkdf2 .derive-bits-button");
deriveBitsButton.addEventListener("click", () => {
getDerivedBits();
});
Спецификации
Совместимость с браузерами
| Рабочие столы | Мобильные устройства | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox для Android | Opera Android | Safari в iOS | Samsung Internet | WebView Android | |
deriveBits |
41 | 7912–79["Не поддерживается: ECDH.", "Не поддерживаются: HKDF, PBKDF2."] |
34 | 28 | 11 | 41 | 34 | 28 | 11 | 4.0 | 41 |
x25519 |
133 | 133 | 130 | Нет | 17 | 133 | 130 | Нет | 17 | Нет | 133 |
См. также
© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/deriveBits