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环境下测试通过.
|