AES加密解密与代码实现详解
先搞定 AES 算法,基本变换包括 SubBytes(字节替代)、ShiftRows(行移 位)、MixColumns(列混淆)、AddRoundKey轮密钥加) 其算法一般描述为 明文及密钥的组织排列方式 ByteSubstitution(字节替代) 非线性的字节替代,单独处理每个字节 求该字节在有限域 GF28上的乘法逆,“0“被映射为自身,即对于α∈GF28, 求 β∈GF28, 使得 αββα1modx8x4x2x1。 对上一步求得的乘法逆作仿射变换 yixi xi4mod8 xi6mod8 xi7mod8 ci 其中 ci是 6310即 011000112的第 i 位),用矩阵表示为 本来打算把求乘法逆和仿射变换算法敲上去,最后还是放弃了.直接打置换表 下面是逆置换表,解密时使用 这里遇到问题了, 本来用纯 c 初始化数组很正常, 封装成类以后发现不能初始化, 不管是声明、构造函数都无法初始化,百歌谷度了一通后没有任何答案,无奈只 能在构造函数中声明一个局部变量数组并初始化,然后用 memcpy,(成员变 量名为 Sbox/InvSbox,局部变量名 sBox/invsBox) ShiftRows(行移位变换) 行移位变换完成基于行的循环位移操作,变换方法 即行移位变换作用于行上,第 0 行不变,第 1 行循环左移 1 个字节,第 2 行循 环左移 2 个字节,第 3 行循环左移 3 个字节。 MixColumns(列混淆变换) 逐列混合,方法 bx 03x3 01x2 01x 02 ax modx4 1 其中 FFmul 为有限域 GF28上的乘法,标准算法应该是循环 8 次(b 与 a 的 每一位相乘,结果相加),但这里只用到最低 2 位,解密时用到的逆列混淆也 只用了低 4 位,所以在这里高 4 位的运算是多余的,只计算低 4 位。 AddRoundKey(轮密钥加变换) 简单来说就是逐字节相加,有限域 GF28上的加法是模 2 加法,即异或 void AESAddRoundKeyunsigned charchar state[][4], unsigned charchar k[][4] { intint r,c; forc0; c4; c { forr0; r4; r { state[r][c] k[r][c]; } } } KeyExpansionKeyExpansion(密钥扩展)(密钥扩展) 将输入的密钥扩展为 11 组 128 位密钥组,其中第 0 组为输入密钥本身 其后第 n 组第 i 列 为 第 n-1 组第 i 列 与 第 n 组第 i-1 列之和(模 2 加法, 1 i 3) 对于每一组 第一列即 i0,有特殊的处理 将前一列即第 n-1 组第 3 列的 4 个字节循环左移 1 个字节, 并对每个字节进行字节替代变换 SubBytes 将第一行(即第一个字节)与轮常量 rc[n]相加 最后再与前一组该列相加 void AESKeyExpansionunsigned charchar* key, unsigned charchar w[][4][4] { intint i,j,r,c; unsigned charchar rc[] {0 x01, 0 x02, 0 x04, 0 x08, 0 x10, 0 x20, 0 x40, 0 x80, 0 x1b, 0 x36}; forr0; r4; r { forc0; c4; c { w[0][r][c] key[rc*4]; } } fori1; i10; i { forj0; j4; j { unsigned charchar t[4]; forr0; r4; r { t[r] j w[i][r][j-1] w[i-1][r][3]; } ifj 0 { unsigned charchar temp t[0]; forr0; r3; r { t[r] Sbox[t[r14]]; } t[3] Sbox[temp]; t[0] rc[i-1]; } forr0; r4; r { w[i][r][j] w[i-1][r][j] t[r]; } } } } 解密的基本运算解密的基本运算 AES 解密算法与加密不同,基本运算中除了 AddRoundKey(轮密钥加)不变 外,其余的都需要进行逆变换,即 InvSubBytes(逆字节替代)、InvShiftRows(逆行移位)、InvMixColumns (逆列混淆) 加密过程加密过程 先将输入的明文按列序组合成 4*4 的矩阵, 直接与第 0 组密钥 (即输入的密钥) 相加(异或),作为轮加密的输入 然后循环 10 次进行 SubBytes、ShiftRows、MixColumns、AddRoundKey 运算,最后恢复原序列 需要注意的是最后一轮并不进行 MixColumns(列混淆变换) unsigned charchar* AESCipherunsigned charchar* { unsigned charchar state[4][4]; intint i,r,c; forr0; r4; r{ forc0; c4 ;c { state[r][c] [c*4r]; } } AddRoundKeystate,w[0]; fori1; i10; i{ SubBytesstate; ShiftRowsstate; ifi10MixColumnsstate; AddRoundKeystate,w[i]; } forr0; r4; r { forc0; c4 ;c{ [c*4r] state[r][c]; } } return ; } 解密过程解密过程 unsigned charchar* AESInvCipherunsigned charchar* { unsigned charchar state[4][4]; intint i,r,c; forr0; r4; r { forc0; c0; i-- { InvShiftRowsstate; InvSubBytesstate; AddRoundKeystate, w[i]; ifiInvMixColumnsstate; } forr0; r4; r { forc0; c4 ;c { [c*4r] state[r][c]; } } return ; } 对外部数据的加密对外部数据的加密/ /解密解密 至此已经实现了 AES 加密与解密的原型, 在使用的时候一般处理的是字符串等,