算法简单,而且效率高,每次可以操作8个字节的数据,加密解密的KEY为16字节,即包含4个int数据的int型数组,加密轮数应为8的倍数,一般比较常用的轮数为64,32,16,QQ原来就是用TEA16来还原密码的.
TEA算法
核心为:
#include<stdint.h>
voidencrypt(uint32_t*v,uint32_t*k){
uint32_tv0=v[0],v1=v[1],sum=0,i;/*setup*/
uint32_tdelta=0x9e3779b9;/*akeyscheduleconstant*/
uint32_tk0=k[0],k1=k[1],k2=k[2],k3=k[3];/*cachekey*/
for(i=0;i<32;i++){/*basiccyclestart*/
sum+=delta;
v0+=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
v1+=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);
}/*endcycle*/
v[0]=v0;v[1]=v1;
}
voiddecrypt(uint32_t*v,uint32_t*k){
uint32_tv0=v[0],v1=v[1],sum=0xC6EF3720,i;/*setup*/
uint32_tdelta=0x9e3779b9;/*akeyscheduleconstant*/
uint32_tk0=k[0],k1=k[1],k2=k[2],k3=k[3];/*cachekey*/
for(i=0;i<32;i++){/*basiccyclestart*/
v1-=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);
v0-=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
sum-=delta;
}/*endcycle*/
v[0]=v0;v[1]=v1;
}
PHP部分代码非我原创
,大家可以了解一下这方面的知识
<?php
$date='8345354023476-3434';
$key='12345';
$t=newtea();
$tea=$t->encrypt($date,$key);
$eetea=$t->decrypt($tea,$key);
var_dump($tea);
var_dump($eetea);
classtea{
private$a,$b,$c,$d;
private$n_iter;
publicfunction__construct(){
$this->setIter(32);
}
privatefunctionsetIter($n_iter){
$this->n_iter=$n_iter;
}
privatefunctiongetIter(){
return$this->n_iter;
}
publicfunctionencrypt($data,$key){
//resizedatato32bits(4bytes)
$n=$this->_resize($data,4);
//convertdatatolong
$data_long[0]=$n;
$n_data_long=$this->_str2long(1,$data,$data_long);
//resizedata_longto64bits(2longsof32bits)
$n=count($data_long);
if(($n&1)==1){
$data_long[$n]=chr(0);
$n_data_long++;
}
//resizekeytoamultipleof128bits(16bytes)
$this->_resize($key,16,true);
if(''==$key)
$key='0000000000000000';
//convertkeytolong
$n_key_long=$this->_str2long(0,$key,$key_long);
//encryptthelongdatawiththekey
$enc_data='';
$w=array(0,0);
$j=0;
$k=array(0,0,0,0);
for($i=0;$i<$n_data_long;++$i){
//getnextkeypartof128bits
if($j+4<=$n_key_long){
$k[0]=$key_long[$j];
$k[1]=$key_long[$j+1];
$k[2]=$key_long[$j+2];
$k[3]=$key_long[$j+3];
}else{
$k[0]=$key_long[$j%$n_key_long];
$k[1]=$key_long[($j+1)%$n_key_long];
$k[2]=$key_long[($j+2)%$n_key_long];
$k[3]=$key_long[($j+3)%$n_key_long];
}
$j=($j+4)%$n_key_long;
$this->_encipherLong($data_long[$i],$data_long[++$i],$w,$k);
//appendtheencipheredlongstotheresult
$enc_data.=$this->_long2str($w[0]);
$enc_data.=$this->_long2str($w[1]);
}
return$enc_data;
}
publicfunctiondecrypt($enc_data,$key){
//convertdatatolong
$n_enc_data_long=$this->_str2long(0,$enc_data,$enc_data_long);
//resizekeytoamultipleof128bits(16bytes)
$this->_resize($key,16,true);
if(''==$key)
$key='0000000000000000';
//convertkeytolong
$n_key_long=$this->_str2long(0,$key,$key_long);
//decryptthelongdatawiththekey
$data='';
$w=array(0,0);
$j=0;
$len=0;
$k=array(0,0,0,0);
$pos=0;
for($i=0;$i<$n_enc_data_long;$i+=2){
//getnextkeypartof128bits
if($j+4<=$n_key_long){
$k[0]=$key_long[$j];
$k[1]=$key_long[$j+1];
$k[2]=$key_long[$j+2];
$k[3]=$key_long[$j+3];
}else{
$k[0]=$key_long[$j%$n_key_long];
$k[1]=$key_long[($j+1)%$n_key_long];
$k[2]=$key_long[($j+2)%$n_key_long];
$k[3]=$key_long[($j+3)%$n_key_long];
}
$j=($j+4)%$n_key_long;
$this->_decipherLong($enc_data_long[$i],$enc_data_long[$i+1],$w,$k);
//appendthedecipheredlongstotheresultdata(removepadding)
if(0==$i){
$len=$w[0];
if(4<=$len){
$data.=$this->_long2str($w[1]);
}else{
$data.=substr($this->_long2str($w[1]),0,$len%4);
}
}else{
$pos=($i-1)*4;
if($pos+4<=$len){
$data.=$this->_long2str($w[0]);
if($pos+8<=$len){
$data.=$this->_long2str($w[1]);
}elseif($pos+4<$len){
$data.=substr($this->_long2str($w[1]),0,$len%4);
}
}else{
$data.=substr($this->_long2str($w[0]),0,$len%4);
}
}
}
return$data;
}
privatefunction_encipherLong($y,$z,&$w,&$k){
$sum=(integer)0;
$delta=0x9E3779B9;
$n=(integer)$this->n_iter;
while($n-->0){
//Cv0+=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
//Cv1+=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);
$sum=$this->_add($sum,$delta);
$y=$this->_add($y,$this->_add(($z<<4),$this->a)^$this->_add($z,$sum)^$this->_add($this->_rshift($z,5),$this->b));
$z=$this->_add($z,$this->_add(($y<<4),$this->a)^$this->_add($y,$sum)^$this->_add($this->_rshift($y,5),$this->b));
}
$w[0]=$y;
$w[1]=$z;
}
privatefunction_decipherLong($y,$z,&$w,&$k){
//sum=delta<<5,ingeneralsum=delta*n
$sum=0xC6EF3720;
$delta=0x9E3779B9;
$n=(integer)$this->n_iter;
while($n-->0){
//Cv1-=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);
//Cv0-=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
$z=$this->_add($z,-($this->_add(($y<<4),$this->a)^$this->_add($y,$sum)^$this->_add($this->_rshift($y,5),$this->b)));
$y=$this->_add($y,-($this->_add(($z<<4),$this->a)^$this->_add($z,$sum)^$this->_add($this->_rshift($z,5),$this->b)));
$sum=$this->_add($sum,-$delta);
}
$w[0]=$y;
$w[1]=$z;
}
privatefunction_resize(&$data,$size,$nonull=false){
$n=strlen($data);
$nmod=$n%$size;
if(0==$nmod)
$nmod=$size;
if($nmod>0){
if($nonull){
for($i=$n;$i<$n-$nmod+$size;++$i){
$data[$i]=$data[$i%$n];
}
}else{
for($i=$n;$i<$n-$nmod+$size;++$i){
$data[$i]=chr(0);
}
}
}
return$n;
}
privatefunction_hex2bin($str){
$len=strlen($str);
returnpack('H'.$len,$str);
}
privatefunction_str2long($start,&$data,&$data_long){
$n=strlen($data);
$tmp=unpack('N*',$data);
$j=$start;
foreach($tmpas$value)
$data_long[$j++]=$value;
return$j;
}
privatefunction_long2str($l){
returnpack('N',$l);
}
privatefunction_rshift($integer,$n){
//convertto32bits
if(0xffffffff<$integer||-0xffffffff>$integer){
$integer=fmod($integer,0xffffffff+1);
}
//converttounsignedinteger
if(0x7fffffff<$integer){
$integer-=0xffffffff+1.0;
}elseif(-0x80000000>$integer){
$integer+=0xffffffff+1.0;
}
//dorightshift
if(0>$integer){
$integer&=0x7fffffff;//removesignbitbeforeshift
$integer>>=$n;//rightshift
$integer|=1<<(31-$n);//setshiftedsignbit
}else{
$integer>>=$n;//usenormalrightshift
}
return$integer;
}
privatefunction_add($i1,$i2){
$result=0.0;
foreach(func_get_args()as$value){
//removesignifnecessary
if(0.0>$value){
$value-=1.0+0xffffffff;
}
$result+=$value;
}
//convertto32bits
if(0xffffffff<$result||-0xffffffff>$result){
$result=fmod($result,0xffffffff+1);
}
//converttosignedinteger
if(0x7fffffff<$result){
$result-=0xffffffff+1.0;
}elseif(-0x80000000>$result){
$result+=0xffffffff+1.0;
}
return$result;
}
//}}}
}
?>
上面的是TEA的算法
,XTEA的算法为:
那
PHP中只需要把运算的位置改下就OK
privatefunction_teaencipherLong($y,$z,&$w,&$k){
$sum=(integer)0;
$delta=0x9E3779B9;
$n=(integer)$this->n_iter;
while($n-->0){
$y=$this->_add($y,$this->_add($z<<4^$this->_rshift($z,5),$z)^$this->_add($sum,$k[$sum&3]));
$sum=$this->_add($sum,$delta);
$z=$this->_add($z,$this->_add($y<<4^$this->_rshift($y,5),$y)^$this->_add($sum,$k[$this->_rshift($sum,11)&3]));
}
$w[0]=$y;
$w[1]=$z;
}
privatefunction_decipherLong($y,$z,&$w,&$k){
//sum=delta<<5,ingeneralsum=delta*n
$sum=0xC6EF3720;
$delta=0x9E3779B9;
$n=(integer)$this->n_iter;
while($n-->0){
$z=$this->_add($z,-($this->_add($y<<4^$this->_rshift($y,5),$y)^$this->_add($sum,$k[$this->_rshift($sum,11)&3])));
$sum=$this->_add($sum,-$delta);
$y=$this->_add($y,-($this->_add($z<<4^$this->_rshift($z,5),$z)^$this->_add($sum,$k[$sum&3])));
}
$w[0]=$y;
$w[1]=$z;
}
XXTEA的算法
核心为
#defineMX(z>>5^y<<2)+(y>>3^z<<4)^(sum^y)+(k[p&3^e]^z);
longbtea(long*v,longn,long*k){
unsignedlongz=v[n-1],y=v[0],sum=0,e,DELTA=0x9e3779b9;
longp,q;
if(n>1){/*CodingPart*/
q=6+52/n;
while(q-->0){
sum+=DELTA;
e=(sum>>2)&3;
for(p=0;p<n-1;p++)y=v[p+1],z=v[p]+=MX;
y=v[0];
z=v[n-1]+=MX;
}
return0;
}elseif(n<-1){/*DecodingPart*/
n=-n;
q=6+52/n;
sum=q*DELTA;
while(sum!=0){
e=(sum>>2)&3;
for(p=n-1;p>0;p--)z=v[p-1],y=v[p]-=MX;
z=v[n-1];
y=v[0]-=MX;
sum-=DELTA;
}
return0;
}
return1;
}
也是运算不一样,这个就不写了,有人已经写过这方面的代码了
#include<stdint.h>
voidencipher(unsignedintnum_rounds,uint32_tv[2],uint32_tconstk[4]){
unsignedinti;
uint32_tv0=v[0],v1=v[1],sum=0,delta=0x9E3779B9;
for(i=0;i<num_rounds;i++){
v0+=(((v1<<4)^(v1>>5))+v1)^(sum+k[sum&3]);
sum+=delta;
v1+=(((v0<<4)^(v0>>5))+v0)^(sum+k[(sum>>11)&3]);
}
v[0]=v0;v[1]=v1;
}
voiddecipher(unsignedintnum_rounds,uint32_tv[2],uint32_tconstk[4]){
unsignedinti;
uint32_tv0=v[0],v1=v[1],delta=0x9E3779B9,sum=delta*num_rounds;
for(i=0;i<num_rounds;i++){
v1−=(((v0<<4)^(v0>>5))+v0)^(sum+k[(sum>>11)&3]);
sum−=delta;
v0−=(((v1<<4)^(v1>>5))+v1)^(sum+k[sum&3]);
}
v[0]=v0;v[1]=v1;
}