📄 qq_tea.cpp
字号:
/********************************************************** TEA - Tiny Encryption Algorithm Feistel cipher by David Wheeler & Roger M. Needham (extended version) **********************************************************/#include "tea.h"
//bool header = true;//是否加密头
/********************************************************** Input values: k[4] 128-bit key v[2] 64-bit plaintext block Output values: v[2] 64-bit ciphertext block **********************************************************/void enc_block(dword *v, dword *k, dword *out) { dword y=v[0], z=v[1];
__asm
{
mov eax, dword ptr[ebp - 4]
bswap eax
mov y, eax
mov eax, dword ptr[ebp -8]
bswap eax
mov z, eax
}
dword ROUND = 0x10,sum=0;
while(ROUND--)
{
sum+=DELTA;
y+=(((z>>5) + k[1])^((z<<4) + k[0])) ^ (z + sum);
z+=(((y>>5) + k[3])^((y<<4) + k[2])) ^ (y + sum);
}
__asm//转换字节位置
{
mov eax,dword ptr[ebp - 4]
bswap eax
mov y, eax
mov eax,dword ptr [ebp - 8]
bswap eax
mov z, eax
}
out[0] = y; out[1] = z;}void dec_block(dword *v, dword *k, dword *out) {
dword y = v[0], z = v[1];
__asm
{
mov eax, dword ptr[ebp - 4]
bswap eax
mov dword ptr[ebp - 4], eax
mov eax, dword ptr[ebp - 8]
bswap eax
mov dword ptr[ebp - 8], eax
}
dword ROUND = 0x10, sum = 0;
sum=DELTA*ROUND;
while (ROUND--)
{
z-=((y>>5) + k[3])^((y<<4) + k[2]) ^ (y + sum);
y-=(((z>>5) + k[1])^((z<<4) + k[0])) ^ (z + sum);
sum-=DELTA;
}
__asm
{
mov eax, dword ptr[ebp - 4]
bswap eax
mov dword ptr[ebp - 4], eax
mov eax, dword ptr[ebp - 8]
bswap eax
mov dword ptr[ebp - 8], eax
}
out[0] = y; out[1] = z;}
/************************************************************************/
/* QQ的TEA加密算法 */
/* pPlainData (global)明文数据 */
/* len 明文长度(local) */
/* pKey 密钥(local) */
/* pCryptData (global)加密后的数据 */
/************************************************************************/
void encrypt(BYTE *pPlainData, dword len, dword *pKey, BYTE *&pCryptData)
{
dword codelen;//密文长度
BYTE *pre_crypt, *pcrypt; //当前加密的明文和密文地址
BYTE plain[8], pre_plain[8];
bool header = true;
//计算头部填充字节数;
int pos = (len + 0x0A) %8;
if (pos != 0)
{
pos = 8 - pos;
};
//计算输出的密文长度
codelen = len + pos + 0x0A;
pCryptData = (BYTE*)malloc(codelen);
memset(pCryptData, 0, codelen);
pcrypt = pCryptData;
srand(time(NULL));
//把pos(明文位置)放到填充的第一个字节里面
plain[0] = rand()&0xF8 | pos;
//|__ __ __ __ |__ __ __ __|
// | pos
//plain[0] 里面有明文位置;
for (int i = 1; i <= pos; i++ )//填充plain[1]--plain[pos]之间的内容
{
plain[i] = rand()&0xFF;
}
pos++;
//初始化上次明文内容
for (i = 0; i < 8; i++)
{//加密第一个64位,前次加密内容当然为0x00000000, 0x00000000
pre_plain[i] = 0x00;
}
// 继续填充2个字节的随机数,这个过程中如果满了8字节就加密之
for (int padding = 0; padding < 2; padding++)
{
if (pos < 8)
{
//填充随机数
plain[pos] = rand()&0xFF;
++pos;
}
if (pos == 8)//满8个就加密
{
//encrypt8bytes(plain_index, pKey, crypt_index);
if (header)//------------------当前明文异或上次密文------------------
{
for (i = 0; i < 8; i++)
{
plain[i] ^= pre_plain[i];
}
header = false;
}
else
{
for (i = 0; i < 8; i++)
{
plain[i] ^= pre_crypt[i];
}
}//-----------------异或完了加密之-----------------------------
enc_block((dword*)plain, (dword*)pKey, (dword*)pcrypt);
for (i = 0; i < 8; i++)//当前密文 = 当前密文 ^ 上次明文
{
pcrypt[i] ^= pre_plain[i];
}
memcpy(pre_plain, plain, 8);
pos = 0;
}
}
unsigned long offset = 0;
//如果没填满,就开始填明文
while (len > 0)
{
if (pos < 8)
{
plain[pos++] = pPlainData[offset++];
len --;
}
if (pos == 8)
{
// encrypt8bytes(pKey);
if (header)//------------------当前明文异或上次密文------------------
{
for (i = 0; i < 8; i++)
{
plain[i] ^= pre_plain[i];
}
header = false;
}
else
{
pre_crypt = pcrypt;
pcrypt += 8;
for (i = 0; i < 8; i++)
{
plain[i] ^= pre_crypt[i];
}
}//-----------------异或完了加密之-----------------------------
// for (i = 0; i < 8; i++)
// {
// plain[i] ^= pre_crypt[i];
// }
//-----------------异或完了加密之-----------------------------
enc_block((dword*)plain, (dword*)pKey, (dword*)pcrypt);
for (i = 0; i < 8; i++)//当前密文 = 当前密文 ^ 上次明文
{
pcrypt[i] ^= pre_plain[i];
}
memcpy(pre_plain, plain, 8);
pos = 0;
}
}
//如果最后不够8字节了,用零填满8个字节
padding = 1;
while (padding <= 7)
{
if (pos < 8)
{
plain[pos++] = 0x00;
padding ++;
}
if (pos == 8)
{
// encrypt8bytes(pKey);
pre_crypt = pcrypt;
pcrypt += 8;
for (i = 0; i < 8; i++)
{
plain[i] ^= pre_crypt[i];
}
//-----------------异或完了加密之-----------------------------
enc_block((dword*)plain, (dword*)pKey, (dword*)pcrypt);
for (i = 0; i < 8; i++)//当前密文 = 当前密文 ^ 上次明文
{
pcrypt[i] ^= pre_plain[i];
}
}
}
}
/************************************************************************/
/* QQ的TEA解密算法 */
/* pCrypeData (global)密文数据 */
/* len 密文长度(local) */
/* pKey 密钥(local) */
/* pPlainData (global)解密后的数据 */
/************************************************************************/
void decrypt(BYTE *pCryptData, dword len, BYTE *pKey, BYTE *&pPlainData)
{
BYTE plain[8];//用来存放解密后的值
BYTE precrypt[8];//用来存放上次解密的密文
BYTE *pcrypt, *pre_crypt;
BYTE *pre_plain,*pplain;//上次解密出的明文
pcrypt = pCryptData;
bool header = true;
//检查密文长度,是否正确
if (0 != len % 8 | len < 16)
{
printf("length error!");
}
dec_block((dword*)pCryptData, (dword*)pKey, (dword*)plain);
//明文长度plain_len
dword pos = plain[0] &0x07;
dword plain_len = len - pos - 0x0A;
pPlainData = new BYTE[plain_len];
pplain = pPlainData;
if (plain_len < 0)
{
printf("length error!");
}
// 这个是临时的preCrypt,和加密时第一个8字节块没有prePlain一样
for (int i = 0; i < 8; i++)
{
precrypt[i] = 0x00;
}
pos ++;
int padding = 1;
while (padding <= 2)
{
if (pos < 8)//证明头字节中有明文信息
{
pos ++;
padding ++;
}
if (pos == 8)//证明头8字节都是无用的填充
{
//解密8字节
//decrypt8Bytes(inData, offset, len)
pre_crypt = pcrypt; pcrypt +=8;
for ( i = 0; i< 8; i++)
{
plain[i] ^= pcrypt[i];//上次明文 ^ 此次密文
}
dec_block((dword*)plain,(dword*)pKey,(dword*)plain);
pos = 0;
}
}
dword offset = 0;
while (plain_len != 0)
{
if (pos < 8)//证明
{
if (header)
{
pPlainData[offset] = plain[pos] ^ precrypt[pos];
}
else
{//保存使用此次明文^上次密文
pPlainData[offset] = plain[pos] ^ pre_crypt[pos];
}
plain_len --;
pos++;
offset ++;
}
if (pos == 8)
{
header = false;
pre_crypt = pcrypt; pcrypt +=8;
for ( i = 0; i< 8; i++)
{
plain[i] ^= pcrypt[i];//上次明文 ^ 此次密文
}
dec_block((dword*)plain,(dword*)pKey,(dword*)plain);
pos = 0;
}
}
for (padding = 1; padding <= 7; padding++)
{
if (pos < 8)
{
if ( (plain[pos] ^ pre_crypt[pos]) != 0)
{
printf("decrypt error!");
}
pos ++;
}
if (pos == 8)
{
pre_crypt = pcrypt; pcrypt +=8;
if (pcrypt - pCryptData >= len)
{
return;
}
for ( i = 0; i< 8; i++)
{
plain[i] ^= pcrypt[i];//上次明文 ^ 此次密文
}
dec_block((dword*)plain,(dword*)pKey,(dword*)plain);
pos = 0;
}
}
}
void main()
{
// volatile int m = 0x100;
// m = m << 2;
dword key[4] = {0x55486B40,0x12B62930,0x05D12B06,0x51B4189D};
dword v[] = {0xab050402, 0x12121212, 0x23232323,0xcdef2376,0x12345678};
BYTE *pcrypt;
dword len = sizeof(v);
encrypt((BYTE*)v, len, key, pcrypt);
int pos = (len + 0x0A) %8;
if (pos != 0)
{
pos = 8 - pos;
};
//计算输出的密文长度
int codelen = len + pos + 0x0A;
printf("密文内容:\n");
for (int i = 0;i < codelen; i++)
{
printf("%02X ", pcrypt[i]);
if ( 0 == (i+1)%8)
{
printf("\n");
}
}
printf("\n");
BYTE *plain;
decrypt((BYTE*)pcrypt, codelen, (BYTE*)key, plain);
printf("解密后内容:\n");
for (i = 0; i < len; i++)
{
printf("%02X ", plain[i]);
if ((i+1)%8 == 0)
{
printf("\n");
}
}
printf("\n\n\n\n\n\n");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -