⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aes.c

📁 一个加密库代码
💻 C
字号:
/* This is an independent implementation of the encryption algorithm:	*/
/*																		*/
/*                 AES by Joan Daemen and Vincent Rijmen           */
/*                                                                      */
/* which was selected as the Advanced Encryption Standard (AES) by the  */
/* US National Institute of Standards (NIST)                            */
/*                                                                      */
/* Copyright in this implementation is held by Dr B R Gladman but I 	*/
/* hereby give permission for its free direct or derivative use subject */
/* to acknowledgment of its origin and compliance with any conditions	*/
/* that the originators of the algorithm place on its exploitation. 	*/
/*                                                                      */
/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 	*/
/*                                                                      */
/* Modified for CryptPak by Christian Thoeing <c.thoeing@web.de>        */
/* Some parts of this implementation are taken from Wei Dai's           */
/* aes.cpp (see Crypto++ library)										*/
/* Refactored by Markus Hahn for VC7/managed code                       */
/* experiments and adjusted for platform independent byte ordering      */

#include "AES.h"
#include "AESBoxes.h"

typedef struct {
	WORD32 key[(AES_KEYSIZE / 4) * 5 + 24];
	WORD32 cbc_iv[4];
} AESCTX;

#define rotr(x,n)   (((x) >> ((int)(n))) | ((x) << (32 - (int)(n))))
#define rotl(x,n)   (((x) << ((int)(n))) | ((x) >> (32 - (int)(n))))

#define ff_mult(a,b) (a && b ? pow_tab[(log_tab[a] + log_tab[b]) % 255] : 0)

#define byte(x,n)   ((WORD8)((x) >> (8 * (n))))

#define ls_box(x)                            \
	((WORD32)sbx_tab[byte(x, 0)] <<  0) ^    \
	((WORD32)sbx_tab[byte(x, 1)] <<  8) ^    \
	((WORD32)sbx_tab[byte(x, 2)] << 16) ^    \
	((WORD32)sbx_tab[byte(x, 3)] << 24)

#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)

#define imix_col(y,x)        \
	u   = star_x(x);         \
	v   = star_x(u);         \
	w   = star_x(v);         \
	t   = w ^ (x);           \
	(y)  = u ^ v ^ w;        \
	(y) ^= rotr(u ^ t,  8) ^ \
	rotr(v ^ t, 16) ^		 \
	rotr(t,24)

void aesSetKey(
	AESCTX* pCtx,
	const WORD8* userKey,
	WORD32 lKeyLen,
	WORD32 lMode)
{
	WORD32 t;
	WORD32* key = pCtx->key;
	int i;

	for (i = 0; i < AES_KEYSIZE / 4; i++)
		key[i] = 0;

	for (i = 0; i < AES_KEYSIZE; i++)
		key[i/4] |= userKey[i%lKeyLen] << ((i%4)*8);

	t = key[7];

	// we use 256-bit Rijndael
	for (i = 0; i < 7; i++)
	{
		t = rotr(t,  8);
		t = ls_box(t) ^ rco_tab[i];
		key[8 * i + 8] = t ^= key[8 * i];
		key[8 * i + 9] = t ^= key[8 * i + 1];
		key[8 * i + 10] = t ^= key[8 * i + 2];
		key[8 * i + 11] = t ^= key[8 * i + 3];
		key[8 * i + 12] = t = key[8 * i + 4] ^ ls_box(t);
		key[8 * i + 13] = t ^= key[8 * i + 5];
		key[8 * i + 14] = t ^= key[8 * i + 6];
		key[8 * i + 15] = t ^= key[8 * i + 7];
	}

	if (lMode == CIPHER_MODE_DECRYPT)
	{
		WORD32 t, u, v, w;

		for (i = 4; i < AES_KEYSIZE + 24; i++)
		{
			imix_col(key[i], key[i]);
		}
	}
}

#define f_rn(bo, bi, n, k)                 \
	bo[n] =  ft_tab[0][byte(bi[n],0)] ^    \
	ft_tab[1][byte(bi[(n + 1) & 3],1)] ^   \
	ft_tab[2][byte(bi[(n + 2) & 3],2)] ^   \
	ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)

#define f_rl(bo, bi, n, k)                                  \
	bo[n] = (WORD32)sbx_tab[byte(bi[n],0)] ^                \
	rotl(((WORD32)sbx_tab[byte(bi[(n + 1) & 3],1)]),  8) ^  \
	rotl(((WORD32)sbx_tab[byte(bi[(n + 2) & 3],2)]), 16) ^  \
	rotl(((WORD32)sbx_tab[byte(bi[(n + 3) & 3],3)]), 24) ^ *(k + n)

#define f_nround(bo, bi, k) \
	f_rn(bo, bi, 0, k); 	\
	f_rn(bo, bi, 1, k); 	\
	f_rn(bo, bi, 2, k); 	\
	f_rn(bo, bi, 3, k); 	\
	k += 4

#define f_lround(bo, bi, k) \
	f_rl(bo, bi, 0, k); 	\
	f_rl(bo, bi, 1, k); 	\
	f_rl(bo, bi, 2, k); 	\
	f_rl(bo, bi, 3, k)

void aesEncrypt(AESCTX* pCtx,
				const WORD32* pInBlock,
				WORD32* pOutBlock)
{
	WORD32 b0[4], b1[4];
	WORD32* kp = pCtx->key;

	b0[0] = pInBlock[0] ^ *kp++;
	b0[1] = pInBlock[1] ^ *kp++;
	b0[2] = pInBlock[2] ^ *kp++;
	b0[3] = pInBlock[3] ^ *kp++;

	f_nround(b1, b0, kp); f_nround(b0, b1, kp);
	f_nround(b1, b0, kp); f_nround(b0, b1, kp);
	f_nround(b1, b0, kp); f_nround(b0, b1, kp);
	f_nround(b1, b0, kp); f_nround(b0, b1, kp);
	f_nround(b1, b0, kp); f_nround(b0, b1, kp);
	f_nround(b1, b0, kp); f_nround(b0, b1, kp);
	f_nround(b1, b0, kp); f_lround(b0, b1, kp);

	pOutBlock[0] = b0[0];
	pOutBlock[1] = b0[1];
	pOutBlock[2] = b0[2];
	pOutBlock[3] = b0[3];
}

#define i_rn(bo, bi, n, k)						\
	bo[n] =  it_tab[0][byte(bi[n],0)] ^         \
	it_tab[1][byte(bi[(n + 3) & 3],1)] ^		\
	it_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
	it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)

#define i_rl(bo, bi, n, k)                                      \
	bo[n] = (WORD32)isb_tab[byte(bi[n],0)] ^                    \
	rotl(((WORD32)isb_tab[byte(bi[(n + 3) & 3],1)]),  8) ^		\
	rotl(((WORD32)isb_tab[byte(bi[(n + 2) & 3],2)]), 16) ^		\
	rotl(((WORD32)isb_tab[byte(bi[(n + 1) & 3],3)]), 24) ^ *(k + n)

#define i_nround(bo, bi, k) \
	i_rn(bo, bi, 0, k); 	\
	i_rn(bo, bi, 1, k); 	\
	i_rn(bo, bi, 2, k); 	\
	i_rn(bo, bi, 3, k); 	\
	k -= 4

#define i_lround(bo, bi, k) \
	i_rl(bo, bi, 0, k); 	\
	i_rl(bo, bi, 1, k); 	\
	i_rl(bo, bi, 2, k); 	\
	i_rl(bo, bi, 3, k)

void aesDecrypt(AESCTX* pCtx,
				const WORD32* pInBlock,
				WORD32* pOutBlock)
{
	WORD32 b0[4], b1[4];
	WORD32* kp = pCtx->key;

	b0[0] = pInBlock[0] ^ kp[AES_KEYSIZE + 24];
	b0[1] = pInBlock[1] ^ kp[AES_KEYSIZE + 25];
	b0[2] = pInBlock[2] ^ kp[AES_KEYSIZE + 26];
	b0[3] = pInBlock[3] ^ kp[AES_KEYSIZE + 27];

	kp += AES_KEYSIZE + 20;

	i_nround(b1, b0, kp); i_nround(b0, b1, kp);
	i_nround(b1, b0, kp); i_nround(b0, b1, kp);
	i_nround(b1, b0, kp); i_nround(b0, b1, kp);
	i_nround(b1, b0, kp); i_nround(b0, b1, kp);
	i_nround(b1, b0, kp); i_nround(b0, b1, kp);
	i_nround(b1, b0, kp); i_nround(b0, b1, kp);
	i_nround(b1, b0, kp); i_lround(b0, b1, kp);

	pOutBlock[0] = b0[0];
	pOutBlock[1] = b0[1];
	pOutBlock[2] = b0[2];
	pOutBlock[3] = b0[3];
}


// public functions

WORD32 AES_GetCipherInfo(CIPHERINFOBLOCK* pInfo)
{
	WORD32 lI;
	WORD8* pSrc;
	WORD8* pDst;
	CIPHERINFOBLOCK tmpInfo;

	tmpInfo.lSizeOf = pInfo->lSizeOf;
	tmpInfo.lBlockSize = AES_BLOCKSIZE;
	tmpInfo.lKeySize = AES_KEYSIZE;
	tmpInfo.blOwnHasher = BOOL_FALSE;
	tmpInfo.lInitDataSize = AES_BLOCKSIZE;
	tmpInfo.lContextSize = sizeof(AESCTX);
	tmpInfo.bCipherIs = CIPHER_IS_BLOCKLINK;

	// copy as many bytes of the information block as possible
	pSrc = (WORD8*) &tmpInfo;
	pDst = (WORD8*) pInfo;
	for (lI = 0; lI < tmpInfo.lSizeOf; lI++)
		*pDst++ = *pSrc++;
	return CIPHER_ERROR_NOERROR;
}

WORD32 AES_SelfTest(void* pTestContext)
{
	// confirmed: this is a Gladman test vector, so it must be good

	// PLAINTEXT:    3243f6a8885a308d313198a2e0370734
	// KEY:          2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfe
	// ENCRYPT       16 byte block, 32 byte key
	// ...
	// R[14].output  1a6e6c2c662e7da6501ffb62bc9e93f3

	const WORD8 testkey[32] =
	{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
  	  0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
	  0x76, 0x2e, 0x71, 0x60, 0xf3, 0x8b, 0x4d, 0xa5,
	  0x6a, 0x78, 0x4d, 0x90, 0x45, 0x19, 0x0c, 0xfe };

	const WORD8 plaintext[16] =
	{ 0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d,
	  0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34 };

	const WORD8 cipher_must[16] =
	{ 0x1a, 0x6e, 0x6c, 0x2c, 0x66, 0x2e, 0x7d, 0xa6,
	  0x50, 0x1f, 0xfb, 0x62, 0xbc, 0x9e, 0x93, 0xf3 };

	WORD32 testbuf[4];
	AESCTX* pCtx = (AESCTX*) pTestContext;
	int nI;

	// init. the encryption
	aesSetKey(pCtx, testkey, 32, CIPHER_MODE_ENCRYPT);

	// don't assume running on x86 and getting the byte ordering automatically
	testbuf[0] = BYTES_TO_WORD32_X86(plaintext);
	testbuf[1] = BYTES_TO_WORD32_X86(plaintext + 4);
	testbuf[2] = BYTES_TO_WORD32_X86(plaintext + 8);
	testbuf[3] = BYTES_TO_WORD32_X86(plaintext + 12);

	aesEncrypt(pCtx, testbuf, testbuf);

	// check the encryption
	for (nI = 0; nI < 4; nI++)
		if (testbuf[nI] != BYTES_TO_WORD32_X86(cipher_must + (nI << 2)))
			return CIPHER_ERROR_INVALID;

	// init. the decryption
	aesSetKey(pCtx, testkey, 32, CIPHER_MODE_DECRYPT);
	aesDecrypt(pCtx, testbuf, testbuf);

	// check the decryption
	for (nI = 0; nI < 4; nI++)
		if (testbuf[nI] != BYTES_TO_WORD32_X86(plaintext + (nI << 2)))
			return CIPHER_ERROR_INVALID;

	return CIPHER_ERROR_NOERROR;
}

WORD32 AES_CreateWorkContext(
	void* pContext,
	const WORD8* pKey,
	WORD32 lKeyLen,
	WORD32 lMode,
	void* pInitData,
	Cipher_RandomGenerator GetRndBytes,
	const void* pRandGenData)
{
	AESCTX* pCtx = (AESCTX*) pContext;
	WORD8* pbInit;

	// we don't have any legacy problems here, since apparently AES (at least the
	// Gladman code transforms bytes in little endian order); thus we do the same
	// but still use our macros to do it the right way - including the IV, which
	// is also serialized in little endian format

	// do the key setup
	aesSetKey(pCtx, pKey, lKeyLen, CIPHER_GETMODE(lMode));

	pbInit = (WORD8*) pInitData;
	if (CIPHER_GETMODE(lMode) == CIPHER_MODE_ENCRYPT)
		GetRndBytes(pbInit, AES_BLOCKSIZE, pRandGenData);

	// set the CBC IV
	pCtx->cbc_iv[0] = BYTES_TO_WORD32_X86(pbInit);
	pCtx->cbc_iv[1] = BYTES_TO_WORD32_X86(pbInit + 4);
	pCtx->cbc_iv[2] = BYTES_TO_WORD32_X86(pbInit + 8);
	pCtx->cbc_iv[3] = BYTES_TO_WORD32_X86(pbInit + 12);

	return CIPHER_ERROR_NOERROR;
}

void AES_ResetWorkContext(
	void* pContext,
	WORD32 lMode,
	void* pInitData,
	Cipher_RandomGenerator GetRndBytes,
	const void* pRandGenData)
{
	AESCTX* pCtx = (AESCTX*) pContext;
	WORD8* pbInit = (WORD8*) pInitData;

	if (CIPHER_GETMODE(lMode) == CIPHER_MODE_ENCRYPT)
		GetRndBytes(pbInit, AES_BLOCKSIZE, pRandGenData);

	pCtx->cbc_iv[0] = BYTES_TO_WORD32_X86(pbInit);
	pCtx->cbc_iv[1] = BYTES_TO_WORD32_X86(pbInit + 4);
	pCtx->cbc_iv[2] = BYTES_TO_WORD32_X86(pbInit + 8);
	pCtx->cbc_iv[3] = BYTES_TO_WORD32_X86(pbInit + 12);
}

WORD32 AES_DestroyWorkContext(void* pContext)
{
	int nI;
	WORD8* pCtxBuf = (WORD8*) pContext;

	for (nI = 0; nI < sizeof(AESCTX); nI++)
		pCtxBuf[nI] = 0x00;

	return CIPHER_ERROR_NOERROR;
}

void AES_EncryptBuffer(
	void* pContext,
	const void* pSource,
	void* pTarget,
	WORD32 lNumOfBytes)
{
	WORD32 lNumOfBlocks;
	WORD32 blk[4];
	WORD8* pbIn = (WORD8*) pSource;
	WORD8* pbOut = (WORD8*) pTarget;
	AESCTX* pCtx = (AESCTX*) pContext;

	lNumOfBlocks = lNumOfBytes / AES_BLOCKSIZE;

	while (lNumOfBlocks--)
	{
		blk[0] = BYTES_TO_WORD32_X86(pbIn);
		blk[1] = BYTES_TO_WORD32_X86(pbIn + 4);
		blk[2] = BYTES_TO_WORD32_X86(pbIn + 8);
		blk[3] = BYTES_TO_WORD32_X86(pbIn + 12);

		blk[0] ^= pCtx->cbc_iv[0];
		blk[1] ^= pCtx->cbc_iv[1];
		blk[2] ^= pCtx->cbc_iv[2];
		blk[3] ^= pCtx->cbc_iv[3];

		aesEncrypt(pCtx, blk, blk);

		// set the new IV
		pCtx->cbc_iv[0] = blk[0];
		pCtx->cbc_iv[1] = blk[1];
		pCtx->cbc_iv[2] = blk[2];
		pCtx->cbc_iv[3] = blk[3];

		WORD32_TO_BYTES_X86(blk[0], pbOut)
		WORD32_TO_BYTES_X86(blk[1], pbOut + 4)
		WORD32_TO_BYTES_X86(blk[2], pbOut + 8)
		WORD32_TO_BYTES_X86(blk[3], pbOut + 12)

		pbIn  += AES_BLOCKSIZE;
		pbOut += AES_BLOCKSIZE;
	}
}

void AES_DecryptBuffer(
	void* pContext,
	const void* pSource,
	void*  pTarget,
	WORD32 lNumOfBytes,
	const void* pPreviousBlock)
{
	WORD32 lNumOfBlocks;
	WORD32 blk[4];
	WORD8* pbIn = (WORD8*) pSource;
	WORD8* pbOut = (WORD8*) pTarget;
	WORD8* pbPrev = (WORD8*) pPreviousBlock;
	WORD32 save_cbc_iv[4];
	AESCTX* pCtx = (AESCTX*) pContext;

	lNumOfBlocks = lNumOfBytes / AES_BLOCKSIZE;

	// load a new IV, if necessary

	if (pPreviousBlock != CIPHER_NULL)
	{
		pCtx->cbc_iv[0] = BYTES_TO_WORD32_X86(pbPrev);
		pCtx->cbc_iv[1] = BYTES_TO_WORD32_X86(pbPrev + 4);
		pCtx->cbc_iv[2] = BYTES_TO_WORD32_X86(pbPrev + 8);
		pCtx->cbc_iv[3] = BYTES_TO_WORD32_X86(pbPrev + 12);
	}

	while (lNumOfBlocks--)
	{
		blk[0] = BYTES_TO_WORD32_X86(pbIn);
		blk[1] = BYTES_TO_WORD32_X86(pbIn + 4);
		blk[2] = BYTES_TO_WORD32_X86(pbIn + 8);
		blk[3] = BYTES_TO_WORD32_X86(pbIn + 12);

		// save the current IV
		save_cbc_iv[0] = blk[0];
		save_cbc_iv[1] = blk[1];
		save_cbc_iv[2] = blk[2];
		save_cbc_iv[3] = blk[3];

		// now decrypt the block
		aesDecrypt(pCtx, blk, blk);

		// dechain the block
		blk[0] ^= pCtx->cbc_iv[0];
		blk[1] ^= pCtx->cbc_iv[1];
		blk[2] ^= pCtx->cbc_iv[2];
		blk[3] ^= pCtx->cbc_iv[3];

		WORD32_TO_BYTES_X86(blk[0], pbOut)
		WORD32_TO_BYTES_X86(blk[1], pbOut + 4)
		WORD32_TO_BYTES_X86(blk[2], pbOut + 8)
		WORD32_TO_BYTES_X86(blk[3], pbOut + 12)

		// set the new IV
		pCtx->cbc_iv[0] = save_cbc_iv[0];
		pCtx->cbc_iv[1] = save_cbc_iv[1];
		pCtx->cbc_iv[2] = save_cbc_iv[2];
		pCtx->cbc_iv[3] = save_cbc_iv[3];

		pbIn  += AES_BLOCKSIZE;
		pbOut += AES_BLOCKSIZE;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -