用CBC加密模式实现IDEA算法

用CBC加密模式实现IDEA算法

分组加密算法加密的数据块长度是固定的。为了安全地加密任意长度的数据,人们引入了加密模式。通过加密模式,加密算法可加密任意长度的数据。密文反馈模式(CBC)是一种常用的加密模式,它首先将输入数据分块,每块的长度为加密算法可处理的块长度,最后一块若不到块长度,则通过填充0比特使其达到块长。上图给出了CBC的原理。其中+代表异或操作,Ek代表使用密钥k进行加密的操作,Dk代表使用密钥k解密的操作。图中上半部分为加密的过程,下半部为解密过程。

//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;


//! 打开密文文件

CFile file( strFile, CFile::modeRead );

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.Read( inBuff, iFileLen );

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;

}


已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页