实现基于IDEA算法的加密工具(6)

3/23/2008来源:软件工程人气:4751


3.5 算法实现代码

/*此处略去信息说明和头文件*/

#include "idea.h"


#define NULL ((void *)0)

typedef int INT32;

typedef char INT8;

typedef unsigned char ULONG8;

typedef unsigned short ULONG16;

typedef unsigned long ULONG32;


#define SUCCESS 0

#define FAIL -1

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

#define _USEDFINDTABLE_ 1 /*是否采用查表实现*/

/*解密时密钥的换位表*/

//ULONG16 outkey[52] = { 0 };

static ULONG8 wz_spkey[52] = {

48,49,50,51,46,47,

42,44,43,45,40,41,/*解密密钥配置,2,3位要交换:44<->43*/

36,38,37,39,34,35,/*解密密钥配置,2,3位要交换:38<->37*/

30,32,31,33,28,29,/*解密密钥配置,2,3位要交换:32<->31*/

24,26,25,27,22,23,/*解密密钥配置,2,3位要交换:26<->25*/

18,20,19,21,16,17,/*解密密钥配置,2,3位要交换:20<->19*/

12,14,13,15,10,11,/*解密密钥配置,2,3位要交换:14<->13*/

6, 8, 7, 9, 4, 5,/*解密密钥配置,2,3位要交换:8<->7*/

0, 1, 2, 3

};


static ULONG8 wz_spmulrevr[18] = {/*变乘法逆的位*/

0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51

};

static ULONG8 wz_spaddrever[18] ={/*变加法逆的位*/

1,2,7,8,13,14,19,20,25,26,31,32,37,38,43,44,49,50

};

INT32 mulInv( ULONG16 x);/*取x的(%0x10001L)乘法逆*/

INT32 handle_data( ULONG16 *data, /*待加密的64位数据首地址*/

ULONG16 *key /* 6组本轮使用的16位长的密钥首地址*/

);

INT32 idea_makekey( ULONG32 *inkey,/*用户输入的128位密钥首地址*/

ULONG16 *outkey/*生成的52组16位密钥的首地址*/

);

INT32 key_leftmove(ULONG32 *inkey);

INT32 key_decryEXP(ULONG16 *outkey);/*解密密钥的变逆处理*/

INT32 MUL( ULONG16 a, ULONG16 b);/*(a*b)*/


 

INT32 idea_dec( ULONG16 *data, /*待解密的64位数据首地址*/

ULONG16 *outkey

)

{


ULONG32 i ;

ULONG16 tmp;

if ( NULL == data NULL == outkey)

{

return FAIL;

}

for ( i = 0 ; i < 48 ; i += 6)/*8轮*/

{

handle_data( data , &outkey[i]);

/*交换中间两个*/

tmp = data[1];

data[1] = data[2];

data[2] = tmp;

}

tmp = data[1];/*最后一轮不交换*/

data[1] = data[2];

data[2] = tmp;


data[0] = MUL(data[0],outkey[48]);

data[1] += outkey[49];

data[2] += outkey[50];


data[3] = MUL(data[3],outkey[51]);

return SUCCESS;

}


INT32 idea_enc( ULONG16 *data, /*待加密的64位数据首地址*/

ULONG16 *outkey

)

{

ULONG32 i ;

ULONG16 tmp;

if ( NULL == data NULL == outkey)

{

return FAIL;

}

for ( i = 0 ; i < 48 ; i += 6)/*8轮*/

{

handle_data( data , &outkey[i]);

/*交换中间两个*/

tmp = data[1];

data[1] = data[2];

data[2] = tmp;

}

tmp = data[1];/*最后一轮不交换*/

data[1] = data[2];

data[2] = tmp;


data[0] = MUL(data[0],outkey[48]);

data[1] += outkey[49];

data[2] += outkey[50];

data[3] = MUL(data[3],outkey[51]);

return SUCCESS;

}


INT32 handle_data( ULONG16 *data, /*待加密的64位数据首地址*/

ULONG16 *key /* 6组本轮使用的16位长的密钥首地址*/

)

{

ULONG16 *D1,*D2,*D3,*D4;

ULONG16 D57;/*提供给第5,7步用的暂存数据的*/

ULONG16 D68;/*提供给第6,8,9,10步用的暂存数据的*/

D1 = &data[0];

D2 = &data[1];

D3 = &data[2];

D4 = &data[3];

/*start*/

*D1 = MUL(*D1,key[0]);/*第1步*/

*D2 += key[1];/*第2步*/

*D3 += key[2];/*第3步*/

*D4 = MUL(*D4,key[3]);/*第4步*/

D57 = *D1 ^ *D3;/*第5步*/

D68 = *D2 ^ *D4;/*第6步*/

D57 = MUL(D57,key[4]);/*第7步*/

D68 += D57;/*第8步*/

D68 = MUL(D68,key[5]);/*第9步*/

*D1 ^= D68;/*第11步*/

*D3 ^= D68;/*第12步*/

D68 += D57;/*第10步*/

*D2 ^= D68;/*第13步*/

*D4 ^= D68;/*第14步*/


return SUCCESS;

}


INT32 idea_makekey( ULONG32 *inkey,/*用户输入的128位密钥首地址*/

ULONG16 *outkey/*生成的52组16位密钥的首地址*/

)

{

ULONG32 i,j,k;

ULONG16 *Pkey = ( ULONG16*)inkey;

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

{

k = i << 3;

for( j = 0 ; j < 8 ; j++)/*生成8组密钥*/

{

outkey[k+j] = Pkey[j] ;

}

key_leftmove(inkey);/*128位密钥左环移25位*/

}

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

{

outkey[48+i] = Pkey[i] ;

}


return SUCCESS;

}


INT32 key_leftmove(ULONG32 *inkey)/*密钥左环移25位*/

{

ULONG32 itmpfirst = 0,itmp = 0 ;

ULONG32 i;

inkey[0] = (inkey[0]<<25) (inkey[0]>>7);

/*取低25位,因为前面已经做了环移,原始的低7位已经移到了高位,保存*/

itmpfirst = inkey[0]&0x1ffffff;

inkey[0] &= 0xfe000000;/*低25位清0*/

for ( i = 1 ; i < 4 ; i++)

{

inkey[i] = (inkey[i]<<25) (inkey[i]>>7);

itmp = inkey[i] & 0x1ffffff;

inkey[i-1] = itmp;

inkey[i] &= 0xfe000000;/*低25位清0*/

}

inkey[i-1] = itmpfirst;/*把最高25位移到最低25位*/


return SUCCESS;

}


 

INT32 key_decryExp(ULONG16 *outkey)/*解密密钥的变逆处理*/

{

/*我习惯用查表的方法实现换位,当然也可以采用一些编程技巧直接实现*/


#if _USEDFINDTABLE_ /*用查表法*/

ULONG16 tmpkey[52] = { 0 };

ULONG32 i;

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

{

tmpkey[i] = outkey[ wz_spkey[i] ] ;/*换位*/

}

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

{

outkey[i] = tmpkey[i];

}

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

{

outkey[wz_spaddrever[i]] = 65536 -outkey[wz_spaddrever[i]] ;/*替换成加法逆*/

}

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

{

outkey[wz_spmulrevr[i]] = mulInv(outkey[wz_spmulrevr[i]] );/*替换成乘法逆*/

}


#else

ULONG16 K1, K2, K3, K4, i;

ULONG16 tmpkey[52] = { 0 };

ULONG16 *pin = outkey ;

ULONG16 *p = tmpkey + 52; /* 从后往前 */

K1 = mulInv(*pin);

K2 = 65536 - *++pin;

K3 = 65536 - *++pin;

K4 = mulInv(*++pin);

pin++;

*--p = K4;

*--p = K3;

*--p = K2;

*--p = K1;

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

{

K1 = *pin++;/*不变的两个*/

K2 = *pin++;

*--p = K2;

*--p = K1;


K1 = mulInv(*pin);

K2 = 65536 - *++pin;

K3 = 65536 - *++pin;

K4 = mulInv(*++pin);

pin++;

*--p = K4;

*--p = K2; /* 交换 */

*--p = K3;

*--p = K1;

}

K1 = *pin++;/*最后一组不交换*/

K2 = *pin++;

*--p = K2;

*--p = K1;

K1 = mulInv(*pin);

K2 = 65536 - *++pin;

K3 = 65536 - *++pin;

K4 = mulInv(*++pin);

*--p = K4;

*--p = K3;

*--p = K2;

*--p = K1;

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

{

outkey[i] = tmpkey[i];

}


 

#endif


return SUCCESS;

}


DllExport INT32 idea_MakeEncKey(ULONG16 *key, ULONG16 *outkey)

{

if ( NULL == outkey NULL == key)

{

return FAIL;

}

idea_makekey( (ULONG32*)key , outkey);

return SUCCESS;


}


INT32 idea_MakeDecKey(ULONG16 *key, ULONG16 *outkey)

{

if ( NULL == outkey NULL == key)

{

return FAIL;

}

idea_makekey( (ULONG32*)key , outkey);

key_decryExp(outkey);

return SUCCESS;

}

/*算法实现结束*/

上述代码在vc6.0环境下测试通过.