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.
SubtleCrypto
接口的 deriveBits()
方法用于从一个基本密钥派生比特序列(数组)。
它以基本密钥、使用的派生算法和需要派生的比特长度为参数。返回一个 Promise
,会兑现一个包含派生比特序列的 ArrayBuffer
。
此方法与 SubtleCrypto.deriveKey()
非常类似,区别在于 deriveKey()
返回的是 CryptoKey
对象,而不是 ArrayBuffer
。本质上,deriveKey()
是由 deriveBits()
和 importKey()
这两个方法组合而成的。
该函数支持的派生算法与 deriveKey()
相同:ECDH、HKDF 和 PBKDF2。参见支持的算法以了解这些算法的详细信息。
语法
deriveBits(algorithm, baseKey, length)
参数
algorithm
-
一个对象,用于定义使用的派生算法。
- 使用 ECDH,则传入
EcdhKeyDeriveParams
对象。 - 使用 HKDF,则传入
HkdfParams
对象。 - 使用 PBKDF2,则传入
Pbkdf2Params
对象。
- 使用 ECDH,则传入
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 上查看完整代码。
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 上查看完整代码。
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 |
浏览器兼容性
BCD tables only load in the browser