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 |
瀏覽器相容性
載入中…