SubtleCrypto: encrypt() 方法

Baseline 已廣泛支援

此特性已相當成熟,可在許多裝置和瀏覽器版本上使用。自 ⁨2020 年 1 月⁩ 起,所有主流瀏覽器均已支援。

安全上下文: 此功能僅在安全上下文(HTTPS)中可用,且支援此功能的瀏覽器數量有限。

注意:此功能在 Web Workers 中可用。

SubtleCrypto 介面的 encrypt() 方法用於加密資料。

它接收以下引數:用於加密的金鑰、特定於演算法的引數以及要加密的資料(也稱為“明文”)。它返回一個 Promise,該 Promise 將以加密後的資料(也稱為“密文”)來fulfilled。

語法

js
encrypt(algorithm, key, data)

引數

algorithm

一個物件,指定要使用的演算法以及任何需要的額外引數

key

一個包含用於加密的金鑰的 CryptoKey 物件。

data

一個 ArrayBuffer、一個 TypedArray 或一個 DataView,其中包含要加密的資料(也稱為 明文)。

返回值

一個 Promise,它將以一個包含“密文”的 ArrayBuffer 來fulfilled。

異常

當遇到以下異常時,Promise 將被 rejected

InvalidAccessError DOMException

當提供的金鑰不適用於請求的操作時(例如,無效的加密演算法,或指定的加密演算法的金鑰無效)丟擲。

OperationError DOMException

當操作由於特定於操作的原因而失敗時(例如,演算法引數大小無效,或 AES-GCM 明文長度超過 239−256 位元組)丟擲。

支援的演算法

Web Crypto API 提供了四種支援 encrypt()decrypt() 操作的演算法。

其中一種演算法——RSA-OAEP——是公鑰加密系統

這裡的另外三種加密演算法都是對稱演算法,並且它們都基於相同的底層密碼 AES(Advanced Encryption Standard)。它們之間的區別在於模式。Web Crypto API 支援三種不同的 AES 模式:

  • CTR(計數器模式)
  • CBC(密碼塊連結模式)
  • GCM(伽羅瓦/計數器模式)

強烈建議使用*認證加密*,它包含對密文未被攻擊者修改的檢查。認證有助於防止*選擇密文*攻擊,在這種攻擊中,攻擊者可以要求系統解密任意訊息,並利用結果推斷出關於金鑰的資訊。雖然可以在 CTR 和 CBC 模式中新增認證,但它們預設不提供,並且在手動實現時很容易犯下細微但嚴重的錯誤。GCM 提供了內建認證,因此通常比其他兩種 AES 模式更受推薦。

RSA-OAEP

RSA-OAEP 公鑰加密系統在 RFC 3447 中進行了規定。

AES-CTR

這代表了計數器模式下的 AES,如 NIST SP800-38A 中所述。

AES 是一種分組密碼,意味著它將訊息分割成若干個塊並逐塊加密。在 CTR 模式下,每次加密訊息塊時,都會混合額外的加密塊。這個額外的塊稱為“計數器塊”。

給定的計數器塊值必須永遠不能與同一金鑰一起使用超過一次。

  • 給定一個長度為 *n* 個塊的訊息,必須為每個塊使用不同的計數器塊。
  • 如果使用相同的金鑰加密多個訊息,則必須為所有訊息的所有塊使用不同的計數器塊。

通常透過將初始計數器塊值分成兩個連線的部分來實現:

  • 一個 nonce(即,僅使用一次的數字)。塊的 nonce 部分對於訊息中的每個塊都保持不變。每次要加密新訊息時,都會選擇一個新的 nonce。Nonces 不必保密,但不能與同一金鑰重複使用。
  • 一個計數器。當加密每個塊時,這個塊部分會遞增。

本質上:nonce 應確保計數器塊不會在訊息之間重複使用,而計數器應確保計數器塊不會在單個訊息內部重複使用。

注意: 有關更多資訊,請參閱 NIST SP800-38A 標準的附錄 B

AES-CBC

這代表了密碼塊連結模式下的 AES,如 NIST SP800-38A 中所述。

AES-GCM

這代表了伽羅瓦/計數器模式下的 AES,如 NIST SP800-38D 中所述。

此模式與其他模式的一個主要區別是 GCM 是“認證”模式,這意味著它包含對密文未被攻擊者修改的檢查。

示例

注意: 您可以在 GitHub 上嘗試工作示例

RSA-OAEP

此程式碼獲取文字框的內容,對其進行編碼以進行加密,並使用 RSA-OAEP 進行加密。在 GitHub 上檢視完整程式碼。

js
function getMessageEncoding() {
  const messageBox = document.querySelector(".rsa-oaep #message");
  let message = messageBox.value;
  let enc = new TextEncoder();
  return enc.encode(message);
}

function encryptMessage(publicKey) {
  let encoded = getMessageEncoding();
  return window.crypto.subtle.encrypt(
    {
      name: "RSA-OAEP",
    },
    publicKey,
    encoded,
  );
}

AES-CTR

此程式碼獲取文字框的內容,對其進行編碼以進行加密,並使用 AES CTR 模式進行加密。在 GitHub 上檢視完整程式碼。

js
function getMessageEncoding() {
  const messageBox = document.querySelector(".aes-ctr #message");
  let message = messageBox.value;
  let enc = new TextEncoder();
  return enc.encode(message);
}

function encryptMessage(key) {
  let encoded = getMessageEncoding();
  // counter will be needed for decryption
  counter = window.crypto.getRandomValues(new Uint8Array(16));
  return window.crypto.subtle.encrypt(
    {
      name: "AES-CTR",
      counter,
      length: 64,
    },
    key,
    encoded,
  );
}
js
let iv = window.crypto.getRandomValues(new Uint8Array(16));
let key = window.crypto.getRandomValues(new Uint8Array(16));
let data = new Uint8Array(12345);
// crypto functions are wrapped in promises so we have to use await and make sure the function that
// contains this code is an async function
// encrypt function wants a cryptokey object
const key_encoded = await window.crypto.subtle.importKey(
  "raw",
  key.buffer,
  "AES-CTR",
  false,
  ["encrypt", "decrypt"],
);
const encrypted_content = await window.crypto.subtle.encrypt(
  {
    name: "AES-CTR",
    counter: iv,
    length: 128,
  },
  key_encoded,
  data,
);

// Uint8Array
console.log(encrypted_content);

AES-CBC

此程式碼獲取文字框的內容,對其進行編碼以進行加密,並使用 AES CBC 模式進行加密。在 GitHub 上檢視完整程式碼。

js
function getMessageEncoding() {
  const messageBox = document.querySelector(".aes-cbc #message");
  let message = messageBox.value;
  let enc = new TextEncoder();
  return enc.encode(message);
}

function encryptMessage(key) {
  let encoded = getMessageEncoding();
  // iv will be needed for decryption
  iv = window.crypto.getRandomValues(new Uint8Array(16));
  return window.crypto.subtle.encrypt({ name: "AES-CBC", iv }, key, encoded);
}

AES-GCM

此程式碼獲取文字框的內容,對其進行編碼以進行加密,並使用 AES GCM 模式進行加密。在 GitHub 上檢視完整程式碼。

js
function getMessageEncoding() {
  const messageBox = document.querySelector(".aes-gcm #message");
  const message = messageBox.value;
  const enc = new TextEncoder();
  return enc.encode(message);
}

function encryptMessage(key) {
  const encoded = getMessageEncoding();
  // iv will be needed for decryption
  const iv = window.crypto.getRandomValues(new Uint8Array(12));
  return window.crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, encoded);
}

規範

規範
Web 加密級別 2
# SubtleCrypto-method-encrypt

瀏覽器相容性

另見