openssl-对称AES算法(一)

Posted by 周思进 on April 16, 2022

本文对 AES 算法比较常见的几个问题点进行梳理说明。

一、块分组长度

AES 作为块密码算法,加解密的时候,需要将操作数据按固定长度的数据块进行分组后再进行处理。对于AES算法,其分组长度都是固定16字节大小。

AES 密钥长度(字节) 分组长度(字节) 加密轮数
AES-128 16 16 10
AES-192 24 16 12
AES-256 32 16 14


二、初始向量

AES 有不同的分组模式,像 ECB 属于最简单的模式,每个分组独立加解密处理,但这种模式是存在安全问题的,不建议使用。而 AES-CBC 分组模式则是比较常用的。

CBC 加密首先是将明文分成固定长度的块,然后将前面一个加密块加密后的密文和下一个明文块进行异或操作,将计算后的结果再用密钥进行加密得到第二个密文块,于此类推与剩余的明文块加密。那第一个明文块加密的时候,因为前面没有被加密的密文,固需要一个初始化向量替代使用。也因此初始化向量长度等于块分组长度。

在使用对称密钥加密时,初始化向量尽量不要重复,否则同样的明文和密钥计算的的密文就是一样的;也因此通常需要把初始化向量和加密数据一起发送给对方。


三、填充方式

对于 CBC 分组模式,如果最后一个分组块长度不足该算法分组固定长度,则需要进行字节填充。针对填充机制,有多种标准,如下是 openssl 库头文件 evp.h 中的声明

/* Padding modes */
#define EVP_PADDING_PKCS7       1
#define EVP_PADDING_ISO7816_4   2
#define EVP_PADDING_ANSI923     3
#define EVP_PADDING_ISO10126    4
#define EVP_PADDING_ZERO        5

默认使用 PKCS7 填充方式,其填充方式就是差多少个字节,就用差的值作为填充值,比如差3个字节,则末尾用3个 03 03 03 字节补充。


四、加密密文长度

填充情况下:
AES 密文长度 = (原文长度/16*16) + 16
或者
AES 密文长度 = (原文长度 + 16) &~ (16-1)