SubtleCrypto: deriveBits() 方法

基线 广泛可用

此功能非常成熟,可在许多设备和浏览器版本上运行。自 2015 年 7 月.

报告反馈

安全上下文:此功能仅在 安全上下文(HTTPS)中可用,在某些或所有 支持的浏览器 中可用。

deriveBits() 方法是 SubtleCrypto 接口的方法,可用于从基础密钥推导出一个位数组。

它采用基础密钥、要使用的推导算法和要推导的位长度作为参数。它返回一个 Promise,该承诺将使用包含推导出位的 ArrayBuffer 来履行。

此方法与 SubtleCrypto.deriveKey() 非常相似,不同之处在于 deriveKey() 返回一个 CryptoKey 对象,而不是 ArrayBuffer。本质上,deriveKey()deriveBits() 后跟 importKey() 组成。

语法

此函数支持与 deriveKey() 相同的推导算法:ECDH、HKDF、PBKDF2 和 X25519。有关这些算法的更多详细信息,请参见 支持的算法
deriveBits(algorithm, baseKey, length)

js

参数

algorithm

要使用 X25519,请传递一个 EcdhKeyDeriveParams 对象,并指定字符串 X25519 作为 name 属性。

baseKey

一个 CryptoKey,表示推导算法的输入。如果 algorithm 是 ECDH,则它将是 ECDH 私钥。否则,它将是推导函数的初始密钥材料:例如,对于 PBKDF2,它可能是密码,使用 SubtleCrypto.importKey() 导入为 CryptoKey

length

一个表示要推导的位数的数字。要与所有浏览器兼容,该数字应是 8 的倍数。

返回值

一个 Promise,它使用包含推导出位的 ArrayBuffer 来履行。

异常

当遇到以下异常之一时,承诺将被拒绝

OperationError DOMException

如果 deriveBits() 调用的 length 参数为 null,并且在某些情况下,如果 length 参数不是 8 的倍数,则会引发此错误。

InvalidAccessError DOMException

当基础密钥不是请求的推导算法的密钥,或者该密钥的 CryptoKey.usages 值不包含 deriveBits 时引发此错误。

NotSupported DOMException

支持的算法

当尝试使用未知算法或不适合推导的算法时引发此错误。

示例

注意:您可以在 GitHub 上 尝试运行示例

ECDH

在此示例中,Alice 和 Bob それぞれ ECDH 密钥对を生成します。

此函数支持与 deriveKey() 相同的推导算法:ECDH、HKDF、PBKDF2 和 X25519。有关这些算法的更多详细信息,请参见 支持的算法
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 generateAlicesKeyPair = window.crypto.subtle.generateKey(
  {
    name: "ECDH",
    namedCurve: "P-384",
  },
  false,
  ["deriveBits"],
);

const generateBobsKeyPair = window.crypto.subtle.generateKey(
  {
    name: "ECDH",
    namedCurve: "P-384",
  },
  false,
  ["deriveBits"],
);

Promise.all([generateAlicesKeyPair, generateBobsKeyPair]).then((values) => {
  const alicesKeyPair = values[0];
  const bobsKeyPair = 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(alicesKeyPair.privateKey, bobsKeyPair.publicKey);
  });
});

次に、Alice の秘密鍵と Bob の公開鍵を使用して共有シークレットを導出します。 GitHub で完全なコードを確認してください

X25519

HTML

この例では、Alice と Bob はそれぞれ X25519 キーペアを生成します。次に、Alice の秘密鍵と Bob の公開鍵を使用して秘密を導出し、Bob の秘密鍵と Alice の公開鍵を使用して生成された秘密と比較して、それらが共有/同一であることを示します。

HTML は、2 つのボタンを定義しています。「キーの変更」ボタンを押すと、Alice と Bob の新しいキーペアが生成されます。「ビットの導出」ボタンを押すと、現在のキーペアセットを使用して共有秘密が導出されます。
<input id="buttonDeriveKeys" type="button" value="Derive bits" />
<input id="buttonChangeKeys" type="button" value="Change keys" />

JavaScript

html

此函数支持与 deriveKey() 相同的推导算法:ECDH、HKDF、PBKDF2 和 X25519。有关这些算法的更多详细信息,请参见 支持的算法
async function deriveSharedSecret(privateKey, publicKey) {
  return await window.crypto.subtle.deriveBits(
    {
      name: "X25519",
      public: publicKey,
    },
    privateKey,
    128,
  );
}

X25519 アルゴリズムを使用して共有秘密を生成する関数は、以下に示されています。これは、一方の当事者の秘密鍵と、もう一方の当事者の公開鍵を取ります。

此函数支持与 deriveKey() 相同的推导算法:ECDH、HKDF、PBKDF2 和 X25519。有关这些算法的更多详细信息,请参见 支持的算法
let alicesKeyPair;
let bobsKeyPair;

async function changeKeys() {
  try {
    alicesKeyPair = await window.crypto.subtle.generateKey(
      {
        name: "X25519",
      },
      false,
      ["deriveBits"],
    );

    bobsKeyPair = 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);

以下のコードは、Alice と Bob の新しいキーを生成する関数を追加します。これは、JavaScript が初めて読み込まれたときに実行され、「キーの変更」ボタンが押されるたびに繰り返されます(これにより、キーを変更することによる共有秘密への影響を確認できます)。

此函数支持与 deriveKey() 相同的推导算法:ECDH、HKDF、PBKDF2 和 X25519。有关这些算法的更多详细信息,请参见 支持的算法
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(
    alicesKeyPair.privateKey,
    bobsKeyPair.publicKey,
  );

  let buffer = new Uint8Array(sharedSecretAlice, 0, 10);
  log(`${buffer}…[${sharedSecretAlice.byteLength} bytes total] (Alice secret)`);

  const sharedSecretBob = await deriveSharedSecret(
    bobsKeyPair.privateKey,
    alicesKeyPair.publicKey,
  );

  buffer = new Uint8Array(sharedSecretBob, 0, 10);
  log(`${buffer}…[${sharedSecretAlice.byteLength} bytes total] (Bob secret)`);
});

以下のコードは、"ビットの導出" ボタンが押されるたびに呼び出されるハンドラー関数を追加します。ハンドラーは、上記で定義された deriveSharedSecret() メソッドを使用して、Alice と Bob の共有秘密を生成し、簡単に比較できるようにログに記録します。

結果

"ビットの導出" ボタンを押すと、Bob と Alice のキーから共有秘密が生成され、ログに記録されます。「キーの変更」ボタンを押すと、両当事者で使用される X25519 キーが変更されます。

PBKDF2

此函数支持与 deriveKey() 相同的推导算法:ECDH、HKDF、PBKDF2 和 X25519。有关这些算法的更多详细信息,请参见 支持的算法
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();
});

规范

この例では、ユーザーにパスワードを要求し、それを用いて PBKDF2 を使用してビットを導出します。 GitHub で完全なコードを確認してください
仕様
# Web 加密 API

浏览器兼容性

SubtleCrypto-method-deriveBits

另请参阅