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