Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.

View in English Always switch to English

SubtleCrypto: Methode wrapKey()

Baseline
Weitgehend verfügbar

Diese Funktion ist gut etabliert und funktioniert auf vielen Geräten und in vielen Browserversionen. Sie ist seit Januar 2020 browserübergreifend verfügbar.

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 Methode wrapKey() der Schnittstelle SubtleCrypto „verpackt“ einen Schlüssel. Das bedeutet, dass sie den Schlüssel zunächst in ein externes, portables Format exportiert und den exportierten Schlüssel anschließend verschlüsselt. Das Verpacken eines Schlüssels hilft, ihn in nicht vertrauenswürdigen Umgebungen zu schützen, etwa in einem ansonsten ungeschützten Datenspeicher oder bei der Übertragung über ein ungeschütztes Netzwerk.

Wie bei SubtleCrypto.exportKey() geben Sie für den Schlüssel ein Exportformat an. Damit ein Schlüssel exportiert werden kann, muss CryptoKey.extractable auf true gesetzt sein.

Da wrapKey() den zu exportierenden Schlüssel auch verschlüsselt, müssen Sie außerdem den Schlüssel übergeben, mit dem er verschlüsselt werden soll. Dieser wird manchmal als „Wrapping Key“ bezeichnet.

Die Umkehrung von wrapKey() ist SubtleCrypto.unwrapKey(): Während wrapKey aus Exportieren und Verschlüsseln besteht, besteht unwrapKey aus Importieren und Entschlüsseln.

Syntax

js
wrapKey(format, key, wrappingKey, wrapAlgo)

Parameter

format

Eine Zeichenfolge, die das Datenformat beschreibt, in das der Schlüssel vor der Verschlüsselung exportiert wird. Sie kann einen der folgenden Werte haben:

raw

Raw-Format.

pkcs8

PKCS-#8-Format.

spki

SubjectPublicKeyInfo-Format.

jwk

JSON-Web-Key-Format.

key

Der zu verpackende CryptoKey.

wrappingkey

Der CryptoKey, mit dem der exportierte Schlüssel verschlüsselt wird. Für diesen Schlüssel muss die Verwendung wrapKey festgelegt sein.

wrapAlgo

Ein Objekt, das den Algorithmus zum Verschlüsseln des exportierten Schlüssels sowie alle erforderlichen zusätzlichen Parameter angibt:

Rückgabewert

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

Ausnahmen

Die Promise wird zurückgewiesen, wenn eine der folgenden Ausnahmen auftritt:

InvalidAccessError DOMException

Wird ausgelöst, wenn der Wrapping Key kein Schlüssel für den angeforderten Verpackungsalgorithmus ist.

NotSupportedError DOMException

Wird ausgelöst, wenn versucht wird, einen unbekannten Algorithmus oder einen Algorithmus zu verwenden, der sich nicht zum Verschlüsseln oder Verpacken eignet.

TypeError

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

Unterstützte Algorithmen

Alle Algorithmen, die zum Verschlüsseln verwendet werden können, können auch zum Verpacken von Schlüsseln verwendet werden, sofern für den Schlüssel die Verwendung „wrapKey“ festgelegt ist. Zum Verpacken von Schlüsseln steht zusätzlich AES-KW zur Verfügung.

AES-KW

AES-KW ist eine Möglichkeit, die AES-Chiffre zum Verpacken von Schlüsseln zu verwenden.

Ein Vorteil von AES-KW gegenüber einem anderen AES-Modus wie AES-GCM ist, dass AES-KW keinen Initialisierungsvektor benötigt. Für die Verwendung von AES-KW muss die Eingabe ein Vielfaches von 64 Bit lang sein.

AES-KW ist in RFC 3394 spezifiziert.

Beispiele

Hinweis: Sie können die funktionsfähigen Beispiele auf GitHub ausprobieren.

Verpacken im Raw-Format

Dieses Beispiel verpackt einen AES-Schlüssel. Es verwendet „raw“ als Exportformat und AES-KW mit einem aus einem Passwort abgeleiteten Schlüssel, um ihn zu verschlüsseln. Den vollständigen Code finden Sie 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));

Verpacken im PKCS-#8-Format

Dieses Beispiel verpackt einen privaten RSA-Signaturschlüssel. Es verwendet „pkcs8“ als Exportformat und AES-GCM mit einem aus einem Passwort abgeleiteten Schlüssel, um ihn zu verschlüsseln. Den vollständigen Code finden Sie 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);
  });

Verpacken im SubjectPublicKeyInfo-Format

Dieses Beispiel verpackt einen öffentlichen RSA-Verschlüsselungsschlüssel. Es verwendet „spki“ als Exportformat und AES-CBC mit einem aus einem Passwort abgeleiteten Schlüssel, um ihn zu verschlüsseln. Den vollständigen Code finden Sie 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));

Verpacken im JSON-Web-Key-Format

Dieses Beispiel verpackt einen privaten ECDSA-Signaturschlüssel. Es verwendet „jwk“ als Exportformat und AES-GCM mit einem aus einem Passwort abgeleiteten Schlüssel, um ihn zu verschlüsseln. Den vollständigen Code finden Sie 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

Spezifikation
Web Cryptography Level 2
# SubtleCrypto-method-wrapKey

Browser-Kompatibilität

Siehe auch