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

📄 tripledes.c

📁 一个加密库代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright 1997-2005 Markus Hahn 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include "TripleDES.h"


// internal constants
#define KEYSETUP_ENCRYPTION     0
#define KEYSETUP_DECRYPTION     1



// prototypes of the support routines
void _expandPureDESKey(const WORD8*, WORD8*);
void _keysetup(WORD8*, int, WORD32*);
void _processBlock(WORD8*, WORD8*, WORD32*);
void _blkcpy(WORD8*, WORD8*);
void _blkcpy_r(WORD8*, WORD8*);


WORD32 TripleDES_GetCipherInfo
(CIPHERINFOBLOCK* pInfo) 
{
	WORD8* pSrc;
	WORD8* pDst;
	CIPHERINFOBLOCK tempinfo;
	WORD32 lI;

	// prepare the information context
	tempinfo.lSizeOf = pInfo->lSizeOf;
	tempinfo.lBlockSize = TRIPLEDES_BLOCKSIZE;
	tempinfo.lKeySize = TRIPLEDES_KEYSIZE; 
	tempinfo.blOwnHasher = BOOL_FALSE;
	tempinfo.lInitDataSize = TRIPLEDES_BLOCKSIZE;
	tempinfo.lContextSize = sizeof(TRIPLEDESCTX);
	tempinfo.bCipherIs = CIPHER_IS_BLOCKLINK;

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

	return CIPHER_ERROR_NOERROR;
}



WORD32 TripleDES_SelfTest 
(void* pTestContext) 
{
	// test the cipher for correct encrypting and decrypting
	// (we test only a single DES stage with the original validation sets)

	static WORD8 refkey[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
	static WORD8 plainBlock[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 };
	static WORD8 cipherBlock[8] = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d };
	WORD8 workBlock[8];
	WORD32 k[32];
	int nI;

	// encrypt the test block
	_keysetup(refkey, KEYSETUP_ENCRYPTION, k);
	_processBlock(plainBlock, workBlock, k);

	// equal ciphertexts?
	for (nI = 0; nI < 8; nI++)
		if (workBlock[nI] != cipherBlock[nI]) return CIPHER_ERROR_INVALID;

	// decrypt the test block
	_keysetup(refkey, KEYSETUP_DECRYPTION, k);
	_processBlock(workBlock, workBlock, k);

	// equal plaintexts?
	for (nI = 0; nI < 8; nI++) 
	{
		if (plainBlock[nI] != workBlock[nI]) return CIPHER_ERROR_INVALID;
	}
	return CIPHER_ERROR_NOERROR;
}



WORD32 TripleDES_CreateWorkContext
(void* pContext,
 const WORD8* pKey,
 WORD32 lKeyLen,
 WORD32 lMode,
 void* pInitData,
 Cipher_RandomGenerator GetRndBytes,
 const void* pRndGenData) 
{
	int nI;
	WORD8* pbInit;
	WORD8 deskey1[8];
	WORD8 deskey2[8];
	WORD8 deskey3[8];
	TRIPLEDESCTX* pCtx;

	pCtx = (TRIPLEDESCTX*) pContext;
	pCtx->blLegacy = (CIPHER_GETFLAGS(lMode) & CIPHER_MODE_FLAG_LEGACY) ? BOOL_TRUE : BOOL_FALSE;

	// create three DES keys from the "pure" key, ignoring the parity
	_expandPureDESKey(pKey, deskey1);
	_expandPureDESKey(pKey + 7, deskey2);
	_expandPureDESKey(pKey + 14, deskey3);

	// run the key setups
	if (CIPHER_GETMODE(lMode) == CIPHER_MODE_ENCRYPT) 
	{
		_keysetup(deskey1, KEYSETUP_ENCRYPTION, pCtx->k1);
		_keysetup(deskey2, KEYSETUP_DECRYPTION, pCtx->k2);
		_keysetup(deskey3, KEYSETUP_ENCRYPTION, pCtx->k3);
	}
	else 
	{
		_keysetup(deskey1, KEYSETUP_DECRYPTION, pCtx->k1);
		_keysetup(deskey2, KEYSETUP_ENCRYPTION, pCtx->k2);
		_keysetup(deskey3, KEYSETUP_DECRYPTION, pCtx->k3);
	}

	// delete the DES keys
	for (nI = 0; nI < 8; nI++) 
	{
		deskey1[nI] = 0;
		deskey2[nI] = 0;
		deskey3[nI] = 0;
	}

	// for encryption create a CBC IV
	pbInit = (WORD8*) pInitData;
	if (lMode == CIPHER_MODE_ENCRYPT)
	{
		GetRndBytes(pbInit, TRIPLEDES_BLOCKSIZE, pRndGenData);
	}

	if (pCtx->blLegacy)
	{
		// the old code stored everything completely reversed
		_blkcpy_r(pbInit, pCtx->cbciv);
	}
	else
	{
		_blkcpy(pbInit, pCtx->cbciv);
	}

	// FIXME: weak keys in triple-DES?
	return CIPHER_ERROR_NOERROR;
}


void TripleDES_ResetWorkContext
(void* pContext,
 WORD32 lMode,
 void* pInitData,
 Cipher_RandomGenerator GetRndBytes,
 const void* pRndGenData) 
{
	TRIPLEDESCTX* pCtx = (TRIPLEDESCTX*) pContext;

	// just reset the CBC IV 
	WORD8* pbInit = (WORD8*) pInitData;
	if (CIPHER_GETMODE(lMode) == CIPHER_MODE_ENCRYPT)
		GetRndBytes(pbInit, TRIPLEDES_BLOCKSIZE, pRndGenData);

	if (pCtx->blLegacy)
	{
		_blkcpy_r(pbInit, pCtx->cbciv);
	}
	else
	{
		_blkcpy(pbInit, pCtx->cbciv);
	}
}



WORD32 TripleDES_DestroyWorkContext
(void* pContext) 
{
	// clear the context
	int nI;
	WORD8* pClearIt = (WORD8*) pContext;
	for (nI = 0; nI < sizeof(TRIPLEDESCTX); nI++) 
		pClearIt[nI] = 0x00;
	return CIPHER_ERROR_NOERROR;
}



void TripleDES_EncryptBuffer
(void* pContext,
 const void* pSource,
 void* pTarget,
 WORD32 lNumOfBytes) 
{
	WORD32 lI, lJ;
	WORD8* pbIn = (WORD8*) pSource;
	WORD8* pbOut = (WORD8*) pTarget;
	TRIPLEDESCTX* pCtx = (TRIPLEDESCTX*) pContext;

	lNumOfBytes &= ~(TRIPLEDES_BLOCKSIZE - 1);

	// work through all blocks... 
	for (lI = 0; lI < lNumOfBytes; lI += TRIPLEDES_BLOCKSIZE) 
	{
		// copy and chain the recent block 
		if (pCtx->blLegacy)
		{
			// (we have to bring back the CBC IV into 64bit little endian)
			for (lJ = 0; lJ < TRIPLEDES_BLOCKSIZE; lJ++)
				pbOut[lI + lJ] = pbIn[lI + lJ] ^ pCtx->cbciv[(TRIPLEDES_BLOCKSIZE - 1) - lJ];
		}
		else
		{
			for (lJ = 0; lJ < TRIPLEDES_BLOCKSIZE; lJ++)
				pbOut[lI + lJ] = pbIn[lI + lJ] ^ pCtx->cbciv[lJ];
		}

		// encrypt the block
		_processBlock(&pbOut[lI], &pbOut[lI], pCtx->k1);
		_processBlock(&pbOut[lI], &pbOut[lI], pCtx->k2);
		_processBlock(&pbOut[lI], &pbOut[lI], pCtx->k3);

		// set the new CBC IV (same as above)
		if (pCtx->blLegacy)
		{
			_blkcpy_r(&pbOut[lI], pCtx->cbciv);
		}
		else
		{
			_blkcpy(&pbOut[lI], pCtx->cbciv);
		}
	}
}



void TripleDES_DecryptBuffer
(void* pContext,
 const void* pSource,
 void* pTarget, 
 WORD32 lNumOfBytes,
 const void* pPreviousBlock) 
{
	WORD32 lI, lJ;
	WORD8 saveiv[TRIPLEDES_BLOCKSIZE];
	WORD8* pbIn = (WORD8*) pSource;
	WORD8* pbOut = (WORD8*) pTarget;
	WORD8* pbPrev;
	TRIPLEDESCTX* pCtx = (TRIPLEDESCTX*) pContext;

	lNumOfBytes &= ~(TRIPLEDES_BLOCKSIZE - 1);

	// load a new CBC IV, if necessary 
	if (pPreviousBlock != CIPHER_NULL)  
	{
		pbPrev = (WORD8*)pPreviousBlock;
		if (pCtx->blLegacy)
		{
			_blkcpy_r(pbPrev, pCtx->cbciv);
		}
		else
		{
			_blkcpy(pbPrev, pCtx->cbciv);
		}
	}

	// work through all blocks... 
	for (lI = 0; lI < lNumOfBytes; lI += 8) 
	{
		// save the recent CBC IV (don't care for the layout right now)
		_blkcpy(&pbIn[lI], saveiv);

		// decrypt the block 
		_processBlock(&pbIn [lI], &pbOut[lI], pCtx->k3);
		_processBlock(&pbOut[lI], &pbOut[lI], pCtx->k2);
		_processBlock(&pbOut[lI], &pbOut[lI], pCtx->k1);

		// dechain the recent block
		if (pCtx->blLegacy)
		{
			// same as above: bring back the IV into the old format
			for (lJ = 0; lJ < TRIPLEDES_BLOCKSIZE; lJ++)
				pbOut[lI + lJ] ^= pCtx->cbciv[(TRIPLEDES_BLOCKSIZE - 1) - lJ];
		}
		else
		{
			for (lJ = 0; lJ < TRIPLEDES_BLOCKSIZE; lJ++)
				pbOut[lI + lJ] ^= pCtx->cbciv[lJ];
		}

		// set the new CBC IV (normalized)
		if (pCtx->blLegacy)
		{
			_blkcpy_r(saveiv, pCtx->cbciv);
		}
		else
		{
			_blkcpy(saveiv, pCtx->cbciv);
		}
	}
}

//////////////////////////////////////////////////////////////////////////////


// support routines implementation...


// constant stuff...

static WORD8 pc1[56] = 
{
	56, 48, 40, 32, 24, 16,  8,  0, 57, 49, 41, 33, 25, 17,
	9,  1, 58, 50, 42, 34, 26, 18, 10,  2, 59, 51, 43, 35,
	62, 54, 46, 38, 30, 22, 14,  6, 61, 53, 45, 37, 29, 21,
	13,  5, 60, 52, 44, 36, 28, 20, 12,  4, 27, 19, 11,  3 
};

static WORD8 totrot[16] = 
{
	1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 
};

static WORD8 pc2[48] = 
{
	13, 16, 10, 23,  0,  4,  2, 27, 14,  5, 20,  9,
	22, 18, 11,  3, 25,  7, 15,  6, 26, 19, 12,  1,
	40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
	43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 
};


static WORD16 bytebit[8] = 
{
	0200, 0100, 040, 020, 010, 04, 02, 01 
};

static WORD32 bigbyte[24] = 
{
	0x800000L,  0x400000L,  0x200000L,  0x100000L,
	0x80000L,   0x40000L,   0x20000L,   0x10000L,
	0x8000L,    0x4000L,    0x2000L,    0x1000L,
	0x800L,     0x400L,     0x200L,     0x100L,
	0x80L,      0x40L,      0x20L,      0x10L,
	0x8L,       0x4L,       0x2L,       0x1L    
};

static unsigned long SP1[64] = 
{
	0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
	0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
	0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
	0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
	0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
	0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
	0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
	0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
	0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
	0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
	0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
	0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
	0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
	0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
	0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,

⌨️ 快捷键说明

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