⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qqcrypt.cpp

📁 一个QQ-TEA加密解密算法的应用程序, 可以直接对数据进行加密和解密, 对于分析QQ登录协议很有帮助
💻 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 + -