密码学实验报告.docx
《密码学实验报告.docx》由会员分享,可在线阅读,更多相关《密码学实验报告.docx(26页珍藏版)》请在冰豆网上搜索。
密码学实验报告
目录
AES加密算法实现2
一.实验目的2
二.实验原理2
三.实验步骤2
四.实验结果6
五.实验心得8
六.源代码:
9
RSA加解密算法实现18
一.实验目的:
18
二.实验要求:
18
三.RSA函数主要代码18
四.运算结果显示:
21
五.实验心得21
AES加密算法实现
一.实验目的
1.深入理解AES加密/解密算法理论的基础上,设计一个AES加密/解密软件系统;
2.完成一个明文分组的加解密,明文和密钥是十六进制,长度都为128比特(32个16进制数),输入明文和密钥,输出密文,进行加密后,能够进行正确的解密;
二.实验原理
AES的区块长度固定为128比特,密钥长度则可以是128,192或256比特;
大多数AES计算是在一个特别的有限域完成的。
AES加密过程是在一个4×4的字节矩阵上运作,这个矩阵又称为“状态矩阵”,其初值就是一个明文区块(矩阵中一个元素大小就是明文区块中的一个Byte)。
加密时,各轮AES加密循环(除最后一轮外)均包含4个步骤:
1.SubBytes—通过一个非线性的替换函数,用查找表的方式把每个字节替换成对应的字节。
2.ShiftRows—将矩阵中的每个行进行循环式移位。
3.MixColumns—列混淆。
这个步骤使用线性转换来混合每列的四个字节。
4.AddRoundKey—矩阵中的每一个字节都与该次回合轮密钥(roundkey)做XOR运算;每个子密钥由密钥生成方案产生。
三.实验步骤
(一)加密
1.密钥生成
voidkeyexpansion(unsignedcharS_BOX[][16],unsignedcharkeys[][44]){
unsignedcharRcon[11]={0,1,2,4,8,16,32,64,128,27,54};
unsignedcharpast[4];
registerinti,j;
//打开密钥文件
if((fp=fopen("Key.txt","r"))==NULL)
{
printf("CANNOTOPENTHEFILE!
\n");
return;
}
printf("\n请输入密钥!
\n");
for(i=0;i<=3;i++)
for(j=0;j<=3;j++)
{
fscanf(fp,"%02x",&keys[j][i]);
printf("%02x",keys[j][i]);
}
for(i=4;i<=43;i++){//maketheother40keys
if(i%4==0){//如果能被4整除,特殊处理
for(j=1;j<=4;j++)//把前一个密钥移位赋值给数组
past[j-1]=keys[j%4][i-1];
for(j=0;j<=3;j++){
if(j==0)
keys[j][i]=S_BOX[past[j]/16][past[j]%16]^Rcon[i/4]^keys[j][i-4];
else
keys[j][i]=S_BOX[past[j]/16][past[j]%16]^keys[j][i-4];
}
}
else{
for(j=0;j<=3;j++){
keys[j][i]=keys[j][i-4]^keys[j][i-1];
}
}
}
}
2.字节变换
voidbytesub(unsignedcharS_BOX[][16],unsignedcharB[][4]){
registerinti,j;
for(i=0;i<=3;i++)
for(j=0;j<=3;j++)
B[i][j]=S_BOX[B[i][j]/16][B[i][j]%16];
}
3.行移位
voidshiftrow(unsignedcharB[][4]){
inti,temp;
temp=B[1][0];
for(i=0;i<=2;i++)
B[1][i]=B[1][i+1];
B[1][3]=temp;
for(i=0;i<=1;i++){
temp=B[2][i];
B[2][i]=B[2][i+2];
B[2][i+2]=temp;
}
temp=B[3][3];
for(i=3;i>=1;i--)
B[3][i]=B[3][i-1];
B[3][0]=temp;
}
4.列混合运算
unsignedcharxtime(unsignedcharinput){//x乘法('02'乘法)
inttemp;
temp=input<<1;
if(input&0x80){
temp^=0x1b;
}
returntemp;
}
voidmixcolumn(unsignedcharinput[][4]){//列混合
inti,j;
unsignedcharoutput[4][4];
for(j=0;j<=3;j++)
for(i=0;i<=3;i++)
output[i][j]=xtime(input[i%4][j])//0x02乘法
^(input[(i+1)%4][j]^xtime(input[(i+1)%4][j]))//0x03乘法
^input[(i+2)%4][j]//0x01乘法
^input[(i+3)%4][j];//0x01乘法
for(i=0;i<=3;i++)
for(j=0;j<=3;j++)
input[i][j]=output[i][j];
}
(二)解密运算
1.逆行移位
voidinvshiftrow(unsignedcharB[][4]){
inti,temp;
temp=B[1][3];
for(i=3;i>=1;i--)
B[1][i]=B[1][i-1];
B[1][0]=temp;
for(i=0;i<=1;i++){
temp=B[2][i];
B[2][i]=B[2][i+2];
B[2][i+2]=temp;
}
temp=B[3][0];
for(i=0;i<=2;i++)
B[3][i]=B[3][i+1];
B[3][3]=temp;
}
2.逆列混合运算
voidinvmixcolum(unsignedcharinput[][4]){
inti,j;
unsignedcharoutput[4][4];
for(j=0;j<4;j++)
for(i=0;i<4;i++)
output[i][j]=(xtime(xtime(xtime(input[i%4][j])))^xtime(xtime(input[i%4][j]))^xtime(input[i%4][j]))//0x0E乘法
^(xtime(xtime(xtime(input[(i+1)%4][j])))^xtime(input[(i+1)%4][j])^input[(i+1)%4][j])//0x0B乘法
^(xtime(xtime(xtime(input[(i+2)%4][j])))^xtime(xtime(input[(i+2)%4][j]))^input[(i+2)%4][j])//0x0D乘法
^(xtime(xtime(xtime(input[(i+3)%4][j])))^input[(i+3)%4][j]);//0x09乘法
for(i=0;i<=3;i++)
for(j=0;j<=3;j++)
input[i][j]=output[i][j];}
3.逆字节变换
voidinvbytesub(unsignedcharN_S_BOX[][16],unsignedcharB[][4]){
registerinti,j;
for(i=0;i<=3;i++)
for(j=0;j<=3;j++)
B[i][j]=N_S_BOX[B[i][j]/16][B[i][j]%16];
}
四.实验结果
我将明文设为1343676988d5f68d642390a2e0f5b434,密钥设为2343457828afcdabf7d48809c34f3c57,运行结果如下:
五.实验心得
本程序是处理的AES分组大小和密钥长度都为128位,迭代轮数为10轮。
由于我能力有限,下载的程序还有很多不足之处,比如不能自动运行产生16轮的轮密钥,只能说是完成了AES的基本功能,我也希望能将它的功能变得更强大,但多次修改后均没有成功。
通过多次调试,对SubBytes,ShiftRows,MixColumns,AddRoundKey等加密过程,InvMixColumns,InvShiftRows,InvSubBytes等解密过程的编程运行过程有了清晰的认识,深入理解了AES的加密和解密过程,对算法、密码保密性和安全性有了新的认识,收获很多。
六.源代码:
#include
#include
FILE*fp;
unsignedcharxtime(unsignedcharinput);
voidkeyexpansion(unsignedcharS_BOX[][16],unsignedcharkeys[][44]);
voidbytesub(unsignedcharS_BOX[][16],unsignedcharB[][4]);
voidshiftrow(unsignedcharB[][4]);
voidmixcolumn(unsignedcharinput[][4]);
voidinvbytesub(unsignedcharN_S_BOX[][16],unsignedcharB[][4]);
voidinvshiftrow(unsignedcharB[][4]);
voidinvmixcolum(unsignedcharinput[][4]);
intjiami(unsignedcharS_BOX[][16]);
intjiemi(unsignedcharS_BOX[][16],unsignedcharN_S_BOX[][16]);
//密钥生成
voidkeyexpansion(unsignedcharS_BOX[][16],unsignedcharkeys[][44]){
unsignedcharRcon[11]={0,1,2,4,8,16,32,64,128,27,54};
unsignedcharpast[4];
registerinti,j;
//打开密钥文件
if((fp=fopen("Key.txt","r"))==NULL)
{
printf("CANNOTOPENTHEFILE!
\n");
return;
}
printf("\n请输入密钥!
\n");
for(i=0;i<=3;i++)
for(j=0;j<=3;j++)
{
fscanf(fp,"%02x",&keys[j][i]);
printf("%02x",keys[j][i]);
}
for(i=4;i<=43;i++){//maketheother40keys
if(i%4==0){//如果能被4整除,特殊处理
for(j=1;j<=4;j++)//把前一个密钥移位赋值给数组
past[j-1]=keys[j%4][i-1];
for(j=0;j<=3;j++){
if(j==0)
keys[j][i]=S_BOX[past[j]/16][past[j]%16]^Rcon[i/4]^keys[j][i-4];
else
keys[j][i]=S_BOX[past[j]/16][past[j]%16]^keys[j][i-4];
}
}
else{
for(j=0;j<=3;j++){
keys[j][i]=keys[j][i-4]^keys[j][i-1];
}
}
}
}
//列混合运算用到的乘2函数
unsignedcharxtime(unsignedcharinput){//x乘法('02'乘法)
inttemp;
temp=input<<1;
if(input&0x80){
temp^=0x1b;
}
returntemp;
}
//列混合运算
voidmixcolumn(unsignedcharinput[][4]){//列混合
inti,j;
unsignedcharoutput[4][4];
for(j=0;j<=3;j++)
for(i=0;i<=3;i++)
output[i][j]=xtime(input[i%4][j])//0x02乘法
^(input[(i+1)%4][j]^xtime(input[(i+1)%4][j]))//0x03乘法
^input[(i+2)%4][j]//0x01乘法
^input[(i+3)%4][j];//0x01乘法
for(i=0;i<=3;i++)
for(j=0;j<=3;j++)
input[i][j]=output[i][j];
}
//行移位
voidshiftrow(unsignedcharB[][4]){
inti,temp;
temp=B[1][0];
for(i=0;i<=2;i++)
B[1][i]=B[1][i+1];
B[1][3]=temp;
for(i=0;i<=1;i++){
temp=B[2][i];
B[2][i]=B[2][i+2];
B[2][i+2]=temp;
}
temp=B[3][3];
for(i=3;i>=1;i--)
B[3][i]=B[3][i-1];
B[3][0]=temp;
}
//字节变换
voidbytesub(unsignedcharS_BOX[][16],unsignedcharB[][4]){
registerinti,j;
for(i=0;i<=3;i++)
for(j=0;j<=3;j++)
B[i][j]=S_BOX[B[i][j]/16][B[i][j]%16];
}
//逆行移位
voidinvshiftrow(unsignedcharB[][4]){
inti,temp;
temp=B[1][3];
for(i=3;i>=1;i--)
B[1][i]=B[1][i-1];
B[1][0]=temp;
for(i=0;i<=1;i++){
temp=B[2][i];
B[2][i]=B[2][i+2];
B[2][i+2]=temp;
}
temp=B[3][0];
for(i=0;i<=2;i++)
B[3][i]=B[3][i+1];
B[3][3]=temp;
}
//逆列混合运算
voidinvmixcolum(unsignedcharinput[][4]){
inti,j;
unsignedcharoutput[4][4];
for(j=0;j<4;j++)
for(i=0;i<4;i++)
output[i][j]=(xtime(xtime(xtime(input[i%4][j])))^xtime(xtime(input[i%4][j]))^xtime(input[i%4][j]))//0x0E乘法
^(xtime(xtime(xtime(input[(i+1)%4][j])))^xtime(input[(i+1)%4][j])^input[(i+1)%4][j])//0x0B乘法
^(xtime(xtime(xtime(input[(i+2)%4][j])))^xtime(xtime(input[(i+2)%4][j]))^input[(i+2)%4][j])//0x0D乘法
^(xtime(xtime(xtime(input[(i+3)%4][j])))^input[(i+3)%4][j]);//0x09乘法
for(i=0;i<=3;i++)
for(j=0;j<=3;j++)
input[i][j]=output[i][j];
}
//逆字节变换
voidinvbytesub(unsignedcharN_S_BOX[][16],unsignedcharB[][4]){
registerinti,j;
for(i=0;i<=3;i++)
for(j=0;j<=3;j++)
B[i][j]=N_S_BOX[B[i][j]/16][B[i][j]%16];
}
intjiami(unsignedcharS_BOX[][16]){
unsignedchare,B[4][4];
unsignedcharkeys[4][44];
inti,j;
if((fp=fopen("Plaintext.txt","r"))==NULL)
{
printf("can'topenthePlaintext.txt!
\n");
return0;
}
printf("请输入信息!
\n");
for(i=0;i<=3;i++)
for(j=0;j<=3;j++){
fscanf(fp,"%02x",&e);
B[j][i]=e;
printf("%02x",e);
}
getchar();
fclose(fp);
keyexpansion(S_BOX,keys);
for(i=0;i<=3;i++)
for(j=0;j<=3;j++)
B[i][j]^=keys[i][j];
intlevel;
for(level=1;level<=9;level++){//1到9轮循环
bytesub(S_BOX,B);
shiftrow(B);
mixcolumn(B);
for(i=0;i<=3;i++)
for(j=0;j<=3;j++)
B[i][j]^=keys[i][level*4+j];
}
bytesub(S_BOX,B);//第10轮循环
shiftrow(B);
for(i=0;i<=3;i++)
for(j=0;j<=3;j++)
B[i][j]^=keys[i][40+j];
if((fp=fopen("Ciphertext.txt","w"))==NULL)
{
printf("can'topenthePlaintext.txt!
\n");
return0;
}
printf("\n加密后的信息为:
\n");
for(i=0;i<=3;i++)
for(j=0;j<=3;j++){
fprintf(fp,"%02x",B[j][i]);
printf("%02x",B[j][i]);
}
putchar('\n');
fclose(fp);
return0;
}
intjiemi(unsignedcharS_BOX[][16],unsignedcharN_S_BOX[][16]){
unsignedcharB[4][4];
unsignedcharkeys[4][44];
unsignedchartemp;
inti,j;
if((fp=fopen("Ciphertext.txt","r"))==NULL)
{
printf("can'topentheCiphertext.txt!
\n");
return0;
}
printf("请输入信息!
\n");
for(i=0;i<=3;i++)
for(j=0;j<=3;j++){
fscanf(fp,"%02x",&temp);
B[j][i]=temp;
printf("%02x",temp);
}
fclose(fp);