AES实验报告
一、实验题目
AES加密算法
二、实验目的和要求
通过实验,掌握AES密码的程序实现,熟悉比特串的操作,矩阵变换,有限域上的乘法,提高C++程序设计能力.
编写 AES 密码的加密解密程序,运行并验证。 (1) 输入 128 比特明文和密文,利用 AES 密码对其加密并输出密文。 (2) 输入 AES 加密的 128 比特密文和密钥,对其进行解密。 (3) 记录调试和验证过程,完成实验报告。
三、实验环境
clion
四、实验内容
1. AES 算法:
包括:字节代换,行移位,列混合,密钥加。 128 比特的种子密钥𝑁𝑘 = 4,即 4 个 32 比特的密钥字,每个密钥字是由 4 个字 节构成,形成 4×4 的矩阵。一个字 4 行,4 个字 4 列。 128 比特的分组长度𝑁𝑏 = 4,即 4 个 32 比特的字,每个字是由 4 个字节构成, 形成 4×4 的矩阵。一个字 4 行,4 个字 4 列。 矩阵按照列为主索引,第一行,0,4,8,12。 2. 每一个元素的运算具体涉及有限域的乘法,幂运算,求逆元。
表示一个元素:两个 16 进制,8 位,一个字节。
五、算法描述及实验步骤
1 | 1.KeyExpansions—-轮密钥使用Rijndael算法的密钥编排密码密钥导出。 |
AES轮函数过程:
字节替换(SubBytes):S盒把字节映射到自己的乘法逆元,再对字节做仿射变换
行移位(ShiftRows):将状态阵列的各行,进行循环移位。不同行位移量不同。位移量的取值与Nb有关
列混淆(MixColumns):将状态阵列视为多项式,与固定多项式进行模的乘法。且要求可逆
密钥加(AddRoundKey):将轮密钥与状态进行逐比特异或。长度=分组长度Nb。密钥加的逆运算是自己。
算法中间结果的分组为状态
密钥编排:
密钥扩展:
由种子密钥扩展,以四字节为元素的一维阵列。轮密钥的总比特数=Nb✖️(轮数 +1)。Nk为列数,前Nk个字为种子密钥。
$$W[N_b*(N_r+1)]$$
Nk≤6:
W[i]=Nk个字长的一段首尾两个字异或;
为Nk整倍时,先将前一个字w[i-1]进行变换:一字节循环移位RotByte → S盒SubByte → 异或常数Rcon[i/Nk]
Nk>6:
Nk整倍数保持一致。 除Nk余4时,w[i-1]执行SubByte
轮密钥选取:
轮函数的选取,从扩展密钥中选每轮选Nb长度的,如此往复。
六、调试过程及结果(附截图)
⭐️运行时遇到:This file does not belong to any project target code insight 在cmake文件中,add_executable把fields.cpp添加进去
1 | ✨✨ **调试成功✨✨** |
1 | ✨✨**运行结果**✨✨ |
☀️☀️修改了main部分,以字符形式输出
1 | int main() |
七、总结体会
❓代码如何进行有限域的乘法?
第1步将数字转换成多项式表达式;第2步是常规的乘法运算,即将多项式乘法展开; 第3步与既约多项式;
xtime(·)算法:
求一个数x与0x02的乘积,一般求一个数的2倍,都是左移一位,在有限域内,要计算有限域的乘法,必须先确定一个GF上的8次不可约多项式,Rijndael密码中,这个多项式确定为x^8+x^4+x^3+x+1
在二进制中,所有的数都能用0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80异或得到,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80的二进制表示如下:
而任何一个数x和a相乘都可以表示为
$$x *a=x(08\oplus02\oplus04\oplus01\oplus80)$$
计算出:则所有乘法结果都可以得到
这种方式,可以用矩阵表示出来
1 | ////*****************************列混合*********************************//// |