SubtleCrypto: encrypt() 方法
SubtleCrypto
接口的 encrypt()
方法对数据进行加密。
它接受以下参数:用于加密的 密钥、一些特定于算法的参数,以及要加密的数据(也称为“明文”)。它返回一个 Promise
,该承诺将以加密后的数据(也称为“密文”)作为结果。
语法
encrypt(algorithm, key, data)
参数
algorithm
-
一个对象,指定要使用的 算法 以及任何必需的额外参数
- 要使用 RSA-OAEP,请传递一个
RsaOaepParams
对象。 - 要使用 AES-CTR,请传递一个
AesCtrParams
对象。 - 要使用 AES-CBC,请传递一个
AesCbcParams
对象。 - 要使用 AES-GCM,请传递一个
AesGcmParams
对象。
- 要使用 RSA-OAEP,请传递一个
key
-
一个
CryptoKey
,包含用于加密的密钥。 data
-
一个
ArrayBuffer
、一个TypedArray
或一个DataView
,包含要加密的数据(也称为 明文)。
返回值
一个 Promise
,以包含“密文”的 ArrayBuffer
作为结果。
异常
当遇到以下异常时,承诺将被拒绝
InvalidAccessError
DOMException
-
当请求的操作对于提供的密钥无效时引发(例如,无效的加密算法,或特定加密算法的无效密钥)。
OperationError
DOMException
-
当操作因特定于操作的原因而失败时引发(例如,算法参数大小无效,或 AES-GCM 明文长度超过 239−256 字节)。
支持的算法
Web Crypto API 提供四种支持 encrypt()
和 decrypt()
操作的算法。
其中一种算法 — RSA-OAEP — 是一种 公钥密码系统。
这里介绍的其他三种加密算法都是 对称算法,它们都基于相同的底层密码 AES(高级加密标准)。它们之间的区别在于 模式。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。nonce 不需要保密,但不能在使用同一个密钥时重复使用。
- 一个计数器。这个部分在每次加密块时都会递增。
本质上:nonce 应该确保计数器块不会从一个消息重用到另一个消息,而计数器应该确保计数器块不会在一个消息内被重用。
注意:有关详细信息,请参阅 NIST SP800-38A 标准的附录 B。
AES-CBC
这表示 AES 采用密码分组链接模式,如 NIST SP800-38A 中所述。
AES-GCM
这表示 AES 采用伽罗瓦/计数器模式,如 NIST SP800-38D 中所述。
这种模式与其他模式的一个主要区别是,GCM 是一种“带认证的”模式,这意味着它包括检查密文是否被攻击者修改。
示例
注意:你可以在 GitHub 上 尝试运行示例。
RSA-OAEP
此代码获取文本框的内容,对其进行编码以供加密,并使用 RSA-OAEP 进行加密。 在 GitHub 上查看完整的代码。
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 上查看完整的代码。
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,
);
}
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 上查看完整的代码。
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: iv,
},
key,
encoded,
);
}
AES-GCM
此代码获取文本框的内容,对其进行编码以供加密,并使用 AES 采用 GCM 模式进行加密。 在 GitHub 上查看完整的代码。
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: iv },
key,
encoded,
);
}
规范
规范 |
---|
Web Cryptography API # SubtleCrypto-method-encrypt |
浏览器兼容性
BCD 表格仅在浏览器中加载
另请参阅
SubtleCrypto.decrypt()
.- RFC 3447 指定 RSAOAEP。
- NIST SP800-38A 指定 CTR 模式。
- NIST SP800-38A 指定 CBC 模式。
- NIST SP800-38D 指定 GCM 模式。