AES算法(十一) NodeJS 环境中实战
本篇将对 AES 算法在 NodeJS 环境中应用做个简单的实战讲解,因为 NodeJS 提供了内置加密模块 crypto ,提供了绝大多数的加密算法的实现,本篇将基于 crypto 模块来做演示,因为文本长度有限,仅展示核心步骤,如需查看完整实现,请移步源码:https://github.com/aurthurxlc/js-aes-examples 。
NodeJS 内核中的 crypto 模块提供了各种各样加密算法的 API,该模块需要底层系统提供 OpenSSL 的支持。
本篇仅对其中的 AES 算法做简单的讲解,如想了解 NodeJS 更多的加密算法,可移步官方文档:https://nodejs.org/api/crypto.html 。
下面就来一一讲解 NodeJS 中 AES 算法加密、解密的核心点,如有看不明白的地方,请先查看一下前面的理论篇章。
AES 加密、解密核心点
1. 首先要引入 crypto 模块
const crypto = require("crypto");
2. 初始化加密函数
const cipher = crypto.createCipheriv(algorithm, key, iv);
初始化加密函数的 algorithm 参数用于指定加密所使用的算法,例如 AES-128-CBC
。
- 其中 AES-128 表示使用 AES 128 位算法,其他可选:
AES-192
、AES-256
- CBC 表示加密模式,其他可选:
CFB
、OFB
、CTR
、GCM
(ECB 模式安全性较差,不做推荐)
key 参数接受 Buffer 类型参数,示例如下:
const key = Buffer.from("e43ee68382dc550fbd1d329486febdd4", "hex");
iv 参数接受 Buffer 类型参数,示例如下:
const iv = Buffer.from("ddffc44a93503156abb36e9bbca876f8", "hex");
3. 加密数据
// toHex
let cText = cipher.update(pText, "utf-8", "hex");
cText += cipher.final("hex");
4. 初始化解密函数
const decipher = crypto.createDecipheriv(algorithm, key, iv);
解密函数所用参数应与加密函数相同,否则无法解密。
5. 解密数据
let dText = decipher.update(cText, "hex", "utf-8");
dText += decipher.final("utf8");
6. 输出结果
console.log("key:" + key.toString("hex"));
console.log("iv:" + iv.toString("hex"));
console.log("明文:" + pText);
console.log("加密后数据:" + cText);
console.log("解密密后数据: " + dText);
// 输出如下,跟 Java 输出结果一致
key:e43ee68382dc550fbd1d329486febdd4
iv:ddffc44a93503156abb36e9bbca876f8
明文:AES 算法基于 Java 实战演示
加密后数据:e8aa678c21aa028988cd74ee2835344519014a4e9365cb8dda7cf24bfe95dfdf0e047cf979587b02500ccad15415b1c3
解密密后数据: AES 算法基于 Java 实战演示
7. 填充模式
上面的函数都不涉及数据填充模式,怎么就结果和 Java 一致了?难道 NodeJS 环境下的 AES 算法解密都不用填充吗?由理论可知,这是不可能的。
翻看 API 文档可知 NodeJS 的加密/解密函数默认是自动填充的,见文档:https://nodejs.org/api/crypto.html#crypto_cipher_setautopadding_autopadding
默认是使用的 PKCS7 填充模式(所以我们未指定填充模式也可以等到跟 Java 相同的加密结果)。
如果需要使用自定义的填充模式,可以使用方法cipher.setAutoPadding(false)
禁用自动填充,再自行将数组补齐即可,若自行填充后的数据长度不符合要求,cipher.final()
函数将会报错。
crypto 模块 AES 相关核心点说明
crypto 模块常用函数
crypto.createCipheriv(algorithm, key, iv[, options])
- 创建 Cipher 加密类对象的函数,并不局限于 AES 算法
- algorithm 参数可选 OpenSSL 算法库支持的所有算法,上文只列举了跟 AES 有关的参数,可用命令
openssl list-cipher-algorithms
查看所支持的算法列表 - key 、iv 参数仅接受 Buffer 类型参数
crypto.createDecipheriv(algorithm, key, iv[, options])
- 创建 Decipher 解密类对象的函数,并不局限于 AES 算法,参数同上加密函数
Cipher 类常用函数
cipher.update(data[, inputEncoding][, outputencoding])
- data
- 表示添加要加密的数据
- 具体数据格式可以是 字符串、二进制等
- inputEncoding(可选)
- 用于指定 data 的数据类型
- 可选参数:
utf-8
、binary
、ascii
,默认是binary
- 如果不指定,data 参数必须是 Buffer 类型
- outputEncoding(可选)
- 用于指定 update 函数返回值的类型
- 可选参数:
binary
、base64
、hex
,默认是binary
- 如果不指定 update 函数返回值将是 Buffer 类型
cipher.setAutoPadding([autoPadding])
- autoPadding(可选)
- 用于指定是否自动填充数据
- 可选参数:
true
、false
- 默认为 true,启用自动填充模式,自动填充模式采用的填充方式是:PKCS7
cipher.final([outputEncoding])
- outputEncoding(可选)
- 用于指定 final 函数返回值的类型
- 可选参数:
binary
、base64
、hex
,默认是binary
- 如果不指定 final 函数返回值将是 Buffer 类型
Decipher 常用函数
decipher.update(data[, inputEncoding][, outputencoding])
- 参数同上加密函数
decipher.setAutoPadding([autoPadding])
- 参数同上加密函数
decipher.final([outputEncoding])
- 参数同上加密函数