SubtleCrypto: deriveBits() 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 deriveBits()-Methode der SubtleCrypto-Schnittstelle kann verwendet werden, um ein Array von Bits aus einem Basisschlüssel abzuleiten.

Sie nimmt als Argumente den Basisschlüssel, den zu verwendenden Ableitungsalgorithmus und die Länge der abzuleitenden Bits. Sie gibt ein Promise zurück, das mit einem ArrayBuffer erfüllt wird, der die abgeleiteten Bits enthält.

Diese Methode ist der SubtleCrypto.deriveKey()-Methode sehr ähnlich, mit dem Unterschied, dass deriveKey() ein CryptoKey-Objekt anstelle eines ArrayBuffer zurückgibt. Im Wesentlichen setzt sich deriveKey() aus deriveBits() gefolgt von importKey() zusammen.

Diese Funktion unterstützt die gleichen Ableitungsalgorithmen wie deriveKey(): ECDH, HKDF, PBKDF2 und X25519. Siehe Unterstützte Algorithmen für weitere Details zu diesen Algorithmen.

Syntax

js
deriveBits(algorithm, baseKey, length)

Parameter

algorithm

Ein Objekt, das den zu verwendenden Ableitungsalgorithmus definiert.

baseKey

Ein CryptoKey, der die Eingabe für den Ableitungsalgorithmus darstellt. Wenn algorithm ECDH ist, handelt es sich um den ECDH-Privatschlüssel. Andernfalls ist es das Ausgangsschlüsselmaterial für die Ableitungsfunktion: Beispielsweise könnte es sich bei PBKDF2 um ein Passwort handeln, das als CryptoKey mithilfe von SubtleCrypto.importKey() importiert wurde.

length

Eine Zahl, die die Anzahl der abzuleitenden Bits repräsentiert. Um mit allen Browsern kompatibel zu sein, sollte die Zahl ein Vielfaches von 8 sein.

Rückgabewert

Ein Promise, das mit einem ArrayBuffer erfüllt wird, der die abgeleiteten Bits enthält.

Ausnahmen

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

OperationError DOMException

Wird ausgelöst, wenn der length-Parameter des deriveBits()-Aufrufs null ist und auch in einigen Fällen, wenn der length-Parameter kein Vielfaches von 8 ist.

InvalidAccessError DOMException

Wird ausgelöst, wenn der Basisschlüssel kein Schlüssel für den angeforderten Ableitungsalgorithmus ist oder wenn der CryptoKey.usages-Wert dieses Schlüssels nicht deriveBits enthält.

NotSupported DOMException

Wird ausgelöst, wenn versucht wird, einen Algorithmus zu verwenden, der entweder unbekannt ist oder nicht für die Ableitung geeignet ist.

Unterstützte Algorithmen

Beispiele

ECDH

In diesem Beispiel generieren Alice und Bob jeweils ein ECDH-Schlüsselpaar.

Wir verwenden dann Alices privaten Schlüssel und Bobs öffentlichen Schlüssel, um ein gemeinsames Geheimnis abzuleiten. Sehen Sie den vollständigen Code auf GitHub.

js
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

In diesem Beispiel generieren Alice und Bob jeweils ein X25519-Schlüsselpaar. Wir verwenden dann Alices privaten Schlüssel und Bobs öffentlichen Schlüssel, um ein Geheimnis abzuleiten, und vergleichen dies mit dem Geheimnis, das mit Bobs privatem Schlüssel und Alices öffentlichem Schlüssel generiert wurde, um zu zeigen, dass sie identisch sind.

HTML

Das HTML definiert zwei Schaltflächen. Die "Change keys"-Schaltfläche wird gedrückt, um neue Schlüsselpaare für Alice und Bob zu generieren. Die "Derive bits"-Schaltfläche wird gedrückt, um ein gemeinsames Geheimnis mit dem aktuellen Satz von Schlüsselpaaren abzuleiten.

html
<input id="buttonDeriveKeys" type="button" value="Derive bits" />
<input id="buttonChangeKeys" type="button" value="Change keys" />

JavaScript

Die Funktion zum Generieren eines gemeinsamen Geheimnisses unter Verwendung des X25519-Algorithmus wird unten angezeigt. Diese nimmt einen privaten Schlüssel von einer Partei und den öffentlichen Schlüssel von einer anderen.

js
async function deriveSharedSecret(privateKey, publicKey) {
  return await window.crypto.subtle.deriveBits(
    {
      name: "X25519",
      public: publicKey,
    },
    privateKey,
    128,
  );
}

Der folgende Code fügt eine Funktion hinzu, um neue Schlüssel für Alice und Bob zu generieren. Dies wird beim ersten Laden des JavaScripts durchgeführt und immer wiederholt, wenn die "Change keys"-Schaltfläche gedrückt wird (dies ermöglicht es uns, die Auswirkungen des Änderns der Schlüssel auf das gemeinsame Geheimnis zu sehen).

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

Der folgende Code fügt eine Handler-Funktion hinzu, die jedes Mal aufgerufen wird, wenn die "Derive bits"-Schaltfläche gedrückt wird. Der Handler generiert die gemeinsamen Geheimnisse für Alice und Bob mithilfe der oben definierten deriveSharedSecret()-Methode und protokolliert sie, um den Vergleich zu erleichtern.

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

Ergebnis

Drücken Sie die "Derive bits"-Schaltfläche, um ein gemeinsames Geheimnis aus Bobs und Alices Schlüsseln zu generieren und zu protokollieren. Drücken Sie die "Change keys"-Schaltfläche, um die von beiden Parteien verwendeten X25519-Schlüssel zu ändern.

PBKDF2

In diesem Beispiel fragen wir den Benutzer nach einem Passwort und verwenden es dann, um einige Bits mit PBKDF2 abzuleiten. Sehen Sie den vollständigen Code auf GitHub.

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

Spezifikationen

Specification
Web Cryptography API
# SubtleCrypto-method-deriveBits

Browser-Kompatibilität

BCD tables only load in the browser

Siehe auch