SubtleCrypto: phương thức deriveBits()
Baseline
Widely available
*
This feature is well established and works across many devices and browser versions. It’s been available across browsers since January 2020.
* Some parts of this feature may have varying levels of support.
Secure context: This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.
Note: This feature is available in Web Workers.
Phương thức deriveBits() của giao diện SubtleCrypto có thể được sử dụng để phái sinh một mảng bit từ một khóa cơ sở.
Nó nhận làm đối số khóa cơ sở, thuật toán phái sinh sẽ sử dụng, và độ dài của các bit cần phái sinh. Nó trả về một Promise sẽ được fulfill với một ArrayBuffer chứa các bit đã phái sinh.
Phương thức này rất giống với SubtleCrypto.deriveKey(), ngoại trừ deriveKey() trả về đối tượng CryptoKey thay vì ArrayBuffer. Về cơ bản deriveKey() được cấu thành từ deriveBits() theo sau bởi importKey().
Hàm này hỗ trợ các thuật toán phái sinh tương tự như deriveKey(): ECDH, HKDF, PBKDF2 và X25519.
Xem Các thuật toán được hỗ trợ để biết thêm chi tiết về các thuật toán này.
Cú pháp
deriveBits(algorithm, baseKey, length)
Tham số
algorithm-
Một đối tượng xác định thuật toán phái sinh sẽ sử dụng.
- Để sử dụng ECDH, truyền một đối tượng
EcdhKeyDeriveParams, chỉ định chuỗiECDHlàm thuộc tínhname. - Để sử dụng HKDF, truyền một đối tượng
HkdfParams. - Để sử dụng PBKDF2, truyền một đối tượng
Pbkdf2Params. - Để sử dụng X25519, truyền một đối tượng
EcdhKeyDeriveParams, chỉ định chuỗiX25519làm thuộc tínhname.
- Để sử dụng ECDH, truyền một đối tượng
baseKey-
Một
CryptoKeyđại diện cho đầu vào của thuật toán phái sinh. Nếualgorithmlà ECDH, đây sẽ là khóa riêng tư ECDH. Nếu không, nó sẽ là tài liệu khóa ban đầu cho hàm phái sinh: ví dụ, đối với PBKDF2 nó có thể là mật khẩu, được nhập dưới dạngCryptoKeybằngSubtleCrypto.importKey(). length-
Một số đại diện cho số bit cần phái sinh. Để tương thích với tất cả trình duyệt, số này nên là bội số của 8.
Giá trị trả về
Một Promise được fulfill với một ArrayBuffer chứa các bit đã phái sinh.
Ngoại lệ
Promise bị reject khi gặp một trong các ngoại lệ sau:
OperationErrorDOMException-
Ném lên nếu tham số length của lệnh gọi
deriveBits()là null, và trong một số trường hợp nếu tham số length không phải là bội số của 8. InvalidAccessErrorDOMException-
Ném lên khi khóa cơ sở không phải là khóa cho thuật toán phái sinh được yêu cầu hoặc nếu giá trị
CryptoKey.usagescủa khóa đó không chứaderiveBits. NotSupportedDOMException-
Ném lên khi cố sử dụng một thuật toán không xác định hoặc không phù hợp để phái sinh.
Các thuật toán được hỗ trợ
Xem mục Các thuật toán được hỗ trợ trong tài liệu deriveKey().
Ví dụ
Note: Bạn có thể thử các ví dụ hoạt động trên GitHub.
ECDH
Trong ví dụ này, Alice và Bob mỗi người tạo một cặp khóa ECDH.
Sau đó chúng ta sử dụng khóa riêng tư của Alice và khóa công khai của Bob để phái sinh một bí mật chia sẻ. Xem mã đầy đủ trên 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]`;
}
// Tạo 2 cặp khóa ECDH: một cho Alice và một cho Bob
// Trong sử dụng bình thường hơn, họ sẽ tạo cặp khóa
// riêng biệt và trao đổi khóa công khai một cách an toàn
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 sau đó tạo bí mật bằng khóa riêng tư của cô ấy và khóa công khai của Bob.
// Bob có thể tạo cùng bí mật bằng khóa riêng tư của anh ấy và khóa công khai của Alice.
deriveSharedSecret(aliceKeyPair.privateKey, bobKeyPair.publicKey);
});
});
X25519
Trong ví dụ này, Alice và Bob mỗi người tạo một cặp khóa X25519. Sau đó chúng ta sử dụng khóa riêng tư của Alice và khóa công khai của Bob để phái sinh một bí mật, và so sánh bí mật đó với bí mật được tạo bằng khóa riêng tư của Bob và khóa công khai của Alice để cho thấy chúng là chia sẻ/giống nhau.
HTML
HTML định nghĩa hai nút. Nút "Change keys" được nhấn để tạo các cặp khóa mới cho Alice và Bob. Nút "Derive bits" được nhấn để phái sinh một bí mật chia sẻ với tập hợp cặp khóa hiện tại.
<input id="buttonDeriveKeys" type="button" value="Derive bits" />
<input id="buttonChangeKeys" type="button" value="Change keys" />
JavaScript
Hàm tạo một bí mật chia sẻ bằng thuật toán X25519 được hiển thị bên dưới. Hàm này nhận khóa riêng tư từ một bên và khóa công khai từ bên kia.
async function deriveSharedSecret(privateKey, publicKey) {
return await window.crypto.subtle.deriveBits(
{
name: "X25519",
public: publicKey,
},
privateKey,
128,
);
}
Mã bên dưới thêm một hàm để tạo khóa mới cho Alice và Bob. Điều này được thực hiện lần đầu tiên khi JavaScript được tải, và lặp lại bất cứ khi nào nút "Change keys" được nhấn (điều này cho phép chúng ta xem hiệu quả của việc thay đổi khóa đối với bí mật chia sẻ).
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");
// Tạo 2 cặp khóa X25519: một cho Alice và một cho Bob
// Trong sử dụng bình thường hơn, họ sẽ tạo cặp khóa
// riêng biệt và trao đổi khóa công khai một cách an toàn
changeKeysButton.addEventListener("click", changeKeys);
Mã bên dưới thêm một hàm xử lý được gọi mỗi khi nút "Derive bits" được nhấn.
Trình xử lý tạo các bí mật chia sẻ cho Alice và Bob bằng phương thức deriveSharedSecret() định nghĩa ở trên, và ghi log chúng để dễ dàng so sánh.
const deriveBitsButton = document.querySelector("#buttonDeriveKeys");
deriveBitsButton.addEventListener("click", async () => {
// Tạo 2 cặp khóa X25519: một cho Alice và một cho Bob
// Trong sử dụng bình thường hơn, họ sẽ tạo cặp khóa
// riêng biệt và trao đổi khóa công khai một cách an toàn
// Alice sau đó tạo bí mật bằng khóa riêng tư của cô ấy và khóa công khai của Bob.
// Bob có thể tạo cùng bí mật bằng khóa riêng tư của anh ấy và khóa công khai của Alice.
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)`);
});
Kết quả
Nhấn nút "Derive bits" để tạo và ghi log một bí mật chia sẻ từ khóa của Bob và Alice. Nhấn nút "Change keys" để thay đổi các khóa X25519 được sử dụng bởi cả hai bên.
PBKDF2
Trong ví dụ này, chúng ta yêu cầu người dùng nhập mật khẩu, sau đó sử dụng nó để phái sinh một số bit bằng PBKDF2. Xem mã đầy đủ trên GitHub.
let salt;
/*
Lấy một số tài liệu khóa để sử dụng làm đầu vào cho phương thức deriveBits.
Tài liệu khóa là mật khẩu do người dùng cung cấp.
*/
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"],
);
}
/*
Phái sinh một số bit từ mật khẩu do người dùng cung cấp.
*/
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();
});
Đặc tả kỹ thuật
| Thông số kỹ thuật |
|---|
| Web Cryptography Level 2> # SubtleCrypto-method-deriveBits> |