XX大学
密码学课程设计
姓名:
学号:
学院:
指导老师:
完成日期:2015.01.06
一:实验任务及要求
任务:使用IDEA算法实现加解密过程。
要求:1、输入至少包括两个分组。
2、核心功能是加解密过程,可适当增加附加功能。
3、2人/组
二:实现原理
IDEA算法是一个分组长度为64比特的分组密码算法,密钥长度为128比特,由8轮迭代操作实现。每个迭代都由三种函数:mod(216)加法、mod(216+1)乘法和逐位异或算法组成。整个算法包括子密钥产生、数据加密过程、数据解密过程三部分。该算法规定明文和密文块均为64比特,密钥长度为128
比特,加解密相同,只是密钥各异。
1、加密过程:
IDEA总共进行8轮迭代操作,每轮需要6个子密钥,另外还需要4个额外子密钥输出变换,所以总共需要52个子密钥,这52个子密钥都是从128比特密钥中扩展出来的。输入的明文为8个字符(即64比特),将64比特数据块分成X1,,X2,,X,3,X,4四个子块,每一子块16比特。这4个子块将作为第一轮迭代的输入,全部共8轮迭代。在每一轮中,这4个子块相互异或、相加和相乘,且与6个16比特子密钥相异或、相加和相乘。最后在输出变换中4个子块与4个子密钥进行运算。见图一。
2、解密过程
和加密密钥一样,解密密钥也需要扩展,不同的是解密密钥是由加密密钥加法逆或乘法逆构成的,且两者一一对应。
IDEA算法的解密过程和加密过程一样,只是加密用加密密钥EK,解密用的是解密密钥DK。输入的密文同样为8个字符(即64比特),将64比特数据块分成Y1,,Y2,,Y,3,Y,4四个子块,每一子块16比特。这4个子块将作为第一轮迭代的输入,全部共8轮迭代。见图二。
(IDEA加密算法轮结构)
三:源代码:
/*c-program of block cipher IDEA*/
#include<windows.h>
#include<stdio.h>
#include<process.h>
#include<string.h>
#include<stdlib.h>
#include<conio.h>
#define maxim 65537L
#define fuyi 65536L
#define one 65535L
#define round 8
#define buf_size 8
# define SIZE 8
#define swap_byte(x,y) t = *(x); *(x) = *(y); *(y) = t
int WINAPI DLLEntryPoint (HINSTANCE hDLL, DWORD dwReason, LPVOID Reserved);
int deideaFile(char *,char *,unsigned char *);
int enideaFile(char *,char *,unsigned char *);
void deideaString(unsigned char *keysession,unsigned char * inputdata,unsigned long inlength,unsigned char *outdata,unsigned long *outlength);
void enideaString(unsigned char *keysession,unsigned char * inputdata,unsigned long inlength,unsigned char *outdata,unsigned long *outlength);
/* encryption algorithm */
void cip(unsigned [],unsigned [],unsigned Z[7][10]);
/* generate encryption subkeys Z's */
void key(unsigned uskey[8], unsigned int Z[7][10]);
/* compute decryption subkeys DK's */
void de_key(unsigned int Z[7][10], unsigned int DK[7][10]);
/* compute inverse of xin by Euclidean gcd alg. */
unsigned int inv(unsigned int xin);
/* multiplication using the Low-High algorithm */
unsigned int mul(unsigned int a,unsigned int b);
void produce_plaintext(unsigned char text[],unsigned int XX[]);
void produce_miwen(unsigned char text[8],unsigned int YY[4]);
typedef struct rc4_key
{
unsigned char state[256];
unsigned char x;
unsigned char y;
} rc4_key;
void prepare_key(unsigned char key_data_ptrp[256], int key_data_len, rc4_key *key)
{
unsigned char t;
unsigned char index1;
unsigned char index2;
unsigned char state[256];
unsigned char key_data_ptr[256];
int counter;
int i;
/* strcpy(key_data_ptr,key_data_ptrp);*/
for(i=0;i<key_data_len;i++)
/*state[i] = key.state[i];*/
key_data_ptr[i]=key_data_ptrp[i];
for(i=0;i<256;i++)
state[i] = key->state[i];
for(counter = 0; counter < 256; counter++)
state[counter] =(char) counter;
key->x = 0;
key->y = 0;
index1 = 0;
index2 = 0;
for(counter = 0; counter < 256; counter++)
{
index2 = (key_data_ptr[index1] +state[counter] + index2) % 256;
swap_byte(state+counter, state+index2);
index1 = (index1 + 1) % key_data_len;
}
for(i=0;i<256;i++)
key->state[i] =state[i];
}
void rc4(unsigned char buffer_ptr[8], int buffer_len, rc4_key *key)
{
unsigned char t;
unsigned char x;
unsigned char y;
unsigned char state[256];
unsigned char xorIndex;
short counter;
int i;
x = key->x;
y = key->y;
for(i=0;i<256;i++)
state[i] = key->state[i];
for(counter = 0; counter < buffer_len; counter++)
{
x = (x + 1) % 256;
y = (state[x] + y) % 256;
swap_byte(state+x, state+y);
xorIndex = (state[x] + state[y]) % 256;
buffer_ptr[counter] ^= state[xorIndex];
}
for(i=0;i<256;i++)
key->state[i] = state[i];
key->x = x;
key->y = y;
}
void RC4RC4(unsigned char lSourcestr[],unsigned char* lSessionkey)
{
unsigned char seed[256];
unsigned char data[256];
unsigned char buf[buf_size];
unsigned char digit[5];
long hex;int rd;
int i;
int n;
rc4_key key;
int abcd;
abcd=strlen((char *)lSessionkey);
strcpy((char *)data,(char *)lSessionkey);
data[abcd]='\0';
n = strlen((char *)data);
if (n&1)
{
strcat((char *)data,"0");
n++;
}
n/=2;
strcpy((char *)digit,"AA");
for (i=0;i<n;i++)
{
digit[2] = data[i*2];
digit[3] = data[i*2+1];
hex=0xaa10;
seed[i] = (char)hex;
}
prepare_key(seed,n,&key);
rd=strlen((char *)lSourcestr);
strcpy((char *)buf,(char *)lSourcestr);
buf[rd]='\0';
rd=strlen((char *)buf);
rc4(buf,rd,&key);
buf[rd]='\0';
strcpy((char *)lSourcestr,(char *)buf);
return;
}
void produce_plaintext(unsigned char text[8],unsigned int XX[4])
{
int i;
for(i=0;i<4;i++)
{
XX[i]=text[2*i];
XX[i]=(XX[i]<<8)+text[2*i+1];
}
}
void produce_miwen(unsigned char text[8],unsigned int YY[4])
{
int i;
for(i=0;i<4;i++)
{
YY[i]=(unsigned int)text[2*i];
YY[i]=(YY[i]<<8)+text[2*i+1];
}
}
/* encryption algorithm */
void cip(unsigned int in[4],unsigned int out[4],unsigned int Z[7][10])
{
unsigned int r,x1,x2,x3,x4,kk,t1,t2,a;
x1=in[0];
x2=in[1];
x3=in[2];
x4=in[3];
for (r=1;r<=8;r++) /* the round function */
{
/* the group operation on 64-bits block */
x1=mul(x1,Z[1][r]);x4=mul(x4,Z[4][r]);
x2=(x2+Z[2][r])&one;x3=(x3+Z[3][r])&one;
/* the function of the MA structure */
kk=mul(Z[5][r],(x1^x3));
t1=mul(Z[6][r],(kk+(x2^x4))&one);
t2=(kk+t1)&one;
/* the involutary permutation PI */
x1=x1^t1;x4=x4^t2;a=x2^t2;x2=x3^t1;x3=a;
}
/* the output transformation */
out[0]=mul(x1,Z[1][round+1]);
out[3]=mul(x4,Z[4][round+1]);
out[1]=(x3+Z[2][round+1])&one;
out[2]=(x2+Z[3][round+1])&one;
}
/* multiplication using the Low-High algorithm */
unsigned int mul(unsigned int a,unsigned int b)
{
long int p;
long unsigned q;
if(a==0) p=maxim-b;
else if(b==0) p=maxim-a;else
{q=(unsigned long)a*(unsigned long)b;
p=(q&one)-(q>>16);if(p<=0) p=p+maxim;
}
return(unsigned ) (p&one);
}
/* compute inverse of xin by Euclidean gcd alg. */
unsigned inv (unsigned xin)
{
long n1,n2,q,r,b1,b2,t;
if(xin==0) b2=0;
else
{n1=maxim;n2=xin;b2=1;b1=0;
do {r=(n1%n2);q=(n1-r)/n2;
if(r==0) {if(b2<0) b2=maxim+b2;}
else {n1=n2;n2=r;t=b2;b2=b1-q*b2;b1=t;}
} while(r!=0);
}
return(unsigned long int )b2;
}
/* generate encryption subkeys Z's */
void key(unsigned int uskey[8],unsigned int Z[7][10])
{
unsigned int S[54];
int i,j,r;
for(i=0;i<8;i++) S[i]=uskey[i];
/*shifts*/
for(i=8;i<54;i++)
{
if((i+2)%8==0)/*forS[14],S[22],...*/
S[i]=((S[i-7]<<9)^(S[i-14]>>7))&one;
else if ((i+1)%8==0)/*for S[15],S[23],...*/
S[i]=((S[i-15]<<9)^(S[i-14]>>7))&one;
else
S[i]=((S[i-7]<<9)^(S[i-6]>>7))&one;
}
/*get subkeys*/
for(r=1;r<=round+1;r++) for(j=1;j<7;j++)
Z[j][r]=S[6*(r-1)+j-1];
}
/* compute decryption subkeys DK's */
void de_key(unsigned int Z[7][10],unsigned int DK[7][10])
{
int j;
for(j=1;j<=round+1;j++)
{ DK[1][round-j+2]=inv(Z[1][j]);
DK[4][round-j+2]=inv(Z[4][j]);
if((j==1)|(j==round+1))
{
DK[2][round-j+2]=(fuyi-Z[2][j])&one;
DK[3][round-j+2]=(fuyi-Z[3][j])&one;
}
else
{
DK[2][round-j+2]=(fuyi-Z[3][j])&one;
DK[3][round-j+2]=(fuyi-Z[2][j])&one;
}
}
for(j=1;j<=round+1;j++)
{DK[5][round+1-j]=Z[5][j];DK[6][round+1-j]=Z[6][j];}
}
int enideaFile(char *sourcefile,char *desfile,unsigned char *sessionkey)
{
FILE *fp1,*fp2;
unsigned char buf1[9],buf2[9];
int numread;
int i;
unsigned int Z[7][10],XX[4],YY[4];
unsigned int uskey[8];
unsigned char initkey[]="12345678";
unsigned char *inputkey;
if((fp1=fopen(sourcefile,"rb"))==NULL){
fprintf(stderr,"Can't open the plaintext_file");
return 10;
}
if((fp2=fopen(desfile,"wb"))==NULL){
fprintf(stderr,"Can't open the ciphertext_file");
return 15;
}
inputkey=sessionkey;
for(i=0;i<8;i++)
uskey[i]=(((unsigned int)inputkey[2*i]<<8)^((unsigned int)inputkey[2*i+1]));
key(uskey,Z); /*generate encryption subkeys Z[i][r]*/
do{
numread=fread(buf1,1,SIZE,fp1);
if(numread==0) break;
if(numread!=SIZE)
{
buf1[numread]='\0';
RC4RC4(buf1,initkey);
buf1[numread]='\0';
fwrite(buf1,1,numread,fp2);
break;
}
buf1[8]='\0';
/* Ming wen in XX[1..5] */
produce_plaintext(buf1,XX);
cip(XX,YY,Z);
for (i=0;i<4;i++)
{
buf2[2*i]=(YY[i]>>8)&0xff;
buf2[2*i+1]=YY[i]&0xff;
}
buf2[8]='\0';
fwrite(buf2,1,SIZE,fp2);
}while(numread!=0);
fclose(fp1);
fclose(fp2);
return 1;
}
int deideaFile(char *sourcefile,char *desfile,unsigned char *sessionkey)
{
FILE *fp1,*fp2;
unsigned char buf1[9],buf2[9];
int numread;
int i;
unsigned int Z[7][10],DK[7][10],TT[4],YY[4];
unsigned int uskey[8];
unsigned char initkey[]="12345678";
unsigned char *inputkey;
if((fp1=fopen(sourcefile,"rb"))==NULL){
fprintf(stderr,"Can't open the ciphertext_file");
return 10;
}
if((fp2=fopen(desfile,"wb"))==NULL){
fprintf(stderr,"Can't open the deplaintext_file");
return 15;
}
inputkey=sessionkey;
for(i=0;i<8;i++)
uskey[i]=(((unsigned int)inputkey[2*i]<<8)^((unsigned int)inputkey[2*i+1]));
key(uskey,Z); /*generate encryption subkeys Z[i][r]*/
de_key(Z,DK);/* compute decryption subkeys DK[i][r]*/
do{
numread=fread(buf1,1,SIZE,fp1);
if(numread==0) break;
if(numread!=SIZE)
{
buf1[numread]='\0';
RC4RC4(buf1,initkey);
buf1[numread]='\0';
fwrite(buf1,1,numread,fp2);
break;
}
buf1[8]='\0';
/* Ming wen in XX[1..5] */
produce_miwen(buf1,YY);
cip(YY,TT,DK);
for (i=0;i<4;i++)
{
buf2[2*i]=(TT[i]>>8)&0xff;
buf2[2*i+1]=TT[i]&0xff;
}
buf2[8]='\0';
fwrite(buf2,1,SIZE,fp2);
}while(numread!=0);
fclose(fp1);
fclose(fp2);
return 1;
}
void DeMemory(unsigned char* a)
{ free(a);
}
void enidea(unsigned char *keysession,unsigned char * inputdata,unsigned long inlength,unsigned char *outdata,unsigned long *outlength)
{
//FILE *fp1,*fp2;
//outputdata="\0";
unsigned char buf1[9],buf2[9];
int i,j,k,n;
unsigned int Z[7][10],XX[4],YY[4];
unsigned int uskey[8];
unsigned char initkey[]="12345678";
unsigned char *inputkey;
unsigned char *temp,*tempoutdata;
inputkey=keysession;
for(i=0;i<8;i++)
uskey[i]=(((unsigned int)inputkey[2*i]<<8)^((unsigned int)inputkey[2*i+1]));
key(uskey,Z); /*generate encryption subkeys Z[i][r]*/
// outdata=(unsigned char *)malloc(inlength*sizeof(unsigned long));
*outlength=inlength;
k=inlength/8;
if(k==0)
{
memcpy(outdata,inputdata,strlen((char *)inputdata));
RC4RC4(outdata,initkey);
}
else
{
temp=inputdata;
tempoutdata=outdata;
for(i=1;i<=k;i++)
{
for(j=0;j<8;j++)
{
buf1[j]=*(temp+j);
}
buf1[8]='\0';
produce_plaintext(buf1,XX);
cip(XX,YY,Z);
for (n=0;n<4;n++)
{
buf2[2*n]=(YY[n]>>8)&0xff;
buf2[2*n+1]=YY[n]&0xff;
}
temp+=8 ;
memcpy(tempoutdata,buf2,8);
tempoutdata+=8;
// strcpy(outdata,buf1);
}
memcpy(tempoutdata,temp,strlen((char *)temp)+1);
RC4RC4(tempoutdata,initkey);
}
// return outdata;
}
void deidea(unsigned char *keysession,unsigned char * inputdata,unsigned long inlength,unsigned char *outdata,unsigned long *outlength)
{
unsigned char buf1[9],buf2[9];
int i,k,j,n;
unsigned int Z[7][10],DK[7][10],TT[4],YY[4];
unsigned int uskey[8];
unsigned char initkey[]="12345678";
unsigned char *inputkey;
unsigned char *temp,*tempoutdata;
//outdata=(unsigned char *)malloc(inlength*sizeof(unsigned long));
*outlength=inlength;
inputkey=keysession;
for(i=0;i<8;i++)
uskey[i]=(((unsigned int)inputkey[2*i]<<8)^((unsigned int)inputkey[2*i+1]));
key(uskey,Z); /*generate encryption subkeys Z[i][r]*/
de_key(Z,DK);/* compute decryption subkeys DK[i][r]*/
k=inlength/8;
if(k==0)
{ memcpy(outdata,inputdata,strlen((char *)inputdata));
RC4RC4(outdata,initkey);
}
else
{temp=inputdata;
tempoutdata=outdata;
for(i=1;i<=k;i++)
{
for(j=0;j<8;j++)
{
buf1[j]=*(temp+j);
}
temp+=8;
produce_miwen(buf1,YY);
cip(YY,TT,DK);
for (n=0;n<4;n++)
{
buf2[2*n]=(TT[n]>>8)&0xff;
buf2[2*n+1]=TT[n]&0xff;
}
memcpy(tempoutdata,buf2,8);
tempoutdata+=8;
}
memcpy(tempoutdata,temp,strlen((char *)temp)+1);
RC4RC4(tempoutdata,initkey);
}
// return outdata;
}
int WINAPI DLLEntryPoint (HINSTANCE hDLL, DWORD dwReason, LPVOID Reserved)
{
switch(dwReason)
{
case DLL_PROCESS_ATTACH:
{break;}
case DLL_PROCESS_DETACH:
{break;}
}
return TRUE;
}
#include "idea.h"
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
void main()
{
unsigned char miwen[600], mingwen[600];int ch=0;char ch1;
unsigned char key[]="18testcppideacma";
unsigned char message[]="18建议不要将系统安装在移动硬盘上。因为移动硬盘速度较慢\n";
unsigned long length;
for(;;)
{cout<<"请根据下方提示选择操作:\n(1):输入明文\n(2):退出"<<endl;cin>>ch;
if(ch==1){cout<<"请输入待加密明文:";cin>>message;
cout<<"明文为:"<<message<<endl;
cout<<"请设置加密密钥(16个字符):";cin>>key;
cout<<"加密进行中...\n";
enidea(key,message,strlen((char *)message),miwen,&length);
cout<<"密文为: "<<miwen<<endl<<endl;}
else if(ch==2) break;
cout<<"是否对生成的密文进行解密(y/n):";cin>>ch1;if(ch1=='y') {
cout<<"请设置解密密钥(16个字符):";cin>>key;
deidea(key,miwen,length,mingwen,&length);
cout<<"明文为: "<<mingwen<<endl;}
}
system("pause");
}
四:程序结果截图:
五:实验总结:
经过这几天的课程设计,系统掌握了IDEA加解密加解密算法的设计思想,了解了其优点和局限性,也有一些体会。其一算法思想的重要性,是整个密码体系的关键,相当于顶层设计;其二具体实现的过程中,要考虑容错性、易维护还有效率问题,在这过程中会遇到很多小困难,要勤于独立思考,也要善于利用身边的工具解决问题。