174
7
7
-
3
:验证加密操作模式
模式
名称
说明
CCM Counter with CBC-MAC
这是最简单的联合操作模式
如全名所示
CCM
结合了
CTR
CBC
两种操作模式
这个模式也要求提供初始向量
而且消息验证是针对纯文本数据的
加密和解密不能并行
运行
GCM Galois/Counter Mode GCM
使用广泛
因为在效率和性能方便表现的好
CCM
类似
GCM
也使用初始向量
但是消息验证是针对密文的
而不是纯文本数据
加密和解密也跟
CCM
一样
不能并行
运行
KW / KWP / Key Wrapping
一系列提议的密钥封装算法模式
供加密和验证数据
TKW
些模式未得到广泛应用
即便对上述几个表格中的模式有一定的了解,也很难在各分类下选出最好的
模式。不过,业界在各分类下都有最流行的操作模式:
加密:
CTR
(可以并行,速度好)。
验证:
CMAC
(唯一得到认可的模式,不过业界未广泛应用)。
验证加密:
GCM
(业界接受的标准)。
虽然业界有使用广泛的模式,但你应该根据自己在安全、性能和伸缩性上的
要求选择合适的模式。流行并不意味着合适。
现在,我们对操作模式有所了解了,下面举例说明具体用法。先从
CTR
加密
模式的
AES
开始。
使用
CTR
加密模式的
AES
使用
CTR
模式的
AES
示例代码在
https://github.com/iddatasecuritybook/
chapter7/blob/master/symmetric-crypto/aes-ctr.js
数据传输安全
175
现在,我们已经掌握了在特定操作模式下使用加密算法
AES
的核心知识。
这个示例将使用
Node
标准库中的
crypto
包(
https://nodejs.org/api/crypto.
html
),因此无需从
npm
中安装任何模块。在
Node
脚本的顶部添加下述初
始化变量:
var crypto = require('crypto');
接下来,设定这个示例将使用的几个变量:
var text = "Encryption Testing AES";
var key = crypto.randomBytes(32); // 256
位的共享密钥
var iv = crypto.randomBytes(16); //
初始向量,
16
字节
var algorithm = 'aes-256-ctr'; //
加密算法和操作模式
这些变量的作用如下:
text
要加密和解密的数据。
key
32
位共享密钥,供
crypto
库加密和解密使用。我们使用 crypto.
randomBytes(
...
) 方法生成这个字符串。
iv
初始向量,一个
16
字节字符串。我们使用 crypto.randomBytes(
...
) 方法
生成这个字符串。
algorithm
使用的加密算法和操作模式。这里使用的是
CTR
操作模式的
AES
加密算
法。
然后,加密数据,生成密文:
var cipher = crypto.createCipher(algorithm, key, iv);
var encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
首先, crypto.createCipher(
...
)传入算法
/
模式、共享密钥和初始向量,
初始化加密算法。
176
7
然后,调用 cipher.update(
...
) 把数据传给加密算法。传入的参数是要编码的
数据、输入的编码格式 utf8 和输出的编码格式 hex
cipher.update(data, input_encoding, output_encoding)
输入的编码格式(第二个参数)应该是 utf8ascii binary 中的一个。
如果未指定编码,数据(第一个参数)必须是缓冲,此时,输入的编码格式
被忽略。
最后,调用 cipher.final(
...
),传入输出的编码格式,返回密文。
这样,输入的纯文本就被编码了。现在,关于密文和解密,你要知道几件事:
密文可以传给接收方了。
为了解密,接收方必须知道共享密钥和初始向量。密钥可以在应用(发送
方)和主机(接收方)之间共享,初始向量可以使用一次性令牌,在双方
之间共享。
现在,假设密文已经传给了接收方,而且接收方也知道共享密钥和初始向量。
接下来就可以解密密文,提取纯文本消息了:
var decipher = crypto.createDecipher(algorithm, key, iv);
var decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
首先,调用 crypto.createDecipher(
...
)传入的参数与加密时一样。
然后,调用 decipher.update(
...
)传入密文、密文的编码格式(这里用的是
hex)和输出的编码格式(这里用的是 utf8)。
最后, decipher.final(
...
)传入输出的编码格式,得到最终解码出来的
消息。

Get Web开发的身份和数据安全 now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.