SubtleCrypto: wrapKey() Methode

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.

Sicherer Kontext: Diese Funktion ist nur in sicheren Kontexten (HTTPS) in einigen oder allen unterstützenden Browsern verfügbar.

Hinweis: Diese Funktion ist in Web Workers verfügbar.

Die wrapKey()-Methode des SubtleCrypto-Interfaces „umhüllt“ einen Schlüssel. Das bedeutet, dass der Schlüssel in einem externen, portablen Format exportiert und anschließend verschlüsselt wird. Das Umhüllen eines Schlüssels hilft, ihn in nicht vertrauenswürdigen Umgebungen zu schützen, wie z.B. in einem ansonsten ungeschützten Datenspeicher oder bei der Übertragung über ein ungeschütztes Netzwerk.

Wie bei SubtleCrypto.exportKey() geben Sie ein Exportformat für den Schlüssel an. Um einen Schlüssel zu exportieren, muss CryptoKey.extractable auf true gesetzt sein.

Da wrapKey() den zu exportierenden Schlüssel verschlüsselt, müssen Sie auch den Schlüssel angeben, der zur Verschlüsselung verwendet werden soll. Dieser wird manchmal als „Verpackungsschlüssel“ bezeichnet.

Das Gegenteil von wrapKey() ist SubtleCrypto.unwrapKey(): Während wrapKey aus Export + Verschlüsselung besteht, besteht unwrapKey aus Import + Entschlüsselung.

Syntax

js
wrapKey(format, key, wrappingKey, wrapAlgo)

Parameter

format

Ein Zeichenfolgewert, der das Datenformat beschreibt, in dem der Schlüssel exportiert wird, bevor er verschlüsselt wird. Es kann eines der folgenden sein:

raw

Roh Format.

pkcs8

PKCS #8 Format.

spki

SubjectPublicKeyInfo Format.

jwk

JSON Web Key Format.

key

Der zu umhüllende CryptoKey.

wrappingkey

Der CryptoKey, der zum Verschlüsseln des exportierten Schlüssels verwendet wird. Der Schlüssel muss die Verwendung wrapKey haben.

wrapAlgo

Ein Objekt, das den zu verwendenden Algorithmus zur Verschlüsselung des exportierten Schlüssels und alle erforderlichen zusätzlichen Parameter spezifiziert:

Rückgabewert

Ein Promise, das mit einem ArrayBuffer erfüllt wird, der den verschlüsselten exportierten Schlüssel enthält.

Ausnahmen

Das Promise wird abgelehnt, wenn eine der folgenden Ausnahmen auftritt:

InvalidAccessError DOMException

Wird ausgelöst, wenn der Verpackungsschlüssel nicht für den angeforderten Umhüllungsalgorithmus geeignet ist.

NotSupported DOMException

Wird ausgelöst, wenn versucht wird, einen unbekannten oder für Verschlüsselung oder Umhüllung ungeeigneten Algorithmus zu verwenden.

TypeError

Wird ausgelöst, wenn versucht wird, ein ungültiges Format zu verwenden.

Unterstützte Algorithmen

Alle Algorithmen, die für die Verschlüsselung verwendet werden können, können auch für die Schlüsselumhüllung verwendet werden, solange der Schlüssel die Verwendung "wrapKey" hat. Für die Schlüsselumhüllung haben Sie die zusätzliche Option von AES-KW.

AES-KW

AES-KW ist eine Möglichkeit, das AES-Cipher für die Schlüsselumhüllung zu verwenden.

Ein Vorteil von AES-KW gegenüber anderen AES-Modi wie AES-GCM ist, dass AES-KW keinen Initialisierungsvektor benötigt. Um AES-KW zu verwenden, muss die Eingabe ein Vielfaches von 64 Bits sein.

AES-KW ist in RFC 3394 spezifiziert.

Beispiele

Rohumhüllung

Dieses Beispiel umhüllt einen AES-Schlüssel. Es verwendet "raw" als Exportformat und AES-KW mit einem passwortabgeleiteten Schlüssel, um ihn zu verschlüsseln. Sehen Sie den vollständigen Code auf GitHub.

js
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 Umhüllung

Dieses Beispiel umhüllt einen RSA-privaten Signaturschlüssel. Es verwendet "pkcs8" als Exportformat und AES-GCM mit einem passwortabgeleiteten Schlüssel, um ihn zu verschlüsseln. Sehen Sie den vollständigen Code auf GitHub.

js
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 Umhüllung

Dieses Beispiel umhüllt einen RSA-öffentlichen Verschlüsselungsschlüssel. Es verwendet "spki" als Exportformat und AES-CBC mit einem passwortabgeleiteten Schlüssel, um ihn zu verschlüsseln. Sehen Sie den vollständigen Code auf GitHub.

js
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 Umhüllung

Dieses Beispiel umhüllt einen ECDSA-privaten Signaturschlüssel. Es verwendet "jwk" als Exportformat und AES-GCM mit einem passwortabgeleiteten Schlüssel, um ihn zu verschlüsseln. Sehen Sie den vollständigen Code auf GitHub.

js
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));

Spezifikationen

Specification
Web Cryptography API
# SubtleCrypto-method-wrapKey

Browser-Kompatibilität

BCD tables only load in the browser

Siehe auch