❶ tea 算法的原理
TEA加密和解密时都使用一个常量值,这个常量值为0x9e3779b,这个值是近似黄金分割率,注意,有些编程人员为了避免在程序中直接出现"mov 变量,0x9e3779b",以免被破解者直接搜索0x9e3779b这个常数得知使用TEA算法,所以有时会使用"sub 变量,0x61C88647"代替"mov 变量,0x9e3779b",0x61C88647=-(0x9e3779b)。
TEA算法每一次可以操作64bit(8byte),采用128bit(16byte)作为key,算法采用迭代的形式,推荐的迭代轮数是64轮,最少32轮。
❷ tea加解密算法经过Keil编译在单片机中运行结果错误,求帮助
c并没有规定int,long 之类的数据类型对应几个char,所以造成按位运算在不同的编译器下运行结果不一样
解决办法
#define int8 char
#define uint8 uchar
#define int16 int //16位mcu
#define int16 (short int)//32位mcu
.......
这个样子就可以避免数据类型的差异所带来的影响(不知道int代表几个char,就用sizeof(int))
还有,你的long btea(long* v,char n,long* k);
而你调用的时候btea(plainbuffer, 2,key);
函数签名和定义的数据类型不一致,也会发生错误(不要以为unsigned可有可无)
你这样调整一下,应该就没有问题了
❸ TEA加密算法的应用
QQTEA 算法建立在标准 TEA算法的基础上,使用16轮的加密(这是最低限,推荐应该是32轮)。QQ在使用这个算法的时候,由于需要加密不定长的数据,所以使用了一些常规的填充办法和交织算法。
1 填充算法
如果明文本身的长度不是8的倍数,那么还要进行填充以使其成为8的倍数。以字节为单位,令N=原始字符串+10+填充字节数n,则N应该是8的倍数。
具体的填充方法:第一个字节为:(random()&0xf8)|n,随后填充(n+2)个字节random()&0xff ,后面接原始数据,最后填充7 个字节0x00 。
因为使用了不同的随机数,所以填充的结果使得即使对于相同的明文,密文的结果也会不同。
2 交织算法
消息被分为多个加密单元,每一个加密单元都是8字节,使用TEA进行加密,加密结果与下一个加密单元做异或运算后再作为待加密的明文。
❹ 招新——第一次尝试破解tea算法
开始接触逆向分析时,入门级别的一道题目,是一个师兄写的考核题《sotired》,尝试着破解了下,以下是具体的过程。
1、双击发现打不开,应该是linux系统下的文件(事实证明确实如此,我在虚拟机那里验证了一下,随便输入字符串,得到的答案是sorry~,给人crakeme的感觉,哈哈)
2、使用反汇编工具ida64位,将文件拖进去,找到main函数,使用F5大法,得到下面的界面:
看到sorry~和wow!congratulation!的字符串,可以推断出有字符串的对比,看到if语句,没错就是它了,看来temp[k]里面有我们想要的东西(用于匹配比较的正确密文)点进去,得到
这里利用一个小插件lazyida,哈哈哈(我比较懒),得到密文,
在这里需要声明下,因为最后读出来的那个0x00111885B有误(lazyida的原因),其实是0x32111885B才对,所以是 0x572CB9C1, 0x73A6EB63, 0x069E6A55, 0x818E33D9, 0x7ED0A862, 0x3211885B,这些16进制的数就是密文啦!有了密文,我们要破解它,就需要找密钥啦,回去看函数
想象下,用户输入一组字符串,for循环了3次,atoui函数猜测应该是某种转换函数,点进去
果然是移位加密转换,结果是int 型,所以v11[6]的字符数据全部被转换了数字,继续往下
又有3次循环,看到encipher函数应该是加密函数来的,然后传递了两个参数,一个是转化后的v11,另一个v7,这里就可以怀疑了,v7应该是密钥,而且用了引用,难道是地址吗?很奇怪,点进去v7,得到
这里又要怀疑了,前面4个都是?一个数字有4个数据,感觉很像数组的样子,于是尝试一波
转换为数组,然后F5大法刷新下!得到
看来我们的推断是正确的,v7是一个数组,里面的数据应该是密钥了!到此,我们成功地拿到了密文和密钥了,接下来就是解密了,解密前需要知道是怎么加密的,回到刚刚的encipher函数,进去
看到这里有人可能要很激动了,这个算法不就是tea算法吗?!(没错,虽然我一开始也不知道,于是我去谷歌了一波!)
tea算法就是把密文结合密钥进行移位再异或的运算,总共进行32轮。解密则是反过来求解,不过需要先算出delta的值,即9e3779b9*32后得到13c6ef3720,明显溢出了(手贱算了下,溢出。tea算法把溢出的忽略了,emmmm,我也不太懂其中的原因,能用先用着,哈哈哈),于是乎,可以写脚本了,打开c++,写入脚本
我们的密文和密钥修改好后,因为有密文有6个16进制的数,所以解密3次,得到结果
好啦,这就是我们的flag了,但是看不懂是吧,没关系,去转换下,谷歌走起!
大家记得把空格消除,然后把它和在一起转化,好啦,虚拟机linux操作系统打开,文件打开,输入flag,得到的就是WOw!congratulation!
以上便是我花了一个下午整理出来的一个逆向题目,希望对大家有帮助,也希望能多多交流哦,嘻嘻~
❺ 如何实现php的TEA算法
算法简单,而且效率高,每次可以操作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;/*akeyscheleconstant*/
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;/*akeyscheleconstant*/
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_mp($tea);
var_mp($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);
//
$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);
//(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的算法为:
#include <stdint.h>
void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const k[4]) {
unsigned int i;
uint32_t v0=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;
}
void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const k[4]) {
unsigned int i;
uint32_t v0=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;
}
那PHP中只需要把运算的位置改下就OK
private function _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;
}
private function _decipherLong($y, $z, &$w, &$k) {
// sum = delta<<5, in general sum = 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;
❻ Tea算法的疑问
我想你能搜到TEA算法的源码吧,不管如何,我也贴一份, encrypt是加密,decrpty是解密。 第一个输入参数是要被加密/解密的信息,是64bit,也就是一个int32数组,数组是两个元素。 第二个参数是128bit的密钥,也就是4个元素的int32数组。密钥你可以理解成密码,只不过在TEA算法中,要求密钥必须是128bit。
所以,TEA算法一次加密/解密64bit信息,如果你要加密/解密的信息长于64bit,那你要分多次进行,如果小于64bit,比如你只想加密一个数字 123,那你应该把这个信息补全到64bit,比如前32bit是你要加密的数字,后32位随便是什么。
看一下我下面的例子, 我用 "0123456789abcdef" 这个字符串(刚好16个字符,128bit)作为密钥,要加密的信息是 {123, 321} 两个整数 (刚好64bit)。然后打印出加密后得到的内容,以及解密后得到的内容(解密后得到的内容就合加密前一样,是{123,321})
另外,你可能会注意到 加密解密时候用到的 delta=0x9e3779b9; 这个数字的得来是 2^32 除以一个常数,这个常数就是传说中的黄金比例 1.6180339887。
我不了解QQ是如何使用TEA的,但是无非就是将用户密码根据一定的方式转换成 128bit的密钥,然后再应用 encrypt/decrypt 函数来对收发数据进行加密/解密,一次处理64bit,和我的例子没有什么实质性的区别。
#include <stdio.h>
#include <stdint.h>
#include <string.h>
void encrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0, i; /* set up */
uint32_t delta=0x9e3779b9; /* a key schele constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i < 32; i++) { /* basic cycle start */
sum += delta;
v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
} /* end cycle */
v[0]=v0; v[1]=v1;
}
void decrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i; /* set up */
uint32_t delta=0x9e3779b9; /* a key schele constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i<32; i++) { /* basic cycle start */
v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
sum -= delta;
} /* end cycle */
v[0]=v0; v[1]=v1;
}
int main()
{
const char *passwd = "0123456789abcdef";
uint32_t value[2] = {123, 321};
uint32_t key[4];
char *p = NULL;
memcpy(key, passwd, sizeof(key));
encrypt(value, key);
printf("After encrypt {%u, %u}\n", value[0], value[1]);
decrypt(value, key);
printf("After descrpt {%u, %u}\n", value[0], value[1]);
return 0;
}
密钥不是胡编乱造的,密钥就相当于密码,不同的人会有不同的密码。但是每个人的密码长度可能与加密算法需要的密码长度不同,这样就要按照一定的规则将用户密码变成符合要求的密钥,比如用 MD5算法 就可以将任意字符串转换成128bit的密钥,然后就可以应用 TEA 来加密数据。要破解这样的数据,除非你知道那个128bit的密钥,也就是只有你知道用户本身的密码是什么,你才能得到128bit的密钥,你才能解密数据。
我的例子里的密钥只是随便写了一个举例用的,你可以改成任何你想要的内容。
❼ TEA加密算法的介绍
TEA算法由剑桥大学计算机实验室的David Wheeler和Roger Needham于1994年发明。它是一种分组密码算法,其明文密文块为64比特,密钥长度为128比特。TEA算法利用不断增加的Delta(黄金分割率)值作为变化,使得每轮的加密是不同,该加密算法的迭代次数可以改变,建议的迭代次数为32轮。
❽ tea算法的介绍
在安全学领域,TEA(Tiny Encryption Algorithm)是一种分组加密算法,它的实现非常简单,通常只需要很精短的几行代码。TEA 算法最初是由剑桥计算机实验室的 David Wheeler 和 Roger Needham 在 1994 年设计的。TEA算法使用64位的明文分组和128位的密钥,它使用Feistel分组加密框架,需要进行 64 轮迭代,尽管作者认为 32 轮已经足够了。该算法使用了一个神秘常数δ作为倍数,它来源于黄金比率,以保证每一轮加密都不相同。但δ的精确值似乎并不重要,这里 TEA 把它定义为 δ=“(√5 - 1)231”(也就是程序中的 0×9E3779B9)。之后 TEA 算法被发现存在缺陷,作为回应,设计者提出了一个 TEA 的升级版本——XTEA(有时也被称为“tean”)。XTEA 跟 TEA 使用了相同的简单运算,但它采用了截然不同的顺序,为了阻止密钥表攻击,四个子密钥(在加密过程中,原 128 位的密钥被拆分为 4 个 32 位的子密钥)采用了一种不太正规的方式进行混合,但速度更慢了。
❾ 什么是TEA算法
TEA算法被广泛地应用于计算机数据加密领域,OICQ的数据安全采用了TEA算法。本文讨论了TEA的算法的原理及实现,并揭示了QQ中该算法的应用,本文是灵钥科技公司(www.panakes.com)在即时通信密码研究公开的第一篇论文,今后我们将陆续发表相关的论文及相应的产品。
TEA算法简介
TEA算法是由剑桥大学计算机实验室的DavidWheeler和RogerNeedham于1994年发明.TEA是TinyEncryptionAlgorithm的缩写。特点是加密速度极快,高速高效,但是抗差分攻击能力差。
TEA加密算法是一种分组密码算法,其明文密文块64比特(8字节),密钥长度128比特(16字节)。TEA加密算法的迭代次数可以改变,建议的迭代次数为32轮,尽管算法的发明人强调加密16轮就很充分了。两个TEAFeistel周期算为一轮。图1示例了TEA一轮的加密流程。
以下示例了TEA的C语言加密算法,TEA的解密算法与加密算法类似。
#defineTEA_ROUNDS0x20
#defineTEA_DELTA0x9E3779B9
#defineTEA_SUM0xE3779B90
voidtiny_encrypt(unsignedlong*constv,unsignedlong*constw,
constunsignedlong*constk)
{
registerunsignedlong
y=v[0],
z=v[1],
a=k[0],
b=k[1],
c=k[2],
d=k[3],
n=TEA_ROUNDS,
sum=0,
delta=TEA_DELTA;
while(n-->0){
sum+=delta;
y+=(z<<4)+a^z+sum^(z>>5)+b;
z+=(y<<4)+c^y+sum^(y>>5)+d;
}
w[0]=y;
w[1]=z;
}
TEA算法利用的不断增加的(即源程序中的delta)值作为变化,,就是黄金分割率。它的作用是使得每轮的加密是不同。的准确值可能不太重要。但是在这里,它被初始化为
=0x9e3779b
QQ是如何利用TEA进行加密的?
TEA算法被广泛应用于QQ的数据加密中,QQ采用16轮的TEA算法加密,在这时采取16轮加密时而不采取标准的32轮加密时为了减少验证服务器的压力。QQ在数据加密前采用了密码学中的常用的填充及交织技术,减少加密数据的相关性,增加破译者的破解难度。
下表列出了QQ应用TEA算法几个方面
序号
应用
相关文件
1
通讯报文的加密/解密
2
消息记录的加密/解密
MsgEx.db
3
本地消息密码、首次登录时间、提示内容验证密码
Matrix.db
4
消息备份文件
*.bak
QQ的TEA算法源程序分析
QQ在进行TEA加密前采用ntohl函数对原文数据和加密密钥进行了变换,从网络字节顺序转换位主机字节顺序进行加密后,再通过htonl函数将数据转换为网络字节顺序的数据。
为什么要这样做呢?因为不同的计算机使用不同的字节顺序存储数据。因此任何从Winsock函数对IP地址和端口号的引用和传给Winsock函数的IP地址和端口号均时按照网络顺序组织的。
为防止分析者分析出QQ是采用TEA加密算法的,程序的设计者采用了subeax,61C88647h指令,而不采用Addeax9e3779b9h指令。因为分析者只需要判断9e3779b9h(即是我们前面提的黄金分割率的值)就知道采用了TEA加密算法。
sub_409A43procnear;CODEXREF:sub_409B8C+AEp
;sub_409B8C+109p...
var_10=dwordptr-10h
var_C=dwordptr-0Ch
var_8=dwordptr-8
var_4=dwordptr-4
arg_0=dwordptr8
arg_4=dwordptr0Ch
arg_8=dwordptr10h
pushebp
movebp,esp
subesp,10h
pushebx
pushesi
movesi,[ebp+arg_0]
pushedi
pushdwordptr[esi];netlong
callntohl
pushdwordptr[esi+4];netlong
movedi,eax;y
callntohl
movebx,eax;z
moveax,[ebp+arg_4]
leaecx,[ebp+var_10]
leaesi,[ebp+var_10]
subeax,ecx
mov[ebp+arg_0],4
mov[ebp+arg_4],eax
jmpshortloc_409A7C
;哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:00409A79
loc_409A79:;CODEXREF:sub_409A43+49j
moveax,[ebp+arg_4]
loc_409A7C:;CODEXREF:sub_409A43+34j
pushdwordptr[eax+esi];netlong
callntohl;对k[0],k[1],k[2],k[3]进行ntohl变化,
mov[esi],eax
addesi,4
dec[ebp+arg_0]
jnzshortloc_409A79
push10h;做十六轮TEA运算
xoreax,eax
popecx
loc_409A93:;CODEXREF:sub_409A43+88j
movedx,ebx
movesi,ebx
shredx,5;z>>5
addedx,[ebp+var_C];z>>5+k[1]
subeax,61C88647h;sum=sum+deltadelta:0x9e3779b9
shlesi,4;z<<4
addesi,[ebp+var_10];z<<4+k[0]
xoredx,esi;(z>>5+k[1])^(z<<4+k[0])
leaesi,[eax+ebx];sum+z
xoredx,esi;(z<<4+k[0])^(sum+z)^(z>>5+k[1])
addedi,edx;y+=(z<<4+k[0])^(sum+z)^(z>>5+k[1])
movedx,edi
movesi,edi
shredx,5;y>>5
addedx,[ebp+var_4];y>>5+k[3]
shlesi,4;y<<4
addesi,[ebp+var_8];y<<4+k[2]
xoredx,esi;(y>>5+k[3])^(y<<4+k[2])
leaesi,[eax+edi];(sum+y)
xoredx,esi;(y<<4+k[2])^(sum+y)^(y>>5+k[3])
addebx,edx;z+=(y<<4+k[2])^(sum+y)^(y>>5+k[3])
dececx
jnzshortloc_409A93
pushedi;hostlong
callhtonl
movesi,[ebp+arg_8]
pushebx;hostlong
mov[esi],eax;加密结果
callhtonl
mov[esi+4],eax;加密结果
popedi
popesi
popebx
leave
retn
sub_409A43endp
结论
作为一种分组加密算法,TEA加密算法在其发展的过程中,目前出现了几种针对TEA算法设计的缺陷攻击方法,使得原有的TEA加密算法变得不安全,在过去的十几年中,TEA算法进行了若干次的改进,历经XTEA,BlockTEA,XXTEA几个版本。目前最新的算法是XXTEA。
QQ采用了最初的TEA算法做其核心的加密算法,QQ在采用TEA算法时采用了16轮的加密,其加密复杂度比32轮减了许多。利用TEA算法的设计缺陷,使得快速破解QQ密码成为可能。
值得一提的QQ在利用TEA算法做加密时,采用了交织及随机填充随机数的技术,增加了密码分析者分析难度,从一定程度上保护了信息的安全。
更多信息请访问www.panakes.com
TEA(Tiny Encryption Algorithm) 是一种优秀的数据加密算法,虽然它比 DES(Data Encryption Standard) 要简单得多, 但有很强的抗差分分析能力,加密速度也比 DES 快得多,而且对 64 位数据加密的密钥长达 128 位,安全性相当好。 下面的程序来自卢开澄《计算机密码学》(清华大学出版社)。
补充:为了使这段程序更加实用,我将其整理为几个单元, 分别用于 Delphi 和 C++Builder 。包括对数据流 TMemoryStream 和字符串的加密/解密功能, 对字符串的加密/解密还通过 Base64 编码/解码,保持加密后的字符串仍为字符串。
// v[2] : 64bit data, k[4] : 128bit key
void encipher( unsigned long * const v, const unsigned long * const k )
{
register unsigned long y = v[0], z = v[1], sum = 0, delta = 0x9E3779B9,
a = k[0], b = k[1], c = k[2], d = k[3], n = 32;
while ( n-- > 0 )
{
sum += delta;
y += ( z << 4 ) + a ^ z + sum ^ ( z >> 5 ) + b;
z += ( y << 4 ) + c ^ y + sum ^ ( y >> 5 ) + d;
}
v[0] = y;
v[1] = z;
}
void decipher( unsigned long * const v, const unsigned long * const k )
{
register unsigned long y = v[0], z = v[1], sum = 0xC6EF3720, delta = 0x9E3779B9,
a = k[0], b = k[1], c = k[2], d = k[3], n = 32;
// sum = delta << 5, in general sum = delta * n
while ( n-- > 0 )
{
z -= ( y << 4 ) + c ^ y + sum ^ ( y >> 5 ) + d;
y -= ( z << 4 ) + a ^ z + sum ^ ( z >> 5 ) + b;
sum -= delta;
}
v[0] = y;
v[1] = z;
}