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

浏览器兼容性

另见