Crypto之AES加密

crypto模块是node.js里的加密模块,提供非对称/对称等加密方法。

AES是项目中常用的非对称加密算法,接下来看看如何使用node.js进行加解密的。

AES简介

AES(英语:Advanced Encryption Standard,缩写:AES), 高级加密标准, 对称加密算法之一。

在linux下执行如下命令查看支持的AES加密模式:

1
2
3
4
openssl list -cipher-algorithms

aes-128-cbc aes-128-ecb aes-192-cbc aes-192-ecb aes-256-cbc
aes-256-ecb

AES密钥长度则可以是128,192或256比特,也就是16,24,32字节。

具体的加密原理参考高级加密标准

准备条件

1
2
3
algorithm: aes-128-cbc  // 算法
key: 8U*JzqV@&7yXBmdc // 密钥, 长度油算法决定
iv: 5aeb293e76a71930 // 初始向量,固定16字节

show me code

node.js原声模块crypto提供了如何AES加密,用到了Cipher和Decipher.

1
2
3
4
5
const crypto = require('crypto')

const algorithm = 'aes-128-cbc'
const key = '8U*JzqV@&7yXBmdc'
const iv = '5aeb293e76a71930'

Cipher和Decipher对象不能通过new关键字声明,只能由crypto.createCipheriv()和crypto.createDecipheriv()创建。

Cipher 加密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 调用crypto的createCipheriv方法创建一个加密对象
const cipher = crypto.createCipheriv(algorithm, key, iv)

// 对数据进行加密
// 如果指定了inputEncoding,那它的值必须是'utf8', 'ascii', or 'latin1'中的一个,并且data数据也是对应的encoding字符串.
// 如果没有指定inputEncoding,data必须是Buffer, TypedArray, or DataView.
// 如果data是Buffer, TypedArray, or DataView, 则忽略inputEncoding.
// 如果没有指定密文的输出格式outputEncoding,将会返回Buffer.
// 如果指定了outputEncoding,将返回指定outputEncoding的字符串,outputEncoding支持'latin1', 'base64' or 'hex'
let encrypted = cipher.update(data[, inputEncoding][, outputEncoding])

// cipher.update()可以执行多次,直到cipher.final([outputEncoding])被调用.
// 在cipher.final()方法调用后,cipher.update()将不可再调用,否则会报错.
// encrypted将是最终的密文
encrypted += cipher.final(outputEncoding)

Decipher 解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 调用crypto的createDecipheriv方法创建一个解密对象
const decipher = crypto.createDecipheriv(algorithm, key, iv)

// 对数据进行解密
// 如果指定了inputEncoding,那它的值必须是'latin1', 'base64', or 'hex'中的一个,并且data数据也是对应的encoding字符串.
// 如果没有指定inputEncoding,data必须是Buffer.
// 如果data是Buffer,则忽略inputEncoding.
// 如果没有指定密文的输出格式outputEncoding,将会返回Buffer.
// 如果指定了outputEncoding,将返回指定outputEncoding的字符串,outputEncoding支持'latin1', 'ascii' or 'utf8'
let decrypted = decipher.update(data[, inputEncoding][, outputEncoding])

// decipher.update()可以执行多次,直到decipher.final([outputEncoding])被调用.
// 在decipher.final()方法调用后,decipher.update()将不可再调用,否则会报错.
// decrypted将是最终的明文
decrypted += decipher.final([outputEncoding])

AES 加解密🌰

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const crypto = require('crypto')

const algorithm = 'aes-128-cbc'
const key = '8U*JzqV@&7yXBmdc'
const iv = '5aeb293e76a71930'

// 解密
function decipher(ciphertext) {
let decip = crypto.createDecipheriv(algorithm, key, iv)
return decip.update(ciphertext, 'base64', 'utf8') + decip.final('utf8')
}

// 加密
function cipher(data) {
let cip = crypto.createCipheriv(algorithm, key, iv)
return cip.update(data, 'utf8', 'base64') + cip.final('base64')
}

let data = 'helloworld'
let result = cipher(data)
console.log(decipher(result))

总结

  1. 如果加解密的都是Buffer,就没有什么编码的问题
  2. 加密使用了编码,那么inputEncoding可选’utf8’, ‘ascii’, or ‘latin1’,outputEncoding可选’latin1’, ‘base64’ or ‘hex’
  3. 解密使用了解码,那么inputEncoding可选’latin1’, ‘base64’, or ‘hex’,outputEncoding可选’utf8’, ‘ascii’ or ‘latin1’

  1. 高级加密标准
  2. node.js 对称加密文档
  3. node.js 对称解密文档