c++ qqcbc+tea qq数据包加密解密

 

 

 

 

qq.h

#define uchar unsigned char
class qq
{
	const int delta = 0x9E3779B9;//黄金数
	int c;//轮数
	
	uchar* buf;
	void EncryptProc();
	void DecryptProc();
public:
	uchar* enData=0;
	uchar* deData=0;
	int* key;
    int len;
    int oriLen;
    qq();
	void setKey(int* key);
	void setKey(uchar* key);
    void Decrypt(uchar* enStr,int c=0x10);
	void Encrypt(uchar* str,int size,int c=0x10);
	~qq();
};

qq.cpp

#include "qq.h"
#include <ctime>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;

qq::qq(){

}

void qq::setKey(int* key){
	this->key = key;
}

void qq::setKey(uchar* key){
	this->key = new int[4];
	for(int i=0;i<4;++i)//将key分为4部分
	{
        int tmp2=0;
        int counter=24;
		for(int j=0;j<12;j+=3){

 int tmp=0;
 int c1=key[i*4*3+j];
 int c2=key[i*4*3+j+1];
if(c1>64&&c1<91){
    tmp+=(c1-'A'+10)*16;
}
else if(c1>96&&c1<123){
    tmp+=(c1-'a'+10)*16;
}
else{
    tmp += (c1-'0')*16;
}

if(c2>64&&c2<91){
    tmp+=(c2-'A'+10);
}
else if(c2>96&&c2<123){
    tmp+=(c2-'a'+10);
}
else{
    tmp += (c2-'0');
}


tmp=tmp<<counter;
counter-=8;
tmp2|=tmp;

        }
this->key[i]=tmp2;
		//cout<<this->key[i]<<endl;
	}
}

//加密后结构 buf[0] +a(rand) + 2(rand) + data +7(0),参考TX
void qq::Encrypt (uchar* str, int size,int c){
	srand(time(0));
	this->c = c;
	int a = ceil((size+10)/8.0)*8- (size+10);//a表示随机填充字节数,buf[0]高3位写入a,buf[0]其余位随机填充
	len = size + a + 10;//加密后总长度
	
	buf = new uchar[len];
	int f=(a&0x7)| (rand() % 32<<3);//将f放在高3位处,其余位随机填充
	buf[0] = f;
	for(int i=1;i<=a+2;++i)
	{
		buf[i] = rand() % 256;//填充a+2个随机数
	}
	memcpy(buf + a + 3, str, size);
	memset(buf + (len - 7), 0, 7);//末尾填充7个0,使得长度为 a+3+7 +size
	
	EncryptProc();
}

void qq::Decrypt(uchar* enStr,int c){
    this->c = c;

if(enStr==0){

}
else 	
{
    int len=strlen((char*)enStr);

    this->len=len/3;
if(this->enData!=0){
delete this->enData;
}

this->enData=new uchar[this->len];
   
for(int i=0;i<len;i+=3){

uchar tmp=0;

 int c1=enStr[i];
 int c2=enStr[i+1];


if(c1>64&&c1<91){
    tmp+=(c1-'A'+10)*16;
}
else if(c1>96&&c1<123){
    tmp+=(c1-'a'+10)*16;
}
else{
    tmp += (c1-'0')*16;
}

if(c2>64&&c2<91){
    tmp+=(c2-'A'+10);
}
else if(c2>96&&c2<123){
    tmp+=(c2-'a'+10);
}
else{
    tmp += (c2-'0');
}


this->enData[i/3]=tmp;

}
}

DecryptProc();



}

 
void qq::EncryptProc()
{
	enData = new uchar[len];
	int times = len / 8;

	int lastLeft1=0,lastRight1=0;
	int lastLeft2=0,lastRight2=0;

	for(int i=0;i<times;++i)
	{
		int c1 = c;
		int b = 8 * i;
		int sum = 0;
		int left=0,right=0,tmpLeft=0,tmpRight=0;


		left= ((int)*(buf+b))<<24|((int)*(buf+b+1))<<16|((int)*(buf+b+2))<<8|*(buf+b+3);
		right= ((int)*(buf+b+4))<<24|((int)*(buf+b+1+4))<<16|((int)*(buf+b+2+4))<<8|*(buf+b+3+4);


		left^=lastLeft2;
		right^=lastRight2;

		tmpLeft=left;
		tmpRight=right;

		while(c1-->0)
		{
			sum += delta;
			left += (((right << 4)&0xFFFFFFF0) + key[0]) ^ (right + sum) ^ (((right >> 5)&0x07ffffff) + key[1]);
			right += (((left << 4)&0xFFFFFFF0) + key[2]) ^ (left + sum) ^ (((left >> 5)&0x07ffffff) + key[3]);
		}

		left^=lastLeft1;
		right^=lastRight1;


		*(enData+b)=left>>24;
		*(enData+b+1)=left>>16;
		*(enData+b+2)=left>>8;
		*(enData+b+3)=left;
		
		
		*(enData+b+4)=right>>24;
		*(enData+b+1+4)=right>>16;
		*(enData+b+2+4)=right>>8;
		*(enData+b+3+4)=right;

		lastLeft1=tmpLeft;
		lastRight1=tmpRight;
		lastLeft2=left;
		lastRight2=right;

	}
	delete buf;
}
 
void qq::DecryptProc()
{

	uchar* temp=deData = new uchar[len];
	int times = len / 8;
	
	int lastLeft1=0,lastRight1=0;
	int lastLeft2=0,lastRight2=0;


	for (int i = 0; i<times; ++i)
	{
		int c1 = c;
		int b = 8 * i;
		int sum = delta<<(int)(log(c)/log(2));//计算加密后的sum值 和下面这句意思一样
        // int sum=c1*delta;
        int left, right,tmpLeft,tmpRight;

		
		//千万别用memcpy或者memmove,int在内存中的字节序是反的,低位在前,高位在后(从左到右),而此时uchar数组的顺序是高位在前的
		//还有特别需要说明的是,int仅仅是字节序存储从人的角度上来说是反的,左移右移操作其实也在站在人的角度上描述的,右移如果在内存中横向看的话其实一直都是在向左走的。还有就是我看到有人提到大小存储,现在基本都是小存储,即低位对应低位,这个问题应该是不会遇到的
		left= ((int)*(enData+b))<<24|((int)*(enData+b+1))<<16|((int)*(enData+b+2))<<8|*(enData+b+3);
		right= ((int)*(enData+b+4))<<24|((int)*(enData+b+1+4))<<16|((int)*(enData+b+2+4))<<8|*(enData+b+3+4);
		
		tmpLeft=left;
		tmpRight=right;

		left^=lastLeft1;
		right^=lastRight1;
		//cout<<left<<' '<<right<<endl;
		while (c1-->0)
		{
			right -= (((left << 4)&0xFFFFFFF0) + key[2]) ^ (left + sum) ^ (((left >> 5)&0x07ffffff) + key[3]);	//这个地方一定要& 因为int是有符号的,所以负数右移会采用算术右移
			left -= (((right << 4)&0xFFFFFFF0) + key[0]) ^ (right + sum) ^ (((right >> 5)&0x07ffffff) + key[1]);
			sum -= delta;
		}
		//cout<<left<<' '<<right<<endl;


		lastLeft1=left;//解密后的密文块,未做XOR
		lastRight1=right;

		left^=lastLeft2;
		right^=lastRight2;

		lastLeft2=tmpLeft;//本次的原始密文块,未做XOR
		lastRight2=tmpRight;


		//同样,这个地方也别用memcpy或者memmove,uchar数组需将高位放在前面以还原数据
		*(temp+b)=left>>24;
		*(temp+b+1)=left>>16;
		*(temp+b+2)=left>>8;
		*(temp+b+3)=left;
		
		
		*(temp+b+4)=right>>24;
		*(temp+b+1+4)=right>>16;
		*(temp+b+2+4)=right>>8;
		*(temp+b+3+4)=right;
		
	}
	int a=temp[0] &0x7 ;
    //cout<<a<<endl;

	oriLen = len - a - 10 ;
	deData = new uchar[oriLen];
	memcpy(deData, temp + a + 3, oriLen);
	delete temp;
}
 
qq::~qq()
{
	delete enData;
	delete deData;
}

test.cpp

#include "qq.h"
#include<cstring>
#include<iostream>

using namespace std;

char* getHexStr(uchar* data,int len){
    char* buf=new char[len*3+1];

    
    for(int i=0,j=0;i<len;++i,j+=3){
        buf[j]= data[i]>>4;
        buf[j+1]= data[i]&0xF;
        buf[j+2]=' ';


        if(buf[j]>9){
            buf[j]=buf[j]-10+'A';
        }
        else{
            buf[j]+='0';
        }


        if(buf[j+1]>9){
            buf[j+1]=buf[j+1]-10+'A';
        }
        else{
            buf[j+1]+='0';
        }

    }

    buf[3*len]='\0';

    return buf;
}


int main(int argc, char const *argv[])
{

// char* str="hello world";
// int len=strlen(str);
// qq* t=new qq();
// int key[]={111,222,333,444};
// t->setKey(key);
// t->Encrypt((uchar*)str,len+1);
// t->Decrypt(0);

// cout<<"sourceHex:"<<getHexStr((uchar*)str,len+1)<<endl;
// cout<<"encryptHex:"<<getHexStr(t->enData,t->len)<<endl;
//  cout<<"decryptHex:"<<getHexStr(t->deData,t->oriLen)<<endl;
//  cout<<"decryptData:"<<t->deData<<endl;

//qq数据包测试
uchar* enStr=(uchar*)"fa c7 38 a6 ee ec f6 b6 ea 8e e6 e5 81 01 29 83 b5 b9 3a cb e1 2d fc 02 b0 7b ca 3d 87 88 3e 86 ed 78 ca a5 62 08 44 49 74 3c 16 89 c6 5f cf 95 32 26 54 dc 7a aa 4d 16 5b 1a 39 0f 84 26 4d f7 46 5f 1f 61 5c 2d 80 97 3e 1f 1a 74 95 38 b1 11 aa db 76 8e 8d 86 1d b7 32 58 8d a7 0f 30 63 c2 af 6a af b3 85 8e 8b 51 03 ";
qq* t=new qq();

t->setKey((uchar*)"c9 b8 07 73 16 a3 0b 57 db 46 91 b9 16 b3 31 64 ");
t->Decrypt(enStr);
    cout<<getHexStr(t->enData,t->len)<<endl;
     cout<<getHexStr(t->deData,t->oriLen)<<endl;
     cout<<getHexStr((uchar*)t->key,16)<<endl;
    cin.get();
    cin.get();

    /* code */
    return 0;
}