?? qqcrypt.cpp
字號:
// QQCrypt.cpp: implementation of the CQQCrypt class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "QQEncrypt.h"
#include "QQCrypt.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CQQCrypt::CQQCrypt()
{
Out = NULL;
Crypt = 0;
preCrypt = 0;
Pos = 0;
padding = 0;
Header = FALSE;
memset(Plain, 0, 8);
memset(prePlain, 0, 8);
memset(Key, 0, 16);
srand(::GetTickCount());
}
CQQCrypt::~CQQCrypt()
{
if (Out) delete[] Out;
}
void CQQCrypt::CopyArray(BYTE arr[], int arr_len, int arr_index, DWORD input)
{
if(arr_index +4 > arr_len) {
// 不能執行
return;
}
arr[arr_index+3]=(BYTE)((input & 0xff000000) >> 24);
arr[arr_index+2]=(BYTE)((input & 0x00ff0000) >> 16);
arr[arr_index+1]=(BYTE)((input & 0x0000ff00) >> 8);
arr[arr_index]=(BYTE)(input & 0x000000ff);
arr[arr_index] &= 0xff;
arr[arr_index+1] &= 0xff;
arr[arr_index+2] &= 0xff;
arr[arr_index+3] &= 0xff;
}
DWORD CQQCrypt::CopyArray(DWORD Out, BYTE arr[], int arr_len, int arr_index)
{
if(arr_index+4 > arr_len) {
return Out;
//不能執行
}
DWORD x1 = arr[arr_index+3] << 24;
DWORD x2 = arr[arr_index+2] << 16;
DWORD x3 = arr[arr_index+1] << 8;
DWORD x4 = arr[arr_index];
DWORD o = x1 | x2 | x3 | x4;
o &= 0xffffffff;
return o;
}
DWORD CQQCrypt::getUnsignedInt(BYTE arrayIn[], int offset, int len)
{
DWORD ret = 0;
int end = 0;
if (len > 8)
end = offset + 8;
else
end = offset + len;
for (int i = offset; i < end; i++) {
ret <<= 8;
ret |= arrayIn[i] & 0xff;
}
return (ret & 0xffffffff) | (ret >> 32);
}
DWORD CQQCrypt::Rand()
{
int rd = rand();
return rd + rd % 1024;
}
void CQQCrypt::Decipher(BYTE arrayIn[], int in_len, BYTE arrayKey[], int key_len, DWORD offset, BYTE arrayOut[])
{
DWORD sum,delta;
//Y=z=a=b=c=d=0;
BYTE tmpArray[24];
if(in_len < 8) {
// Error:return
return;
}
if(in_len < 16) {
// Error:return
return;
}
sum = 0xE3779B90;
sum = sum & 0xFFFFFFFF;
delta = 0x9E3779B9;
delta = delta & 0xFFFFFFFF;
/**//*tmpArray[3] = arrayIn[offset];
tmpArray[2] = arrayIn[offset + 1];
tmpArray[1] = arrayIn[offset + 2];
tmpArray[0] = arrayIn[offset + 3];
tmpArray[7] = arrayIn[offset + 4];
tmpArray[6] = arrayIn[offset + 5];
tmpArray[5] = arrayIn[offset + 6];
tmpArray[4] = arrayIn[offset + 7];
tmpArray[11] = arrayKey[0];
tmpArray[10] = arrayKey[1];
tmpArray[9] = arrayKey[2];
tmpArray[8] = arrayKey[3];
tmpArray[15] = arrayKey[4];
tmpArray[14] = arrayKey[5];
tmpArray[13] = arrayKey[6];
tmpArray[12] = arrayKey[7];
tmpArray[19] = arrayKey[8];
tmpArray[18] = arrayKey[9];
tmpArray[17] = arrayKey[10];
tmpArray[16] = arrayKey[11];
tmpArray[23] = arrayKey[12];
tmpArray[22] = arrayKey[13];
tmpArray[21] = arrayKey[14];
tmpArray[20] = arrayKey[15];
Y=CopyArray(Y,tmpArray,0);
z=CopyArray(z,tmpArray,4);
a=CopyArray(a,tmpArray,8);
b=CopyArray(b,tmpArray,12);
c=CopyArray(c,tmpArray,16);
d=CopyArray(d,tmpArray,20);*/
DWORD Y = getUnsignedInt(arrayIn, (int)offset, 4);
DWORD z = getUnsignedInt(arrayIn, (int)offset + 4, 4);
DWORD a = getUnsignedInt(arrayKey, 0, 4);
DWORD b = getUnsignedInt(arrayKey, 4, 4);
DWORD c = getUnsignedInt(arrayKey, 8, 4);
DWORD d = getUnsignedInt(arrayKey, 12, 4);
for(int i=1;i<=16;i++) {
z -= ((Y<<4)+c) ^ (Y+sum) ^ ((Y>>5)+d);
z &= 0xFFFFFFFF;
Y -= ((z<<4)+a) ^ (z+sum) ^ ((z>>5)+b);
Y &= 0xFFFFFFFF;
sum -= delta;
sum &= 0xFFFFFFFF;
}
CopyArray(tmpArray,24,0,Y);
CopyArray(tmpArray,24,4,z);
arrayOut[0] = tmpArray[3];
arrayOut[1] = tmpArray[2];
arrayOut[2] = tmpArray[1];
arrayOut[3] = tmpArray[0];
arrayOut[4] = tmpArray[7];
arrayOut[5] = tmpArray[6];
arrayOut[6] = tmpArray[5];
arrayOut[7] = tmpArray[4];
}
void CQQCrypt::Decipher(BYTE arrayIn[], int in_len, BYTE arrayKey[], int key_len, BYTE arrayOut[])
{
Decipher(arrayIn, in_len, arrayKey, key_len, 0, arrayOut);
}
void CQQCrypt::Encipher(BYTE arrayIn[], int in_len, BYTE arrayKey[], int key_len, DWORD offset, BYTE arrayOut[])
{
BYTE tmpArray[24];
//DWORD Y,z,a,b,c,d;
//Y=z=a=b=c=d=0;
DWORD sum,delta;
if(in_len < 8) {
// Error:
return;
}
if(key_len < 16) {
// Error:
return;
}
sum = 0;
delta = 0x9E3779B9;
delta &= 0xFFFFFFFF;
/**//*tmpArray[3] = arrayIn[offset];
tmpArray[2] = arrayIn[offset + 1];
tmpArray[1] = arrayIn[offset + 2];
tmpArray[0] = arrayIn[offset + 3];
tmpArray[7] = arrayIn[offset + 4];
tmpArray[6] = arrayIn[offset + 5];
tmpArray[5] = arrayIn[offset + 6];
tmpArray[4] = arrayIn[offset + 7];
tmpArray[11] = arrayKey[0];
tmpArray[10] = arrayKey[1];
tmpArray[9] = arrayKey[2];
tmpArray[8] = arrayKey[3];
tmpArray[15] = arrayKey[4];
tmpArray[14] = arrayKey[5];
tmpArray[13] = arrayKey[6];
tmpArray[12] = arrayKey[7];
tmpArray[19] = arrayKey[8];
tmpArray[18] = arrayKey[9];
tmpArray[17] = arrayKey[10];
tmpArray[16] = arrayKey[11];
tmpArray[23] = arrayKey[12];
tmpArray[22] = arrayKey[13];
tmpArray[21] = arrayKey[14];
tmpArray[20] = arrayKey[15];
Y=CopyArray(Y,tmpArray,0);
z=CopyArray(z,tmpArray,4);
a=CopyArray(a,tmpArray,8);
b=CopyArray(b,tmpArray,12);
c=CopyArray(c,tmpArray,16);
d=CopyArray(d,tmpArray,20);*/
DWORD Y = getUnsignedInt(arrayIn, (int)offset, 4);
DWORD z = getUnsignedInt(arrayIn, (int)offset + 4, 4);
DWORD a = getUnsignedInt(arrayKey, 0, 4);
DWORD b = getUnsignedInt(arrayKey, 4, 4);
DWORD c = getUnsignedInt(arrayKey, 8, 4);
DWORD d = getUnsignedInt(arrayKey, 12, 4);
for(int i=1;i<=16;i++) {
sum += delta;
sum &= 0xFFFFFFFF;
Y += ((z<<4)+a) ^ (z+sum) ^ ((z>>5)+b);
Y &= 0xFFFFFFFF;
z += ((Y<<4)+c) ^ (Y+sum) ^ ((Y>>5)+d);
z &= 0xFFFFFFFF;
}
CopyArray(tmpArray, 24, 0,Y);
CopyArray(tmpArray, 24, 4,z);
arrayOut[0] = tmpArray[3];
arrayOut[1] = tmpArray[2];
arrayOut[2] = tmpArray[1];
arrayOut[3] = tmpArray[0];
arrayOut[4] = tmpArray[7];
arrayOut[5] = tmpArray[6];
arrayOut[6] = tmpArray[5];
arrayOut[7] = tmpArray[4];
}
void CQQCrypt::Encipher(BYTE arrayIn[], int in_len, BYTE arrayKey[], int key_len, BYTE arrayOut[])
{
Encipher(arrayIn, in_len, arrayKey, key_len, 0, arrayOut);
}
void CQQCrypt::Encrypt8Bytes()
{
BYTE Crypted[8];
for(Pos=0; Pos<=7; Pos++) {
if(Header == TRUE){
Plain[Pos] = (BYTE)(Plain[Pos] ^ prePlain[Pos]);
} else {
Plain[Pos] = (BYTE)(Plain[Pos] ^ Out[preCrypt + Pos]);
}
}
Encipher(Plain, 8, Key, 8, Crypted);
for(int i=0; i<=7; i++) {
Out[Crypt + i] = (BYTE)Crypted[i];
}
for(Pos=0;Pos<=7;Pos++) {
Out[Crypt + Pos] = (BYTE)(Out[Crypt + Pos] ^ prePlain[Pos]);
}
//Plain.CopyTo(prePlain,0);
memcpy(prePlain, Plain, 8);
preCrypt = Crypt;
Crypt = Crypt + 8;
Pos = 0;
Header = FALSE;
}
BOOL CQQCrypt::Decrypt8Bytes(BYTE arrayIn[], int in_len, DWORD offset)
{
//DWORD lngTemp;
for(Pos=0; Pos<=7; Pos++) {
if(contextStart + Pos > in_len -1) {
return TRUE;
}
prePlain[Pos] = (byte)(prePlain[Pos] ^ arrayIn[offset+Crypt+Pos]);
}
try {
Decipher(prePlain, 8, Key, 8, prePlain);
//prePlain = Decipher(prePlain, Key);
}
catch (...) {
return FALSE;
}
//lngTemp = prePlain.Length - 1;
contextStart += 8;
Crypt+=8;
Pos = 0;
return TRUE;
}
BOOL CQQCrypt::Decrypt8Bytes(BYTE arrayIn[], int in_len)
{
return Decrypt8Bytes(arrayIn, in_len, 0);
}
int CQQCrypt::QQ_Encrypt(BYTE arrayIn[], int in_len, BYTE arrayKey[], int key_len, DWORD offset, BYTE *&ArrayOut)
{
DWORD l;
ArrayOut = 0;
Pos = 1;
padding = 0;
Crypt = preCrypt = 0;
//arrayKey.CopyTo(Key,0); // Key Must Be 16 Length!
memcpy(Key, arrayKey, key_len);
Header = TRUE;
Pos = 2;
//計算頭部填充字節數
Pos = (in_len+10) % 8;
if(Pos != 0)
Pos = 8-Pos;
//輸出長度
if (Out) delete[] Out;
int out_len = in_len + Pos + 10;
Out = new BYTE[out_len];
//把POS存到PLAIN的第一個字節
//0xf8后面3位是空的,正好給Pos
Plain[0] = (BYTE)((Rand() & 0xf8) | Pos);
//用隨機數填充1到Pos的內容
for(int i=1;i<=Pos;i++) {
Plain[i] = (BYTE)(Rand() & 0xff);
}
Pos++;
padding = 1;
//繼續填充兩個字節隨機數,滿8字節就加密
while(padding < 3) {
if( Pos < 8) {
Plain[Pos] = (BYTE)(Rand() & 0xff);
padding++;
Pos++;
}
else if(Pos == 8) {
Encrypt8Bytes();
}
}
int I = (int)offset;
l = 0;
//明文內容,滿8字節加密到讀完
l = in_len;
while ( l > 0) {
if(Pos<8) {
Plain[Pos] = arrayIn[I];
I++;
Pos++;
l--;
} else if(Pos == 8) {
Encrypt8Bytes();
}
}
//末尾填充0,保證是8的倍數
padding = 1;
while(padding < 9) {
if(Pos<8) {
Plain[Pos] = 0;
Pos++;
padding++;
} else if(Pos == 8) {
Encrypt8Bytes();
}
}
ArrayOut = Out;
return out_len;
}
int CQQCrypt::QQ_Encrypt(BYTE arrayIn[], int in_len, BYTE arrayKey[], int key_len, BYTE *&ArrayOut)
{
return QQ_Encrypt(arrayIn, in_len, arrayKey, key_len, 0, ArrayOut);
}
int CQQCrypt::QQ_Decrypt(BYTE arrayIn[], int in_len, BYTE arrayKey[], int key_len, DWORD offset, BYTE *&ArrayOut)
{
//檢查是否是8的倍數至少16字節
CString str;
ArrayOut = 0;
if(in_len < 16 || (in_len % 8 != 0)) {
//Return What?
return 0;
}
if(key_len != 16) {
//Return What?
return 0;
}
BYTE *m;
DWORD I,Count;
int m_len = offset+8;
m= new BYTE[m_len];
memcpy(Key, arrayKey, key_len);
//arrayKey.CopyTo(Key,0);
Crypt = preCrypt = 0;
//計算消息頭部,明文開始的偏移,解密第一字節和7相與得到
//prePlain = this.Decipher(arrayIn,arrayKey,offset);
Decipher(arrayIn, in_len, arrayKey, key_len, offset, prePlain);
Pos = prePlain[0] & 7;
//計算明文長度
Count = in_len - Pos - 10;
if(Count <= 0) {
//Return What?
return 0;
}
if (Out) delete[] Out;
int out_len = Count;
Out = new BYTE[out_len];
preCrypt = 0;
Crypt = 8;
contextStart = 8;
Pos++;
padding = 1;
//跳過頭部
while(padding < 3) {
if(Pos<8) {
Pos++;
padding++;
}
else if(Pos==8) {
for(int i=0;i<m_len;i++)
m[i]=arrayIn[i];
//if(this.Decrypt8Bytes(arrayIn,offset) == false)
if(Decrypt8Bytes(arrayIn, in_len, offset) == FALSE) {
//Return What?
return 0;
}
}
}
//解密明文
I=0;
while(Count != 0) {
if(Pos<8) {
Out[I] = (BYTE)(m[offset+preCrypt+Pos] ^ prePlain[Pos]);
I++;
Count--;
Pos++;
}
else if(Pos == 8) {
m = arrayIn;
preCrypt = Crypt - 8;
//if(this.Decrypt8Bytes(arrayIn,offset) == false)
if(Decrypt8Bytes(arrayIn, in_len, offset) == FALSE) {
//Return What?
return 0;
}
}
}
//最后的解密部分,檢查尾部是不是0
for(padding=1; padding<=7; padding++) {
if(Pos<8) {
if( (m[offset+preCrypt+Pos] ^ prePlain[Pos]) != 0 ) {
//Return What?
//這里解不出
return 0;
}
Pos++;
}
else if(Pos == 8) {
for(int i=0;i<m_len;i++)
m[i] = arrayIn[i];
preCrypt = Crypt;
//if(this.Decrypt8Bytes(arrayIn,offset) == false)
if(Decrypt8Bytes(arrayIn, in_len, offset) == FALSE) {
//Return What?
return 0;
}
}
}
ArrayOut = Out;
return out_len;
}
int CQQCrypt::QQ_Decrypt(BYTE arrayIn[], int in_len, BYTE arrayKey[], int key_len, BYTE *&ArrayOut)
{
return QQ_Decrypt(arrayIn, in_len, arrayKey, key_len, 0, ArrayOut);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -