SubtleCrypto: phương thức sign()
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 sign() của giao diện SubtleCrypto tạo một signature số.
Nó nhận làm đối số một key để ký, một số tham số cụ thể cho thuật toán, và dữ liệu cần ký. Nó trả về một Promise sẽ được fulfill với chữ ký.
Bạn có thể sử dụng phương thức SubtleCrypto.verify() tương ứng để xác minh chữ ký.
Cú pháp
sign(algorithm, key, data)
Tham số
algorithm-
Một chuỗi hoặc đối tượng chỉ định thuật toán chữ ký sẽ sử dụng và các tham số của nó:
- Để sử dụng RSASSA-PKCS1-v1_5, truyền chuỗi
RSASSA-PKCS1-v1_5hoặc một đối tượng có dạng{ name: "RSASSA-PKCS1-v1_5" }. - Để sử dụng RSA-PSS, truyền một đối tượng
RsaPssParams. - Để sử dụng ECDSA, truyền một đối tượng
EcdsaParams. - Để sử dụng HMAC, truyền chuỗi
HMAChoặc một đối tượng có dạng{ name: "HMAC" }. - Để sử dụng Ed25519, truyền chuỗi
Ed25519hoặc một đối tượng có dạng{ name: "Ed25519" }.
- Để sử dụng RSASSA-PKCS1-v1_5, truyền chuỗi
key-
Một đối tượng
CryptoKeychứa khóa sẽ dùng để ký. Nếualgorithmxác định một hệ mật mã khóa công khai, đây là khóa riêng tư. data-
Một đối tượng
ArrayBuffer,TypedArrayhoặcDataViewchứa dữ liệu cần ký.
Giá trị trả về
Một Promise được fulfill với một ArrayBuffer chứa chữ ký.
Ngoại lệ
Promise bị reject khi gặp ngoại lệ sau:
InvalidAccessErrorDOMException-
Ném lên khi khóa ký không phải là khóa cho thuật toán ký được yêu cầu hoặc khi cố sử dụng một thuật toán không xác định hoặc không phù hợp để ký.
Các thuật toán được hỗ trợ
Web Crypto API cung cấp các thuật toán sau có thể được sử dụng để ký và xác minh chữ ký.
RSASSA-PKCS1-v1_5, RSA-PSS, ECDSA và Ed25519 là các hệ mật mã khóa công khai sử dụng khóa riêng tư để ký và khóa công khai để xác minh. Tất cả các hệ thống này đều sử dụng thuật toán digest để hash thông báo thành một giá trị cố định ngắn trước khi ký.
- Đối với RSASSA-PKCS1-v1_5 và RSA-PSS, lựa chọn thuật toán digest được truyền vào các hàm
generateKey()hoặcimportKey(). - Đối với ECDSA, lựa chọn thuật toán digest được bao gồm trong tham số
algorithmtruyền vào hàmsign(). - Đối với Ed25519, thuật toán digest luôn là SHA-512.
Thuật toán HMAC khác với các thuật toán còn lại ở chỗ nó không phải là hệ mật mã khóa công khai: nó sử dụng cùng thuật toán và khóa để ký và xác minh. Điều này có nghĩa là khóa xác minh phải được giữ bí mật, do đó thuật toán này không phù hợp cho nhiều trường hợp sử dụng chữ ký. Tuy nhiên, nó có thể là lựa chọn tốt khi người ký và người xác minh là cùng một thực thể.
RSASSA-PKCS1-v1_5
Thuật toán RSASSA-PKCS1-v1_5 được chỉ định trong RFC 3447.
RSA-PSS
Thuật toán RSA-PSS được chỉ định trong RFC 3447.
Nó khác với RSASSA-PKCS1-v1_5 ở chỗ nó kết hợp một salt ngẫu nhiên trong thao tác ký, vì vậy cùng một thông báo được ký với cùng một khóa sẽ không cho ra cùng chữ ký mỗi lần. Một thuộc tính bổ sung, xác định độ dài salt, được truyền vào các hàm sign() và verify() khi chúng được gọi.
ECDSA
ECDSA (Elliptic Curve Digital Signature Algorithm - Thuật toán chữ ký số đường cong elliptic) là một biến thể của Thuật toán chữ ký số, được chỉ định trong FIPS-186, sử dụng Mật mã đường cong Elliptic (RFC 6090).
Chữ ký được mã hóa dưới dạng các giá trị s1 và s2 được chỉ định trong RFC 6090 (tương ứng được gọi là r và s trong RFC 4754), mỗi giá trị trong mảng byte big-endian, với độ dài là kích thước bit của đường cong được làm tròn lên thành số nguyên byte.
Các giá trị này được nối liền nhau theo thứ tự này.
Cách mã hóa này cũng đã được đề xuất bởi tiêu chuẩn IEEE 1363-2000, và đôi khi được gọi là định dạng IEEE P1363. Nó khác với cấu trúc chữ ký X.509, vốn là định dạng mặc định được tạo ra bởi một số công cụ và thư viện như OpenSSL.
Ed25519
Ed25519 là một thuật toán chữ ký số được xây dựng trên đường cong elliptic Curve25519, là một phần của họ thuật toán EdDSA (Edwards-Curve Digital Signature Algorithm) được định nghĩa trong RFC 8032.
HMAC
Thuật toán HMAC tính toán và xác minh các mã xác thực thông báo dựa trên hash theo tiêu chuẩn FIPS 198-1 (PDF).
Thuật toán digest sẽ sử dụng được chỉ định trong đối tượng HmacKeyGenParams mà bạn truyền vào generateKey(), hoặc trong đối tượng HmacImportParams mà bạn truyền vào importKey().
Thuật toán HMAC sử dụng cùng thuật toán và khóa để ký và xác minh: điều này có nghĩa là khóa xác minh phải được giữ bí mật, do đó thuật toán này không phù hợp cho nhiều trường hợp sử dụng chữ ký. Tuy nhiên, nó có thể là lựa chọn tốt khi người ký và người xác minh là cùng một thực thể.
Ví dụ
Note: Bạn có thể thử các ví dụ hoạt động trên GitHub.
RSASSA-PKCS1-v1_5
Đoạn mã này lấy nội dung của một hộp văn bản, mã hóa nó để ký, và ký nó bằng khóa riêng tư. Xem mã nguồn đầy đủ trên GitHub.
/*
Lấy nội dung của hộp văn bản "message", và mã hóa nó
thành dạng chúng ta có thể sử dụng cho thao tác ký.
*/
function getMessageEncoding() {
const messageBox = document.querySelector(".rsassa-pkcs1 #message");
let message = messageBox.value;
let enc = new TextEncoder();
return enc.encode(message);
}
let encoded = getMessageEncoding();
let signature = await window.crypto.subtle.sign(
"RSASSA-PKCS1-v1_5",
privateKey,
encoded,
);
RSA-PSS
Đoạn mã này lấy nội dung của một hộp văn bản, mã hóa nó để ký, và ký nó bằng khóa riêng tư. Xem mã nguồn đầy đủ trên GitHub.
/*
Lấy nội dung của hộp văn bản "message", và mã hóa nó
thành dạng chúng ta có thể sử dụng cho thao tác ký.
*/
function getMessageEncoding() {
const messageBox = document.querySelector(".rsa-pss #message");
let message = messageBox.value;
let enc = new TextEncoder();
return enc.encode(message);
}
let encoded = getMessageEncoding();
let signature = await window.crypto.subtle.sign(
{
name: "RSA-PSS",
saltLength: 32,
},
privateKey,
encoded,
);
ECDSA
Đoạn mã này lấy nội dung của một hộp văn bản, mã hóa nó để ký, và ký nó bằng khóa riêng tư. Xem mã nguồn đầy đủ trên GitHub.
/*
Lấy nội dung của hộp văn bản "message", và mã hóa nó
thành dạng chúng ta có thể sử dụng cho thao tác ký.
*/
function getMessageEncoding() {
const messageBox = document.querySelector(".ecdsa #message");
let message = messageBox.value;
let enc = new TextEncoder();
return enc.encode(message);
}
let encoded = getMessageEncoding();
let signature = await window.crypto.subtle.sign(
{
name: "ECDSA",
hash: { name: "SHA-384" },
},
privateKey,
encoded,
);
HMAC
Đoạn mã này lấy nội dung của một hộp văn bản, mã hóa nó để ký, và ký nó bằng khóa bí mật. Xem mã nguồn đầy đủ trên GitHub.
/*
Lấy nội dung của hộp văn bản "message", và mã hóa nó
thành dạng chúng ta có thể sử dụng cho thao tác ký.
*/
function getMessageEncoding() {
const messageBox = document.querySelector(".hmac #message");
let message = messageBox.value;
let enc = new TextEncoder();
return enc.encode(message);
}
let encoded = getMessageEncoding();
let signature = await window.crypto.subtle.sign("HMAC", key, encoded);
Ed25519 (tạo cặp khóa, ký và xác minh)
Đoạn mã này tạo cặp khóa ký Ed25519, sử dụng khóa riêng tư để ký nội dung (đã mã hóa) của một <input> văn bản, sau đó xác minh chữ ký bằng khóa công khai.
Nó được dẫn xuất từ mã nguồn này trên GitHub, mà bạn có thể chạy trực tiếp tại đây.
HTML
HTML định nghĩa một phần tử <input> chứa văn bản cần ký, và một nút bắt đầu thao tác tạo khóa, ký văn bản rồi xác minh chữ ký.
<label for="message">Nhập thông báo cần ký:</label>
<input
type="text"
id="message"
name="message"
size="25"
value="The lion roars near dawn" />
<input id="sign-button" type="button" value="Run" />
JavaScript
JavaScript đầu tiên lấy các phần tử <input> #sign-button và #message, sau đó thêm trình lắng nghe cho sự kiện click trên nút.
Trình xử lý sự kiện xóa log và chạy các thao tác khác truyền nội dung của phần tử <input>.
const button = document.querySelector("#sign-button");
const input = document.querySelector("#message");
button.addEventListener("click", () => {
// Clear log
logElement.innerText = "";
logElement.scrollTop = logElement.scrollHeight;
// Run test
test(input.value);
});
Đầu tiên nó tạo khóa bằng thuật toán Ed25519, sau đó mã hóa văn bản và ký văn bản đó bằng khóa riêng tư.
Cuối cùng nó gọi SubtleCrypto.verify() với khóa công khai để xác minh chữ ký.
async function test(data) {
log(`Message: ${data}`);
try {
// Generate keys
const { publicKey, privateKey } = await crypto.subtle.generateKey(
{
name: "Ed25519",
},
true,
["sign", "verify"],
);
log(`publicKey: ${publicKey}, type: ${publicKey.type}`);
log(`privateKey: ${privateKey}, type: ${privateKey.type}`);
// Encode data prior to signing
const encoder = new TextEncoder();
encodedData = encoder.encode(data);
// Log the first part of the encoded data
const shorterEncodedBuffer = new Uint8Array(encodedData.buffer, 0, 14);
log(
`encodedData: ${shorterEncodedBuffer}...[${encodedData.byteLength} bytes total]`,
);
// log(`encodedData: ${encodedData}`);
// Sign the data using the private key.
const signature = await crypto.subtle.sign(
{
name: "Ed25519",
},
privateKey,
encodedData,
);
// Log the first part of the signature data
const signatureBuffer = new Uint8Array(signature, 0, 14);
log(
`signature: ${signatureBuffer}...[${signature.byteLength} bytes total]`,
);
// Verify the signature using the public key
const verifyResult = await crypto.subtle.verify(
{
name: "Ed25519",
},
publicKey,
signature,
encodedData,
);
// Log result - true if the text was signed with the corresponding public key.
log(`signature verified?: ${verifyResult}`);
} catch (error) {
log(error);
}
}
Kết quả
Đặc tả kỹ thuật
| Specification |
|---|
| Web Cryptography Level 2> # SubtleCrypto-method-sign> |
Tương thích trình duyệt
Xem thêm
SubtleCrypto.verify().- RFC 3447 chỉ định RSASSA-PKCS1-v1_5.
- RFC 3447 chỉ định RSA-PSS.
- FIPS-186 chỉ định ECDSA.
- FIPS 198-1 chỉ định HMAC.