CSTest/网络客户端/AES.cpp

599 lines
19 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "AES.h"
//CONSTRUCTOR
AES::AES() :
m_bKeyInit(false), m_keylength(0), m_blockSize(0), m_iROUNDS(0)
{
}
//DESTRUCTOR
AES::~AES()
{
}
void AES::Xor(char* buff, char const* chain)
{
if (false == m_bKeyInit)
return;
for (int i = 0; i < m_blockSize; i++)
*(buff++) ^= *(chain++);
}
void AES::DefEncryptBlock(char const* in, char* result)
{
if (false == m_bKeyInit)
return;
int* Ker = m_Ke[0];
int t0 = ((unsigned char)*(in++) << 24);
t0 |= ((unsigned char)*(in++) << 16);
t0 |= ((unsigned char)*(in++) << 8);
(t0 |= (unsigned char)*(in++)) ^= Ker[0];
int t1 = ((unsigned char)*(in++) << 24);
t1 |= ((unsigned char)*(in++) << 16);
t1 |= ((unsigned char)*(in++) << 8);
(t1 |= (unsigned char)*(in++)) ^= Ker[1];
int t2 = ((unsigned char)*(in++) << 24);
t2 |= ((unsigned char)*(in++) << 16);
t2 |= ((unsigned char)*(in++) << 8);
(t2 |= (unsigned char)*(in++)) ^= Ker[2];
int t3 = ((unsigned char)*(in++) << 24);
t3 |= ((unsigned char)*(in++) << 16);
t3 |= ((unsigned char)*(in++) << 8);
(t3 |= (unsigned char)*(in++)) ^= Ker[3];
int a0, a1, a2, a3;
//Apply Round Transforms
for (int r = 1; r < m_iROUNDS; r++)
{
Ker = m_Ke[r];
a0 = (sm_T1[(t0 >> 24) & 0xFF] ^ sm_T2[(t1 >> 16) & 0xFF]
^ sm_T3[(t2 >> 8) & 0xFF] ^ sm_T4[t3 & 0xFF]) ^ Ker[0];
a1 = (sm_T1[(t1 >> 24) & 0xFF] ^ sm_T2[(t2 >> 16) & 0xFF]
^ sm_T3[(t3 >> 8) & 0xFF] ^ sm_T4[t0 & 0xFF]) ^ Ker[1];
a2 = (sm_T1[(t2 >> 24) & 0xFF] ^ sm_T2[(t3 >> 16) & 0xFF]
^ sm_T3[(t0 >> 8) & 0xFF] ^ sm_T4[t1 & 0xFF]) ^ Ker[2];
a3 = (sm_T1[(t3 >> 24) & 0xFF] ^ sm_T2[(t0 >> 16) & 0xFF]
^ sm_T3[(t1 >> 8) & 0xFF] ^ sm_T4[t2 & 0xFF]) ^ Ker[3];
t0 = a0;
t1 = a1;
t2 = a2;
t3 = a3;
}
//Last Round is special
Ker = m_Ke[m_iROUNDS];
int tt = Ker[0];
result[0] = sm_S[(t0 >> 24) & 0xFF] ^ (tt >> 24);
result[1] = sm_S[(t1 >> 16) & 0xFF] ^ (tt >> 16);
result[2] = sm_S[(t2 >> 8) & 0xFF] ^ (tt >> 8);
result[3] = sm_S[t3 & 0xFF] ^ tt;
tt = Ker[1];
result[4] = sm_S[(t1 >> 24) & 0xFF] ^ (tt >> 24);
result[5] = sm_S[(t2 >> 16) & 0xFF] ^ (tt >> 16);
result[6] = sm_S[(t3 >> 8) & 0xFF] ^ (tt >> 8);
result[7] = sm_S[t0 & 0xFF] ^ tt;
tt = Ker[2];
result[8] = sm_S[(t2 >> 24) & 0xFF] ^ (tt >> 24);
result[9] = sm_S[(t3 >> 16) & 0xFF] ^ (tt >> 16);
result[10] = sm_S[(t0 >> 8) & 0xFF] ^ (tt >> 8);
result[11] = sm_S[t1 & 0xFF] ^ tt;
tt = Ker[3];
result[12] = sm_S[(t3 >> 24) & 0xFF] ^ (tt >> 24);
result[13] = sm_S[(t0 >> 16) & 0xFF] ^ (tt >> 16);
result[14] = sm_S[(t1 >> 8) & 0xFF] ^ (tt >> 8);
result[15] = sm_S[t2 & 0xFF] ^ tt;
}
//Convenience method to decrypt exactly one block of plaintext, assuming
//Rijndael's default block size (128-bit).
// in - The ciphertext.
// result - The plaintext generated from a ciphertext using the session key.
void AES::DefDecryptBlock(char const* in, char* result)
{
if (false == m_bKeyInit)
return;
int* Kdr = m_Kd[0];
int t0 = ((unsigned char)*(in++) << 24);
t0 = t0 | ((unsigned char)*(in++) << 16);
t0 |= ((unsigned char)*(in++) << 8);
(t0 |= (unsigned char)*(in++)) ^= Kdr[0];
int t1 = ((unsigned char)*(in++) << 24);
t1 |= ((unsigned char)*(in++) << 16);
t1 |= ((unsigned char)*(in++) << 8);
(t1 |= (unsigned char)*(in++)) ^= Kdr[1];
int t2 = ((unsigned char)*(in++) << 24);
t2 |= ((unsigned char)*(in++) << 16);
t2 |= ((unsigned char)*(in++) << 8);
(t2 |= (unsigned char)*(in++)) ^= Kdr[2];
int t3 = ((unsigned char)*(in++) << 24);
t3 |= ((unsigned char)*(in++) << 16);
t3 |= ((unsigned char)*(in++) << 8);
(t3 |= (unsigned char)*(in++)) ^= Kdr[3];
int a0, a1, a2, a3;
for (int r = 1; r < m_iROUNDS; r++) // apply round transforms
{
Kdr = m_Kd[r];
a0 = (sm_T5[(t0 >> 24) & 0xFF] ^ sm_T6[(t3 >> 16) & 0xFF]
^ sm_T7[(t2 >> 8) & 0xFF] ^ sm_T8[t1 & 0xFF]) ^ Kdr[0];
a1 = (sm_T5[(t1 >> 24) & 0xFF] ^ sm_T6[(t0 >> 16) & 0xFF]
^ sm_T7[(t3 >> 8) & 0xFF] ^ sm_T8[t2 & 0xFF]) ^ Kdr[1];
a2 = (sm_T5[(t2 >> 24) & 0xFF] ^ sm_T6[(t1 >> 16) & 0xFF]
^ sm_T7[(t0 >> 8) & 0xFF] ^ sm_T8[t3 & 0xFF]) ^ Kdr[2];
a3 = (sm_T5[(t3 >> 24) & 0xFF] ^ sm_T6[(t2 >> 16) & 0xFF]
^ sm_T7[(t1 >> 8) & 0xFF] ^ sm_T8[t0 & 0xFF]) ^ Kdr[3];
t0 = a0;
t1 = a1;
t2 = a2;
t3 = a3;
}
//Last Round is special
Kdr = m_Kd[m_iROUNDS];
int tt = Kdr[0];
result[0] = sm_Si[(t0 >> 24) & 0xFF] ^ (tt >> 24);
result[1] = sm_Si[(t3 >> 16) & 0xFF] ^ (tt >> 16);
result[2] = sm_Si[(t2 >> 8) & 0xFF] ^ (tt >> 8);
result[3] = sm_Si[t1 & 0xFF] ^ tt;
tt = Kdr[1];
result[4] = sm_Si[(t1 >> 24) & 0xFF] ^ (tt >> 24);
result[5] = sm_Si[(t0 >> 16) & 0xFF] ^ (tt >> 16);
result[6] = sm_Si[(t3 >> 8) & 0xFF] ^ (tt >> 8);
result[7] = sm_Si[t2 & 0xFF] ^ tt;
tt = Kdr[2];
result[8] = sm_Si[(t2 >> 24) & 0xFF] ^ (tt >> 24);
result[9] = sm_Si[(t1 >> 16) & 0xFF] ^ (tt >> 16);
result[10] = sm_Si[(t0 >> 8) & 0xFF] ^ (tt >> 8);
result[11] = sm_Si[t3 & 0xFF] ^ tt;
tt = Kdr[3];
result[12] = sm_Si[(t3 >> 24) & 0xFF] ^ (tt >> 24);
result[13] = sm_Si[(t2 >> 16) & 0xFF] ^ (tt >> 16);
result[14] = sm_Si[(t1 >> 8) & 0xFF] ^ (tt >> 8);
result[15] = sm_Si[t0 & 0xFF] ^ tt;
}
//Encrypt exactly one block of plaintext.
// in - The plaintext.
// result - The ciphertext generated from a plaintext using the key.
void AES::EncryptBlock(char const* in, char* result)
{
if (false == m_bKeyInit)
return;
if (DEFAULT_BLOCK_SIZE == m_blockSize)
{
DefEncryptBlock(in, result);
return;
}
int BC = m_blockSize / 4;
int SC = (BC == 4) ? 0 : (BC == 6 ? 1 : 2);
int s1 = sm_shifts[SC][1][0];
int s2 = sm_shifts[SC][2][0];
int s3 = sm_shifts[SC][3][0];
//Temporary Work Arrays
int i;
int tt;
int* pi = t;
for (i = 0; i < BC; i++)
{
*pi = ((unsigned char)*(in++) << 24);
*pi |= ((unsigned char)*(in++) << 16);
*pi |= ((unsigned char)*(in++) << 8);
(*(pi++) |= (unsigned char)*(in++)) ^= m_Ke[0][i];
}
//Apply Round Transforms
for (int r = 1; r < m_iROUNDS; r++)
{
for (i = 0; i < BC; i++)
a[i] = (sm_T1[(t[i] >> 24) & 0xFF]
^ sm_T2[(t[(i + s1) % BC] >> 16) & 0xFF]
^ sm_T3[(t[(i + s2) % BC] >> 8) & 0xFF]
^ sm_T4[t[(i + s3) % BC] & 0xFF]) ^ m_Ke[r][i];
memcpy(t, a, 4 * BC);
}
int j;
//Last Round is Special
for (i = 0, j = 0; i < BC; i++)
{
tt = m_Ke[m_iROUNDS][i];
result[j++] = sm_S[(t[i] >> 24) & 0xFF] ^ (tt >> 24);
result[j++] = sm_S[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16);
result[j++] = sm_S[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8);
result[j++] = sm_S[t[(i + s3) % BC] & 0xFF] ^ tt;
}
}
//Decrypt exactly one block of ciphertext.
// in - The ciphertext.
// result - The plaintext generated from a ciphertext using the session key.
void AES::DecryptBlock(char const* in, char* result)
{
if (false == m_bKeyInit)
return;
if (DEFAULT_BLOCK_SIZE == m_blockSize)
{
DefDecryptBlock(in, result);
return;
}
int BC = m_blockSize / 4;
int SC = BC == 4 ? 0 : (BC == 6 ? 1 : 2);
int s1 = sm_shifts[SC][1][1];
int s2 = sm_shifts[SC][2][1];
int s3 = sm_shifts[SC][3][1];
//Temporary Work Arrays
int i;
int tt;
int* pi = t;
for (i = 0; i < BC; i++)
{
*pi = ((unsigned char)*(in++) << 24);
*pi |= ((unsigned char)*(in++) << 16);
*pi |= ((unsigned char)*(in++) << 8);
(*(pi++) |= (unsigned char)*(in++)) ^= m_Kd[0][i];
}
//Apply Round Transforms
for (int r = 1; r < m_iROUNDS; r++)
{
for (i = 0; i < BC; i++)
a[i] = (sm_T5[(t[i] >> 24) & 0xFF]
^ sm_T6[(t[(i + s1) % BC] >> 16) & 0xFF]
^ sm_T7[(t[(i + s2) % BC] >> 8) & 0xFF]
^ sm_T8[t[(i + s3) % BC] & 0xFF]) ^ m_Kd[r][i];
memcpy(t, a, 4 * BC);
}
int j;
//Last Round is Special
for (i = 0, j = 0; i < BC; i++)
{
tt = m_Kd[m_iROUNDS][i];
result[j++] = sm_Si[(t[i] >> 24) & 0xFF] ^ (tt >> 24);
result[j++] = sm_Si[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16);
result[j++] = sm_Si[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8);
result[j++] = sm_Si[t[(i + s3) % BC] & 0xFF] ^ tt;
}
}
std::string AES::base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (i = 0; (i < 4); i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if (i)
{
for (j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
while ((i++ < 3))
ret += '=';
}
return ret;
}
string AES::base64_decode(std::string const& encoded_string) {
int in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i == 4) {
for (i = 0; i < 4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
}
}
if (i) {
for (j = i; j < 4; j++)
char_array_4[j] = 0;
for (j = 0; j < 4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
}
return ret;
}
//Expand a user-supplied key material into a session key.
// key - The 128/192/256-bit user-key to use.
// chain - initial chain block for CBC and CFB modes.
// keylength - 16, 24 or 32 bytes
// blockSize - The block size in bytes of this Rijndael (16, 24 or 32 bytes).
void AES::MakeKey(char const* key, char const* chain, int keylength,
int blockSize)
{
if (NULL == key)
return;
if (!(16 == keylength || 24 == keylength || 32 == keylength))
return;
if (!(16 == blockSize || 24 == blockSize || 32 == blockSize))
return;
m_keylength = keylength;
m_blockSize = blockSize;
//Initialize the chain
memcpy(m_chain0, chain, m_blockSize);
memcpy(m_chain, chain, m_blockSize);
//Calculate Number of Rounds
switch (m_keylength)
{
case 16:
m_iROUNDS = (m_blockSize == 16) ? 10 : (m_blockSize == 24 ? 12 : 14);
break;
case 24:
m_iROUNDS = (m_blockSize != 32) ? 12 : 14;
break;
default: // 32 bytes = 256 bits
m_iROUNDS = 14;
}
int BC = m_blockSize / 4;
int i, j;
for (i = 0; i <= m_iROUNDS; i++)
{
for (j = 0; j < BC; j++)
m_Ke[i][j] = 0;
}
for (i = 0; i <= m_iROUNDS; i++)
{
for (j = 0; j < BC; j++)
m_Kd[i][j] = 0;
}
int ROUND_KEY_COUNT = (m_iROUNDS + 1) * BC;
int KC = m_keylength / 4;
//Copy user material bytes into temporary ints
int* pi = tk;
char const* pc = key;
for (i = 0; i < KC; i++)
{
*pi = (unsigned char)*(pc++) << 24;
*pi |= (unsigned char)*(pc++) << 16;
*pi |= (unsigned char)*(pc++) << 8;
*(pi++) |= (unsigned char)*(pc++);
}
//Copy values into round key arrays
int t = 0;
for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++)
{
m_Ke[t / BC][t % BC] = tk[j];
m_Kd[m_iROUNDS - (t / BC)][t % BC] = tk[j];
}
int tt, rconpointer = 0;
while (t < ROUND_KEY_COUNT)
{
//Extrapolate using phi (the round key evolution function)
tt = tk[KC - 1];
tk[0] ^= (sm_S[(tt >> 16) & 0xFF] & 0xFF) << 24
^ (sm_S[(tt >> 8) & 0xFF] & 0xFF) << 16
^ (sm_S[tt & 0xFF] & 0xFF) << 8
^ (sm_S[(tt >> 24) & 0xFF] & 0xFF)
^ (sm_rcon[rconpointer++] & 0xFF) << 24;
if (KC != 8)
for (i = 1, j = 0; i < KC;)
tk[i++] ^= tk[j++];
else
{
for (i = 1, j = 0; i < KC / 2;)
tk[i++] ^= tk[j++];
tt = tk[KC / 2 - 1];
tk[KC / 2] ^= (sm_S[tt & 0xFF] & 0xFF)
^ (sm_S[(tt >> 8) & 0xFF] & 0xFF) << 8
^ (sm_S[(tt >> 16) & 0xFF] & 0xFF) << 16
^ (sm_S[(tt >> 24) & 0xFF] & 0xFF) << 24;
for (j = KC / 2, i = j + 1; i < KC;)
tk[i++] ^= tk[j++];
}
//Copy values into round key arrays
for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++)
{
m_Ke[t / BC][t % BC] = tk[j];
m_Kd[m_iROUNDS - (t / BC)][t % BC] = tk[j];
}
}
//Inverse MixColumn where needed
for (int r = 1; r < m_iROUNDS; r++)
for (j = 0; j < BC; j++)
{
tt = m_Kd[r][j];
m_Kd[r][j] = sm_U1[(tt >> 24) & 0xFF] ^ sm_U2[(tt >> 16) & 0xFF]
^ sm_U3[(tt >> 8) & 0xFF] ^ sm_U4[tt & 0xFF];
}
m_bKeyInit = true;
}
void AES::Encrypt(char const* in, char* result, size_t n, int iMode)
{
if (false == m_bKeyInit)
return;
//n should be > 0 and multiple of m_blockSize
if (0 == n || n % m_blockSize != 0)
return;
int i;
char const* pin;
char* presult;
if (CBC == iMode) //CBC mode, using the Chain
{
for (i = 0, pin = in, presult = result; i < n / m_blockSize; i++)
{
Xor(m_chain, pin);
EncryptBlock(m_chain, presult);
memcpy(m_chain, presult, m_blockSize);
pin += m_blockSize;
presult += m_blockSize;
}
}
else if (CFB == iMode) //CFB mode, using the Chain
{
for (i = 0, pin = in, presult = result; i < n / m_blockSize; i++)
{
EncryptBlock(m_chain, presult);
Xor(presult, pin);
memcpy(m_chain, presult, m_blockSize);
pin += m_blockSize;
presult += m_blockSize;
}
}
else //ECB mode, not using the Chain
{
for (i = 0, pin = in, presult = result; i < n / m_blockSize; i++)
{
EncryptBlock(pin, presult);
pin += m_blockSize;
presult += m_blockSize;
}
}
}
void AES::Decrypt(char const* in, char* result, size_t n, int iMode)
{
if (false == m_bKeyInit)
return;
//n should be > 0 and multiple of m_blockSize
if (0 == n || n % m_blockSize != 0)
return;
int i;
char const* pin;
char* presult;
if (CBC == iMode) //CBC mode, using the Chain
{
for (i = 0, pin = in, presult = result; i < n / m_blockSize; i++)
{
DecryptBlock(pin, presult);
Xor(presult, m_chain);
memcpy(m_chain, pin, m_blockSize);
pin += m_blockSize;
presult += m_blockSize;
}
}
else if (CFB == iMode) //CFB mode, using the Chain, not using Decrypt()
{
for (i = 0, pin = in, presult = result; i < n / m_blockSize; i++)
{
EncryptBlock(m_chain, presult);
//memcpy(presult, pin, m_blockSize);
Xor(presult, pin);
memcpy(m_chain, pin, m_blockSize);
pin += m_blockSize;
presult += m_blockSize;
}
}
else //ECB mode, not using the Chain
{
for (i = 0, pin = in, presult = result; i < n / m_blockSize; i++)
{
DecryptBlock(pin, presult);
pin += m_blockSize;
presult += m_blockSize;
}
}
}
string AES::EncryptionAES(const string& strSrc, const char* key, Mode iMode)
{
size_t length = strSrc.length();
int block_num = length / BLOCK_SIZE + 1;
//<2F><><EFBFBD><EFBFBD>
char* szDataIn = new char[block_num * BLOCK_SIZE + 1];
memset(szDataIn, 0x00, block_num * BLOCK_SIZE + 1);
strcpy_s(szDataIn, block_num * BLOCK_SIZE + 1, strSrc.c_str());
//<2F><><EFBFBD><EFBFBD>PKCS7Padding<6E><67><EFBFBD>
int k = length % BLOCK_SIZE;
int j = length / BLOCK_SIZE;
int padding = BLOCK_SIZE - k;
for (int i = 0; i < padding; i++)
{
szDataIn[j * BLOCK_SIZE + k + i] = padding;
}
szDataIn[block_num * BLOCK_SIZE] = '\0';
//<2F><><EFBFBD>ܺ<EFBFBD><DCBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
char* szDataOut = new char[block_num * BLOCK_SIZE + 1];
memset(szDataOut, 0, block_num * BLOCK_SIZE + 1);
//<2F><><EFBFBD>н<EFBFBD><D0BD><EFBFBD>AES<45><53>CBCģʽ<C4A3><CABD><EFBFBD><EFBFBD>
MakeKey(key, key, 16, 16);
Encrypt(szDataIn, szDataOut, block_num * BLOCK_SIZE, iMode);
string str = base64_encode((unsigned char*)szDataOut,
block_num * BLOCK_SIZE);
delete[] szDataIn;
delete[] szDataOut;
return str;
}
string AES::DecryptionAES(const string& strSrc, const char* key, Mode iMode)
{
string strData = base64_decode(strSrc);
size_t length = strData.length();
//<2F><><EFBFBD><EFBFBD>
char* szDataIn = new char[length + 1];
memcpy(szDataIn, strData.c_str(), length + 1);
//<2F><><EFBFBD><EFBFBD>
char* szDataOut = new char[length + 1];
memcpy(szDataOut, strData.c_str(), length + 1);
//<2F><><EFBFBD><EFBFBD>AES<45><53>ECBģʽ<C4A3><CABD><EFBFBD><EFBFBD>
MakeKey(key, key, 16, 16);
Decrypt(szDataIn, szDataOut, length, iMode);
//ȥPKCS7Padding<6E><67><EFBFBD><EFBFBD>
if (0x00 < szDataOut[length - 1] <= 0x16)
{
int tmp = szDataOut[length - 1];
for (int i = length - 1; i >= length - tmp; i--)
{
if (szDataOut[i] != tmp)
{
memset(szDataOut, 0, length);
break;
}
else
szDataOut[i] = 0;
}
}
string strDest(szDataOut);
delete[] szDataIn;
delete[] szDataOut;
return strDest;
}