SubtleCrypto: sign() 方法
Baseline 廣泛可用 *
注意:此功能在 Web Workers 中可用。
sign() 是 SubtleCrypto 介面的一個方法,用於生成數字 簽名。
它接受以下引數:用於簽名的 金鑰、演算法特定的引數以及要簽名的資料。它返回一個 Promise,該 Promise 將以簽名結果 fulfilled。
您可以使用相應的 SubtleCrypto.verify() 方法來驗證簽名。
語法
sign(algorithm, key, data)
引數
algorithm-
一個字串或物件,用於指定要使用的簽名演算法及其引數
- 要使用 RSASSA-PKCS1-v1_5,請傳遞字串
RSASSA-PKCS1-v1_5或形式為{ name: "RSASSA-PKCS1-v1_5" }的物件。 - 要使用 RSA-PSS,請傳遞一個
RsaPssParams物件。 - 要使用 ECDSA,請傳遞一個
EcdsaParams物件。 - 要使用 HMAC,請傳遞字串
HMAC或形式為{ name: "HMAC" }的物件。 - 要使用 Ed25519,請傳遞字串
Ed25519或形式為{ name: "Ed25519" }的物件。
- 要使用 RSASSA-PKCS1-v1_5,請傳遞字串
key-
一個
CryptoKey物件,其中包含用於簽名的金鑰。如果algorithm指定了公鑰加密系統,則此金鑰為私鑰。 data-
一個
ArrayBuffer、一個TypedArray或一個DataView物件,其中包含要簽名的資料。
返回值
一個 Promise,它 fulfilled 一個包含簽名的 ArrayBuffer。
異常
當遇到以下異常時,Promise 將被拒絕
InvalidAccessErrorDOMException-
當簽名金鑰不是請求籤名演算法的金鑰,或者嘗試使用未知演算法或不適用於簽名的演算法時丟擲。
支援的演算法
Web Crypto API 提供以下可用於簽名和驗籤的演算法。
RSASSA-PKCS1-v1_5、RSA-PSS、ECDSA 和 Ed25519 是 公鑰加密系統,它們使用私鑰進行簽名,使用公鑰進行驗證。所有這些系統都使用 摘要演算法 在簽名之前將訊息雜湊為一個短的固定大小值。
- 對於 RSASSA-PKCS1-v1_5 和 RSA-PSS,摘要演算法的選擇在呼叫
generateKey()或importKey()函式時傳入。 - 對於 ECDSA,摘要演算法的選擇包含在傳遞給
sign()函式的algorithm引數中。 - 對於 Ed25519,摘要演算法始終是 SHA-512。
HMAC 演算法與其他演算法不同,它不是公鑰加密系統:它使用相同的演算法和金鑰進行簽名和驗證。這意味著驗證金鑰必須保密,而這又意味著此演算法不適用於許多簽名用例。然而,當簽名方和驗證方是同一實體時,它可能是一個不錯的選擇。
RSASSA-PKCS1-v1_5
RFC 3447 中指定了 RSASSA-PKCS1-v1_5 演算法。
RSA-PSS
RFC 3447 中指定了 RSA-PSS 演算法。
它與 RSASSA-PKCS1-v1_5 不同之處在於,它在簽名操作中包含了一個隨機鹽,因此用同一金鑰簽名同一訊息每次生成的簽名都會不同。在呼叫 sign() 和 verify() 函式時,會傳入一個定義鹽長度的附加屬性。
ECDSA
ECDSA(橢圓曲線數字簽名演算法)是數字簽名演算法 (DSA) 的一個變體,在 FIPS-186 中指定,它使用了橢圓曲線密碼學(RFC 6090)。
簽名被編碼為 RFC 6090 中指定的 s1 和 s2 值(在 RFC 4754 中分別稱為 r 和 s),每個值都以大端位元組陣列的形式表示,其長度為曲線的位元大小向上舍入到最接近的整數字節。這些值按此順序連線在一起。
此編碼也是由 IEEE 1363-2000 標準提出的,有時也被稱為 IEEE P1363 格式。它與 X.509 簽名結構不同,後者是一些工具和庫(如 OpenSSL)預設生成的格式。
Ed25519
Ed25519 是一種基於 Curve25519 橢圓曲線的數字簽名演算法,該曲線屬於 RFC 8032 中定義的愛德華茲曲線數字簽名演算法 (EdDSA) 系列演算法。
HMAC
HMAC 演算法根據 FIPS 198-1 標準 (PDF) 計算和驗證基於雜湊的訊息認證碼。
要使用的摘要演算法在傳遞給 generateKey() 的 HmacKeyGenParams 物件,或傳遞給 importKey() 的 HmacImportParams 物件中指定。
HMAC 演算法對簽名和驗證使用相同的演算法和金鑰:這意味著驗證金鑰必須保密,這又意味著此演算法不適用於許多簽名用例。然而,當簽名方和驗證方是同一實體時,它可能是一個不錯的選擇。
示例
注意: 您可以在 GitHub 上 嘗試工作示例。
RSASSA-PKCS1-v1_5
此程式碼獲取文字框的內容,對其進行編碼以便籤名,然後使用私鑰進行簽名。 在 GitHub 上檢視完整的原始碼。
/*
Fetch the contents of the "message" textbox, and encode it
in a form we can use for the sign operation.
*/
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
此程式碼獲取文字框的內容,對其進行編碼以便籤名,然後使用私鑰進行簽名。 在 GitHub 上檢視完整的原始碼。
/*
Fetch the contents of the "message" textbox, and encode it
in a form we can use for the sign operation.
*/
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
此程式碼獲取文字框的內容,對其進行編碼以便籤名,然後使用私鑰進行簽名。 在 GitHub 上檢視完整的原始碼。
/*
Fetch the contents of the "message" textbox, and encode it
in a form we can use for the sign operation.
*/
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
此程式碼獲取文字框的內容,對其進行編碼以便籤名,然後使用金鑰進行簽名。 在 GitHub 上檢視完整的原始碼。
/*
Fetch the contents of the "message" textbox, and encode it
in a form we can use for the sign operation.
*/
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(金鑰生成、簽名和驗證)
此程式碼生成一個 Ed25519 簽名金鑰對,使用私鑰簽名文字 <input> 的(編碼後的)內容,然後使用公鑰驗證簽名。它改編自 GitHub 上的此原始碼,您可以在 此處線上執行。
HTML
HTML 定義了一個包含要簽名文字的 <input> 元素,以及一個啟動操作(建立金鑰、簽名文字、然後驗證簽名)的按鈕。
<label for="message">Enter a message to sign:</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 首先獲取 #sign-button 和 #message <input> 元素,然後為按鈕的 click 事件新增一個監聽器。事件處理程式會清除日誌並執行其他操作,將 <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);
});
首先,它使用 Ed25519 演算法生成金鑰,然後對文字進行編碼並使用私鑰對該文字進行簽名。最後,它使用公鑰呼叫 SubtleCrypto.verify() 來驗證簽名。
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);
}
}
結果
規範
| 規範 |
|---|
| Web 加密級別 2 # SubtleCrypto-method-sign |
瀏覽器相容性
載入中…
另見
SubtleCrypto.verify().- RFC 3447 指定了 RSASSA-PKCS1-v1_5。
- RFC 3447 指定了 RSA-PSS。
- FIPS-186 指定了 ECDSA。
- FIPS 198-1 指定了 HMAC。