Spec-Zone.ru › Web APIs

SubtleCrypto: метод wrapKey()

Базовая Широко доступная

Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна в браузерах с июля 2015 года.

  • Подробнее
  • Полная совместимость
  • Отправить отзыв

Безопасный контекст: Эта функция доступна только в безопасных контекстах (HTTPS), в некоторых или всех поддерживающих браузерах.

Примечание: Эта функция доступна в Web Workers.

Метод wrapKey() интерфейса SubtleCrypto "обертывает" ключ. Это означает, что он экспортирует ключ в внешний, переносимый формат, а затем шифрует экспортированный ключ. Обертывание ключа помогает защитить его в ненадежных средах, таких как внутри иначе незащищённого хранилища данных или при передаче по незащищенной сети.

Как и в случае с SubtleCrypto.exportKey(), вы указываете формат экспорта ключа для ключа. Для экспорта ключа он должен иметь значение CryptoKey.extractable true.

Но поскольку wrapKey() также шифрует экспортируемый ключ, вам также необходимо указать ключ, который должен быть использован для его шифрования. Это иногда называется "ключом обертывания".

Обратной операцией к wrapKey() является SubtleCrypto.unwrapKey(): в то время как wrapKey состоит из экспорта + шифрования, unwrapKey состоит из импорта + дешифрования.

Синтаксис

wrapKey(format, key, wrappingKey, wrapAlgo)

Параметры

format

Строка, описывающая формат данных, в котором ключ будет экспортирован перед шифрованием. Она может быть одной из следующих:

raw

Формат "сырой".

pkcs8

Формат PKCS #8.

spki

Формат SubjectPublicKeyInfo.

jwk

Формат JSON Web Key.

key

Ключ CryptoKey для обертывания.

wrappingkey

Ключ CryptoKey, используемый для шифрования экспортированного ключа. Ключ должен иметь установленное использование wrapKey.

wrapAlgo

Объект, определяющий алгоритм для шифрования экспортированного ключа и любые необходимые дополнительные параметры:

  • Для использования RSA-OAEP, передайте объект RsaOaepParams.
  • Для использования AES-CTR, передайте объект AesCtrParams.
  • Для использования AES-CBC, передайте объект AesCbcParams.
  • Для использования AES-GCM, передайте объект AesGcmParams.
  • Для использования AES-KW, передайте строку "AES-KW", или объект в формате { name: "AES-KW" }.

Возвращаемое значение

Обещание Promise, которое выполняется с ArrayBuffer, содержащим зашифрованный экспортированный ключ.

Исключения

Обещание отклоняется, когда возникает одно из следующих исключений:

InvalidAccessError DOMException

Возникает, когда ключ обертывания не является ключом для запрошенного алгоритма обертывания.

NotSupported DOMException

Возникает при попытке использовать алгоритм, который либо неизвестен, либо не подходит для шифрования или обертывания.

TypeError

Возникает при попытке использовать неверный формат.

Поддерживаемые алгоритмы

Все алгоритмы, применимые для шифрования, также применимы для обертывания ключей, при условии, что ключ имеет установленное использование "wrapKey". Для обертывания ключей у вас есть дополнительный вариант AES-KW.

AES-KW

AES-KW — это способ использования шифра AES для обертывания ключей.

Одно из преимуществ использования AES-KW по сравнению с другим режимом AES, таким как AES-GCM, заключается в том, что AES-KW не требует вектора инициализации. Для использования AES-KW входные данные должны быть кратны 64 битам.

AES-KW определен в RFC 3394.

Примеры

Примечание: Вы можете попробовать рабочие примеры на GitHub.

Обертывание в формате "сырой"

В этом примере обертывается ключ AES. Он использует "сырой" формат экспорта и AES-KW, с ключом, полученным из пароля, для его шифрования. Полный код см. на GitHub.

let salt;

/*
Get some key material to use as input to the deriveKey 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"],
  );
}

/*
Given some key material and some random salt
derive an AES-KW key using PBKDF2.
*/
function getKey(keyMaterial, salt) {
  return window.crypto.subtle.deriveKey(
    {
      name: "PBKDF2",
      salt,
      iterations: 100000,
      hash: "SHA-256",
    },
    keyMaterial,
    { name: "AES-KW", length: 256 },
    true,
    ["wrapKey", "unwrapKey"],
  );
}

/*
Wrap the given key.
*/
async function wrapCryptoKey(keyToWrap) {
  // get the key encryption key
  const keyMaterial = await getKeyMaterial();
  salt = window.crypto.getRandomValues(new Uint8Array(16));
  const wrappingKey = await getKey(keyMaterial, salt);

  return window.crypto.subtle.wrapKey("raw", keyToWrap, wrappingKey, "AES-KW");
}

/*
Generate an encrypt/decrypt secret key,
then wrap it.
*/
window.crypto.subtle
  .generateKey(
    {
      name: "AES-GCM",
      length: 256,
    },
    true,
    ["encrypt", "decrypt"],
  )
  .then((secretKey) => wrapCryptoKey(secretKey))
  .then((wrappedKey) => console.log(wrappedKey));

Обертывание в формате PKCS #8

В этом примере обертывается закрытый ключ подписи RSA. Он использует формат "pkcs8" и AES-GCM, с ключом, полученным из пароля, для его шифрования. Полный код см. на GitHub.

let salt;
let iv;

/*
Get some key material to use as input to the deriveKey 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"],
  );
}

/*
Given some key material and some random salt
derive an AES-GCM key using PBKDF2.
*/
function getKey(keyMaterial, salt) {
  return window.crypto.subtle.deriveKey(
    {
      name: "PBKDF2",
      salt,
      iterations: 100000,
      hash: "SHA-256",
    },
    keyMaterial,
    { name: "AES-GCM", length: 256 },
    true,
    ["wrapKey", "unwrapKey"],
  );
}

/*
Wrap the given key.
*/
async function wrapCryptoKey(keyToWrap) {
  // get the key encryption key
  const keyMaterial = await getKeyMaterial();
  salt = window.crypto.getRandomValues(new Uint8Array(16));
  const wrappingKey = await getKey(keyMaterial, salt);
  iv = window.crypto.getRandomValues(new Uint8Array(12));

  return window.crypto.subtle.wrapKey("pkcs8", keyToWrap, wrappingKey, {
    name: "AES-GCM",
    iv,
  });
}

/*
Generate a sign/verify key pair,
then wrap the private key.
*/
window.crypto.subtle
  .generateKey(
    {
      name: "RSA-PSS",
      // Consider using a 4096-bit key for systems that require long-term security
      modulusLength: 2048,
      publicExponent: new Uint8Array([1, 0, 1]),
      hash: "SHA-256",
    },
    true,
    ["sign", "verify"],
  )
  .then((keyPair) => wrapCryptoKey(keyPair.privateKey))
  .then((wrappedKey) => {
    console.log(wrappedKey);
  });

Обертывание в формате SubjectPublicKeyInfo

В этом примере обертывается открытый ключ шифрования RSA. Он использует формат "spki" и AES-CBC, с ключом, полученным из пароля, для его шифрования. Полный код см. на GitHub.

let salt;
let iv;

/*
Get some key material to use as input to the deriveKey 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"],
  );
}

/*
Given some key material and some random salt
derive an AES-CBC key using PBKDF2.
*/
function getKey(keyMaterial, salt) {
  return window.crypto.subtle.deriveKey(
    {
      name: "PBKDF2",
      salt,
      iterations: 100000,
      hash: "SHA-256",
    },
    keyMaterial,
    { name: "AES-CBC", length: 256 },
    true,
    ["wrapKey", "unwrapKey"],
  );
}

/*
Wrap the given key.
*/
async function wrapCryptoKey(keyToWrap) {
  // get the key encryption key
  const keyMaterial = await getKeyMaterial();
  salt = window.crypto.getRandomValues(new Uint8Array(16));
  const wrappingKey = await getKey(keyMaterial, salt);
  iv = window.crypto.getRandomValues(new Uint8Array(16));

  return window.crypto.subtle.wrapKey("spki", keyToWrap, wrappingKey, {
    name: "AES-CBC",
    iv,
  });
}

/*
Generate an encrypt/decrypt key pair,
then wrap it.
*/
window.crypto.subtle
  .generateKey(
    {
      name: "RSA-OAEP",
      // Consider using a 4096-bit key for systems that require long-term security
      modulusLength: 2048,
      publicExponent: new Uint8Array([1, 0, 1]),
      hash: "SHA-256",
    },
    true,
    ["encrypt", "decrypt"],
  )
  .then((keyPair) => wrapCryptoKey(keyPair.publicKey))
  .then((wrappedKey) => console.log(wrappedKey));

Обертывание в формате JSON Web Key

В этом примере обертывается закрытый ключ подписи ECDSA. Он использует формат "jwk" и AES-GCM, с ключом, полученным из пароля, для его шифрования. Полный код см. на GitHub.

let salt;
let iv;

/*
Get some key material to use as input to the deriveKey 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"],
  );
}

/*
Given some key material and some random salt
derive an AES-GCM key using PBKDF2.
*/
function getKey(keyMaterial, salt) {
  return window.crypto.subtle.deriveKey(
    {
      name: "PBKDF2",
      salt,
      iterations: 100000,
      hash: "SHA-256",
    },
    keyMaterial,
    { name: "AES-GCM", length: 256 },
    true,
    ["wrapKey", "unwrapKey"],
  );
}

/*
Wrap the given key.
*/
async function wrapCryptoKey(keyToWrap) {
  // get the key encryption key
  const keyMaterial = await getKeyMaterial();
  salt = window.crypto.getRandomValues(new Uint8Array(16));
  const wrappingKey = await getKey(keyMaterial, salt);
  iv = window.crypto.getRandomValues(new Uint8Array(12));

  return window.crypto.subtle.wrapKey("jwk", keyToWrap, wrappingKey, {
    name: "AES-GCM",
    iv,
  });
}

/*
Generate a sign/verify key pair,
then wrap the private key
*/
window.crypto.subtle
  .generateKey(
    {
      name: "ECDSA",
      namedCurve: "P-384",
    },
    true,
    ["sign", "verify"],
  )
  .then((keyPair) => wrapCryptoKey(keyPair.privateKey))
  .then((wrappedKey) => console.log(wrappedKey));

Спецификации

Спецификация
API криптографии веб
# SubtleCrypto-method-wrapKey

Совместимость браузеров

Рабочие столы Мобильные устройства
Chrome Edge Firefox Opera Safari Chrome Android Firefox для Android Opera Android Safari на iOS Samsung Internet WebView Android
wrapKey 37 79
12–79Не поддерживается: AES-CTR.
34 24 7 37 34 24 7 3.0 37

См. также

  • SubtleCrypto.exportKey()
  • Формат PKCS #8.
  • Формат SubjectPublicKeyInfo.
  • Формат JSON Web Key.
  • Спецификация AES-KW.

© 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/wrapKey

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API