本科实验报告
课程名称:姓 名:实 验:系:专 业:学 号:指导教师:
信息与通信安全 邓敏 实验一
信电系 信息与通信工程 3110100978 谢磊
年 月 日
AES 与基于AES 的CMAC
一、实验目的
1、熟悉AES加解密过程,掌握其算法实现; 2、熟悉CMAC生成过程,掌握其算法实现。
二、实验任务
1、复习AES 原理;
2、用C/C++ 编写AES 算法并调试通过; 3、复习CMAC 原理;
4、在实现 AES 基础上,用C/C++ 编写CMAC 算法并调试通过。
三、实验原理
1.AES原理
AES加解密过程如下图所示,明文分组的长度为128位即16字节,秘钥长度可以为16,24或32字节(128,182或256位)。根据秘钥的长度,算法被称为AES-128、AES-192、或AES-256,本次实验采用AES-128。
1.1AES加密过程
AES明文输入为一个128位分组,在代码实现中被描述为4x4的字节方阵,一般称其为state数组,并且按照如下方式填入到数组当中,原始密钥也为128为分组,并按同样的方式填入数组。
k0 k4 k8 k12 in0 in4 in8 in12 in1 in2 in3 in5 in6 in7 in9 in10 in11 in13 in14 in15 k1 k2 k3 k5 k6 k7 k9 k10 k11 k13 k14 k15 AES加密过程共进行十轮,前九轮由四个步骤组成,四个步骤依次为字节代替(SubBytes),行移位(ShiftRows),列混淆(MixColumns),轮密钥加(AddRoundKey),第十轮依次进行除列混淆的三个步骤。 1.1.1字节代替
AES定义了一个S盒,它是由16x16个字节组成的矩阵,包含了8位所能表示的256个数的一个置换,字节代替将输入字节的高四位作为行值,低四位作为列值,以这些行列值作为索引从S盒的对应位置取出元素作为输入。 1.1.2行移位变换
行移位变换完成基于行的循环移位操作,state的第0行不动,第1行循环左移1个字节,第2行循环左移2个字节,第3行循环左移3个字节。 1.1.3列混淆
列混淆变换的正向列混淆变换对每列独立地进行操作。每列中的每个字节被映射为一个新值,此值由该列中的四个字节通过函数变换得到,这个变换可由下面基于state的矩阵乘法表示。
状态中单列的列混淆变换可表示为
's0,j?(2*s0,j)?(3*s1,j)?s2,j?s3,js1',j?s0,j?(2*s1,j)?(3*s2,j)?s3,js'2,j?s0,j?s1,j?(2*s2,j)?(3*s3,j)
's3,j?(3*s0,j)?s1,j?s2,j?(2*s3,j)1.1.4轮密钥加
轮密钥加变换用于将输入或中间态S的每一列与一个密钥字W[i]进行按位异或,其中, W[i]由原始密钥通过密钥扩展算法产生。 1.2AES解密过程
AES解密过程为加密过程的逆,同为十轮,四个步骤按一定顺序执行,四个步骤分别为逆向字节替代(InvSubBytes),逆向行移位(InvShiftRows),逆向列混淆(InvMixColumns),轮密钥加(AddRoundKey),其中轮密钥加与加密过程中的步骤相同。 1.2.1逆向字节替代
AES定义了一个逆S盒,其替代方法与加密过程相同
1.2.2逆向行移位
逆向行移位与行移位变换相反,逆行移位变换将态State的后三行按相反的方向进行移位操作,即第0行保持不变,第1行向右移1个字节,第2行向右移2个字节,第3行向右移3个字节。 1.2.2逆向列混淆
逆列混淆变换的处理方法与列混淆变换类似,每一列都通过与一个固定的多项相乘进行变换。 写为矩阵乘法的形式,逆列混淆变换按以下方式对列进行变换:
1.3AES秘钥扩展
AES加密解密过程中,每一轮都需要一个与输入分组具有相同长度的扩展密钥W[i]的参与。由于外部输入的加密密钥长度有限,所以在算法中要用一个密钥扩展程序把外部密钥扩展成更长的比特串,以生成各轮的加密和解密密钥。其一轮过程如下图所示,一共需要进行十次,由原密钥扩展出10个密钥,分别用于每轮加解密。
其中g函数为行移位,自己替代以及与轮常量异或。
2.CMAC原理
CMAC为基于密码的消息认证码,生成认证码的过程课分为两种。
首先,当消息长度是分组长度b的n倍时,在此我们选择b=128,可将消息换分为n组(M1,M2.......Mn)。算法使用了k位的加密密钥K和n位的常数K1.对于AES,密钥长度k为128、192或256位,在此我们选择128位,CMAC按如下方式计算
C1?E(K,M1)C2?E(K,[M2?C1]) ?
Cn?E(K,[Mn?Cn?1?K1])T?MSBTlen(Cn)其中,T为消息认证码,也成为tag;Tlen是T的位长度,MSBs(X)是位串的X最左边的s位。
如果消息不是密文分组长度的整数倍时,则最后分组的右边(低有效位)填充一个1和若干0使得最后的分组长度为b。除了使用一个不同的n位密钥K2代替K1外,和前面所述的一样进行CMAC运算。
两个n位的密钥由K位的加密密钥按如下方式导出:
L?E(K,0n) K1?L*xK2?L*x2?(L*x)*x
其中乘法(*)在域GF(2^n)内进行。
四、AES模块代码实现
1、字节替代
state值由16进制表示,因此state[r][c]=16i+j,i为高四位,j为低4位,s盒为16x16矩阵,因此只需用state[r][c] = sbox[state[r][c]]即可完成字节替代。其实现代码如下: void SubBytes(unsigned char state[4][4]) { int r,c; for(r=0; r<4; r++) { for(c=0; c<4; c++) { state[r][c] = sbox[state[r][c]]; } } }
2、行移位
代码实现时,一行一行的完成,因为第一行不变,因此行移位由r=1开始到r=3,定义一个中间数组变量存储移位后改行每列的值,变换可由t[c] = state[r][(c+r)%4]实现,例如当r=1,c=1,t[1]=state[2],r=1,c=3,t[3]=state[0],即完成了第一行的移位,然后再将t[c]赋值回state[r][c]即可。模块代码实现如下: void ShiftRows(unsigned char state[][4]) { unsigned char t[4]; int r,c; for(r=1; r<4; r++)