现代密码学实验报告

更新时间:2024-04-21 08:18:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

现 代 密 码 学 实 验 报 告

学生姓名 学 号 专业班级 指导教师

学 院 信息科学与工程学院 完成时间 2014年5月

实验一 对称密码算法实验

[实验目的]

1.掌握密码学中经典的对称密码算法DES、AES、RC4的算法原理。 2.掌握DES、AES、RC4的算法流程和实现方法。

[实验预备]

1.DES算法有什么特点?算法中的哪些结构保证了其混淆和扩散的特性?

答:分组比较短、密钥太短、密码生命周期短、运算速度较慢。采用替代和置换的方法简单有效地遵循了香农定理,替代操作通过S盒达到了混淆效果,置换操作通过P盒扩散效果。

2.AES算法的基本原理和特点。

答:AES加密数据块分组长度必须为128比特,密钥长度可以是128比特、192比特、256比特中的任意一个(如果数据块及密钥长度不足时,会补齐)。AES加密有很多轮的重复和变换。大致步骤如下:1、密钥扩展(KeyExpansion),2、初始轮(Initial Round),3、重复轮(Rounds),每一轮又包括:SubBytes、ShiftRows、MixColumns、AddRoundKey,4、最终轮(Final Round),最终轮没有MixColumns。

3.流密码RC4的密钥流生成以及S盒初始化过程。

答:RC4由伪随机数生成器和异或运算组成。RC4的密钥长度可变,范围是[1,255]。RC4一个字节一个字节地加解密。给定一个密钥,伪随机数生成器接受密钥并产生一个S盒。S盒用来加密数据,而且在加密过程中S盒会变化。 初始化长度为256的S盒。第一个for循环将0到255的互不重复的元素装入S盒。第二个for循环根据密钥打乱S盒。下面i,j是两个指针。每收到一个字节,就进行while循环。通过一定的算法((a),(b))定位S盒中的一个元素,并与输入字节异或,得到k。循环中还改变了S盒((c))。如果输入的是明文,输出的就是密文;如果输入的是密文,输出的就是明文。

[实验内容]

1. 分析DES、AES、RC4、SHA的实现过程。 2. 用程序设计语言将算法过程编程实现。 3. 完成字符串数据的加密运算和解密运算 输入明文:Idolikethisbook 输入密钥:cryption

[实验步骤] 1. 预习DES、AES、RC4算法。 2. 写出算法流程,用程序设计语言将算法过程编程实现。 DES算法流程:

代码:

#include \#include \#include #include #include using namespace std; enum{encrypt,decrypt};

//ENCRYPT:加密,DECRYPT:解密

void des_run(char out[8],char in[8],bool type=encrypt); //设置密钥

void des_setkey(const char key[8]);

static void f_func(bool in[32],const bool ki[48]); //f函数

static void s_func(bool out[32],const bool in[48]); //s盒代替 //变换

static void transform(bool *out, bool *in, const char *table, int len); static void xor(bool *ina, const bool *inb, int len); //异或

static void rotatel(bool *in, int len, int loop);

//循环左移

//字节组转换成位组

static void bytetobit(bool *out,const char *in, int bits); //位组转换成字节组

static void bittobyte(char *out, const bool *in, int bits); //置换IP表

const static char ip_table[64]={58,50,42,34,26,18,10,2,

60,52,44,36,28,20,12,4, 62,54,46,38,30,22,14,6, 64,56,48,40,32,24,16,8, 57,49,41,33,25,17,9,1, 59,51,43,35,27,19,11,3, 61,53,45,37,29,21,13,5, 63,55,47,39,31,23,15,7}; //逆置换IP-1表

const static char ipr_table[64]={40,8,48,16,56,24,64,32,

39,7,47,15,55,23,63,31, 38,6,46,14,54,22,62,30, 37,5,45,13,53,21,61,29, 36,4,44,12,52,20,60,28, 35,3,43,11,51,19,59,27, 34,2,42,10,50,18,58,26, 33,1,41,9,49,17,57,25}; //E位选择表

static const char e_table[48]={32,1,2,3,4,5,4,5,

6,7,8,9,8,9,10,11, 12,13,12,13,14,15, 16,17,16,17,18,19, 20,21,20,21,22,23, 24,25,24,25,26,27, 28,29,28,29,30,31,32,1}; //P换位表

const static char p_table[32]={16,7,20,21,29,12,28,

17,1,15,23,26,5,18, 31,10,2,8,24,14,32, 27,3,9,19,13,30,6,22,11,4,25}; //pc1选位表

const static char pc1_table[56]={57,49,41,33,25,17,9,

1,58,50,42,34,26,18, 10,2,59,51,43,35,27, 19,11,3,60,52,44,36, 63,55,47,39,31,23,15, 7,62,54,46,38,30,22, 14,6,61,53,45,37,29,

21,13,5,28,20,12,4}; //pc2选位表

const static char pc2_table[48]={14,17,11,24,1,5,3,28,

15,6,21,10,23,19,12,4, 26,8,16,7,27,20,13,2, 41,52,31,37,47,55,30, 40,51,45,33,48,44,49, 39,56,34,53,46,42,50,36,29,32}; //左移位数表

const static char loop_table[16]={1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1}; //S盒

const static char s_box[8][4][16]={//s1 14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7,0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8, 4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0,15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13, //s2 15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10,3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5, 0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15,13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9, //s3 10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8,13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1, 13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7,1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12, //s4 7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15,13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9, 10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4,3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14, //s5 2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9,14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6, 4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14,11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3, //s6 12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11,10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8, 9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6,4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13, //s7 4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1,13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6, 1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2,6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12, //s8 13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7,1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2, 7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8,2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11}; static bool subkey[16][48]; //16圈子密钥

void des_run(char out[8],char in[8],bool type) { static bool m[64],tmp[32],*li=&m[0],*ri=&m[32];bytetobit(m,in,64); transform(m,m,ip_table,64); if(type==encrypt) { for(int i=0;i<16;i++)

{ memcpy(tmp,ri,32); f_func(ri,subkey[i]); xor(ri,li,32); memcpy(li,tmp,32); } }else { for(int i=15;i>=0;i--) { memcpy(tmp,li,32); f_func(li,subkey[i]); xor(li,ri,32); memcpy(ri,tmp,32); } } transform(m,m,ipr_table,64); bittobyte(out,m,64); }

void des_setkey(const char key[8]) { static bool k[64], *kl=&k[0], *kr=&k[28]; bytetobit(k,key,64); transform(k,k,pc1_table,56); for(int i=0;i<16;i++) { rotatel(kl,28,loop_table[i]); rotatel(kr,28,loop_table[i]); transform(subkey[i],k,pc2_table,48); } }

void f_func(bool in[32],const bool ki[48]) { static bool mr[48]; transform(mr,in,e_table,48); xor(mr,ki,48); s_func(in,mr); transform(in,in,p_table,32); }

void s_func(bool out[32],const bool in[48]) {

for(char i=0,j,k;i<8;i++,in+=6,out+=4) { j=(in[0]<<1)+in[5]; k=(in[1]<<3)+(in[2]<<2)+(in[3]<<1)+in[4]; bytetobit(out,&s_box[i][j][k],4); } }

void transform(bool *out,bool *in,const char *table,int len) { static bool tmp[256]; for(int i=0;i

void xor(bool *ina,const bool *inb,int len) { for(int i=0;i

void rotatel(bool *in,int len,int loop) { static bool tmp[256]; memcpy(tmp,in,loop); memcpy(in,in+loop,len-loop); memcpy(in+len-loop,tmp,loop); }

void bytetobit(bool *out,const char *in,int bits) { for(int i=0;i>(i%8))&1; }

void bittobyte(char *out,const bool *in,int bits) { memset(out,0,(bits+7)/8); for(int i=0;i

void main()

{ string str; puts(\ cout<>str;

// getline(cin,str); printf(\ char key[8]; cout<<\ for(int p=0;p<=7;p++) cin>>key[p]; des_setkey(key); int m=str.size(); int n=m/8+1; str=str.substr(0,m); int i=0; string aw,mw; for(n;n>0;n--) { char *str1=new char[8]; string temp; temp=str.substr(i,8); i=i+8; strcpy(str1,temp.c_str()); des_run(str1,str1,encrypt); aw=aw+str1; aw=aw.substr(0,m+6);//m+1-->m+6 des_run(str1,str1,decrypt); mw=mw+str1; string temp1; strcpy(str1,temp1.c_str()); str1=\ temp=\ } puts(\ cout<

AES算法流程图:

代码:

#include #include #include

#define null 0

const unsigned char Sbox[256] = { // forward s-box

0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,

0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};

const unsigned char ISbox[256] = { // inverse s-box

0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,

0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d}; static unsigned char AesRcon[11*4]= { 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00 }; static unsigned char gfmultby01(unsigned char b) {

return b; }

static unsigned char gfmultby02(unsigned char b) {

if (b < 0x80)

return (unsigned char)(int)(b <<1); else

return (unsigned char)( (int)(b << 1) ^ (int)(0x11B) ); }

static unsigned char gfmultby03(unsigned char b) {

return (unsigned char) ( (int)gfmultby02(b) ^ (int)b ); }

static unsigned char gfmultby09(unsigned char b) {

return (unsigned char)( (int)gfmultby02(gfmultby02(gfmultby02(b))) ^ (int)b ); }

static unsigned char gfmultby0b(unsigned char b) {

return (unsigned char)( (int)gfmultby02(gfmultby02(gfmultby02(b))) ^ (int)gfmultby02(b) ^ (int)b ); }

static unsigned char gfmultby0d(unsigned char b) {

return (unsigned char)( (int)gfmultby02(gfmultby02(gfmultby02(b))) ^ (int)gfmultby02(gfmultby02(b)) ^ (int)(b) ); }

static unsigned char gfmultby0e(unsigned char b) {

return (unsigned char)( (int)gfmultby02(gfmultby02(gfmultby02(b))) ^ (int)gfmultby02(gfmultby02(b)) ^ (int)gfmultby02(b) ); }

//密钥移位函数

unsigned char* RotWord(unsigned char* word) {

unsigned char* temp = new unsigned char[4]; temp[0] = word[1]; temp[1] = word[2]; temp[2] = word[3]; temp[3] = word[0]; return temp; }

unsigned char* SubWord(unsigned char* word) { unsigned char* temp = new unsigned char[4]; for(int j=0;j<4;j++) { temp[j] = Sbox[word[j]]; } return temp; }

void chartomatrix(unsigned char*str,unsigned char Base[][4]) {

int r,c;

for(c=0;c<4;c++) {

for(r=0;r<4;r++)

Base[r][c]=str[4 * c+r]; } }

void ByteSub(unsigned char a[4][4],unsigned char b[4][4]) //字节转换 {

int r,c;

for(r=0;r<4;r++) for(c=0;c<4;c++)

b[r][c]=(Sbox[a[r][c]]); }

void IvByteSub(unsigned char a[][4],unsigned char b[][4]) //逆字节转换 {

int r,c;

for(r=0;r<4;r++)

for(c=0;c<4;c++)

b[r][c]=ISbox[a[r][c]]; }

void ShiftRow(unsigned char b[][4],unsigned char C[][4]) //行变换 {

int r,c;

for(r=0;r<4;r++) {

for(c=0;c<4;c++) C[r][c]=b[r][(c+r)%4]; } }

void IvShiftRow(unsigned char b[][4],unsigned char C[][4]) //逆移动行变换 {

int r,c;

for(r=0;r<4;r++) {

for(c=0;c<4;c++) C[r][c]=b[r][(c+4-r)%4]; } }

void MixColumn(unsigned char C[][4],unsigned char d[][4]) //混合列变换 {

int c;

for(c=0;c<4;c++)

d[0][c]=(unsigned char)((int)gfmultby02(C[0][c]) ^ (int)gfmultby03(C[1][c]) ^ (int)gfmultby01(C[2][c]) ^ (int)gfmultby01(C[3][c]));

for(c=0;c<4;c++)

d[1][c]=(unsigned char)((int)gfmultby01(C[0][c]) ^ (int)gfmultby02(C[1][c]) ^ (int)gfmultby03(C[2][c]) ^ (int)gfmultby01(C[3][c]));

for(c=0;c<4;c++)

d[2][c]=(unsigned char)((int)gfmultby01(C[0][c]) ^ (int)gfmultby01(C[1][c]) ^ (int)gfmultby02(C[2][c]) ^ (int)gfmultby03(C[3][c]));

for(c=0;c<4;c++)

d[3][c]=(unsigned char)((int)gfmultby03(C[0][c]) ^ (int)gfmultby01(C[1][c]) ^ (int)gfmultby01(C[2][c]) ^ (int)gfmultby02(C[3][c])); }

void IvMixColumn(unsigned char C[][4],unsigned char d[][4]) //逆混合列变换 {

int c;

for(c=0;c<4;c++)

d[0][c]=(unsigned char)((int)gfmultby0e(C[0][c]) ^ (int)gfmultby0b(C[1][c]) ^ (int)gfmultby0d(C[2][c]) ^ (int)gfmultby09(C[3][c]));

for(c=0;c<4;c++)

d[1][c]=(unsigned char)((int)gfmultby09(C[0][c]) ^ (int)gfmultby0e(C[1][c]) ^ (int)gfmultby0b(C[2][c]) ^ (int)gfmultby0d(C[3][c]));

for(c=0;c<4;c++)

d[2][c]=(unsigned char)((int)gfmultby0d(C[0][c]) ^ (int)gfmultby09(C[1][c]) ^ (int)gfmultby0e(C[2][c]) ^ (int)gfmultby0b(C[3][c]));

for(c=0;c<4;c++)

d[3][c]=(unsigned char)((int)gfmultby0b(C[0][c]) ^ (int)gfmultby0d(C[1][c]) ^ (int)gfmultby09(C[2][c]) ^ (int)gfmultby0e(C[3][c])); }

void AddRoundKey(unsigned char d[][4],unsigned char key[][4],unsigned char e[][4]) //加循环密钥 {

int r,c;

for(r=0;r<4;r++) for(c=0;c<4;c++)

e[r][c]=(unsigned char)((int)d[r][c]^(int)key[r][c]); }

void KeyProducing(unsigned char*key,unsigned char K[4][44]) //扩展初始密钥到44列 {

unsigned char BaseK[4][4]={0}; chartomatrix(key,BaseK);

int r,c;

unsigned char *temp=new unsigned char[4]; for(c=0;c<4;++c) {

for(r=0;r<4;++r) K[r][c]=BaseK[r][c]; }

for(c=4;c<44;c++) {

if(c%4!=0) for(r=0;r<4;r++) K[r][c]=(unsigned char)((int)K[r][c-4] ^ (int)K[r][c-1]); else

{ for(r=0;r<4;r++) temp[r]=K[r][c-1];

temp=SubWord(RotWord(temp));

temp[0] = (unsigned char)( (int)temp[0] ^ (int) AesRcon[c+0] ); temp[1] = (unsigned char)( (int)temp[1] ^ (int) AesRcon[c+1] ); temp[2] = (unsigned char)( (int)temp[2] ^ (int) AesRcon[c+2] ); temp[3] = (unsigned char)( (int)temp[3] ^ (int) AesRcon[c+3] ); for(r=0;r<4;r++) K[r][c]=(unsigned char)((int)K[r][c-4] ^ temp[r]); } } }

void Encode(unsigned char *Mwen,unsigned char K[][44],unsigned char*out) {

unsigned char BaseM[4][4]={0}; int round,r,c;

unsigned char Ki[4][4]={0};

unsigned char e[4][4]={0},b[4][4]={0},C[4][4]={0},d[4][4]={0};

chartomatrix(Mwen,BaseM); for(r=0;r<4;r++) for(c=0;c<4;c++) Ki[r][c]=K[r][c]; //第0个循环密钥

AddRoundKey(BaseM,Ki,e); //ARK,使用第0个循环密钥 for(round=1;round<10;round++) {

ByteSub(e,b); //字节转换

ShiftRow(b,C); //移动行变换

MixColumn(C,d); //混合列变换 for(r=0;r<4;r++) for(c=0;c<4;c++) Ki[r][c]=K[r][4*round+c]; //产生第round轮循环的密钥Ki

AddRoundKey(d,Ki,e); //roundth循环加密 }

ByteSub(e,b); //第10次循环加密的移动行变换 for(r=0;r<4;r++) for(c=0;c<4;c++) Ki[r][c]=K[r][4*10+c]; //产生第10轮循环的密钥Ki

AddRoundKey(C,Ki,e); //10th循环加密 for(c=0;c<4;c++) {

for(r=0;r<4;r++)

out[r+4*c]=e[r][c]; //加密结果转换成输入 } }

void Decode(unsigned char*Miwen,unsigned char K[][44],unsigned char*out) {

unsigned char BaseM[4][4]={0}; unsigned char Ki[4][4]={0};

unsigned char e[4][4]={0},b[4][4]={0},C[4][4]={0},d[4][4]={0}; int round,r,c;

chartomatrix(Miwen,BaseM); for(r=0;r<4;r++) for(c=0;c<4;c++) Ki[r][c]=K[r][4*10+c]; //产生第10轮循环的密钥Ki

AddRoundKey(BaseM,Ki,e); //10th循环解密

for(round=9;round>0;round--)

{

IvShiftRow(e,b); IvByteSub(b,C); for(r=0;r<4;r++) for(c=0;c<4;c++) Ki[r][c]=K[r][4*round+c]; //产生第round轮循环的密钥Ki AddRoundKey(C,Ki,d); IvMixColumn(d,e); }

IvShiftRow(e,b); IvByteSub(b,C); for(r=0;r<4;r++) for(c=0;c<4;c++) Ki[r][c]=K[r][c]; //产生第round轮循环的密钥Ki

AddRoundKey(C,Ki,e); //ARK,使用第0个循环密钥 for(c=0;c<4;c++) for(r=0;r<4;r++)

out[r+4*c]=e[r][c]; //加密结果转换成输入 }

void main() {

unsigned char K[4][44]={0};

unsigned char *Mwen=new unsigned char[17]; unsigned char key[]=\ unsigned char outjiam[16]={0}; unsigned char outjiem[16]={0}; int i;

char filename[15] ;

cout<<\请输入待加密字符串所在文件的文件名:(文件名的长度不要超过15个字符)\ cin>>filename;

ifstream file;

file.open(filename,ios::binary,0); file.seekg(0,ios::beg); file.get(Mwen,17,'#'); file.close();

cout<<\加密前的明文:\ cout<

KeyProducing(key,K);

Encode(Mwen,K,outjiam); cout<<\加密后的密文:\\n\ for(i=0;i<16;i++) cout<

Decode(outjiam,K,outjiem);

cout<<\密文解密后的明文:\\n\

for(i=0;i<16;i++) { if(outjiem[i] >=128) cout<<(char)(outjiem[i]8); else cout<<(char)(outjiem[i]); }

cout<

RC4算法流程:

算法的初始化部分(用类C伪代码表示): for (i=0; i

for (i=0; i

j=(j+s[i]+k[i])%n; swap(s[i], s[j]); }

在初始化的过程中,密钥的主要功能是将S-box搅乱,i确保S-box的每个元素都得到处理,j保证S-box的搅乱是随机的。而不同的S-box在经过伪随机子密码生成算法的处理后可以得到不同的子密钥序列,并且,该序列是随机的: i=j=0;

while (明文未结束) {

++i%=n; j=(j+s)%n; swap(s, s[j]);

sub_k=s((s+s[j])%n); }

得到的子密码sub_k用以和明文进行xor运算,得到密文,解密过程也完全相同。

代码:

#include #include #include using namespace std;

typedef unsigned long ULONG;

void rc4_init(unsigned char *s, unsigned char *key, unsigned long Len) {

int i = 0, j = 0; char k[256] = {0};

unsigned char temp = 0; for(i = 0; i < 256; i++) {

s[i] = i;

k[i] = key[i % Len]; }

for (i = 0; i < 256; i++) {

j = (j + s[i] + k[i]) % 256; temp = s[i]; s[i] = s[j]; s[j] = temp; } }

void rc4_crypt(unsigned char *s, unsigned char *Data, unsigned long Len) {

int i = 0, j = 0, t = 0; unsigned long k = 0; unsigned char temp; for(k = 0; k < Len; k++) {

i = (i + 1) % 256; j = (j + s[i]) % 256; temp = s[i]; s[i] = s[j]; s[j] = temp;

t = (s[i] + s[j]) % 256; Data[k] ^= s[t]; } }

int main() {

unsigned char s[256] = {0}, s2[256] = {0}; cout<<\ cout<<\请输入加密内容:\

char pData[600]; cin>>pData; cout<<\请输入密钥:\ char key[256]; cin>>key; cout<

ULONG len = strlen(pData); int i; system(\ cout<<\ cout<<\明文为:\ cout<<\密钥为:\ cout<<\密钥长度为:\ rc4_init(s, (unsigned char *)key, strlen(key)); cout<<\盒初始化填充完毕……\ for(i = 0; i < 256; i++) {

s2[i] = s[i]; }

cout<<\加密后:\

rc4_crypt(s, (unsigned char *)pData, len); cout<<\密文为:\ cout<<\解密后:\

rc4_crypt(s2, (unsigned char *)pData, len); cout<<\解密为:\

return 0; }

3.输入指定的明文、密钥进行实验,验证结果。

DES运行截图:

AES

文件:

目录:

运行截图:

RC4运行截图:

4. 自己选择不同的输入,记录输出结果。 DES:

AES:

RC4:

写出所编写程序的流程图和运行界面、运行结果。 [问题讨论]

1. 在DES算法中有哪些是弱密钥?哪些是半弱密钥? 答:弱密钥(十六进制编码): 0101010101010101 FEFEFEFEFEFEFEFE

1F1F1F1F0F0F0E0E E0E0E0E0F1F1F1F1 半弱密钥: E01FE01FE01FE01F FE01FE01FE01FE01 E001E001F101F101 FE1FFE1FFE01FE01。

2. 改变明文或密钥中的一个比特值可能影响AES值中的多少比特? 答:两个以上的比特。

3.分析实验中在编辑、编译、运行等各环节中所出现的问题及解决方法。 答:DES是分组密码,所以在完成一个一轮的8组加密后,要达到加密可变长度的明文时,必须很好的将算法循环成为一个完美的整体。但这个过程必须选择好输入与输出的方法和存储结构,比如使用string作为存储明文和密文的输出时,要注意到这种引用型的变量在存储时是属于同一片连续存储空间,所以一旦输出则会全部输出。所以必须每一次循环后赋空值达到释放空间的效果,然后用循环控制输出,用函数截取位数,达到控制效果。

AES算法在实现时要注意一个特别重要的地方,因为是给文件加密,所以必须将准备好的txt格式的记事本中放入要加密的明文,然后该文件必须放置在当前程序运行的目录之下,否则将无法加密。

RC4算法较为简单只需注意各处循环的参数指针即可,循环的嵌套以及输入输出与算法的结合,出错后,调整了相关的i,j值及循环位置即完成了。 回答问题

实验二 公钥密码算法实验

[实验目的]

1.掌握密码学中常用的公钥密码算法RSA、ECC的算法原理。 2.掌握RSA、ECC的算法流程和实现方法。

[实验预备]

1.RSA和ECC密码系统所基于的数学难题是什么? 2.RSA和ECC算法的基本原理。

3.公钥密码系统可以取代对称密码系统吗? 4.RSA和ECC的实现过程。

[实验内容]

1. 分析RSA、ECC的实现过程。 2. 用程序设计语言将算法过程编程实现 3. 完成数据的加密运算和解密运算 输入明文:security 输入密钥:cryption 对ASCII码进行加密和解密。

[实验步骤] 1. 预习RSA、ECC算法。 2. 了解大素数的生成、大数的运算、公钥、私钥的生成。 3. 写出算法流程,用程序设计语言将算法过程编程实现。 RSA算法流程:

代码:

#include #include using namespace std;

int CheckPrime() {

int n; double k; cin >> n; k = sqrt(n); int i;

if(n>=2 && n<=10000) {

for(i=2; i<=k; i++) {

if(n%i == 0) return 0; }

if(i>k) return n; } else

cout << \输入的数字不符合要求,请重新输入!\ return 0; }

int CreatePassword(int e,int p,int q,int m) {

int d=1; int n; int ou;//与n互素的个数 int c;//密文

n=p*q; ou=(p-1)*(q-1);

while(((e*d)%ou)!=1) d++;

//cout<<\私钥d为\

for(int i=0;i

c=(m*m)%ou; } return c; }

void jiami(int e,int temp1,int temp2) { int m; int c;

char mm[8] ;

char cc[8];//用来存放密文 int j; cout<<\输入明文\

for(j=0;j<8;j++) {

cin>>mm[j]; }

/*for(int j=0;j<8;j++) {

cout<

for(j=0;j<8;j++)

{

m = (int)mm[j];//字符转换成ascii c=CreatePassword(e,temp1,temp2,m); cc[j] = (char)c; }

cout<<\输出的密文是\ for(j=0;j<8;j++) {

cout<

void jiemi(int e,int temp1,int temp2) { int m; int c;

char mm[8] ;

char cc[8];//用来存放密文 int j; cout<<\输入密文\

for(j=0;j<8;j++) {

cin>>cc[j]; }

/*for(int j=0;j<8;j++) {

cout<

for(j=0;j<8;j++) {

c = (int)cc[j];//字符转换成ascii

m=CreatePassword(e,temp1,temp2,c); mm[j] = (char)m; }

cout<<\输出的明文是\ for(j=0;j<8;j++) {

cout<

void Test() { int i; int temp1,temp2; int e;//公钥

cout<<\请输入两个素数:\

temp1=CheckPrime(); while(temp1==0) {

temp1=CheckPrime();

cout<<\重新输入\ }

temp2=CheckPrime(); while(temp2==0) {

temp2=CheckPrime();

cout<<\重新输入\ }

cout<<\输入公钥e\ cin>>e;

cout<<\公钥e为\ cout<<\输入你想选择的操作\ cout<<\ 加密 2:解密 cin>>i; switch(i) { case 1: jiami(e,temp1,temp2); Test(); case 2: jiemi(e,temp1,temp2); Test(); case 3:Test(); case 0:break; } } int main() {

cout<<\欢迎进入RSA算法\

3:返回 0:退出\ cout<

4. 输入指定的明文和密钥进行实验,验证结果。

写出所编写程序的流程图和运行界面、运行结果。

[问题讨论]

1. 总结算法的特点,分析算法的安全性;

答:产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次一密,速度太慢。RSA的安全性依赖于大数分解,但是否等同于大数分解一直未能得到理论上的证明,因为没有证明破解RSA就一定需要作大数分解。假设存在一种无须分解大数的算法,那它肯定可以修改成为大数分解算法。 RSA 的一些变种算法已被证明等价于大数分解。不管怎样,分解n是最显然的攻击方法。人们已能分解多个十进制位的大素数。因此,模数n必须选大一些,因具体适用情况而定。

2. 分析实验中在编辑、编译、运行等各环节中所出现的问题及解决方法。 答:生成大素数这个问题开始纠结了一段时间,但是后来老师不要求特别大的素数,所以才开始做。开始的时候一直有一个问题,如果用ASC码的话,那么要求的大小写会成为不同密文。后来又试着用字母数字代替,这才勉强完成。总体来说,技术不够,完成得并不完美。 回答问题

实验三 SKEY协议设计实验

[实验目的]

1.掌握身份认证协议的原理和基本思想。 2.掌握SKEY协议的机制和实现方法。

[实验预备]

1.SKEY协议的作用。 2.SKEY协议的安全性分析。 3.SKEY协议的实现过程。

[实验内容]

1. 分析SKEY协议的实现过程。 2. 用程序设计语言将算法过程编程实现。 3. 演示SKEY协议的身份鉴别过程。 [实验步骤] 1. 预习SKEY协议的机制。

2. 选择和实现相应的摘要算法MD5或SHA。 选择了MD5算法,代码如下:

文件:

//See internet RFC 1321, \/* GLOBAL.H - RSAREF types and constants */

#ifndef _MD5_GLOBAL_H #define _MD5_GLOBAL_H

/* PROTOTYPES should be set to one if and only if the compiler supports function argument prototyping.

The following makes PROTOTYPES default to 0 if it has not already

been defined with C compiler flags. */

#ifndef PROTOTYPES #define PROTOTYPES 1 #endif

/* POINTER defines a generic pointer type */

typedef unsigned char *POINTER;

/* UINT2 defines a two byte word */ typedef unsigned short int UINT2;

/* UINT4 defines a four byte word */ typedef unsigned long int UINT4;

/* PROTO_LIST is defined depending on how PROTOTYPES is defined above. If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it returns an empty list. */

#if PROTOTYPES

#define PROTO_LIST(list) list #else

#define PROTO_LIST(list) () #endif

#endif

文件:

/* MD5.H - header file for MD5C.C */

//See internet RFC 1321, \

/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved.

License to copy and use this software is granted provided that it is identified as the \Algorithm\or this function.

License is also granted to make and use derivative works provided that such works are identified as \Security, Inc. MD5 Message-Digest Algorithm\mentioning or referencing the derived work.

RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided \without express or implied warranty of any kind.

These notices must be retained in any copies of any part of this

documentation and/or software. */

/* MD5 context. */

#ifndef _MD5CONTEXT_H #define _MD5CONTEXT_H

#include \

typedef struct { UINT4 state[4]; /* state (ABCD) */ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } MD5_CTX;

#ifdef __cplusplus //added by Jim Howard so that these functions can be called from c++ extern \ {

#endif void MD5Init PROTO_LIST ((MD5_CTX *)); void MD5Update PROTO_LIST ((MD5_CTX *, unsigned char *, unsigned int)); void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); #ifdef __cplusplus }

#endif #endif

文件:

//See internet RFC 1321, \

/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm */

/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved.

License to copy and use this software is granted provided that it is identified as the \Algorithm\or this function.

License is also granted to make and use derivative works provided that such works are identified as \

Security, Inc. MD5 Message-Digest Algorithm\mentioning or referencing the derived work.

RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided \without express or implied warranty of any kind.

These notices must be retained in any copies of any part of this documentation and/or software. */

#include \#include \

/* Constants for MD5Transform routine. */

#define S11 7 #define S12 12 #define S13 17 #define S14 22 #define S21 5 #define S22 9 #define S23 14 #define S24 20 #define S31 4 #define S32 11 #define S33 16 #define S34 23 #define S41 6 #define S42 10 #define S43 15 #define S44 21

static void MD5Transform PROTO_LIST ((UINT4 [4],unsigned char [64])); static void Encode PROTO_LIST

((unsigned char *, UINT4 *, unsigned int)); static void Decode PROTO_LIST

((UINT4 *, unsigned char *, unsigned int));

static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));

static unsigned char PADDING[64] = {

0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

/* F, G, H and I are basic MD5 functions. */

#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) #define I(x, y, z) ((y) ^ ((x) | (~z)))

/* ROTATE_LEFT rotates x left n bits. */

#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))

/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent recomputation. */

#define FF(a, b, c, d, x, s, ac) { \\

(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \\ (a) = ROTATE_LEFT ((a), (s)); \\ (a) += (b); \\ }

#define GG(a, b, c, d, x, s, ac) { \\

(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \\ (a) = ROTATE_LEFT ((a), (s)); \\ (a) += (b); \\ }

#define HH(a, b, c, d, x, s, ac) { \\

(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \\ (a) = ROTATE_LEFT ((a), (s)); \\ (a) += (b); \\ }

#define II(a, b, c, d, x, s, ac) { \\

(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \\ (a) = ROTATE_LEFT ((a), (s)); \\ (a) += (b); \\ }

/* MD5 initialization. Begins an MD5 operation, writing a new context. */

void MD5Init (context)

MD5_CTX *context; /* context */

{

context->count[0] = context->count[1] = 0; /* Load magic initialization constants. */

context->state[0] = 0x67452301; context->state[1] = 0xefcdab89; context->state[2] = 0x98badcfe; context->state[3] = 0x10325476; }

/* MD5 block update operation. Continues an MD5 message-digest operation, processing another message block, and updating the context. */

void MD5Update (context, input, inputLen)

MD5_CTX *context; /* context */ unsigned char *input; /* input block */

unsigned int inputLen; /* length of input block */ {

unsigned int i, index, partLen;

/* Compute number of bytes mod 64 */

index = (unsigned int)((context->count[0] >> 3) & 0x3F);

/* Update number of bits */

if ((context->count[0] += ((UINT4)inputLen << 3))

< ((UINT4)inputLen << 3)) context->count[1]++;

context->count[1] += ((UINT4)inputLen >> 29);

partLen = 64 - index;

/* Transform as many times as possible. */

if (inputLen >= partLen) { MD5_memcpy

((POINTER)&context->buffer[index], (POINTER)input, partLen); MD5Transform (context->state, context->buffer);

for (i = partLen; i + 63 < inputLen; i += 64) MD5Transform (context->state, &input[i]);

index = 0;

} else i = 0;

/* Buffer remaining input */ MD5_memcpy

((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i); }

/* MD5 finalization. Ends an MD5 message-digest operation, writing the the message digest and zeroizing the context. */

void MD5Final (digest, context)

unsigned char digest[16]; /* message digest */

MD5_CTX *context; /* context */ {

unsigned char bits[8];

unsigned int index, padLen;

/* Save number of bits */

Encode (bits, context->count, 8);

/* Pad out to 56 mod 64. */

index = (unsigned int)((context->count[0] >> 3) & 0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); MD5Update (context, PADDING, padLen);

/* Append length (before padding) */ MD5Update (context, bits, 8);

/* Store state in digest */

Encode (digest, context->state, 16);

/* Zeroize sensitive information. */

MD5_memset ((POINTER)context, 0, sizeof (*context)); }

/* MD5 basic transformation. Transforms state based on block. */

static void MD5Transform (state, block) UINT4 state[4];

unsigned char block[64]; {

UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];

Decode (x, block, 64);

/* Round 1 */

FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */

/* Round 2 */

GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */

GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */

/* Round 3 */

HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */

/* Round 4 */

II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */

state[0] += a; state[1] += b; state[2] += c; state[3] += d;

/* Zeroize sensitive information. */

MD5_memset ((POINTER)x, 0, sizeof (x));

}

/* Encodes input (UINT4) into output (unsigned char). Assumes len is a multiple of 4. */

static void Encode (output, input, len) unsigned char *output; UINT4 *input; unsigned int len; {

unsigned int i, j;

for (i = 0, j = 0; j < len; i++, j += 4) {

output[j] = (unsigned char)(input[i] & 0xff);

output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); } }

/* Decodes input (unsigned char) into output (UINT4). Assumes len is a multiple of 4. */

static void Decode (output, input, len) UINT4 *output;

unsigned char *input; unsigned int len; {

unsigned int i, j;

for (i = 0, j = 0; j < len; i++, j += 4)

output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); }

/* Note: Replace \ */

static void MD5_memcpy (output, input, len) POINTER output; POINTER input; unsigned int len; {

unsigned int i;

for (i = 0; i < len; i++)

output[i] = input[i]; }

/* Note: Replace \ */

static void MD5_memset (output, value, len) POINTER output; int value;

unsigned int len; {

unsigned int i;

for (i = 0; i < len; i++)

((char *)output)[i] = (char)value; }

文件:

// md5class.cpp: implementation of the CMD5 class.

//See internet RFC 1321, \//

//Use this code as you see fit. It is provided \//without express or implied warranty of any kind.

//////////////////////////////////////////////////////////////////////

#include \

#include \#include #include #include

////////////////////////////////////////////////////////////////////// // Construction/Destruction

//////////////////////////////////////////////////////////////////////

CMD5::CMD5() { m_digestValid = false; //we don't have a plaintext string yet m_digestString[32]=0; //the digest string is always 32 characters, so put a null in position 32 }

CMD5::~CMD5() { }

CMD5::CMD5(const char* plainText) { m_plainText = const_cast(plainText); //get a pointer to the plain text. If casting away the const-ness worries you, //you could make a local copy of the plain text string.

m_digestString[32]=0; m_digestValid = calcDigest(); }

////////////////////////////////////////////////////////////////////// // Implementation

//////////////////////////////////////////////////////////////////////

void CMD5::setPlainText(const char* plainText) {

//set plaintext with a mutator, it's ok to

//to call this multiple times. If casting away the const-ness of plainText //worries you, you could either make a local copy of the plain //text string instead of just pointing at the user's string, or

//modify the RFC 1321 code to take 'const' plaintext, see example below.

m_plainText = const_cast(plainText); m_digestValid = calcDigest(); }

/* Use a function of this type with your favorite string class

if casting away the const-ness of the user's text buffer violates you coding standards.

void CMD5::setPlainText(CString& strPlainText) { static CString plaintext(strPlainText); m_plainText = strPlainText.GetBuffer(); m_digestValid = calcDigest(); } */

const char* CMD5::getMD5Digest()

{ //access message digest (aka hash), return 0 if plaintext has not been set if(m_digestValid) { return m_digestString; } else return 0; }

bool CMD5::calcDigest() {

//See RFC 1321 for details on how MD5Init, MD5Update, and MD5Final //calculate a digest for the plain text MD5_CTX context; MD5Init(&context);

//the alternative to these ugly casts is to go into the RFC code and change the declarations

MD5Update(&context, reinterpret_cast(m_plainText), ::strlen(m_plainText)); MD5Final(reinterpret_cast (m_digest),&context);

//make a string version of the numeric digest value int p=0;

for (int i = 0; i<16; i++) { ::sprintf(&m_digestString[p],\ p+=2; }

return true; }

文件:

// md5class.h: interface for the CMD5 class. //

//////////////////////////////////////////////////////////////////////

#if !defined(AFX_MD51_H__2A1EA377_D065_11D4_A8C8_0050DAC6D85C__INCLUDED_)

#define AFX_MD51_H__2A1EA377_D065_11D4_A8C8_0050DAC6D85C__INCLUDED_

#if _MSC_VER > 1000 #pragma once

#endif // _MSC_VER > 1000

/***************************************************************************

This class is a utility wrapper for 'C' code contained in internet RFC 1321, \

It calculates a cryptological hash value, called a \ string. For every unique character string the MD5 hash is guaranteed to be unique. The MD5 hash has the property that given the digest, it's

thought to be impossible to get back to the plain text string with existing technology. In this implementation the digest is always a 32 digit hex number, regardless of the length of the input plaintext.

This class is helpful for programs which store passwords. Rather than storing

the password directly, the programmer should store the MD5 digest of the password. Then when the user enters a password, compute the MD5 digest of the input password. If it is identical to the stored digest, then the user

has entered the correct password. It doesn't matter if an evil person sees the digest, since he or she can't get from the digest to the password. At least not unless the user enters a word out of the dictionary, since the evil person could hash the whole dictionary. One way to defeat a dictionary attack is to append a non-text character onto the password, so that even if the user enters a dumb password like \ password, i.e. password = \ By always appending a nonalpha character, your stored digest isn't in the attacker's dictionary. You can then safely post the digest of the password on a highway billboard.

Example pseudocode: { std::string storedPasswordDigest = GetPasswordDigestFromStorage(); std::string passwordEnteredbyUser; cout << \ cin >> passwordEnteredbyUser; CMD5 md5(passwordEnteredbyUser.c_str()); //note c_str() returns a pointer to the std::string's character buffer, just like CString's \ if(md5.getMD5Digest != storedPasswordDigest) { //user has entered an invalid password cout << \ exit(1); }

//if we get here, then the user entered a valid password }

************************************************************************** Use this code as you see fit. It is provided \ without express or implied warranty of any kind.

Jim Howard, jnhtx@jump.net

***************************************************************************/

class CMD5 {

public: CMD5(); //default ctor CMD5(const char* plainText); //set plaintext in ctor void setPlainText(const char* plainText); //set plaintext with a mutator, it's ok to //to call this multiple times, the digest is recalculated after each call. const char* getMD5Digest(); //access message digest (aka hash), return 0 if plaintext has not been set virtual ~CMD5(); private: bool calcDigest(); //this function computes the digest by calling the RFC 1321 'C' code bool m_digestValid; //false until the plaintext has been set and digest computed unsigned char m_digest[16]; //the numerical value of the digest char m_digestString[33]; //Null terminated string value of the digest expressed in hex digits char* m_plainText; //a pointer to the plain text. If casting away the const-ness //worries you, you could either make a local copy of the plain //text string instead of just pointing at the user's string or //modify the RFC 1321 code to take 'const' plaintext. };

#endif

// !defined(AFX_MD51_H__2A1EA377_D065_11D4_A8C8_0050DAC6D85C__INCLUDED_)

3. 写出算法流程,用程序设计语言将协议过程编程实现。 算法流程:

输入用户名-->系统记录用户名-->然后给出随机数R-->用MD5算法不断计算101次-->用户得到X1-X100的动态密码-->系统保留用户名及X101-->验证身份时用户输入X100-->系统将X100代入MD5算法算出X101-->与系统保留的X101比较,一致则验证通过,反之不成功-->动态密码用完,回到第三个步骤。

Main函数代码:

//Example program for the CMD5 class wrapper of the RFC 1321 Message Digest 5 code. //Use this code as you see fit. It is provided \//without express or implied warranty of any kind. #ifdef _DEBUG

#pragma warning( disable : 4786) //This warning always occurs with the ms compiler when using , it's nothing to worry about #endif

#include #include \#include #include #include #include #include #include using namespace std;

using namespace std; //required to use STL with MS compiler int Rget() { int r; srand((unsigned)time(0)); r=(rand()00)+1; return r; }

int main() {

//This program calculates message digests for the test strings given //in RFC 1321, \ int a; cout<<\欢迎进入系统登录界面****************\ cout<<\本系统由挫到不能再挫的渣渣写成,出现问题,那肯定是你的问题!\ cout<<\请选择功能:1.创建用户 2.增加用户 3.退出\ cin>>a; if(a==1) { string user; cout<<\请输入您的用户名:\ cin>>user; int R;

R=Rget(); cout<<\验证码为:\ strstream ss; string tr; ss<>tr; string X[101]; X[0]=tr; cout<<\您的活动密钥为(请妥善保管):\ for(int m=0;m<102;m++) { vector v;

v.push_back(std::string(X[m])); CMD5 md5; for(int i=0; i>b; if(b==2) return 0; else if(b==1) { string miyao,huanzhi; cout<<\请输入验证密钥:\ for(int k=100;k>0;k--) { cin>>miyao; vector v1;

v1.push_back(std::string(miyao)); CMD5 md51; for(int er=0; er

md51.setPlainText( v1[er].c_str() ); huanzhi=md51.getMD5Digest(); } if(miyue==huanzhi) { cout<<\验证完毕,您的身份是\ miyue=miyao; } else { cout<<\错误!非法用户未通过审核!\ return 0; } } } else return 0; }while(b==1); return 0; } else if(a==2) { cout<<\对不起,本系统不支持多用户功能,如给您带来不便,请谅解,新功能敬请期待第二代!\ } else if(a==3) { cout<<\灰常感谢您的使用,祝您生活愉快!\ return 0; } else { cout<<\操作不规范,强制退出,请重新开启系统!\ return 0; } }

4. 验证SKEY协议的身份鉴别过程。

本文来源:https://www.bwwdw.com/article/9sxp.html

Top