# 用CBC加密模式实现IDEA算法

//IDEA.h

bool SetKey( unsigned short *key, unsigned short kLen );

void idea_encrypt( unsigned short *in, unsigned short *out );

void idea_decrypt( unsigned short *in, unsigned short *out );

//IDEA.c

#include <string.h>

#include <stdlib.h>

#include "idea.h"

//! 宏定义，IDEA迭代轮次

#define ROUNDS 8

//! 宏定义，参与加密过程的子密钥数目

#define KEYLEN (6*ROUNDS+4)

//! 宏定义，获取低16位字

#define low16(x) ((x) & 0xffff)

//! 用于保存52个加密子密钥

unsigned short gEnkey[52];

//! 用于保存52个解密子解钥

unsigned short gDekey[52];

typedef unsigned short IDEAkey[KEYLEN];

struct IDEA_MSG_ITEM

{

unsigned short X[4];

unsigned short Z[6];

unsigned short W[4];

};

struct IDEA_MSG

{

IDEA_MSG_ITEM items[8];

unsigned short Y[4];

unsigned short LZ[4];

};

IDEA_MSG gIDEA_MSG;

unsigned int inv( unsigned int x )

{

unsigned int t0,t1;

unsigned int q,y;

if( x <= 1 )

return x;

t1 = (unsigned int)(0x10001l / x);

y = (unsigned int)(0x10001l % x);

if( y == 1 )

return low16( 1 - t1 );

t0 = 1 ;

do

{

q = x / y;

x = x % y;

t0 += q * t1;

if (x == 1)

return t0;

q = y / x;

y = y % x;

t1 += q * t0;

} while( y != 1 );

return low16( 1-t1 );

}

unsigned short mul( unsigned int a, unsigned int b )

{

unsigned int p;

if(a)

{

if(b)

{

p=(unsigned int)a*b;

b=(unsigned int)(low16(p));

a=(unsigned int)(p>>16);

return b-a+(b<a);

}

else

{

return 1-a;

}

}

else

return 1-b;

}

#define IDEA_MUL(x,y) (x=mul(low16(x),y))

// 名称：MakeEnkey

// 功能：由用户输入密钥生成52个子密钥，每个子密钥16位

//  参数：userKey: 用户输入密钥; exKey: 52个加密子密钥

// 返回：无

void MakeEnkey( unsigned short *userKey, unsigned short *enKey )

{

int i,j;

//! 用户输入密钥分成8组，生成第1组共8个子密钥

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

enKey[j] = *userKey++;

//! 以下动作循环执行52次

//! 输入密钥循环左移25位，分成8组，得到一个子密钥

//! 当前轮次循环左移后的密钥，即是下一轮次的输入密钥

for( i=0; j<KEYLEN; j++ )

{

i++;

enKey[i+7] = ((enKey[i&7] << 9) | (enKey[i+1 & 7] >> 7));

enKey += i&8;

i &= 7;

}

}

// 名称：MakeDekey

// 功能：由52个加密子密钥生成52个解密子密钥，每个子密钥16位

//  参数：userKey: 用户输入密钥; exKey: 52个加密子密钥

// 返回：无

void MakeDekey( IDEAkey enKey, IDEAkey deKey )

{

int j;

unsigned int t1,t2,t3;

unsigned short usTemp[KEYLEN];

unsigned short *p = usTemp + KEYLEN;

t1 = inv( *enKey++ );

t2 =- *enKey++;

t3 =- *enKey++;

*--p = inv( *enKey++ );

*--p = t3;

*--p = t2;

*--p = t1;

for( j=1; j<ROUNDS; j++ )

{

t1 = *enKey++;

*--p = *enKey++;

*--p = t1;

t1 = inv( *enKey++ );

t2 = -*enKey++;

t3 = -*enKey++;

*--p = inv( *enKey++ );

*--p = t2;

*--p = t3;

*--p = t1;

}

t1 = *enKey++;

*--p = *enKey++;

*--p = t1;

t1 = inv( *enKey++ );

t2 = -*enKey++;

t3 = -*enKey++;

*--p = inv( *enKey++ );

*--p = t3;

*--p = t2;

*--p = t1;

for( j=0,p=usTemp; j<KEYLEN; j++ )

{

*deKey++ = *p;

*p++ = 0;

}

}

// 名称：SetKey

// 功能：调用函数，由用户输入密钥生成52个字密钥

//  参数：key: 用户输入密钥; kLen: 密钥长度

// 返回：成功返回true，否则返回false

bool SetKey( unsigned short *key, unsigned short kLen )

{

if( kLen != 8 )

return false;

MakeEnkey( key, gEnkey );

MakeDekey( gEnkey, gDekey );

return true;

}

// 名称：idea_encrypt

// 功能：IDEA加/解密过程8轮迭代及最后变换运算

//  参数：in: 64位输入明文; out: 64位输出密文; enKey: 加密子密钥

// 返回：无

void cipher_idea( unsigned short in[4], unsigned short out[4], const IDEAkey enKey )

{

unsigned short x1,x2,x3,x4,t1,t2;

int r = 0;

x1 = *in++;

x2 = *in++;

x3 = *in++;

x4 = *in;

//! 8轮迭代计算

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

{

gIDEA_MSG.items[r].X[0] = x1;

gIDEA_MSG.items[r].X[1] = x2;

gIDEA_MSG.items[r].X[2] = x3;

gIDEA_MSG.items[r].X[3] = x4;

gIDEA_MSG.items[r].Z[0] = enKey[0];

gIDEA_MSG.items[r].Z[1] = enKey[1];

gIDEA_MSG.items[r].Z[2] = enKey[2];

gIDEA_MSG.items[r].Z[3] = enKey[3];

gIDEA_MSG.items[r].Z[4] = enKey[4];

gIDEA_MSG.items[r].Z[5] = enKey[5];

IDEA_MUL( x1, *enKey++ );

x2 += *enKey++;

x3 += *enKey++;

IDEA_MUL( x4, *enKey++ );

t2 = x1 ^ x3;

IDEA_MUL( t2, *enKey++ );

t1 = t2 + (x2 ^ x4);

IDEA_MUL( t1, *enKey++ );

t2 = t1 + t2;

x1 ^= t1;

x4 ^= t2;

t2 ^= x2;

x2 = x3 ^ t1;

x3 = t2;

gIDEA_MSG.items[r].W[0] = x1;

gIDEA_MSG.items[r].W[1] = x2;

gIDEA_MSG.items[r].W[2] = x3;

gIDEA_MSG.items[r].W[3] = x4;

}

gIDEA_MSG.LZ[0] = enKey[0];

gIDEA_MSG.LZ[1] = enKey[1];

gIDEA_MSG.LZ[2] = enKey[2];

gIDEA_MSG.LZ[3] = enKey[3];

//! 最后变换

IDEA_MUL( x1, *enKey++ );

gIDEA_MSG.Y[0] = x1;

*out++ = x1;

gIDEA_MSG.Y[1] = (x3 + *enKey++);

*out++ = gIDEA_MSG.Y[1];

gIDEA_MSG.Y[2] = (x2 + *enKey++);

*out++ = gIDEA_MSG.Y[2];

IDEA_MUL( x4, *enKey );

gIDEA_MSG.Y[3] = x4;

*out = x4;

}

// 名称：idea_encrypt

// 功能：调用函数实现，IDEA加密

//  参数：in: 指向明文输入缓冲区; out: 指向密文输出缓冲区

// 返回：无

void idea_encrypt( unsigned short *in, unsigned short *out )

{

cipher_idea( in, out, gEnkey );

}

// 名称：idea_decrypt

// 功能：调用函数实现，IDEA解密

//  参数：in: 指向密文输入缓冲区; out: 指向明文输出缓冲区

// 返回：无

void idea_decrypt( unsigned short *in, unsigned short *out )

{

cipher_idea( in, out, gDekey );

}

//main.c

// 工程：IDEA

// 功能：用CBC方式实现IDEA加、解密功能

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <afxwin.h>

#include "idea.h"

#include<time.h>

#define DECRYPT_FILE "IDEA加密密文.txt"

#define ENCRYPT_FILE "IDEA解密明文.txt"

//! 约束文件最大2M

#define MAX_FILE 1024*1024*2

// 名称：usage

// 功能：帮助信息

//  参数：应用程序名称

// 返回：提示信息

void Usage( const char *appname )

{

printf( "\n\tusage: idea -e 明文文件 128位密钥\n" );

printf( "\tusage: idea -d 密文文件 128位密钥\n" );

}

// 名称：FileIn

// 功能：读取磁盘文件到内存

//  参数：strFile:文件名称；inBuff:指向文件内容缓冲区

// 返回：实际读取内容大小(字节)

int FileIn( const char *strFile, unsigned char *&inBuff )

{

int iFileLen=0, iBuffLen=0;

//! 打开密文文件

iFileLen = ( int )file.GetLength();

if( iFileLen>MAX_FILE )

{

printf( "文件长度不能大于 %dM,!\n", MAX_FILE/(1024*1024) );

goto out;

}

if( iFileLen % 8 != 0 )

iBuffLen = ( iFileLen/8+1 ) * 8;

else

iBuffLen = iFileLen;

inBuff = new unsigned char[iBuffLen];

if( !inBuff )

goto out;

ZeroMemory( inBuff, iBuffLen );

file.Close();

out:

return iBuffLen;

}

// 名称：FileOut

// 功能：加/解密结果输出到当前目录磁盘文件中

//  参数：strOut指向输出字符缓冲区，输出大小len，strFile为输出文件

// 返回：无

void FileOut( const char *strOut, int len, const char *strFile )

{

//! 输出到文件

CFile outfile( strFile , CFile::modeCreate | CFile::modeWrite );

outfile.Write( strOut , len );

outfile.Close();

}

// 名称：CheckParse

// 功能：校验应用程序入口参数

//  参数：argc等于main主函数argc参数，argv指向main主函数argv参数

// 返回：若参数合法返回true，否则返回false

//  备注：简单的入口参数校验

bool CheckParse( int argc, char** argv )

{

if( (argc != 4) ||

(argv[1][1]!='e' && argv[1][1]!='d') ||

(strlen( argv[3] ) >(128/8) ) )

{

Usage( argv[0] );

return false;

}

return true;

}

//! 程序主函数(Use MFC in a Shared DLL)

int main( int argc, char **argv )

{

int len,klen,i;

char FileName[20];

unsigned char *inBuffer=(unsigned char *)malloc(MAX_FILE); //输入缓冲区

char *strOut=(char *)malloc(MAX_FILE); //字符输出缓冲区

unsigned short cbc[4]={123,345,567,789}; //实现CBC加密方式的64位初始向量

unsigned short in[4]; //64位的输入

unsigned short out[4]; //64位的输出

unsigned short key[4]; //64位密钥

CheckParse(argc,argv);

strcpy(FileName,argv[2]);

len = FileIn(FileName, inBuffer);

key[0]=(argv[3][0]<<8)|argv[3][1];

key[1]=(argv[3][2]<<8)|argv[3][3];

key[2]=(argv[3][4]<<8)|argv[3][5];

key[3]=(argv[3][6]<<8)|argv[3][7];

klen=8;

SetKey( key,klen); //提取密钥

if(argv[1][1]=='e')

{

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

{

in[0]=(inBuffer[i]<<8)|inBuffer[i+1];

in[1]=(inBuffer[i+2]<<8)|inBuffer[i+3];

in[2]=(inBuffer[i+4]<<8)|inBuffer[i+5];

in[3]=(inBuffer[i+6]<<8)|inBuffer[i+7]; //形成64位的明文分组

in[0]=in[0]^cbc[0];

in[1]=in[1]^cbc[1];

in[2]=in[2]^cbc[2];

in[3]=in[3]^cbc[3]; //cbc异或

idea_encrypt(in,out);

cbc[0]=out[0];

cbc[1]=out[1];

cbc[2]=out[2];

cbc[3]=out[3]; //

strOut[i]=(char)(out[0]>>8);

strOut[i+1]=(char)(out[0]&0x00FF);

strOut[i+2]=(char)(out[1]>>8);

strOut[i+3]=(char)(out[1]&0x00FF);

strOut[i+4]=(char)(out[2]>>8);

strOut[i+5]=(char)(out[2]&0x00FF);

strOut[i+6]=(char)(out[3]>>8);

strOut[i+7]=(char)(out[3]&0x00FF); //将64位的密文输出到字符缓冲区

}

FileOut(strOut, len , DECRYPT_FILE);

}//加密

else if(argv[1][1]=='d')

{

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

{

in[0]=(inBuffer[i]<<8)|inBuffer[i+1];

in[1]=(inBuffer[i+2]<<8)|inBuffer[i+3];

in[2]=(inBuffer[i+4]<<8)|inBuffer[i+5];

in[3]=(inBuffer[i+6]<<8)|inBuffer[i+7];

idea_decrypt(in,out);

out[0]=out[0]^cbc[0];

out[1]=out[1]^cbc[1];

out[2]=out[2]^cbc[2];

out[3]=out[3]^cbc[3]; //

cbc[0]=in[0];

cbc[1]=in[1];

cbc[2]=in[2];

cbc[3]=in[3];

strOut[i]=(char)(out[0]>>8);

strOut[i+1]=(char)(out[0]&0x00FF);

strOut[i+2]=(char)(out[1]>>8);

strOut[i+3]=(char)(out[1]&0x00FF);

strOut[i+4]=(char)(out[2]>>8);

strOut[i+5]=(char)(out[2]&0x00FF);

strOut[i+6]=(char)(out[3]>>8);

strOut[i+7]=(char)(out[3]&0x00FF);

}

FileOut(strOut, len , ENCRYPT_FILE);

}//解密

return true;

}

01-23

03-23
09-23 7万+
09-01 3万+
01-25 4597
09-26
03-23
05-04 2万+
04-03 292
05-18 4571
07-14 7113
08-13 1万+
07-20 504
03-30 1004
05-30 6842
04-20 9706