mirror of
https://github.com/xhacker-zzz/QmcWasm.git
synced 2024-11-25 04:22:16 +00:00
290 lines
7.3 KiB
C++
290 lines
7.3 KiB
C++
#ifndef QQMUSIC_CPP_TENCENTTEA_HPP
|
||
#define QQMUSIC_CPP_TENCENTTEA_HPP
|
||
|
||
#include <cstdlib>
|
||
#include <cstdio>
|
||
#include <cstdint>
|
||
#include <vector>
|
||
#include <time.h>
|
||
#include <arpa/inet.h>
|
||
|
||
const uint32_t DELTA = 0x9e3779b9;
|
||
|
||
#define ROUNDS 32
|
||
#define SALT_LEN 2
|
||
#define ZERO_LEN 7
|
||
|
||
void TeaDecryptECB(uint8_t* src, uint8_t* dst, std::vector<uint8_t> key, size_t rounds = ROUNDS) {
|
||
if (key.size() != 16 || (rounds & 1) != 0)
|
||
{
|
||
return;
|
||
}
|
||
uint32_t y, z, sum;
|
||
uint32_t k[4];
|
||
int i;
|
||
|
||
//now encrypted buf is TCP/IP-endian;
|
||
//TCP/IP network byte order (which is big-endian).
|
||
y = ntohl(*((uint32_t*)src));
|
||
z = ntohl(*((uint32_t*)(src + 4)));
|
||
//std::cout << ntohl(0x0a3aea41);
|
||
|
||
for (i = 0; i < 4; i++) {
|
||
//key is TCP/IP-endian;
|
||
k[i] = ntohl(*((uint32_t*)(key.data() + i * 4)));
|
||
}
|
||
|
||
sum = (DELTA * rounds);
|
||
for (i = 0; i < rounds; i++) {
|
||
z -= ((y << 4) + k[2]) ^ (y + sum) ^ ((y >> 5) + k[3]);
|
||
y -= ((z << 4) + k[0]) ^ (z + sum) ^ ((z >> 5) + k[1]);
|
||
sum -= DELTA;
|
||
}
|
||
|
||
*((uint32_t*)dst) = ntohl(y);
|
||
*((uint32_t*)(dst + 4)) = ntohl(z);
|
||
|
||
//now plain-text is TCP/IP-endian;
|
||
}
|
||
|
||
void TeaEncryptECB(uint8_t* src, uint8_t* dst, std::vector<uint8_t> key, size_t rounds = ROUNDS) {
|
||
if (key.size() != 16 || (rounds & 1) != 0)
|
||
{
|
||
return;
|
||
}
|
||
uint32_t y, z, sum;
|
||
uint32_t k[4];
|
||
int i;
|
||
|
||
//now encrypted buf is TCP/IP-endian;
|
||
//TCP/IP network byte order (which is big-endian).
|
||
y = ntohl(*((uint32_t*)src));
|
||
z = ntohl(*((uint32_t*)(src + 4)));
|
||
//std::cout << ntohl(0x0a3aea41);
|
||
|
||
for (i = 0; i < 4; i++) {
|
||
//key is TCP/IP-endian;
|
||
k[i] = ntohl(*((uint32_t*)(key.data() + i * 4)));
|
||
}
|
||
|
||
sum = 0;
|
||
for (i = 0; i < rounds; i++) {
|
||
sum += DELTA;
|
||
y += ((z << 4) + k[0]) ^ (z + sum) ^ ((z >> 5) + k[1]);
|
||
z += ((y << 4) + k[2]) ^ (y + sum) ^ ((y >> 5) + k[3]);
|
||
}
|
||
|
||
*((uint32_t*)dst) = ntohl(y);
|
||
*((uint32_t*)(dst + 4)) = ntohl(z);
|
||
|
||
//now plain-text is TCP/IP-endian;
|
||
}
|
||
|
||
/*pKeyΪ16byte*/
|
||
/*
|
||
<20><><EFBFBD><EFBFBD>:nInBufLenΪ<6E><CEAA><EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD><DCB5><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD>(Body)<29><><EFBFBD><EFBFBD>;
|
||
<20><><EFBFBD><EFBFBD>:<3A><><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>ܺ<EFBFBD><DCBA>ij<EFBFBD><C4B3><EFBFBD>(<28><>8byte<74>ı<EFBFBD><C4B1><EFBFBD>);
|
||
*/
|
||
/*TEA<45><41><EFBFBD><EFBFBD><EFBFBD>㷨,CBCģʽ*/
|
||
/*<2A><><EFBFBD>ĸ<EFBFBD>ʽ:PadLen(1byte)+Padding(var,0-7byte)+Salt(2byte)+Body(var byte)+Zero(7byte)*/
|
||
int encryptTencentTeaLen(int nInBufLen)
|
||
{
|
||
|
||
int nPadSaltBodyZeroLen/*PadLen(1byte)+Salt+Body+Zero<72>ij<EFBFBD><C4B3><EFBFBD>*/;
|
||
int nPadlen;
|
||
|
||
/*<2A><><EFBFBD><EFBFBD>Body<64><79><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD>PadLen,<2C><>С<EFBFBD><D0A1><EFBFBD>賤<EFBFBD>ȱ<EFBFBD><C8B1><EFBFBD>Ϊ8byte<74><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
|
||
nPadSaltBodyZeroLen = nInBufLen/*Body<64><79><EFBFBD><EFBFBD>*/ + 1 + SALT_LEN + ZERO_LEN/*PadLen(1byte)+Salt(2byte)+Zero(7byte)*/;
|
||
if ((nPadlen = nPadSaltBodyZeroLen % 8)) /*len=nSaltBodyZeroLen%8*/
|
||
{
|
||
/*ģ8<C4A3><38>0<EFBFBD>貹0,<2C><>1<EFBFBD><31>7,<2C><>2<EFBFBD><32>6,...,<2C><>7<EFBFBD><37>1*/
|
||
nPadlen = 8 - nPadlen;
|
||
}
|
||
|
||
return nPadlen;
|
||
}
|
||
|
||
/*pKeyΪ16byte*/
|
||
/*
|
||
<20><><EFBFBD><EFBFBD>:pInBufΪ<66><CEAA><EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD><DCB5><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD>(Body),nInBufLenΪpInBuf<75><66><EFBFBD><EFBFBD>;
|
||
<20><><EFBFBD><EFBFBD>:pOutBufΪ<66><CEAA><EFBFBD>ĸ<EFBFBD>ʽ,pOutBufLenΪpOutBuf<75>ij<EFBFBD><C4B3><EFBFBD><EFBFBD><EFBFBD>8byte<74>ı<EFBFBD><C4B1><EFBFBD>;
|
||
*/
|
||
/*TEA<45><41><EFBFBD><EFBFBD><EFBFBD>㷨,CBCģʽ*/
|
||
/*<2A><><EFBFBD>ĸ<EFBFBD>ʽ:PadLen(1byte)+Padding(var,0-7byte)+Salt(2byte)+Body(var byte)+Zero(7byte)*/
|
||
bool encryptTencentTea(std::vector<uint8_t> inBuf, std::vector<uint8_t> key, std::vector<uint8_t> &outBuf)
|
||
{
|
||
srand(time(0));
|
||
int nPadlen = encryptTencentTeaLen(inBuf.size());
|
||
size_t ivCrypt;
|
||
std::vector<uint8_t> srcBuf;
|
||
srcBuf.resize(8);
|
||
std::vector<uint8_t> ivPlain;
|
||
ivPlain.resize(8);
|
||
int tmpIdx, i, j;
|
||
|
||
/*<2A><><EFBFBD>ܵ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(8byte),ȡǰ<C8A1><C7B0>10byte*/
|
||
srcBuf[0] = (((char)rand()) & 0x0f8)/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>PadLen,<2C><><EFBFBD><EFBFBD>*/ | (char)nPadlen;
|
||
tmpIdx = 1; /*tmpIdxָ<78><D6B8>srcBuf<75><66>һ<EFBFBD><D2BB>λ<EFBFBD><CEBB>*/
|
||
|
||
while (nPadlen--) srcBuf[tmpIdx++] = (char)rand(); /*Padding*/
|
||
|
||
/*come here, tmpIdx must <= 8*/
|
||
|
||
for (i = 0; i < 8; i++) ivPlain[i] = 0;
|
||
ivCrypt = 0;//ivPlain /*make zero iv*/
|
||
|
||
auto outBufPos = 0; /*init outBufPos*/
|
||
|
||
#define cryptBlock {\
|
||
/*tmpIdx==8*/\
|
||
outBuf.resize(outBuf.size() + 8);\
|
||
for (j = 0; j < 8; j++) /*<2A><><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>ǰ8<C7B0><38>byte<74><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(iv_cryptָ<74><D6B8><EFBFBD><EFBFBD>)*/\
|
||
srcBuf[j] ^= outBuf[j + ivCrypt];\
|
||
/*pOutBuffer<65><72>pInBuffer<65><72>Ϊ8byte, pKeyΪ16byte*/\
|
||
/*<2A><><EFBFBD><EFBFBD>*/\
|
||
TeaEncryptECB(srcBuf.data(), outBuf.data()+outBufPos, key, 16);\
|
||
for (j = 0; j < 8; j++) /*<2A><><EFBFBD>ܺ<EFBFBD><DCBA><EFBFBD><EFBFBD><EFBFBD>ǰ8<C7B0><38>byte<74><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(iv_plainָ<6E><D6B8><EFBFBD><EFBFBD>)*/\
|
||
outBuf[j + outBufPos] ^= ivPlain[j];\
|
||
/*<2A><><EFBFBD>浱ǰ<E6B5B1><C7B0>iv_plain*/\
|
||
for (j = 0; j < 8; j++) ivPlain[j] = srcBuf[j];\
|
||
/*<2A><><EFBFBD><EFBFBD>iv_crypt*/\
|
||
tmpIdx = 0;\
|
||
ivCrypt = outBufPos;\
|
||
outBufPos += 8;\
|
||
}
|
||
|
||
|
||
for (i = 1; i <= SALT_LEN;) /*Salt(2byte)*/
|
||
{
|
||
if (tmpIdx < 8)
|
||
{
|
||
srcBuf[tmpIdx++] = (char)rand();
|
||
i++; /*i inc in here*/
|
||
}
|
||
if (tmpIdx == 8)
|
||
{
|
||
cryptBlock
|
||
}
|
||
}
|
||
|
||
/*tmpIdxָ<78><D6B8>srcBuf<75><66>һ<EFBFBD><D2BB>λ<EFBFBD><CEBB>*/
|
||
|
||
auto inBufPos = 0;
|
||
while (inBufPos < inBuf.size())
|
||
{
|
||
if (tmpIdx < 8)
|
||
{
|
||
srcBuf[tmpIdx++] = inBuf[inBufPos];
|
||
inBufPos++;
|
||
}
|
||
if (tmpIdx == 8)
|
||
{
|
||
cryptBlock
|
||
}
|
||
}
|
||
|
||
/*tmpIdxָ<78><D6B8>srcBuf<75><66>һ<EFBFBD><D2BB>λ<EFBFBD><CEBB>*/
|
||
|
||
for (i = 1; i <= ZERO_LEN;)
|
||
{
|
||
if (tmpIdx < 8)
|
||
{
|
||
srcBuf[tmpIdx++] = 0;
|
||
i++; //i inc in here
|
||
}
|
||
if (tmpIdx == 8)
|
||
{
|
||
cryptBlock
|
||
}
|
||
}
|
||
return true;
|
||
#undef cryptBlock
|
||
}
|
||
|
||
bool decryptTencentTea(std::vector<uint8_t> inBuf, std::vector<uint8_t> key, std::vector<uint8_t> &out) {
|
||
if (inBuf.size() % 8 != 0) {
|
||
return false;
|
||
//inBuf size not a multiple of the block size
|
||
}
|
||
if (inBuf.size() < 16) {
|
||
return false;
|
||
//inBuf size too small
|
||
}
|
||
|
||
std::vector<uint8_t> tmpBuf;
|
||
tmpBuf.resize(8);
|
||
|
||
TeaDecryptECB(inBuf.data(), tmpBuf.data(), key, 16);
|
||
|
||
auto nPadLen = tmpBuf[0] & 0x7; //ֻҪ<D6BB><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ
|
||
/*<2A><><EFBFBD>ĸ<EFBFBD>ʽ:PadLen(1byte)+Padding(var,0-7byte)+Salt(2byte)+Body(var byte)+Zero(7byte)*/
|
||
auto outLen = inBuf.size() - 1 /*PadLen*/ - nPadLen - SALT_LEN - ZERO_LEN;
|
||
std::vector<uint8_t> outBuf;
|
||
outBuf.resize(outLen);
|
||
|
||
std::vector<uint8_t> ivPrev;
|
||
ivPrev.resize(8);
|
||
std::vector<uint8_t> ivCur;
|
||
ivCur.resize(8);
|
||
for (size_t i = 0; i < 8; i++)
|
||
{
|
||
ivCur[i] = inBuf[i]; // init iv
|
||
}
|
||
auto inBufPos = 8;
|
||
|
||
// <20><><EFBFBD><EFBFBD> Padding Len <20><> Padding
|
||
auto tmpIdx = 1 + nPadLen;
|
||
|
||
// CBC IV <20><><EFBFBD><EFBFBD>
|
||
#define cryptBlock {\
|
||
ivPrev = ivCur;\
|
||
for (size_t k = inBufPos; k < inBufPos + 8; k++)\
|
||
{\
|
||
ivCur[k - inBufPos] = inBuf[k];\
|
||
}\
|
||
for (size_t j = 0; j < 8; j++) {\
|
||
tmpBuf[j] ^= ivCur[j];\
|
||
}\
|
||
TeaDecryptECB(tmpBuf.data(), tmpBuf.data(), key, 16);\
|
||
inBufPos += 8;\
|
||
tmpIdx = 0;\
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD> Salt
|
||
for (size_t i = 1; i <= SALT_LEN; ) {
|
||
if (tmpIdx < 8) {
|
||
tmpIdx++;
|
||
i++;
|
||
}
|
||
else {
|
||
cryptBlock
|
||
}
|
||
}
|
||
|
||
// <20><>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD>
|
||
auto outBufPos = 0;
|
||
while (outBufPos < outLen) {
|
||
if (tmpIdx < 8) {
|
||
outBuf[outBufPos] = tmpBuf[tmpIdx] ^ ivPrev[tmpIdx];
|
||
outBufPos++;
|
||
tmpIdx++;
|
||
}
|
||
else {
|
||
cryptBlock
|
||
}
|
||
}
|
||
|
||
// У<><D0A3>Zero
|
||
for (size_t i = 1; i <= ZERO_LEN; i++) {
|
||
if (tmpBuf[i] != ivPrev[i]) {
|
||
return false;
|
||
//zero check failed
|
||
}
|
||
}
|
||
out = outBuf;
|
||
return true;
|
||
#undef cryptBlock
|
||
}
|
||
|
||
#endif //QQMUSIC_CPP_TENCENTTEA_HPP
|