基于C++的DES加密算法实现.docx
《基于C++的DES加密算法实现.docx》由会员分享,可在线阅读,更多相关《基于C++的DES加密算法实现.docx(27页珍藏版)》请在冰豆网上搜索。
基于C++的DES加密算法实现
今天偶尔想到数据加密技术,刚才简单讨论了一下MD5和SHA,这里顺便提一下双向加密的标准DES。
以前在一个宽带流媒体服务器项目中用到了DES加密,虽然使用环境相对单纯,但算法实现本身是具有普遍意义的。
下述程序是很久以前在RSA公司的网站找到的,效率很高,稳定性较好,便一直在实践中使用。
首先在头文件中定义一个DES类:
//des.h
#ifndef__DES_H
#define__DES_H
classDES{
public:
//Encrypt/decryptthedatain"data",accordingtothe"key".
//Callerisresponsibleforconfirmingthebuffersizeof"data"
//pointstois8*"blocks"bytes.
//Thedataencrypted/decryptedisstoredindata.
//Thereturncodeis1:
success,other:
failed.
intencrypt(unsignedcharkey[8],unsignedchar*data,intblocks=1);
intdecrypt(unsignedcharkey[8],unsignedchar*data,intblocks=1);
//Encrypt/decryptanysizedata,accordingtoaspecialmethod.
//Beforecallingyencrypt,copydatatoanewbufferwithsize
//calculatedbyextend.
intyencrypt(unsignedcharkey[8],unsignedchar*data,intsize);
intydecrypt(unsignedcharkey[8],unsignedchar*in,intblocks,int*size=0);
intextend(intsize){return(size/8+1)*8;};
private:
voiddes(unsignedchar*in,unsignedchar*out,intblocks);
voiddes_block(unsignedchar*in,unsignedchar*out);
private:
unsignedlongKnL[32];
enumMode{ENCRYPT,DECRYPT};
voiddeskey(unsignedcharkey[8],Modemd);
voidusekey(unsignedlong*);
voidcookey(unsignedlong*);
private:
voidscrunch(unsignedchar*,unsignedlong*);
voidunscrun(unsignedlong*,unsignedchar*);
voiddesfunc(unsignedlong*,unsignedlong*);
private:
staticunsignedcharDf_Key[24];
staticunsignedshortbytebit[8];
staticunsignedlongbigbyte[24];
staticunsignedcharpc1[56];
staticunsignedchartotrot[16];
staticunsignedcharpc2[48];
staticunsignedlongSP1[64];
staticunsignedlongSP2[64];
staticunsignedlongSP3[64];
staticunsignedlongSP4[64];
staticunsignedlongSP5[64];
staticunsignedlongSP6[64];
staticunsignedlongSP7[64];
staticunsignedlongSP8[64];
};
#endif
而后,具体实现DES类:
//des.cpp
#include
#include"Sinodes.h"
intDES:
:
encrypt(unsignedcharkey[8],unsignedchar*data,intblocks)
{
if((!
data)||(blocks<1))
return0;
deskey(key,ENCRYPT);
des(data,data,blocks);
return1;
};
intDES:
:
decrypt(unsignedcharkey[8],unsignedchar*data,intblocks)
{
if((!
data)||(blocks<1))
return0;
deskey(key,DECRYPT);
des(data,data,blocks);
return1;
};
intDES:
:
yencrypt(unsignedcharkey[8],unsignedchar*data,intsize)
{
if((!
data)||(size<1))
return0;
//Thelastcharofdataisbitwisecomplementedandfilledtherest
//buffer.Ifsizeis16,itwillextendto24,and17still24.
charlastChar=*(data+size-1);
intblocks=size/8+1;
memset(data+size,~lastChar,blocks*8-size);
deskey(key,ENCRYPT);
returnencrypt(data,data,blocks);
};
intDES:
:
ydecrypt(unsignedcharkey[8],unsignedchar*data,intblocks,int*size)
{
if((!
data)||(blocks<1))
return0;
deskey(key,DECRYPT);
if(!
decrypt(data,data,blocks))
return0;
if(size!
=0)
{
intpos=blocks*8-1;
charendChar=data[pos];
while((pos>0)&&(data[pos]==endChar))
pos--;
if(data[pos]!
=~endChar)
return0;
*size=pos+1;
}
return1;
};
//-----------------------------------------------------------------------
//des
//Encrpts/Decrypts(accordingtothekeycurrentlyloadedintthe
//internalkeyregister)SOMEblocksofeightbytesataddress'in'
//intotheblockataddress'out'.Theycanbethesame.
//
//"in"
//"out"
//"block"Numberofblocks.
//-----------------------------------------------------------------------
voidDES:
:
des(unsignedchar*in,unsignedchar*out,intblocks)
{
for(inti=0;ides_block(in,out);
};
//-----------------------------------------------------------------------
//des_block
//Encrpts/Decrypts(accordingtothekeycurrentlyloadedintthe
//internalkeyregister)oneblockofeightbytesataddress'in'
//intotheblockataddress'out'.Theycanbethesame.
//
//"in"
//"out"
//-----------------------------------------------------------------------
voidDES:
:
des_block(unsignedchar*in,unsignedchar*out)
{
unsignedlongwork[2];
scrunch(in,work);
desfunc(work,KnL);
unscrun(work,out);
};
//----------------------------------------------------------------------
//deskey
//Setstheinternalkeyregister(KnR)accordingtothehexadecimal
//keycontainedinthe8bytesofhexkey,accordingtotheDES,
//forencryptionordecrytionaccordingtoMODE
//
//"key"isthe64bitskey.
//"md"meansencryptionordecryption.
//----------------------------------------------------------------------
voidDES:
:
deskey(unsignedcharkey[8],Modemd)
{
registerintii,j,l,m,n;
unsignedcharpc1m[56],pcr[56];
unsignedlongkn[32];
for(j=0;j<56;j++){
l=pc1[j];
m=l&07;
pc1m[j]=(key[l>>3]&bytebit[m])?
1:
0;
}
for(ii=0;ii<16;ii++){
if(md==DECRYP)m=(15-ii)<<1;
elsem=ii<<1;
n=m+1;
kn[m]=kn[n]=0L;
for(j=0;j<28;j++){
l=j+totrot[ii];
if(l<28)pcr[j]=pc1m[l];
elsepcr[j]=pc1m[l-28];
}
for(j=28;j<56;j++){
l=j+totrot[ii];
if(l<56)pcr[j]=pc1m[l];
elsepcr[j]=pc1m[l-28];
}
for(j=0;j<24;j++){
if(pcr[pc2[j]])kn[m]|=bigbyte[j];
if(pcr[pc2[j+24]])kn[n]|=bigbyte[j];
}
}
cookey(kn);
return;
};
//----------------------------------------------------------------------
//cookey
//Onlycalledbydeskey.
//-----------------------------------------------------------------------
voidDES:
:
cookey(registerunsignedlong*raw1)
{
registerunsignedlong*cook,*raw0;
unsignedlongdough[32];
registerinti;
cook=dough;
for(i=0;i<16;i++,raw1++){
raw0=raw1++;
*cook=(*raw0&0x00fc0000L)<<6;
*cook|=(*raw0&0x00000fc0L)<<10;
*cook|=(*raw1&0x00fc0000L)>>10;
*cook++|=(*raw1&0x00000fc0L)>>6;
*cook=(*raw0&0x0003f000L)<<12;
*cook|=(*raw0&0x0000003fL)<<16;
*cook|=(*raw1&0x0003f000L)>>4;
*cook++|=(*raw1&0x0000003fL);
}
usekey(dough);
return;
};
//----------------------------------------------------------------------
//usekey
//Onlycalledbycookey.
//Loadstheinteralkeyregisterwiththedataincookedkey.
//-----------------------------------------------------------------------
voidDES:
:
usekey(registerunsignedlong*from)
{
registerunsignedlong*to,*endp;
to=KnL,endp=&KnL[32];
while(toreturn;
};
voidDES:
:
scrunch(registerunsignedchar*outof,registerunsignedlong*into)
{
*into=(*outof++&0xffL)<<24;
*into|=(*outof++&0xffL)<<16;
*into|=(*outof++&0xffL)<<8;
*into++|=(*outof++&0xffL);
*into=(*outof++&0xffL)<<24;
*into|=(*outof++&0xffL)<<16;
*into|=(*outof++&0xffL)<<8;
*into|=(*outof&0xffL);
return;
};
voidDES:
:
unscrun(registerunsignedlong*outof,registerunsignedchar*into)
{
*into++=(*outof>>24)&0xffL;
*into++=(*outof>>16)&0xffL;
*into++=(*outof>>8)&0xffL;
*into++=*outof++&0xffL;
*into++=(*outof>>24)&0xffL;
*into++=(*outof>>16)&0xffL;
*into++=(*outof>>8)&0xffL;
*into=*outof&0xffL;
return;
};
voidDES:
:
desfunc(registerunsignedlong*block,registerunsignedlong*keys)
{
registerunsignedlongfval,work,right,leftt;
registerintround;
leftt=block[0];
right=block[1];
work=((leftt>>4)^right)&0x0f0f0f0fL;
right^=work;
leftt^=(work<<4);
work=((leftt>>16)^right)&0x0000ffffL;
right^=work;
leftt^=(work<<16);
work=((right>>2)^leftt)&0x33333333L;
leftt^=work;
right^=(work<<2);
work=((right>>8)^leftt)&0x00ff00ffL;
leftt^=work;
right^=(work<<8);
right=((right<<1)|((right>>31)&1L))&0xffffffffL;
work=(leftt^right)&0xaaaaaaaaL;
leftt^=work;
right^=work;
leftt=((leftt<<1)|((leftt>>31)&1L))&0xffffffffL;
for(round=0;round<8;round++){
work=(right<<28)|(right>>4);
work^=*keys++;
fval=SP7[work&0x3fL];
fval|=SP5[(work>>8)&0x3fL];
fval|=SP3[(work>>16)&0x3fL];
fval|=SP1[(work>>24)&0x3fL];
work=right^*keys++;
fval|=SP8[work&0x3fL];
fval|=SP6[(work>>8)&0x3fL];
fval|=SP4[(work>>16)&0x3fL];
fval|=SP2[(work>>24)&0x3fL];
leftt^=fval;
work=(leftt<<28)|(leftt>>4);
work^=*keys++;
fval=SP7[work&0x3fL];
fval|=SP5[(work>>8)&0x3fL];
fval|=SP3[(work>>16)&0x3fL];
fval|=SP1[(work>>24)&0x3fL];
work=leftt^*keys++;
fval|=SP8[work&0x3fL];
fval|=SP6[(work>>8)&0x3fL];
fval|=SP4[(work>>16)&0x3fL];
fval|=SP2[(work>>24)&0x3fL];
right^=fval;
}
right=(right<<31)|(right>>1);
work=(leftt^right)&0xaaaaaaaaL;
leftt^=work;
right^=work;
leftt=(leftt<<31)|(leftt>>1);
work=((leftt>>8)^right)&0x00ff00ffL;
right^=work;
leftt^=(work<<8);
work=((leftt>>2)^right)&0x33333333L;
right^=work;
leftt^=(work<<2);
work=((right>>16)^leftt)&0x0000ffffL;
leftt^=work;
right^=(work<<16);
work=((right>>4)^leftt)&0x0f0f0f0fL;
leftt^=work;
right^=(work<<4);
*block++=right;
*block=leftt;
return;
};
//-----------------------------------------------------------------------
//Initialofstaticdatamembers.Thesedatawillbeusedbyallthe
//instancesofclass,andcannotbechanged.
//-----------------------------------------------------------------------
unsignedcharDES:
:
Df_Key[24]={
0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67};
unsignedshortDES:
:
bytebit[8]={
0200,0100,040,020,010,04,02,01};
unsignedlongDES:
:
bigbyte[24]={
0x800000L,0x400000L,