1.AES
1 | AES(Advanced Encryption Standard)是取代其前任标准(DES)而成为新标准的一种对称密码算法。全世界的企业和密码学家提交了多个对称密码算法作为AES的候选,最终在2000年从这些候选算法中选出了一种名为==Rijndael==的对称密码算法,并将其确定为了AES。 |
2.AES的加密和解密
0123456789ABCDEF
ABCDEFGHIJKLMNOP
1 | 和DES—样,AES算法也是由多个轮所构成的,下图展示了每一轮的大致计算步骤。DES使用Feistel网络作为其基本结构,而AES没有使用Feistel网络,而是使用了SPN Rijndael的输人分组为128比特,也就是16字节。 |
1 | SubBytes -- 字节代换 |
下图展示了AES中一轮的解密过程。从图中我们可以看出,SubBytes、ShiftRows、MixColumns分别存在反向运算InvSubBytes、InvShiftRows、InvMixColumns,这是因为AES不像Feistel网络一样能够用同一种结构实现加密和解密。
1 | InvSubBytes -- 逆字节替代 |
3.Go中对AES的使用
加解密实现思路
加密 - CBC分组模式
1
2
3
4
5
6
71. 创建并返回一个使用AES算法的cipher.Block接口
- 秘钥长度为128bit, 即 128/8 = 16字节(byte)
2. 对最后一个明文分组进行数据填充
- AES是以128比特的明文(比特序列)为一个单位来进行加密的
- 最后一组不够128bit, 则需要进行数据填充
3. 创建一个密码分组为链接模式的, 底层使用AES加密的BlockMode接口
4. 加密连续的数据块
解密
1
2
3
41. 创建并返回一个使用AES算法的cipher.Block接口
2. 创建一个密码分组为链接模式的, 底层使用AES解密的BlockMode接口
3. 数据块解密
4. 去掉最后一组的填充数据
加解密的代码实现
AES加密代码
1 | // AES加密 |
AES解密
1 | // AES解密 |
重要的函数说明
生成一个底层使用AES加解密的Block接口对象
1
2
3
4函数对应的包: import "crypto/aes"
func NewCipher(key []byte) (cipher.Block, error)
- 参数 key: aes对称加密使用的密码, 密码长度为128bit, 即16byte
- 返回值 cipher.Block: 创建出的使用AES加/解密的Block接口对象创建一个密码分组为CBC模式, 底层使用b加密的BlockMode接口对象
1
2
3
4
5函数对应的包: import "crypto/cipher"
func NewCBCEncrypter(b Block, iv []byte) BlockMode
- 参数 b: 使用aes.NewCipher函数创建出的Block接口对象
- 参数 iv: 事先准备好的一个长度为一个分组长度的比特序列, 每个分组为64bit, 即8byte
- 返回值: 得到的BlockMode接口对象使用cipher包的BlockMode接口对象对数据进行加解密
1
2
3
4
5
6
7
8
9
10接口对应的包: import "crypto/cipher"
type BlockMode interface {
// 返回加密字节块的大小
BlockSize() int
// 加密或解密连续的数据块,src的尺寸必须是块大小的整数倍,src和dst可指向同一内存地址
CryptBlocks(dst, src []byte)
}
接口中的 CryptBlocks(dst, src []byte) 方法:
- 参数 dst: 传出参数, 存储加密或解密运算之后的结果
- 参数 src: 传入参数, 需要进行加密或解密的数据切片(字符串)创建一个密码分组为CBC模式, 底层使用b解密的BlockMode接口对象
1
2
3
4
5
6函数对应的包: import "crypto/cipher"
func NewCBCDecrypter(b Block, iv []byte) BlockMode
- 参数 b: 使用des.NewCipher函数创建出的Block接口对象
- 参数 iv: 事先准备好的一个长度为一个分组长度的比特序列, 每个分组为128bit, 即16byte,
该序列的值需要和NewCBCEncrypter函数的第二个参数iv值相同
- 返回值: 得到的BlockMode接口对象