Spec-Zone.ru › Web APIs

SubtleCrypto: метод importKey()

Базовый Широко распространённый *

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

* Некоторые части этой функции могут иметь различный уровень поддержки.

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

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

Примечание: Эта функция доступна в Потоках веб-работы.

Метод importKey() интерфейса SubtleCrypto импортирует ключ: то есть, он принимает на вход ключ во внешнем, переносимом формате и возвращает объект CryptoKey, который можно использовать в API шифрования веб-браузера.

Функция поддерживает несколько форматов импорта; подробности см. в разделе Поддерживаемые форматы.

Синтаксис

importKey(format, keyData, algorithm, extractable, keyUsages)

Параметры

format

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

  • raw: формат Необработанный.
  • pkcs8: формат PKCS #8.
  • spki: формат SubjectPublicKeyInfo.
  • jwk: формат JSON Web Key.
keyData

ArrayBuffer, массив TypedArray, DataView или объект JSONWebKey, содержащий ключ в указанном формате.

algorithm

Объект, определяющий тип импортируемого ключа и предоставляющий дополнительные параметры, специфичные для алгоритма.

  • Для RSASSA-PKCS1-v1_5, RSA-PSS или RSA-OAEP: передайте объект RsaHashedImportParams.
  • Для ECDSA или ECDH: передайте объект EcKeyImportParams.
  • Для HMAC: передайте объект HmacImportParams.
  • Для AES-CTR, AES-CBC, AES-GCM и AES-KW: передайте строку, идентифицирующую алгоритм, или объект вида { name: ALGORITHM }, где ALGORITHM — имя алгоритма.
  • Для PBKDF2: передайте строку PBKDF2 или объект вида { name: "PBKDF2" }.
  • Для HKDF: передайте строку HKDF или объект вида { name: "HKDF" }.
  • Для Ed25519: передайте строку Ed25519 или объект вида { name: "Ed25519" }.
  • Для X25519: передайте строку X25519 или объект вида { name: "X25519" }.
extractable

Логическое значение, указывающее, будет ли возможно экспортировать ключ с помощью SubtleCrypto.exportKey() или SubtleCrypto.wrapKey().

keyUsages

Array, указывающий, что можно делать с ключом. Возможные значения массива:

  • encrypt: ключ может использоваться для шифрования сообщений.
  • decrypt: ключ может использоваться для дешифрования сообщений.
  • sign: ключ может использоваться для подписи сообщений.
  • verify: ключ может использоваться для проверки подписей.
  • deriveKey: ключ может использоваться для вывода нового ключа.
  • deriveBits: ключ может использоваться для вывода бит.
  • wrapKey: ключ может использоваться для заворачивания ключа.
  • unwrapKey: ключ может использоваться для разворачивания ключа.

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

Promise, который выполняется с импортированным ключом как объектом CryptoKey.

Исключения

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

SyntaxError DOMException

Возникает, когда keyUsages пуст, но раскодированный ключ имеет тип secret или private.

TypeError

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

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

Этот API поддерживает четыре разных формата импорта/экспорта ключей: Необработанный, PKCS #8, SubjectPublicKeyInfo и JSON Web Key.

Необработанный

Этот формат можно использовать для импорта или экспорта секретных ключей AES или HMAC, а также открытых ключей кривых Эллиптических кривых.

В этом формате ключ предоставляется в виде ArrayBuffer, содержащего сырые байты ключа.

PKCS #8

Этот формат можно использовать для импорта или экспорта закрытых ключей RSA или Эллиптических кривых.

Формат PKCS #8 определен в RFC 5208 с использованием ASN.1 обозначения:

PrivateKeyInfo ::= SEQUENCE {
    version                   Version,
    privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
    privateKey                PrivateKey,
    attributes           [0]  IMPLICIT Attributes OPTIONAL }

Метод importKey() ожидает получения этого объекта в виде ArrayBuffer, содержащего DER-кодированный вид PrivateKeyInfo. DER — это набор правил для кодирования структур ASN.1 в двоичный вид.

Вероятнее всего, вы встретите этот объект в формате PEM. Формат PEM — это способ кодирования двоичных данных в ASCII. Он состоит из заголовка и футера, а между ними — base64-кодированные двоичные данные. PEM-кодированный PrivateKeyInfo выглядит так:

-----BEGIN PRIVATE KEY-----
MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAU9BD0jxDfF5OV380z
9VIEUN2W5kJDZ3hbuaDenCxLiAMsoquKTfFaou71eLdN0TShZANiAARMUhCee/cp
xmjGc1roj0D0k6VlUqtA+JVCWigXcIAukOeTHCngZDKCrD4PkXDBvbciJdZKvO+l
ml2FIkoovZh/8yeTKmjUMb804g6OmjUc9vVojCRV0YdaSmYkkJMJbLg=
-----END PRIVATE KEY-----

Чтобы преобразовать его в формат, который может принять importKey(), вам необходимо выполнить два действия:

  • декодировать base64 часть между заголовком и футером, используя Window.atob().
  • преобразовать полученную строку в ArrayBuffer.

См. раздел Примеры для получения более конкретных указаний.

SubjectPublicKeyInfo

Этот формат можно использовать для импорта или экспорта открытых ключей RSA или Эллиптических кривых.

SubjectPublicKey определен в RFC 5280, раздел 4.1 с использованием ASN.1 обозначения:

SubjectPublicKeyInfo  ::=  SEQUENCE  {
    algorithm            AlgorithmIdentifier,
    subjectPublicKey     BIT STRING  }

Как и в случае с PKCS #8, метод importKey() ожидает получения этого объекта в виде ArrayBuffer, содержащего DER-кодированный вид SubjectPublicKeyInfo.

Опять же, вы, скорее всего, встретите этот объект в формате PEM. PEM-кодированный SubjectPublicKeyInfo выглядит так:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3j+HgSHUnc7F6XzvEbD0
r3M5JNy+/kabiJVu8IU1ERAl3Osi38VgiMzjDBDOrFxVzNNzl+SXAHwXIV5BHiXL
CQ6qhwYsDgH6OqgKIwiALra/wNH4UHxj1Or/iyAkjHRR/kGhUtjyVCjzvaQaDpJW
2G+syd1ui0B6kJov2CRUWiPwpff8hBfVWv8q9Yc2yD5hCnykVL0iAiyn+SDAk/rv
8dC5eIlzCI4efUCbyG4c9O88Qz7bS14DxSfaPTy8P/TWoihVVjLaDF743LgM/JLq
CDPUBUA3HLsZUhKm3BbSkd7Q9Ngkjv3+yByo4/fL+fkYRa8j9Ypa2N0Iw53LFb3B
gQIDAQAB
-----END PUBLIC KEY-----

Точно так же, как и с PKCS #8, для преобразования этого в формат, который может принять importKey(), необходимо сделать следующее:

  • декодировать base64 часть между заголовком и футером, используя Window.atob().
  • преобразовать полученную строку в ArrayBuffer.

См. раздел Примеры для получения более конкретных указаний.

JSON Web Key

Формат JSON Web Key можно использовать для импорта или экспорта открытых или закрытых ключей RSA или Эллиптических кривых, а также секретных ключей AES и HMAC.

Формат JSON Web Key определен в RFC 7517. Он описывает способ представления открытых, закрытых и секретных ключей в виде JSON-объектов.

JSON Web Key может выглядеть примерно так (это закрытый ключ EC):

{
  "crv": "P-384",
  "d": "wouCtU7Nw4E8_7n5C1-xBjB4xqSb_liZhYMsy8MGgxUny6Q8NCoH9xSiviwLFfK_",
  "ext": true,
  "key_ops": ["sign"],
  "kty": "EC",
  "x": "SzrRXmyI8VWFJg1dPUNbFcc9jZvjZEfH7ulKI1UkXAltd7RGWrcfFxqyGPcwu6AQ",
  "y": "hHUag3OvDzEr0uUQND4PXHQTXP5IDGdYhJhL-WLKjnGjQAw0rNGy5V29-aV-yseW"
};

Примеры

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

Прямой импорт

В этом примере импортируется ключ AES из ArrayBuffer, содержащего сырые байты для использования. Полный код см. на GitHub.

const rawKey = window.crypto.getRandomValues(new Uint8Array(16));

/*
Import an AES secret key from an ArrayBuffer containing the raw bytes.
Takes an ArrayBuffer string containing the bytes, and returns a Promise
that will resolve to a CryptoKey representing the secret key.
*/
function importSecretKey(rawKey) {
  return window.crypto.subtle.importKey("raw", rawKey, "AES-GCM", true, [
    "encrypt",
    "decrypt",
  ]);
}

Импорт PKCS #8

В этом примере импортируется закрытый ключ подписи RSA из закодированного PEM объекта PKCS #8. Полный код см. на GitHub.

/*
Convert a string into an ArrayBuffer
from https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
*/
function str2ab(str) {
  const buf = new ArrayBuffer(str.length);
  const bufView = new Uint8Array(buf);
  for (let i = 0, strLen = str.length; i < strLen; i++) {
    bufView[i] = str.charCodeAt(i);
  }
  return buf;
}

const pemEncodedKey = `-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDD0tPV/du2vftjvXj1t/gXTK39sNBVrOAEb/jKzXae+Xa0H+3LhZaQIQNMfACiBSgIfZUvEGb+7TqXWQpoLoFR/R7MvGWcSk98JyrVtveD8ZmZYyItSY7m2hcasqAFiKyOouV5vzyRe87/lEyzzBpF3bQQ4IDaQu+K9Hj5fKuU6rrOeOhsdnJc+VdDQLScHxvMoLZ9Vtt+oK9J4/tOLwr4CG8khDlBURcBY6gPcLo3dPU09SW+6ctX2cX4mkXx6O/0mmdTmacr/vu50KdRMleFeZYOWPAEhhMfywybTuzBiPVIZVP8WFCSKNMbfi1S9A9PdBqnebwwHhX3/hsEBt2BAgMBAAECggEABEI1P6nf6Zs7mJlyBDv+Pfl5rjL2cOqLy6TovvZVblMkCPpJyFuNIPDK2tK2i897ZaXfhPDBIKmllM2Hq6jZQKB110OAnTPDg0JxzMiIHPs32S1d/KilHjGff4Hjd4NXp1l1Dp8BUPOllorR2TYm2x6dcCGFw9lhTr8O03Qp4hjn84VjGIWADYCk83mgS4nRsnHkdiqYnWx1AjKlY51yEK6RcrDMi0Th2RXrrINoC35sVv+APt2rkoMGi52RwTEseA1KZGFrxjq61ReJif6p2VXEcvHeX6CWLx014LGk43z6Q28P6HgeEVEfIjyqCUea5Du/mYb/QsRSCosXLxBqwQKBgQD1+fdC9ZiMrVI+km7Nx2CKBn8rJrDmUh5SbXn2MYJdrUd8bYNnZkCgKMgxVXsvJrbmVOrby2txOiqudZkk5mD3E5O/QZWPWQLgRu8ueYNpobAX9NRgNfZ7rZD+81vh5MfZiXfuZOuzv29iZhU0oqyZ9y75eHkLdrerNkwYOe5aUQKBgQDLzapDi1NxkBgsj9iiO4KUa7jvD4JjRqFy4Zhj/jbQvlvM0F/uFp7sxVcHGx4r11C+6iCbhX4u+Zuu0HGjT4d+hNXmgGyxR8fIUVxOlOtDkVJa5sOBZK73/9/MBeKusdmJPRhalZQfMUJRWIoEVDMhfg3tW/rBj5RYAtP2dTVUMQKBgDs8yr52dRmT+BWXoFWwaWB0NhYHSFz/c8v4D4Ip5DJ5M5kUqquxJWksySGQa40sbqnD05fBQovPLU48hfgr/zghn9hUjBcsoZOvoZR4sRw0UztBvA+7jzOz1hKAOyWIulR6Vca0yUrNlJ6G5R56+sRNkiOETupi2dLCzcqb0PoxAoGAZyNHvTLvIZN4iGSrjz5qkM4LIwBIThFadxbv1fq6pt0O/BGf2o+cEdq0diYlGK64cEVwBwSBnSg4vzlBqRIAUejLjwEDAJyA4EE8Y5A9l04dzV7nJb5cRak6CrgXxay/mBJRFtaHxVlaZGxYPGSYE6UFS0+3EOmmevvDZQBf4qECgYEA0ZF6Vavz28+8wLO6SP3w8NmpHk7K9tGEvUfQ30SgDx4G7qPIgfPrbB4OP/E0qCfsIImi3sCPpjvUMQdVVZyPOIMuB+rV3ZOxkrzxEUOrpOpR48FZbL7RN90yRQsAsrp9e4iv8QwB3VxLe7X0TDqqnRyqrc/osGzuS2ZcHOKmCU8=
-----END PRIVATE KEY-----`;

/*
Import a PEM encoded RSA private key, to use for RSA-PSS signing.
Takes a string containing the PEM encoded key, and returns a Promise
that will resolve to a CryptoKey representing the private key.
*/
function importPrivateKey(pem) {
  // fetch the part of the PEM string between header and footer
  const pemHeader = "-----BEGIN PRIVATE KEY-----";
  const pemFooter = "-----END PRIVATE KEY-----";
  const pemContents = pem.substring(
    pemHeader.length,
    pem.length - pemFooter.length - 1,
  );
  // base64 decode the string to get the binary data
  const binaryDerString = window.atob(pemContents);
  // convert from a binary string to an ArrayBuffer
  const binaryDer = str2ab(binaryDerString);

  return window.crypto.subtle.importKey(
    "pkcs8",
    binaryDer,
    {
      name: "RSA-PSS",
      hash: "SHA-256",
    },
    true,
    ["sign"],
  );
}

Импорт SubjectPublicKeyInfo

В этом примере импортируется открытый ключ шифрования RSA из закодированного PEM объекта SubjectPublicKeyInfo. Полный код см. на GitHub.

// from https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
function str2ab(str) {
  const buf = new ArrayBuffer(str.length);
  const bufView = new Uint8Array(buf);
  for (let i = 0, strLen = str.length; i < strLen; i++) {
    bufView[i] = str.charCodeAt(i);
  }
  return buf;
}

const pemEncodedKey = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy3Xo3U13dc+xojwQYWoJLCbOQ5fOVY8LlnqcJm1W1BFtxIhOAJWohiHuIRMctv7dzx47TLlmARSKvTRjd0dF92jx/xY20Lz+DXp8YL5yUWAFgA3XkO3LSJgEOex10NB8jfkmgSb7QIudTVvbbUDfd5fwIBmCtaCwWx7NyeWWDb7A9cFxj7EjRdrDaK3ux/ToMLHFXVLqSL341TkCf4ZQoz96RFPUGPPLOfvN0x66CM1PQCkdhzjE6U5XGE964ZkkYUPPsy6Dcie4obhW4vDjgUmLzv0z7UD010RLIneUgDE2FqBfY/C+uWigNPBPkkQ+Bv/UigS6dHqTCVeD5wgyBQIDAQAB
-----END PUBLIC KEY-----`;

function importRsaKey(pem) {
  // fetch the part of the PEM string between header and footer
  const pemHeader = "-----BEGIN PUBLIC KEY-----";
  const pemFooter = "-----END PUBLIC KEY-----";
  const pemContents = pem.substring(
    pemHeader.length,
    pem.length - pemFooter.length - 1,
  );
  // base64 decode the string to get the binary data
  const binaryDerString = window.atob(pemContents);
  // convert from a binary string to an ArrayBuffer
  const binaryDer = str2ab(binaryDerString);

  return window.crypto.subtle.importKey(
    "spki",
    binaryDer,
    {
      name: "RSA-OAEP",
      hash: "SHA-256",
    },
    true,
    ["encrypt"],
  );
}

Импорт JSON Web Key

Этот код импортирует закрытый ключ подписи ECDSA, используя объект JSON Web Key, представляющий его. Полный код см. на GitHub.

const jwkEcKey = {
  crv: "P-384",
  d: "wouCtU7Nw4E8_7n5C1-xBjB4xqSb_liZhYMsy8MGgxUny6Q8NCoH9xSiviwLFfK_",
  ext: true,
  key_ops: ["sign"],
  kty: "EC",
  x: "SzrRXmyI8VWFJg1dPUNbFcc9jZvjZEfH7ulKI1UkXAltd7RGWrcfFxqyGPcwu6AQ",
  y: "hHUag3OvDzEr0uUQND4PXHQTXP5IDGdYhJhL-WLKjnGjQAw0rNGy5V29-aV-yseW",
};

/*
Import a JSON Web Key format EC private key, to use for ECDSA signing.
Takes an object representing the JSON Web Key, and returns a Promise
that will resolve to a CryptoKey representing the private key.
*/
function importPrivateKey(jwk) {
  return window.crypto.subtle.importKey(
    "jwk",
    jwk,
    {
      name: "ECDSA",
      namedCurve: "P-384",
    },
    true,
    ["sign"],
  );
}

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

Спецификация
API криптографии веб-браузера
# SubtleCrypto-метод-importKey

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

Рабочие столы Мобильные устройства
Chrome Edge Firefox Opera Safari Chrome Android Firefox для Android Opera Android Safari на iOS Samsung Internet WebView Android
importKey 37 79
12–79["Не поддерживается: RSA-PSS, ECDSA, ECDH.", "Не поддерживается: AES-CTR, HKDF, PBKDF2."]
34 24 7 37 34 24 7 3.0 37
ed25519 113 113 129 99 17 113 129 Нет 17 Нет Нет
x25519 133 133 130 Нет 17 133 130 Нет 17 Нет 133

См. также

  • SubtleCrypto.exportKey()
  • Формат PKCS #8.
  • Формат SubjectPublicKeyInfo.
  • Формат JSON Web Key.

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

Spec-Zone.ru

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