五邑大学本科生实验指导书《密码学基础》实验指导书课程名称:密码学基础课程编号:课程性质:专业选修课课程总学时:48实验总学时:8任课教师:***一、实验教学目的和基本要求《密码学基础》是计算科学与技术本科专业开设的一门专业选修课,本课程的主要目标是让学生学习和了解密码学的一些基本概念,理解和掌握一些常用密码算法,包括加密和解密、认证理论及算法、安全计算原理及算法,学会进行效率分析和安全性分析。
密码学是信息安全的核心技术,是实现安全通信的基础,所以实验和理论一样都很重要,实验能够让学生通过多个密码算法的程序设计实现,更好地掌握密码算法设计的机理和方法,熟悉网络攻击和防范方法。
同时,基于密码系统设计的基本方法和基本步骤,帮助学生理解密码学在信息安全中的地位,并引导了解密码学领域及信息安全领域的新进展、新方向。
具体要求如下:1.要求学生在上机前对本次实验的原理、内容、方案进行充分准备。
2.每次实验必须按要求的格式撰写《实验报告》,内容大体包括:实验目的、实验内容、实验及算法原理、程序清单、结果分析、总结。
3.实验成绩作为平时成绩的一部分。
二、实验内容及学时分配实验一 古典密码学实验(2学时)一、实验目的通过实现简单的古典密码算法,理解密码学的相关概念如明文(plaintext )、密文(ciphertext )、加密密钥(encryption key)、解密密钥(decryption key )、加密算法(encryption algorithm)、解密算法(decryption algorithm)等。
二、实验内容1)用C\C++语言实现仿射变换(Affine )加/解密算法;2)用C\C++语言实现统计26个英文字母出现的频率的程序;3)利用仿射变换加/解密程序对一段较长的英文文章进行加密,再利用统计软件对明文和密文中字母出现的频率进行统计并作对比,观察有什么规律。
放射变换:加密:()26mod ,b am m E c b a +==解密:()()26mod 1,b c a c D m b a -==-其中a, b 为密钥,25,0≤≤b a ,且gcd(a, 26)=1实验要求:加/解密程序对任意满足条件的a 、b 都能够处理。
三、实验步骤(1)统计26个英文字母出现的频率的程序#include<iostream>#include<fstream>#include<vector>using namespace std;void main(){ifstream in("a.txt");vector<int> s;vector<int> n(26,0);for(int i=0;i<26;++i)s.push_back(97+i);for(char x;in>>x; )for(int i=0;i<26;++i)if(int(x)==s[i]){n[i]++;}float sum=0.0;for(int j=0;j<26;++j)sum+=n[j];cout<<"统计结果如下:"<<endl;for(int k=0;k<26;++k){// n[k]=n[k]/sum;cout<<' '<<char(k+97)<<"出现的概率为:"<<n[k]/sum<<endl;//cout<<n[k]<<endl;}(2)仿射变换加/解密程序对一段较长的英文文章进行加密#include <stdafx.h>#include<iostream>#include<fstream>#include<vector>using namespace std;//////////判断两个数是不是互素(辗转相除)////////bool gcd(int a){int f=26,g,r;g=a;do{r=f%g;f=g;g=r;}while(r);if(f==1)return 1;elsereturn 0;}//////////////////求逆//////int inv(int a){int x,i;for(i=1;i<=30;++i)if((26*i+1)%a==0){x=(26*i+1)/a;break;}return x;}//////////////////////////////////////////////////////////void main(){cout<<"请你选择操作密码的方式:"<<endl<<" 0-表示加密"<<endl<<" 1-表示解密"<<endl;int z;cin>>z;if(z==0||z==1){//////////////////////////////////////////cout<<"请输入密钥a和b:"<<endl;int a,b;cin>>a>>b;if((a<1||a>25)||(b<0||b>25))cout<<"a,b的输入范围有错!"<<endl;elseif(gcd(a)==0)cout<<"密钥a有误,与26不互素"<<endl;else{if(z==0)////加密算法{ifstream in("a.txt");ofstream out("b.txt");vector<int> s;for(char x;in>>x; )s.push_back(int(x));for(int i=0;i<s.size();++i){s[i]=(a*(s[i]-97)+b)%26;out<<char(s[i]+97);}cout<<endl;cout<<"加密成功!明文请见\"b.txt\""<<endl;}else////解密算法{ifstream in("b.txt");ofstream out("a.txt");vector<int> s;for(char x;in>>x; )s.push_back(int(x));for(int i=0;i<s.size();++i){s[i]=inv(a)*(s[i]-97-b+26)%26;out<<char(s[i]+97);}out<<endl;cout<<"解密成功!密文请见\"a.txt\""<<endl;}}////////////////////////////////////////}elsecout<<"所选操作无效!"<<endl;}四、实验结果及分析该程序是对文件进行操作,结果如下:(1)统计26个英文字母出现的频率的程序(2)仿射变换加/解密程序对一段较长的英文文章进行加密下面是文本内容:实验二 AES密码的实现(4学时)一、实验目的通过实现AES密码算法,理解对称密码机制。
二、实验内容1)在深入理解AES加密/解密算法理论的基础上,设计一个AES加密/解密软件系统;2)完成一个明文分组的加解密,明文和密钥是十六进制,长度都为64比特(16个16进制数),输入明文和密钥,输出密文,进行加密后,能够进行正确的解密;3)程序运行时,要求输出每一轮使用的密钥,以及每一轮加密或解密之后的16进制表示的值;4)要求提供所设计系统的报告及完整的软件。
三、实验步骤1.字节替换SubBytes()变换是一个基于S盒的非线性置换,它用于将输入或中间态的每一个字节通过一个简单的查表操作,将其映射为另一个字节。
映射方法是把输入字节的高四位作为S盒的行值,低四位作为列值,然后取出S盒中对应的行和列的元素作为输出。
unsigned char subbytes(unsigned char state[4][4]){printf("after subbyte:\n"); //取出中间态state映射到S盒中的值赋给中间态state for(i=0;i<4;i++){for(j=0;j<4;j++)state[i][j]=sbox[state[i][j]]; }for(i=0;i<4;i++) //输出到屏幕显示state{for(j=0;j<4;j++)printf("\t\t%02x ",state[i][j]);printf("\n");}printf("\n");return 0;}2.行移位ShiftRows()完成基于行的循环移位操作,变换方法是第0行不动,第一行循环左移一个字节,第二位循环左移两个字节,第三行循环左移三个字节。
unsigned char shiftrows(unsigned char state[4][4]){printf("after shiftrows:\n"); // 在中间态的行上,k=state[1][0]; // 第0行不变state[1][0]=state[1][1]; // 第一行循环左移一个字节state[1][1]=state[1][2]; // 第二行循环左移两个字节state[1][2]=state[1][3]; // 第三行循环左移三个字节state[1][3]=k;k=state[2][0];state[2][0]=state[2][2];state[2][2]=k;k=state[2][1];state[2][1]=state[2][3];state[2][3]=k;k=state[3][0];state[3][0]=state[3][3];state[3][3]=state[3][2];state[3][2]=state[3][1];state[3][1]=k;for(i=0;i<4;i++) //输出到屏幕显示state{for(j=0;j<4;j++)printf("\t\t%02x ",state[i][j]);printf("\n");}printf("\n");return 0;}3.列混合MixColumns()实现逐列混合,方法是s’(x)=c(x)*s(x)mod(x^4+1)unsigned char mixcolumns(unsigned char state[4][4]){ printf("after mixcolumns:\n");// 实现(02 03 01 01) 与中间态state分别相乘后异或得相应值for(i=0;i<4;i++) // (01 02 03 01){ // (01 01 02 03)k=state[0][i]; // (03 01 01 02)temp[0] = state[0][i] ^ state[1][i] ^ state[2][i] ^ state[3][i] ;temp[1] = state[0][i] ^ state[1][i] ; temp[1] = xtime(temp[1]); state[0][i] ^= temp[1] ^ temp[0] ;temp[1] = state[1][i] ^ state[2][i] ; temp[1] = xtime(temp[1]); state[1][i] ^= temp[1] ^ temp[0] ;temp[1] = state[2][i] ^ state[3][i] ; temp[1] = xtime(temp[1]); state[2][i] ^= temp[1] ^ temp[0] ;temp[1] = state[3][i] ^ k ; temp[1] = xtime(temp[1]); state[3][i] ^= temp[1] ^ temp[0] ;}for(i=0;i<4;i++) //输出到屏幕显示state{for(j=0;j<4;j++)printf("\t\t%02x ",state[i][j]);printf("\n");}printf("\n");return 0;}4.轮密钥加AddRoundKey()用于将输入或中间态S的每一列与一个密钥字ki进行按位异或,每一个轮密钥由Nb个字组成。