SubtleCrypto: deriveBits() 方法
Baseline 广泛可用 *
注意:此功能在 Web Workers 中可用。
SubtleCrypto 接口的 deriveBits() 方法可用于从基础密钥派生出一个比特数组。
它接收基础密钥、要使用的派生算法以及要派生的比特长度作为其参数。它返回一个 Promise,该 Promise 将以包含派生比特的 ArrayBuffer 来兑现。
此方法与 SubtleCrypto.deriveKey() 非常相似,不同之处在于 deriveKey() 返回的是 CryptoKey 对象,而不是 ArrayBuffer。本质上 deriveKey() 由 deriveBits() 和 importKey() 组成。
此函数支持与 deriveKey() 相同的派生算法:ECDH、HKDF、PBKDF2 和 X25519。有关这些算法的更多详细信息,请参阅 支持的算法。
语法
deriveBits(algorithm, baseKey, length)
参数
algorithm-
定义要使用的 派生算法 的一个对象。
- 要使用 ECDH,请传入一个
EcdhKeyDeriveParams对象,并将name属性指定为字符串ECDH。 - 要使用 HKDF,请传入一个
HkdfParams对象。 - 要使用 PBKDF2,请传入一个
Pbkdf2Params对象。 - 要使用 X25519,请传入一个
EcdhKeyDeriveParams对象,并将name属性指定为字符串X25519。
- 要使用 ECDH,请传入一个
baseKey-
一个
CryptoKey,代表派生算法的输入。如果algorithm是 ECDH,那么它将是 ECDH 私钥。否则,它将是派生函数的初始密钥材料:例如,对于 PBKDF2,它可能是一个密码,使用SubtleCrypto.importKey()导入为CryptoKey。 length-
一个表示要派生的比特数的数字。为了与所有浏览器兼容,该数字应为 8 的倍数。
返回值
一个 Promise,它将以包含派生比特的 ArrayBuffer 来兑现。
异常
当遇到以下任何异常时,Promise 将被拒绝
OperationErrorDOMException-
如果
deriveBits()调用中的 length 参数为 null,以及在某些情况下 length 参数不是 8 的倍数时,会引发此错误。 InvalidAccessErrorDOMException-
当基础密钥不是所请求派生算法的密钥,或者该密钥的
CryptoKey.usages值不包含deriveBits时引发。 NotSupportedDOMException-
尝试使用未知算法或不适合派生的算法时引发。
支持的算法
请参阅 deriveKey() 文档的“支持的算法”部分。
示例
注意: 您可以在 GitHub 上 尝试实际示例。
ECDH
在此示例中,Alice 和 Bob 分别生成了一个 ECDH 密钥对。
然后,我们使用 Alice 的私钥和 Bob 的公钥来派生一个共享密钥。 在 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} 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
在此示例中,Alice 和 Bob 分别生成了一个 X25519 密钥对。然后,我们使用 Alice 的私钥和 Bob 的公钥来派生一个密钥,并将其与使用 Bob 的私钥和 Alice 的公钥生成的密钥进行比较,以证明它们是共享/相同的。
HTML
HTML 定义了两个按钮。“更改密钥”按钮用于为 Alice 和 Bob 生成新的密钥对。“派生比特”按钮用于使用当前的密钥对集派生一个共享密钥。
<input id="buttonDeriveKeys" type="button" value="Derive bits" />
<input id="buttonChangeKeys" type="button" value="Change keys" />
JavaScript
下面显示了使用 X25519 算法生成共享密钥的函数。该函数接收一方的私钥和另一方的公钥。
async function deriveSharedSecret(privateKey, publicKey) {
return await window.crypto.subtle.deriveBits(
{
name: "X25519",
public: publicKey,
},
privateKey,
128,
);
}
下面的代码添加了一个函数,用于为 Alice 和 Bob 生成新密钥。这在 JavaScript 首次加载时完成,并在每次按下“更改密钥”按钮时重复(这使我们能够看到更改密钥对共享密钥的影响)。
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);
下面的代码添加了一个处理程序函数,该函数在每次按下“派生比特”按钮时调用。处理程序使用上面定义的 deriveSharedSecret() 方法为 Alice 和 Bob 生成共享密钥,并将它们记录下来以便于比较。
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)`);
});
结果
按下“派生比特”按钮以生成并记录 Bob 和 Alice 密钥之间的共享密钥。按下“更改密钥”按钮以更改双方使用的 X25519 密钥。
PBKDF2
在此示例中,我们要求用户输入密码,然后使用该密码通过 PBKDF2 派生一些比特。 在 GitHub 上查看完整代码。
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();
});
规范
| 规范 |
|---|
| Web 加密级别 2 # SubtleCrypto-method-deriveBits |
浏览器兼容性
加载中…