Rijndaels的使用

       高級加密標準(Advanced Encryption Standard,AES),在密碼學中又稱Rijndael加密法,是美國聯邦政府採用的一種區塊加密標準。這個標準用來替代原先的DES,已經被多方分析且廣爲全世界所使用。

       1.加密的調用方法

bool CGlobalFun::Encryption(const CString &strFilePath) 
{
	if (!PathFileExists(strFilePath))
	{
		return false;
	}

	fstream iniFile;
	iniFile.open(strFilePath,ios::binary|ios::in);
	iniFile.seekg(0,ios::end);
	int length = iniFile.tellg();

	iniFile.seekg(0,ios::beg);
	unsigned char *buf=new unsigned char [length];
	iniFile.read((char*)buf,length);

	if (iniFile)
	{
		unsigned char* sKeyAes=new unsigned char [length+16];
		memset(sKeyAes,0,sizeof(sKeyAes));
		long nRet = AESEncode((unsigned char*)AES_KEY, buf, length, sKeyAes,length + 16);
		if (nRet != -99)
		{
			CString strFileEncPath;
			strFileEncPath = strFilePath + ".enc";

			fstream iniEncFile;
			iniEncFile.open(strFileEncPath,ios::binary|ios::out);
			iniEncFile.write((const char *)sKeyAes,nRet);
			iniEncFile.close();
			delete sKeyAes;
		}
	}

	iniFile.close();
	delete buf;

	return true;
}

2.解密的調用方法

bool CGlobalFun::Decryption(const CString &strFilePath) 
{
	CString strFileEncPath;
	strFileEncPath = strFilePath + ".enc";

	if (!PathFileExists(strFileEncPath))
	{
		return false;
	}

	fstream iniEncFile;
	iniEncFile.open(strFileEncPath,ios::binary|ios::in);
	iniEncFile.seekg(0,ios::end);
	int length = iniEncFile.tellg();

	unsigned char *buf=new unsigned char [length];
	iniEncFile.seekg(0,ios::beg);
	iniEncFile.read((char*)buf,length);

	if (iniEncFile)
	{
		unsigned char* sKeyAes=new unsigned char [length+16];
		memset(sKeyAes,0,sizeof(sKeyAes));
		long oLen = AESDecode((unsigned char*)AES_KEY, buf, length, sKeyAes,length);
		if (oLen != -99)
		{
			fstream iniFile;
			iniFile.open(strFilePath,ios::binary|ios::out);
			iniFile.write((const char *)sKeyAes,oLen);
			iniFile.close();
			delete sKeyAes;
		}
	}

	delete buf;
	iniEncFile.close();

	return true;
}

Rijndaels.h

/**
 * Rijndael --pronounced Reindaal-- is a symmetric cipher with a 128-bit
 * block size and 256-bit key-size.
 */

#ifndef _RIJNDAEL_H_
#define _RIJNDAEL_H_

#define KEY_LEN_BYTES	32			// 密鑰256位
#define ROUNDS			14
#define ROUND_KEY_COUNT ((ROUNDS + 1) * 4)


typedef unsigned char BYTE;
typedef BYTE * PBYTE;

long AESEncode(unsigned char * pKey, unsigned char * pIn, long nInLen, unsigned char * pOut,long nOutLen);
long AESDecode(unsigned char * pKey, unsigned char * pIn, long nInLen, unsigned char * pOut,long nOutLen);
int DecodeBase64(unsigned char * btSrc, int iSrcLen, unsigned char * btRet, int * piRetLen);
int EncodeBase64(unsigned char * btSrc, int iSrcLen, unsigned char * btRet, int * piRetLen);

class CRijndael{

public:
	CRijndael();
	~CRijndael();

public:
	static int BLOCK_SIZE;

	void Init();

    /**
	 * Set IV in CBC mode.
	 *
	 * @param pIV point the 16 bytes IV data.
	 */
	
	void setIV(PBYTE pIV);


	/**
     * Expand a user-supplied key material into a session encryption key.
     *
     * @param key The 256-bit user-key to use.
     */
	void makeKey(PBYTE pKey);

    /**
     * Encrypt an arbitrary length array.
     * @return number of bytes written.
     */
    int encrypt(BYTE* in, int inOffset, int inLen,
                          BYTE* out, int outOffset);
    /**
     * Decrypt an arbitrary length array.
     */
    int decrypt(BYTE* in, int inOffset, int inLen,
                          BYTE* out, int outOffset);

protected:

    /**
     * Invert a session encryption key into a session decryption key.
     */
	void invertKey(int* K);


    /**
     * Encrypt exactly one block of plaintext.
     */
    void blockEncrypt(BYTE* in, BYTE* out);
    void blockEncrypt(BYTE* in, int inOffset,
                              BYTE* out, int outOffset);

    /**
     * Decrypt exactly one block of plaintext.
     */
    void blockDecrypt(BYTE* in, BYTE* out);
    void blockDecrypt(BYTE* in, int inOffset,
                          BYTE* out, int outOffset);


private:
	static bool ROUNDS_12,  ROUNDS_14;
	static int limit;
	BYTE S[256], Si[256];
	int T1[256],T2[256],T3[256],T4[256],T5[256],T6[256],T7[256],T8[256];
	int U1[256],U2[256],U3[256],U4[256];
	BYTE rcon[30];

	int m_encKey[ROUND_KEY_COUNT];
	int m_decKey[ROUND_KEY_COUNT];

	BYTE m_iv[16];
};


#endif //_RIJNDAEL_H_

Rijndaels.cpp

/**
* Rijndael --pronounced Reindaal-- is a symmetric cipher with a 128-bit
* block size and 256-bit key-size.
*/
#include "stdafx.h"
#include "Rijndaels.h"
#include <string.h>

int CRijndael::BLOCK_SIZE = 0x10;		// block size in bytes
int CRijndael::limit = 14 * 4;		 // (ROUNDS-1) * 4 
bool CRijndael::ROUNDS_14 = 1;
bool CRijndael::ROUNDS_12 = 1;

CRijndael::CRijndael()
{
	Init();
}

CRijndael::~CRijndael()
{
}

void CRijndael::Init()
{	
	//S-BOX		
	unsigned char sinput[256]=
	{
		0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
			0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
			0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
			0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
			0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
			0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
			0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
			0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
			0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
			0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
			0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
			0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
			0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
			0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
			0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
			0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16
	};
	// intialise S-boxes and T-boxes
	memcpy(S, sinput, sizeof(S));
		
	int ROOT = 0x11B;
	int i, j = 0;
	
	for (i = 0; i < 256; i++) 
	{
		int s, s2, s3, i2, i4, i8, i9, ib, id, ie, t;
		s = S[i] & 0xFF;
		Si[s] = (BYTE)i;
		s2 = s << 1;
	
		if (s2 >= 0x100)
			s2 ^= ROOT;

		s3 = s2 ^ s;
		i2 = i << 1;
		if (i2 >= 0x100) 
			i2 ^= ROOT;

		i4 = i2 << 1;
		if (i4 >= 0x100)
			i4 ^= ROOT;

		i8 = i4 << 1;
		if (i8 >= 0x100)
			i8 ^= ROOT;

		i9 = i8 ^ i;
		ib = i9 ^ i2;
		id = i9 ^ i4;
		ie = i8 ^ i4 ^ i2;
		
		T1[i] = t = (s2 << 0x18) | (s << 0x10) | (s << 8) | s3;
		T2[i] = ((t >>  8) & 0xFFFFFF) | (t << 0x18);
		T3[i] = ((t >> 0x10) & 0xFFFF) | (t << 0x10);
		T4[i] = ((t >> 0x18) & 0xFF) | (t <<  8);
		
		T5[s] = U1[i] = t = (ie << 0x18) | (i9 << 0x10) | (id << 8) | ib;
		T6[s] = U2[i] = ((t >> 8) & 0xFFFFFF) | (t << 0x18);
		T7[s] = U3[i] = ((t >> 0x10) & 0xFFFF) | (t << 0x10);
		T8[s] = U4[i] = ((t >> 0x18) & 0xFF) | (t << 8);
	}
	//
	// round constants
	//
	int r = 1;
	rcon[0] = 1;
	for (i = 1; i < 30; i++) 
	{
		r <<= 1;
		if (r >= 0x100) 
			r ^= ROOT;

		rcon[i] = (BYTE)r;
	}

	// Initialise default IV
	memset(m_iv, 0x00, sizeof(m_iv));
}

/**
* Expand a user-supplied key material into a session encryption key.
*
* @param key The 256-bit user-key to use.
* @exception InvalidKeyException  If the key is invalid.
*/
void CRijndael::makeKey(PBYTE keyBytes)
{
	if (keyBytes == NULL)
		return ;
	
	int KC = KEY_LEN_BYTES / 4; // keylen in 32-bit elements
	int tk[KEY_LEN_BYTES/4];
	int K[ROUND_KEY_COUNT];
	
	int i, j;
	int tp1,tp2,tp3,tp4;
	// copy user material bytes into temporary ints
	for (i = 0, j = 0; i < KC; )
	{	
		tp1=(keyBytes[j++]) << 0x18;
		tp2=(keyBytes[j++] & 0xFF) << 0x10 ;
		tp3=(keyBytes[j++] & 0xFF) <<  8;
		tp4=(keyBytes[j++] & 0xFF);
		tk[i++] =tp1|tp2|tp3|tp4;
	}
	
	// copy values into round key arrays
	int t = 0;
	for ( ; t < KC; t++)
		K[t] = tk[t];
	
	char ts[1000];
	strcpy(ts,"");
	int tt, rconpointer = 0;
	while (t < ROUND_KEY_COUNT) 
	{
		// extrapolate using phi (the round key evolution function)
		tt = tk[KC - 1];
		tk[0] ^= (S[(BYTE)((tt >> 0x10) & 0xFF)] ) << 0x18 ^
			(S[(BYTE)((tt >> 8) & 0xFF)] & 0xFF) << 0x10 ^
			(S[(BYTE)((tt) & 0xFF)] & 0xFF) <<  8 ^
			(S[(BYTE)((tt >> 0x18) & 0xFF)] & 0xFF)       ^
			(rcon[rconpointer++] ) << 0x18;
	       
		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] ^=	(S[(BYTE)((tt      ) & 0xFF)] & 0xFF)      ^
				(S[(BYTE)((tt >>  8) & 0xFF)] & 0xFF) <<  8 ^
				(S[(BYTE)((tt >> 0x10) & 0xFF)] & 0xFF) << 0x10 ^
				(S[(BYTE)((tt >> 0x18) & 0xFF)]       ) << 0x18;
			
			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++)
			K[t] = tk[j];
		
		
	}
	//   char ttt[10];
	
	//		sprintf(ttt,"%d %d ,",j,i);
	//           strcat(ts,ttt);
	//	 for(int dd=0;dd<60;dd++)
	//	 {
	//			sprintf(ttt,"%d,",K[dd]);
	//            strcat(ts,ttt);
	//	 }
	//MessageBox(NULL,ts,"a",MB_OK);
	memcpy(m_encKey, K, sizeof(K));
	
	// decryption key
	invertKey(K);
	memcpy(m_decKey, K, sizeof(K));
}


/**
* Invert a session encryption key into a session decryption key.
*/
void CRijndael::invertKey(int* K) 
{
	int i=0;
	for(i=0; i<ROUND_KEY_COUNT/2-4;i+=4) 
	{
		int jj0 = K[i+0];
		int jj1 = K[i+1];
		int jj2 = K[i+2];
		int jj3 = K[i+3];
		K[i+0] = K[ROUND_KEY_COUNT-i-4+0];
		K[i+1] = K[ROUND_KEY_COUNT-i-4+1];
		K[i+2] = K[ROUND_KEY_COUNT-i-4+2];
		K[i+3] = K[ROUND_KEY_COUNT-i-4+3];
		K[ROUND_KEY_COUNT-i-4+0] = jj0;
		K[ROUND_KEY_COUNT-i-4+1] = jj1;
		K[ROUND_KEY_COUNT-i-4+2] = jj2;
		K[ROUND_KEY_COUNT-i-4+3] = jj3;
	}
	
	for (int r = 4; r < ROUND_KEY_COUNT-4; r++) 
	{
		int tt = K[r];
		K[r] = U1[(tt >> 0x18) & 0xFF] ^
			U2[(tt >> 0x10) & 0xFF] ^
			U3[(tt >>  8) & 0xFF] ^
			U4[ tt         & 0xFF];
	}
	
	int j0 = K[ROUND_KEY_COUNT-4];
	int j1 = K[ROUND_KEY_COUNT-3];
	int j2 = K[ROUND_KEY_COUNT-2];
	int j3 = K[ROUND_KEY_COUNT-1];
	for(i=ROUND_KEY_COUNT-1; i>3; i-- ) 
		K[i] = K[i-4];

	K[0] = j0;
	K[1] = j1;
	K[2] = j2;
	K[3] = j3;
} // invertKey


/**
* Encrypt exactly one block of plaintext.
*/
void CRijndael::blockEncrypt(BYTE* in, BYTE* out) 
{
	blockEncrypt(in, 0, out, 0);
}

void CRijndael::blockEncrypt(BYTE* in, int inOffset,
							 BYTE* out, int outOffset)
{
	int* K = &m_encKey[0];
	
	// plaintext to ints + key
	int keyOffset = 0;
	int tp1,tp2,tp3,tp4;

	tp1=(in[inOffset++]) << 0x18 ;
	tp2=(in[inOffset++] & 0xFF) << 0x10 ;
	tp3=(in[inOffset++] & 0xFF) <<  8 ;
	tp4=(in[inOffset++] & 0xFF);
	int t0= (tp1|tp2|tp3|tp4) ^ K[keyOffset++];

	tp1=(in[inOffset++]) << 0x18 ;
	tp2=(in[inOffset++] & 0xFF) << 0x10 ;
	tp3=(in[inOffset++] & 0xFF) <<  8 ;
	tp4=(in[inOffset++] & 0xFF);
	int t1= (tp1|tp2|tp3|tp4) ^ K[keyOffset++];

	tp1=(in[inOffset++]) << 0x18 ;
	tp2=(in[inOffset++] & 0xFF) << 0x10 ;
	tp3=(in[inOffset++] & 0xFF) <<  8 ;
	tp4=(in[inOffset++] & 0xFF);
	int t2= (tp1|tp2|tp3|tp4) ^ K[keyOffset++];

	tp1=(in[inOffset++]) << 0x18 ;
	tp2=(in[inOffset++] & 0xFF) << 0x10 ;
	tp3=(in[inOffset++] & 0xFF) <<  8 ;
	tp4=(in[inOffset] & 0xFF);
	int t3= (tp1|tp2|tp3|tp4) ^ K[keyOffset++];

	// apply round transforms
	while( keyOffset < limit ) 
	{
		int a0, a1, a2;
		a0 = T1[(t0 >> 0x18) & 0xFF] ^
			T2[(t1 >> 0x10) & 0xFF] ^
			T3[(t2 >>  8) & 0xFF] ^
			T4[(t3       ) & 0xFF] ^ K[keyOffset++];
		a1 = T1[(t1 >> 0x18) & 0xFF] ^
			T2[(t2 >> 0x10) & 0xFF] ^
			T3[(t3 >>  8) & 0xFF] ^
			T4[(t0       ) & 0xFF] ^ K[keyOffset++];
		a2 = T1[(t2 >> 0x18) & 0xFF] ^
			T2[(t3 >> 0x10) & 0xFF] ^
			T3[(t0 >>  8) & 0xFF] ^
			T4[(t1       ) & 0xFF] ^ K[keyOffset++];
		t3 = T1[(t3 >> 0x18) & 0xFF] ^
			T2[(t0 >> 0x10) & 0xFF] ^
			T3[(t1 >>  8) & 0xFF] ^
			T4[(t2       ) & 0xFF] ^ K[keyOffset++];
		t0 = a0; t1 = a1; t2 = a2;
	}
	
	// last round is special
	int tt = K[keyOffset++];
	out[outOffset++] = (BYTE)(S[(t0 >> 0x18) & 0xFF] ^ ((tt >> 0x18) & 0xFF));
	out[outOffset++] = (BYTE)(S[(t1 >> 0x10) & 0xFF] ^ ((tt >> 0x10) & 0xFFFF));
	out[outOffset++] = (BYTE)(S[(t2 >>  8) & 0xFF] ^ ((tt >>  8) & 0xFFFFFF));
	out[outOffset++] = (BYTE)(S[(t3       ) & 0xFF] ^ (tt       ));
	tt = K[keyOffset++];
	out[outOffset++] = (BYTE)(S[(t1 >> 0x18) & 0xFF] ^ ((tt >> 0x18) & 0xFF));
	out[outOffset++] = (BYTE)(S[(t2 >> 0x10) & 0xFF] ^ ((tt >> 0x10) & 0xFFFF));
	out[outOffset++] = (BYTE)(S[(t3 >>  8) & 0xFF] ^ ((tt >>  8) & 0xFFFFFF));
	out[outOffset++] = (BYTE)(S[(t0       ) & 0xFF] ^ (tt       ));
	tt = K[keyOffset++];
	out[outOffset++] = (BYTE)(S[(t2 >> 0x18) & 0xFF] ^ ((tt >> 0x18) & 0xFF));
	out[outOffset++] = (BYTE)(S[(t3 >> 0x10) & 0xFF] ^ ((tt >> 0x10) & 0xFFFF));
	out[outOffset++] = (BYTE)(S[(t0 >>  8) & 0xFF] ^ ((tt >>  8) & 0xFFFFFF));
	out[outOffset++] = (BYTE)(S[(t1       ) & 0xFF] ^ (tt       ));
	tt = K[keyOffset++];
	out[outOffset++] = (BYTE)(S[(t3 >> 0x18) & 0xFF] ^ ((tt >> 0x18) & 0xFF));
	out[outOffset++] = (BYTE)(S[(t0 >> 0x10) & 0xFF] ^ ((tt >> 0x10) & 0xFFFF));
	out[outOffset++] = (BYTE)(S[(t1 >>  8) & 0xFF] ^ ((tt >>  8) & 0xFFFFFF));
	out[outOffset  ] = (BYTE)(S[(t2       ) & 0xFF] ^ (tt       ));
}

/**
* Decrypt exactly one block of plaintext.
*/
void CRijndael::blockDecrypt(BYTE* in, BYTE* out) 
{
	blockDecrypt(in, 0, out, 0);
}

void CRijndael::blockDecrypt(BYTE* in, int inOffset,
							 BYTE* out, int outOffset)
{
	int* K = &m_decKey[0];
	
	int keyOffset = 8;
	int t0, t1, t2, t3, a0, a1, a2;
	int tp1,tp2,tp3,tp4;
	
	tp1=(in[inOffset++]       )<< 0x18 ;
	tp2=(in[inOffset++] & 0xFF) << 0x10;
	tp3=(in[inOffset++] & 0xFF) <<  8 ;
	tp4=(in[inOffset++] & 0xFF)        ;
	t0 = (tp1|tp2|tp3|tp4) ^ K[4];
	tp1=(in[inOffset++]       )<< 0x18 ;
	tp2=(in[inOffset++] & 0xFF) << 0x10;
	tp3=(in[inOffset++] & 0xFF) <<  8 ;
	tp4=(in[inOffset++] & 0xFF)        ;
	t1 = (tp1|tp2|tp3|tp4) ^ K[5];
	tp1=(in[inOffset++]       )<< 0x18 ;
	tp2=(in[inOffset++] & 0xFF) << 0x10;
	tp3=(in[inOffset++] & 0xFF) <<  8 ;
	tp4=(in[inOffset++] & 0xFF)        ;
	t2 = (tp1|tp2|tp3|tp4) ^ K[6];
	tp1=(in[inOffset++]       )<< 0x18 ;
	tp2=(in[inOffset++] & 0xFF) << 0x10;
	tp3=(in[inOffset++] & 0xFF) <<  8 ;
	tp4=(in[inOffset] & 0xFF)        ;
	t3 = (tp1|tp2|tp3|tp4) ^ K[7];

	if(ROUNDS_12) 
	{
		a0 = T5[(t0>>0x18) & 0xFF] ^ T6[(t3>>0x10)&0xFF] ^
			T7[(t2>> 8)&0xFF] ^ T8[(t1     )&0xFF] ^ K[keyOffset++];
		a1 = T5[(t1>>0x18) & 0xFF] ^ T6[(t0>>0x10)&0xFF] ^
			T7[(t3>> 8)&0xFF] ^ T8[(t2     )&0xFF] ^ K[keyOffset++];
		a2 = T5[(t2>>0x18) & 0xFF] ^ T6[(t1>>0x10)&0xFF] ^
			T7[(t0>> 8)&0xFF] ^ T8[(t3     )&0xFF] ^ K[keyOffset++];
		t3 = T5[(t3>>0x18) & 0xFF] ^ T6[(t2>>0x10)&0xFF] ^
			T7[(t1>> 8)&0xFF] ^ T8[(t0     )&0xFF] ^ K[keyOffset++];
		t0 = T5[(a0>>0x18) & 0xFF] ^ T6[(t3>>0x10)&0xFF] ^
			T7[(a2>> 8)&0xFF] ^ T8[(a1     )&0xFF] ^ K[keyOffset++];
		t1 = T5[(a1>>0x18) & 0xFF] ^ T6[(a0>>0x10)&0xFF] ^
			T7[(t3>> 8)&0xFF] ^ T8[(a2     )&0xFF] ^ K[keyOffset++];
		t2 = T5[(a2>>0x18) & 0xFF] ^ T6[(a1>>0x10)&0xFF] ^
			T7[(a0>> 8)&0xFF] ^ T8[(t3     )&0xFF] ^ K[keyOffset++];
		t3 = T5[(t3>>0x18) & 0xFF] ^ T6[(a2>>0x10)&0xFF] ^
			T7[(a1>> 8)&0xFF] ^ T8[(a0     )&0xFF] ^ K[keyOffset++];
		
		if(ROUNDS_14) 
		{
			a0 = T5[(t0>>0x18) & 0xFF] ^ T6[(t3>>0x10)&0xFF] ^
				T7[(t2>> 8)&0xFF] ^ T8[(t1     )&0xFF] ^ K[keyOffset++];
			a1 = T5[(t1>>0x18) & 0xFF] ^ T6[(t0>>0x10)&0xFF] ^
				T7[(t3>> 8)&0xFF] ^ T8[(t2     )&0xFF] ^ K[keyOffset++];
			a2 = T5[(t2>>0x18) & 0xFF] ^ T6[(t1>>0x10)&0xFF] ^
				T7[(t0>> 8)&0xFF] ^ T8[(t3     )&0xFF] ^ K[keyOffset++];
			t3 = T5[(t3>>0x18) & 0xFF] ^ T6[(t2>>0x10)&0xFF] ^
				T7[(t1>> 8)&0xFF] ^ T8[(t0     )&0xFF] ^ K[keyOffset++];
			t0 = T5[(a0>>0x18) & 0xFF] ^ T6[(t3>>0x10)&0xFF] ^
				T7[(a2>> 8)&0xFF] ^ T8[(a1     )&0xFF] ^ K[keyOffset++];
			t1 = T5[(a1>>0x18) & 0xFF] ^ T6[(a0>>0x10)&0xFF] ^
				T7[(t3>> 8)&0xFF] ^ T8[(a2     )&0xFF] ^ K[keyOffset++];
			t2 = T5[(a2>>0x18) & 0xFF] ^ T6[(a1>>0x10)&0xFF] ^
				T7[(a0>> 8)&0xFF] ^ T8[(t3     )&0xFF] ^ K[keyOffset++];
			t3 = T5[(t3>>0x18) & 0xFF] ^ T6[(a2>>0x10)&0xFF] ^
				T7[(a1>> 8)&0xFF] ^ T8[(a0     )&0xFF] ^ K[keyOffset++];
		}
	} // if ROUNDS_12

	a0 = T5[(t0>>0x18) & 0xFF] ^ T6[(t3>>0x10)&0xFF] ^
		T7[(t2>> 8)&0xFF] ^ T8[(t1     )&0xFF] ^ K[keyOffset++];
	a1 = T5[(t1>>0x18) & 0xFF] ^ T6[(t0>>0x10)&0xFF] ^
		T7[(t3>> 8)&0xFF] ^ T8[(t2     )&0xFF] ^ K[keyOffset++];
	a2 = T5[(t2>>0x18) & 0xFF] ^ T6[(t1>>0x10)&0xFF] ^
		T7[(t0>> 8)&0xFF] ^ T8[(t3     )&0xFF] ^ K[keyOffset++];
	t3 = T5[(t3>>0x18) & 0xFF] ^ T6[(t2>>0x10)&0xFF] ^
		T7[(t1>> 8)&0xFF] ^ T8[(t0     )&0xFF] ^ K[keyOffset++];
	t0 = T5[(a0>>0x18) & 0xFF] ^ T6[(t3>>0x10)&0xFF] ^
		T7[(a2>> 8)&0xFF] ^ T8[(a1     )&0xFF] ^ K[keyOffset++];
	t1 = T5[(a1>>0x18) & 0xFF] ^ T6[(a0>>0x10)&0xFF] ^
		T7[(t3>> 8)&0xFF] ^ T8[(a2     )&0xFF] ^ K[keyOffset++];
	t2 = T5[(a2>>0x18) & 0xFF] ^ T6[(a1>>0x10)&0xFF] ^
		T7[(a0>> 8)&0xFF] ^ T8[(t3     )&0xFF] ^ K[keyOffset++];
	t3 = T5[(t3>>0x18) & 0xFF] ^ T6[(a2>>0x10)&0xFF] ^
		T7[(a1>> 8)&0xFF] ^ T8[(a0     )&0xFF] ^ K[keyOffset++];
	a0 = T5[(t0>>0x18) & 0xFF] ^ T6[(t3>>0x10)&0xFF] ^
		T7[(t2>> 8)&0xFF] ^ T8[(t1     )&0xFF] ^ K[keyOffset++];
	a1 = T5[(t1>>0x18) & 0xFF] ^ T6[(t0>>0x10)&0xFF] ^
		T7[(t3>> 8)&0xFF] ^ T8[(t2     )&0xFF] ^ K[keyOffset++];
	a2 = T5[(t2>>0x18) & 0xFF] ^ T6[(t1>>0x10)&0xFF] ^
		T7[(t0>> 8)&0xFF] ^ T8[(t3     )&0xFF] ^ K[keyOffset++];
	t3 = T5[(t3>>0x18) & 0xFF] ^ T6[(t2>>0x10)&0xFF] ^
		T7[(t1>> 8)&0xFF] ^ T8[(t0     )&0xFF] ^ K[keyOffset++];
	t0 = T5[(a0>>0x18) & 0xFF] ^ T6[(t3>>0x10)&0xFF] ^
		T7[(a2>> 8)&0xFF] ^ T8[(a1     )&0xFF] ^ K[keyOffset++];
	t1 = T5[(a1>>0x18) & 0xFF] ^ T6[(a0>>0x10)&0xFF] ^
		T7[(t3>> 8)&0xFF] ^ T8[(a2     )&0xFF] ^ K[keyOffset++];
	t2 = T5[(a2>>0x18) & 0xFF] ^ T6[(a1>>0x10)&0xFF] ^
		T7[(a0>> 8)&0xFF] ^ T8[(t3     )&0xFF] ^ K[keyOffset++];
	t3 = T5[(t3>>0x18) & 0xFF] ^ T6[(a2>>0x10)&0xFF] ^
		T7[(a1>> 8)&0xFF] ^ T8[(a0     )&0xFF] ^ K[keyOffset++];
	a0 = T5[(t0>>0x18) & 0xFF] ^ T6[(t3>>0x10)&0xFF] ^
		T7[(t2>> 8)&0xFF] ^ T8[(t1     )&0xFF] ^ K[keyOffset++];
	a1 = T5[(t1>>0x18) & 0xFF] ^ T6[(t0>>0x10)&0xFF] ^
		T7[(t3>> 8)&0xFF] ^ T8[(t2     )&0xFF] ^ K[keyOffset++];
	a2 = T5[(t2>>0x18) & 0xFF] ^ T6[(t1>>0x10)&0xFF] ^
		T7[(t0>> 8)&0xFF] ^ T8[(t3     )&0xFF] ^ K[keyOffset++];
	t3 = T5[(t3>>0x18) & 0xFF] ^ T6[(t2>>0x10)&0xFF] ^
		T7[(t1>> 8)&0xFF] ^ T8[(t0     )&0xFF] ^ K[keyOffset++];
	t0 = T5[(a0>>0x18) & 0xFF] ^ T6[(t3>>0x10)&0xFF] ^
		T7[(a2>> 8)&0xFF] ^ T8[(a1     )&0xFF] ^ K[keyOffset++];
	t1 = T5[(a1>>0x18) & 0xFF] ^ T6[(a0>>0x10)&0xFF] ^
		T7[(t3>> 8)&0xFF] ^ T8[(a2     )&0xFF] ^ K[keyOffset++];
	t2 = T5[(a2>>0x18) & 0xFF] ^ T6[(a1>>0x10)&0xFF] ^
		T7[(a0>> 8)&0xFF] ^ T8[(t3     )&0xFF] ^ K[keyOffset++];
	t3 = T5[(t3>>0x18) & 0xFF] ^ T6[(a2>>0x10)&0xFF] ^
		T7[(a1>> 8)&0xFF] ^ T8[(a0     )&0xFF] ^ K[keyOffset++];
	a0 = T5[(t0>>0x18) & 0xFF] ^ T6[(t3>>0x10)&0xFF] ^
		T7[(t2>> 8)&0xFF] ^ T8[(t1     )&0xFF] ^ K[keyOffset++];
	a1 = T5[(t1>>0x18) & 0xFF] ^ T6[(t0>>0x10)&0xFF] ^
		T7[(t3>> 8)&0xFF] ^ T8[(t2     )&0xFF] ^ K[keyOffset++];
	a2 = T5[(t2>>0x18) & 0xFF] ^ T6[(t1>>0x10)&0xFF] ^
		T7[(t0>> 8)&0xFF] ^ T8[(t3     )&0xFF] ^ K[keyOffset++];
	t3 = T5[(t3>>0x18) & 0xFF] ^ T6[(t2>>0x10)&0xFF] ^
		T7[(t1>> 8)&0xFF] ^ T8[(t0     )&0xFF] ^ K[keyOffset++];
	t0 = T5[(a0>>0x18) & 0xFF] ^ T6[(t3>>0x10)&0xFF] ^
		T7[(a2>> 8)&0xFF] ^ T8[(a1     )&0xFF] ^ K[keyOffset++];
	t1 = T5[(a1>>0x18) & 0xFF] ^ T6[(a0>>0x10)&0xFF] ^
		T7[(t3>> 8)&0xFF] ^ T8[(a2     )&0xFF] ^ K[keyOffset++];
	t2 = T5[(a2>>0x18) & 0xFF] ^ T6[(a1>>0x10)&0xFF] ^
		T7[(a0>> 8)&0xFF] ^ T8[(t3     )&0xFF] ^ K[keyOffset++];
	t3 = T5[(t3>>0x18) & 0xFF] ^ T6[(a2>>0x10)&0xFF] ^
		T7[(a1>> 8)&0xFF] ^ T8[(a0     )&0xFF] ^ K[keyOffset++];
	a0 = T5[(t0>>0x18) & 0xFF] ^ T6[(t3>>0x10)&0xFF] ^
		T7[(t2>> 8)&0xFF] ^ T8[(t1     )&0xFF] ^ K[keyOffset++];
	a1 = T5[(t1>>0x18) & 0xFF] ^ T6[(t0>>0x10)&0xFF] ^
		T7[(t3>> 8)&0xFF] ^ T8[(t2     )&0xFF] ^ K[keyOffset++];
	a2 = T5[(t2>>0x18) & 0xFF] ^ T6[(t1>>0x10)&0xFF] ^
		T7[(t0>> 8)&0xFF] ^ T8[(t3     )&0xFF] ^ K[keyOffset++];
	t3 = T5[(t3>>0x18) & 0xFF] ^ T6[(t2>>0x10)&0xFF] ^
		T7[(t1>> 8)&0xFF] ^ T8[(t0     )&0xFF] ^ K[keyOffset++];
	
	t1 = K[0];
	out[outOffset++] = (BYTE)(Si[(a0 >> 0x18) & 0xFF] ^ ((t1 >> 0x18) & 0xFF));
	out[outOffset++] = (BYTE)(Si[(t3 >> 0x10) & 0xFF] ^ ((t1 >> 0x10) & 0xFFFF));
	out[outOffset++] = (BYTE)(Si[(a2 >>  8) & 0xFF] ^ ((t1 >>  8) & 0xFFFFFF));
	out[outOffset++] = (BYTE)(Si[(a1       ) & 0xFF] ^ (t1       ));
	t1 = K[1];
	out[outOffset++] = (BYTE)(Si[(a1 >> 0x18) & 0xFF] ^ ((t1 >> 0x18) & 0xFF));
	out[outOffset++] = (BYTE)(Si[(a0 >> 0x10) & 0xFF] ^ ((t1 >> 0x10) & 0xFFFF));
	out[outOffset++] = (BYTE)(Si[(t3 >>  8) & 0xFF] ^ ((t1 >>  8) & 0xFFFFFF));
	out[outOffset++] = (BYTE)(Si[(a2       ) & 0xFF] ^ (t1       ));
	t1 = K[2];
	out[outOffset++] = (BYTE)(Si[(a2 >> 0x18) & 0xFF] ^ ((t1 >> 0x18) & 0xFF));
	out[outOffset++] = (BYTE)(Si[(a1 >> 0x10) & 0xFF] ^ ((t1 >> 0x10) & 0xFFFF));
	out[outOffset++] = (BYTE)(Si[(a0 >>  8) & 0xFF] ^ ((t1 >>  8) & 0xFFFFFF));
	out[outOffset++] = (BYTE)(Si[(t3       ) & 0xFF] ^ (t1       ));
	t1 = K[3];
	out[outOffset++] = (BYTE)(Si[(t3 >> 0x18) & 0xFF] ^ ((t1 >> 0x18) & 0xFF));
	out[outOffset++] = (BYTE)(Si[(a2 >> 0x10) & 0xFF] ^ ((t1 >> 0x10) & 0xFFFF));
	out[outOffset++] = (BYTE)(Si[(a1 >>  8) & 0xFF] ^ ((t1 >>  8) & 0xFFFFFF));
	out[outOffset  ] = (BYTE)(Si[(a0       ) & 0xFF] ^ (t1       ));
}


/**
* Encrypt an arbitrary length array.
* @return number of bytes written.
*/
int CRijndael::encrypt(BYTE* in, int inOffset, int inLen,
					   BYTE* out, int outOffset) {
	//int size = inLen;
	int written = 0;
	while (inLen > 0) 
	{
		memset(m_iv, 0x00, sizeof(m_iv));
		for(int i = 0; i < BLOCK_SIZE; i++)
			m_iv[i] ^= in[inOffset+i];
	
		blockEncrypt(m_iv, 0, out, outOffset);
		memcpy(m_iv, out+outOffset, BLOCK_SIZE);
		inOffset  += BLOCK_SIZE;
		outOffset += BLOCK_SIZE;
		inLen     -= BLOCK_SIZE;
		written   += BLOCK_SIZE;
	}
	
	return written;
}


/**
* Decrypt an arbitrary length array.
*/
int CRijndael::decrypt(BYTE* in, int inOffset, int inLen,
					   BYTE* out, int outOffset) {
	//int size = inLen;
	int written = 0;
	while (inLen > 0) 
	{
		blockDecrypt(in, inOffset, out, outOffset);
		
		memset(m_iv, 0x00, sizeof(m_iv));
		for(int i = 0; i < BLOCK_SIZE; i++)
			out[outOffset+i] ^= m_iv[i];
	
		memcpy(m_iv, in+inOffset, BLOCK_SIZE);

		inOffset  += BLOCK_SIZE;
		outOffset += BLOCK_SIZE;
		inLen     -= BLOCK_SIZE;
		written   += BLOCK_SIZE;
	}

	return written;
}

void CRijndael::setIV(PBYTE pIV)
{
	memcpy(m_iv, pIV, sizeof(m_iv));
}


long AESEncode(unsigned char * pKey, unsigned char * pIn, long nInLen, unsigned char * pOut,long nOutLen)
{
	try
	{
		//長度控制
		if (nOutLen!=nInLen+16)
		{
			return -99;
		}

		//取待加密數據除以16後的餘數,得到16-餘數的值
		CRijndael cipher;
		cipher.makeKey(pKey);
		BYTE bPad = (BYTE)(CRijndael::BLOCK_SIZE - nInLen%CRijndael::BLOCK_SIZE);

		//將待加密數據中16整數倍的數據先加密(爲了減少內存操作,不將數據合併後再加密)
		nOutLen = cipher.encrypt(pIn, 0, nInLen - (nInLen%CRijndael::BLOCK_SIZE), pOut, 0);

		//生成填充數據
		BYTE* pPad = new BYTE[CRijndael::BLOCK_SIZE];
		memcpy(pPad, pIn+nOutLen, nInLen - nOutLen);
		memset(pPad+nInLen - nOutLen, bPad, bPad);
		//加密填充數據
		nOutLen += cipher.encrypt(pPad, 0, CRijndael::BLOCK_SIZE, pOut, nOutLen);
		delete pPad;
		
		//返回加密後數據長度
		return nOutLen;
	}
	catch(...)
	{
		return -99;
	}
}

long AESDecode(unsigned char * pKey, unsigned char * pIn, long nInLen, unsigned char * pOut,long nOutLen)
{
	try
	{
		//長度控制
		if (nOutLen!=nInLen)
		{
			return -99;
		}
		if(nInLen % CRijndael::BLOCK_SIZE != 0)
		{
			return -99;
		}
		
		//創建密鑰對象		
		CRijndael cipher;
		cipher.makeKey(pKey);

		//解密數據
		BYTE* pBuf = new BYTE[nInLen];
		long nOutLen = cipher.decrypt(pIn, 0, nInLen, pBuf, 0);
		//安全檢查
		if(nOutLen != nInLen)
		{
			return -99;
		}
		
		//安全檢查,填充數據是否正確
		BYTE bPad = pBuf[nOutLen-1];
		if(CRijndael::BLOCK_SIZE < bPad)
		{
			delete pBuf;
			return -99;
		}
		for(int i = 0; i < bPad; i++)
		{
			if(pBuf[nOutLen - 1 - i] != bPad)
			{
				delete pBuf;
				return -99;
			}
		}
		
		//保存解密後數據
		nOutLen -= bPad;
		memcpy(pOut, pBuf, nOutLen);
		delete pBuf;

		//返回解密後數據長度
		return nOutLen;
	}
	catch(...)
	{
		return -99;
	}
} 

char D2HC(int dec)
{
	if (dec>=0 && dec<=9)
		return dec+'0';
	return dec-10+'A';
}

void B2HS(BYTE *bin,char *hex,int len)
{
	int i;

	for (i=0;i<len;i++) {
		hex[i*2]=D2HC(bin[i]>>4);
		hex[i*2+1]=D2HC(bin[i]&0x0F);
	}
}
/*====================================================================
 Base64編碼函數
 btSrc指向被編碼的數據緩衝區
 iSrcLen被編碼的數據的大小(字節)
 btRet指向存放Base64編碼的數據緩衝區
 piRetLen指向存放Base64編碼的數據緩衝區的長度
 若btRet爲NULL函數返回0,piRetLen傳回btSrc的Base64編碼所需緩衝區的大小
 若btRet指向的緩衝區太小,函數返回-1
 否則函數返回實際btSrc的Base64編碼所需緩衝區的大小
=====================================================================*/
int EncodeBase64(unsigned char * btSrc, int iSrcLen, unsigned char * btRet, int * piRetLen) //Base64編碼
{
	int i = 0, j = 0, k = 0 ;
	BYTE EncodeBase64Map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	
	i = (iSrcLen+2) / 3 * 4 ; //獲取btSrc的Base64編碼所需緩衝區的大小
	if(btRet != NULL)
	{
		if(*piRetLen < i) //Base64編碼所需緩衝區偏小
			return -1 ;
		*piRetLen = i ; //*piRetLen返回btSrc的Base64編碼的緩衝區大小
	}
	else
	{
		*piRetLen = i ;
		return 0 ;
	}

	k = iSrcLen - iSrcLen % 3 ;
	for(i=j=0; i<k; i+=3) //編碼
	{
		btRet[j++] = EncodeBase64Map[(btSrc[i]>>2)&0x3F] ;
		if (j >= *piRetLen )
			break;
		btRet[j++] = EncodeBase64Map[((btSrc[i]<<4) + (btSrc[i+1]>>4))&0x3F] ;
		if (j >= *piRetLen )
			break;
		btRet[j++] = EncodeBase64Map[((btSrc[i+1]<<2) + (btSrc[i+2]>>6))&0x3F] ;
		if (j >= *piRetLen )
			break;
		btRet[j++] = EncodeBase64Map[btSrc[i+2]&0x3F] ;
		if (j >= *piRetLen )
			break;
	}

	k = iSrcLen - k ;

	if(1 == k)
	{
		btRet[j++] = EncodeBase64Map[(btSrc[i]>>2)&0x3F] ;
		if (j >= *piRetLen )
			return ++j;
		btRet[j++] = EncodeBase64Map[(btSrc[i]<<4)&0x3F] ;
		if (j >= *piRetLen )
			return ++j;
		btRet[j++] = '=' ;
		btRet[j++] = '=' ;

		if (j >= *piRetLen )
			return ++j;
	}

	else if(2 == k)
	{
		btRet[j++] = EncodeBase64Map[(btSrc[i]>>2)&0x3F] ;
		if (j >= *piRetLen )
			return ++j;
		btRet[j++] = EncodeBase64Map[((btSrc[i]<<4) + (btSrc[i+1]>>4))&0x3F] ;
		if (j >= *piRetLen )
			return ++j;
		btRet[j++] = EncodeBase64Map[(btSrc[i+1]<<2)&0x3F] ;
		if (j >= *piRetLen )
			return ++j;
		btRet[j] = '=' ;
		if (j >= *piRetLen )
			return ++j;
	}

	return ++j ;
}

/*====================================================================
 Base64解碼函數
 btSrc指向被解碼的數據緩衝區
 iSrcLen被解碼的數據的大小(字節)
 btRet指向存放Base64解碼的數據緩衝區
 piRetLen指向存放Base64解碼的數據緩衝區的長度
 若btRet爲NULL函數返回0,piRetLen傳回btSrc的Base64解碼所需緩衝區的大小
 若btRet指向的緩衝區太小,函數返回-1
 否則函數返回btSrc的Base64解碼所需緩衝區的大小
=====================================================================*/
int DecodeBase64(unsigned char * btSrc, int iSrcLen, unsigned char * btRet, int * piRetLen) //Base64解碼
{
	int i = 0, j = 0 ;
	BYTE EncodeBase64Map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	BYTE DecodeBase64Map[256] = {0} ;
	
	for(j = iSrcLen; j>0 && '='==btSrc[j-1]; --j) ; //忽略=號
	i = (j/4)*3+(j%4+1)/2; //計算解碼後 字符串的長度
	
	if(btRet != NULL)
	{
		if(*piRetLen < i) //Base64解碼所需緩衝區偏小
			return -1 ;
		*piRetLen = i ; //*piRetLen返回btSrc的Base64解碼的緩衝區大小
	}
	else
	{
		*piRetLen = i ;
		return 0 ;
	}

	j = sizeof(EncodeBase64Map) ;
	for(i=0; i<j; ++i)
		DecodeBase64Map[ EncodeBase64Map[i] ] = i ;
	for(i=j=0; i<iSrcLen; i+=4)
	{
		btRet[j++] = DecodeBase64Map[btSrc[i  ]] << 2 | DecodeBase64Map[btSrc[i+1]] >> 4 ;
		if (j >= *piRetLen )
			break;
		btRet[j++] = DecodeBase64Map[btSrc[i+1]] << 4 | DecodeBase64Map[btSrc[i+2]] >> 2 ;
		if (j >= *piRetLen )
			break;
		btRet[j++] = DecodeBase64Map[btSrc[i+2]] << 6 | DecodeBase64Map[btSrc[i+3]] ;

		if (j >= *piRetLen )
			break;
	}

	return *piRetLen ;
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章