603 lines
19 KiB
C++
603 lines
19 KiB
C++
#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)
|
||
{
|
||
if (strSrc == "")
|
||
return"";
|
||
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)
|
||
{
|
||
if (strSrc == "")
|
||
return"";
|
||
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;
|
||
}
|
||
|