SubtleCrypto.deriveBits()

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.

* Some parts of this feature may have varying levels of support.

安全上下文: 此项功能仅在一些支持的浏览器安全上下文(HTTPS)中可用。

SubtleCrypto 接口的 deriveBits() 方法用于从一个基本密钥派生比特序列(数组)。

它以基本密钥、使用的派生算法和需要派生的比特长度为参数。返回一个 Promise,会兑现一个包含派生比特序列的 ArrayBuffer

此方法与 SubtleCrypto.deriveKey() 非常类似,区别在于 deriveKey() 返回的是 CryptoKey 对象,而不是 ArrayBuffer。本质上,deriveKey() 是由 deriveBits()importKey() 这两个方法组合而成的。

该函数支持的派生算法与 deriveKey() 相同:ECDH、HKDF 和 PBKDF2。参见支持的算法以了解这些算法的详细信息。

语法

js
deriveBits(algorithm, baseKey, length)

参数

algorithm

一个对象,用于定义使用的派生算法

baseKey

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

length

一个数字,表示要派生的比特位数。为了兼容所有浏览器,此数字应为 8 的倍数。

返回值

一个 Promise,会兑现一个包含派生的比特序列的 ArrayBuffer

异常

当发生一下几种异常时,promise 会被拒绝:

OperationError DOMException

deriveBits()length 参数为 null,或在某些情况下如果 length 参数不是 8 的倍数,则会抛出此异常。

InvalidAccessError DOMException

若基本密钥不是要求的派生算法的密钥,或 CryptoKey.usages 的值不包含 deriveBits,则会抛出此异常。

NotSupported DOMException

若尝试使用未知或不适用于派生的算法,则会抛出此异常。

支持的算法

示例

备注: 你可以在 GitHub 上尝试可用的示例

ECDH

在此示例中,Alice 和 Bob 分别生成了一个 ECDH 密钥对。

然后,我们使用 Alice 的私钥和 Bob 的公钥来派生一个共享密钥(shared secret)。在 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} 字节]`;
}

// 生成两个 ECDH 密钥对:一个是 Alice 的,一个是 Bob 的
// 在正常的使用情况下,他们会单独生成密钥对,并安全地交换公钥。
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 使用她的私钥和 Bob 的公钥生成一个密钥(secret)。
    // Bob 可以使用他的私钥和 Alice 的公钥来生成相同的密钥。
    deriveSharedSecret(alicesKeyPair.privateKey, bobsKeyPair.publicKey);
  });
});

PBKDF2

在此示例中,我们要求用户提供密码,然后使用 PBKDF2 派生比特序列。在 GitHub 上查看完整代码

js
let salt;

/*
获取用于作为 deriveBits 方法的输入的密钥材料。
密钥材料是用户提供的密码。
*/
function getKeyMaterial() {
  const password = window.prompt("请输入你的密码");
  const enc = new TextEncoder();
  return window.crypto.subtle.importKey(
    "raw",
    enc.encode(password),
    { name: "PBKDF2" },
    false,
    ["deriveBits", "deriveKey"],
  );
}

/*
通过用户提供的密码派生比特序列。
*/
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} 字节]`;
}

const deriveBitsButton = document.querySelector(".pbkdf2 .derive-bits-button");
deriveBitsButton.addEventListener("click", () => {
  getDerivedBits();
});

规范

Specification
Web Cryptography API
# SubtleCrypto-method-deriveBits

浏览器兼容性

Report problems with this compatibility data on GitHub
desktopmobileserver
Chrome
Edge
Firefox
Opera
Safari
Chrome Android
Firefox for Android
Opera Android
Safari on iOS
Samsung Internet
WebView Android
WebView on iOS
Deno
Node.js
deriveBits
X25519 algorithm

Legend

Tip: you can click/tap on a cell for more information.

Full support
Full support
Partial support
Partial support
In development. Supported in a pre-release version.
In development. Supported in a pre-release version.
No support
No support
See implementation notes.
Has more compatibility info.

参见