SubtleCrypto.encrypt()
SubtleCrypto.encrypt()
方法以算法、密钥、明文为参数返回一个包含加密数据的 Promise
对象。
语法
var result = crypto.encrypt(algo, key, cleartext)
;
参数
algo
是一个使用加密函数的对象或者DOMString
,后者是{"name": algo}
的缩写。支持的值是:{"name": "AES-CBC", iv}
iv
是具有 16 个随机字节的ArrayBuffer
或ArrayBufferView
(这些应该由RandomSource.getRandomValues()
生成)。{"name": "AES-CTR", counter, length}
{"name": "AES-GCM", iv, additionalData, tagLength}
(additionalData
和tagLength
是可选的){"name": "RSA-OAEP", label}
(label
是可选的)
key
是一个包含签名密钥的CryptoKey
。cleartext
是一个包含需要加密的明文
ArrayBuffer
或者ArrayBufferView
对象。
返回值
- 返回值是一个
Promise
对象,返回一个由 cleartext (en-US) 加密生成的 ciphertext (en-US) 的ArrayBuffer
。
异常
当遇到以下异常时,promise 将会返回一次错误(reject):
- InvalidAccessError
- 当针对提供的 key 值执行的操作无效时(例如加密算法或者 key 值无效),将会抛出该错误。
- OperationError
- 发生于由于特定于操作的原因使得操作失败时,例如算法参数的大小无效,或者 AES-GCM 明文长度超过 2³⁹−256 字节。
支持的算法
Crypto 接口提供了支持 encrypt()
和 decrypt()
操作的四种算法。
其中的 RSA-OAEP 算法是一种非对称加密的公钥密码(public-key cryptosystem (en-US))。
其它三种算法则都是对称密钥加密(symmetric algorithms (en-US)),并且它们都是基于同一种基础加密,即 AES (Advanced Encryption Standard)。它们不同之处在于分组加密的操作方式(mode)。Crypto 接口支持以下三种 AES 加密类型:
- CTR (Counter Mode)
- CBC (Cipher Block Chaining)
- GCM (Galois/Counter Mode)
这里强烈建议使用认证加密(authenticated encryption),它可以检测密文是否已被攻击者篡改。使用认证也可以避免选择密文攻击(chosen-ciphertext attacks),即攻击者可以请求系统解密任意的消息,然后使用解密结果来倒推出关于密钥的一些信息。虽然 CTR 和 CBC 模式可以添加认证,但是它们默认不提供该操作,并且在手动实现它们的时候,很同意犯一些微小但严重的错误。GCM 不支持内置的认证,由于这个原因,常常推荐使用另外两种 AES 加密算法。
RSA-OAEP
关于 RSA-OAEP 公钥加密算法的规范位于 RFC 3447。
AES-CTR
使用 Counter 模式的 AES 算法,相关规范位于 NIST SP800-38A。
AES-CBC
使用 Cipher Block Chaining 模式的 AES 算法,规范位于NIST SP800-38A。
AES-GCM
使用 Galois/Counter 模式的 AES 算法,规范位于 NIST SP800-38D。
这种模式与上面的模式不同之处在于,GCM 是一种 "认证(authenticated)" 模式,意思就是它包含了检测密文是否未被攻击者篡改的功能。
示例
注意: 你可以在 GitHub 尝试这个示例(try the working examples)。
RSA-OAEP
以下代码获取文本框中的内容,编码后进行加密,使用的算法为 RSA-OAEP。可以在 GitHub 查看完整代码:See the complete code on 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 模式加密,完整代码:See the complete code on 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 = new Uint8array(16); let key = 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 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 模式加密,完整代码:See the complete code on 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 }, key, encoded ); }
AES-GCM
使用 AES 的 GCM 模式加密,完整代码:See the complete code on GitHub。
function getMessageEncoding() { const messageBox = document.querySelector(".aes-gcm #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(12)); return window.crypto.subtle.encrypt( { name: "AES-GCM", iv: iv }, key, encoded ); }
规范
Specification | Status | Comment |
---|---|---|
Web Cryptography API SubtleCrypto.encrypt() |
Recommendation | Initial definition. |
浏览器兼容性
BCD tables only load in the browser
另见
SubtleCrypto.decrypt()
.- RFC 3447 specifies RSAOAEP.
- NIST SP800-38A specifies CTR mode.
- NIST SP800-38A specifies CBC mode.
- NIST SP800-38D specifies GCM mode.