#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;
    //����
    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());

    //����PKCS7Padding��䡣
    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';

    //���ܺ������
    char* szDataOut = new char[block_num * BLOCK_SIZE + 1];
    memset(szDataOut, 0, block_num * BLOCK_SIZE + 1);

    //���н���AES��CBCģʽ����
    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();
    //����
    char* szDataIn = new char[length + 1];
    memcpy(szDataIn, strData.c_str(), length + 1);
    //����
    char* szDataOut = new char[length + 1];
    memcpy(szDataOut, strData.c_str(), length + 1);

    //����AES��ECBģʽ����
    MakeKey(key, key, 16, 16);
    Decrypt(szDataIn, szDataOut, length, iMode);

    //ȥPKCS7Padding���
    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;
}