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

📄 twofish.c

📁 一个加密库代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	WORD32 lX2 = pBlock[0] ^ pCtx->subKeys[OUTPUTWHITEN];
	WORD32 lX3 = pBlock[1] ^ pCtx->subKeys[OUTPUTWHITEN + 1];
	WORD32 lX0 = pBlock[2] ^ pCtx->subKeys[OUTPUTWHITEN + 2];
	WORD32 lX1 = pBlock[3] ^ pCtx->subKeys[OUTPUTWHITEN + 3];

	// decryption loop (unrolled)
	WORD32 lT0;
	WORD32 lT1;
	dec_loop(lX0, lX1, lX2, lX3, 31)
	dec_loop(lX2, lX3, lX0, lX1, 29)
	dec_loop(lX0, lX1, lX2, lX3, 27)
	dec_loop(lX2, lX3, lX0, lX1, 25)
	dec_loop(lX0, lX1, lX2, lX3, 23)
	dec_loop(lX2, lX3, lX0, lX1, 21)
	dec_loop(lX0, lX1, lX2, lX3, 19)
	dec_loop(lX2, lX3, lX0, lX1, 17)
	dec_loop(lX0, lX1, lX2, lX3, 15)
	dec_loop(lX2, lX3, lX0, lX1, 13)
	dec_loop(lX0, lX1, lX2, lX3, 11)
	dec_loop(lX2, lX3, lX0, lX1, 9)
	dec_loop(lX0, lX1, lX2, lX3, 7)
	dec_loop(lX2, lX3, lX0, lX1, 5)
	dec_loop(lX0, lX1, lX2, lX3, 3)
	dec_loop(lX2, lX3, lX0, lX1, 1)

	// final rewhitening and back copy
	pBlock[0] = lX0 ^ pCtx->subKeys[INPUTWHITEN];
	pBlock[1] = lX1 ^ pCtx->subKeys[INPUTWHITEN + 1];
	pBlock[2] = lX2 ^ pCtx->subKeys[INPUTWHITEN + 2];
	pBlock[3] = lX3 ^ pCtx->subKeys[INPUTWHITEN + 3];
}



// interface implementation

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

	// prepare the information context
	tempinfo.lSizeOf = pInfo->lSizeOf;
	tempinfo.lBlockSize = TWOFISH_BLOCKSIZE;
	tempinfo.lKeySize = TWOFISH_KEYSIZE;
	tempinfo.blOwnHasher = BOOL_FALSE;
	tempinfo.lInitDataSize = TWOFISH_BLOCKSIZE;
	tempinfo.lContextSize = sizeof(TWOFISHCTX);
	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 Twofish_SelfTest
(void* pCtx)
{
	// encrypt, decrypt and check an official test vector

	WORD8 testkey[32] =
	{
		0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
		0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
		0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
		0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
	};

	WORD8 plaintext[16] = {
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	};

	WORD8 cipher_must[16] =
	{
		0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8,
		0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20
	};

	WORD8 ciphertext[16];
	WORD8 finaltext[16];
	WORD8 initdata[16];
	WORD32 blk[4];
	int nI;

	for (nI = 0; nI < 16; nI++) initdata[nI] = 0;

	// create a context (used for en- and decryption,
	// because CBC isn't used and we init. in decryption
	// mode we don't need a random number generator)
	Twofish_CreateWorkContext(pCtx,
		testkey,
		32,
		CIPHER_MODE_DECRYPT,
		initdata,
		0,
		0);

	// (just to be sure)
	for (nI = 0; nI < 16; nI++)
		ciphertext[nI] = finaltext[nI] = 0xfe;

	// test the encryption

	blk[0] = BYTES_TO_WORD32_X86(plaintext);
	blk[1] = BYTES_TO_WORD32_X86(plaintext + 4);
	blk[2] = BYTES_TO_WORD32_X86(plaintext + 8);
	blk[3] = BYTES_TO_WORD32_X86(plaintext + 12);

	twofish_blockEncrypt((TWOFISHCTX*)pCtx, blk);

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

	for (nI = 0; nI < 16; nI++)
		if (ciphertext[nI] != cipher_must[nI])
			return CIPHER_ERROR_INVALID;

	// test the decryption
	twofish_blockDecrypt((TWOFISHCTX*)pCtx, blk);

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

	for (nI = 0; nI < 16; nI++)
		if (plaintext[nI] != finaltext[nI])
			return CIPHER_ERROR_INVALID;

	// tests passed
	return CIPHER_ERROR_NOERROR;
}



WORD32 Twofish_CreateWorkContext
(void* pContext,
 const WORD8* pKey,
 WORD32 lKeyLen,
 WORD32 lMode,
 void* pInitData,
 Cipher_RandomGenerator GetRndBytes,
 const void* pRndGenData)
{
	WORD8* pbInit;

	int nI, nJ, nQ;

	WORD32 lA;
	WORD32 lB;

	TWOFISHCTX* pCtx = (TWOFISHCTX*) pContext;

	WORD32 lK0, lK1, lK2, lK3;
	WORD32 lB0, lB1, lB2, lB3;

	WORD32 key32[TWOFISH_KEYSIZE / 4];
	WORD32 sboxKeys[TWOFISH_KEYSIZE / 8];

	// even and odd key dwords
	WORD32 k32e[TWOFISH_KEYSIZE / 8];
	WORD32 k32o[TWOFISH_KEYSIZE / 8];

	// copy the key material, depends on a fixed key size(!)
	// (direct copy is possible here)
	
	for (nI = 0; nI < (TWOFISH_KEYSIZE / 4); nI++, pKey += 4)
		key32[nI] = BYTES_TO_WORD32_X86(pKey);

	// calculate the subkeys, pass #1
	nJ = (TWOFISH_KEYSIZE / 8) - 1;
	for (nI = 0; nI < (TWOFISH_KEYSIZE / 8); nI++)
	{
		// split into even/odd key dwords
		k32e[nI] = key32[nI << 1];
		k32o[nI] = key32[(nI << 1) + 1];

		// compute S-box keys using (12,8) Reed-Solomon code over GF(256),
		// in reversed order
		sboxKeys[nJ--] = RS_MDS_Encode(k32e[nI], k32o[nI]);
	}

	// compute round subkeys for PHT
	nQ = 0;
	for (nI = 0; nI < (TOTALSUBKEYS / 2); nI++, nQ += SK_STEP)
	{
		lA = f32(nQ,           k32e); // lA uses even key dwords
		lB = f32(nQ + SK_BUMP, k32o); // lB uses odd key dwords
		lB = ROL(lB, 8);

		// combine with a PHT
		pCtx->subKeys[nI << 1] = lA + lB;
		lB = lA + (lB << 1);
		pCtx->subKeys[(nI << 1) + 1] = ROL(lB, SK_ROTL);
	}

	// fully expand the table (subkeys calc., pass #2)
	lK0 = sboxKeys[0];
	lK1 = sboxKeys[1];
	lK2 = sboxKeys[2];
	lK3 = sboxKeys[3];
	for (nI = 0; nI < 256; nI++)
	{
		lB0 = p8(04)[nI] ^ b0(lK3);
		lB1 = p8(14)[nI] ^ b1(lK3);
		lB2 = p8(24)[nI] ^ b2(lK3);
		lB3 = p8(34)[nI] ^ b3(lK3);

		lB0 = p8(03)[lB0] ^ b0(lK2);
		lB1 = p8(13)[lB1] ^ b1(lK2);
		lB2 = p8(23)[lB2] ^ b2(lK2);
		lB3 = p8(33)[lB3] ^ b3(lK2);

		pCtx->sbox[        (nI << 1)] = mds[0][p8(01)[p8(02)[lB0] ^ b0(lK1)] ^ b0(lK0)];
		pCtx->sbox[    1 + (nI << 1)] = mds[1][p8(11)[p8(12)[lB1] ^ b1(lK1)] ^ b1(lK0)];
		pCtx->sbox[0x200 + (nI << 1)] = mds[2][p8(21)[p8(22)[lB2] ^ b2(lK1)] ^ b2(lK0)];
		pCtx->sbox[0x201 + (nI << 1)] = mds[3][p8(31)[p8(32)[lB3] ^ b3(lK1)] ^ b3(lK0)];
	}

	// clear all the local buffers now
	for (nI = 0; nI < (TWOFISH_KEYSIZE / 4); nI++)
		key32[nI] = 0;
	for (nI = 0; nI < (TWOFISH_KEYSIZE / 8); nI++)
	{
		k32e[nI] = k32o[nI] = 0;
		sboxKeys[nI] = 0;
	}

	// create and save the CBC iv or get it for decryption
	pbInit = (WORD8*) pInitData;
	if (CIPHER_GETMODE(lMode) == CIPHER_MODE_ENCRYPT)
	{
		GetRndBytes(pbInit, TWOFISH_BLOCKSIZE, pRndGenData);
	}

	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 Twofish_ResetWorkContext
(void* pContext,
 WORD32 lMode,
 void* pInitData,
 Cipher_RandomGenerator GetRndBytes,
 const void* pRndGenData)
{
	WORD8* pbInit;
	TWOFISHCTX* pCtx = (TWOFISHCTX*) pContext;

	// create and save the CBC iv or get it for decryption
	pbInit = (WORD8*) pInitData;
	if (CIPHER_GETMODE(lMode) == CIPHER_MODE_ENCRYPT)
	{
		GetRndBytes(pbInit, 16, pRndGenData);
	}

	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 Twofish_DestroyWorkContext
(void* pContext)
{
	WORD8* pDel = (WORD8*) pContext;
	int nI;

	// just clear the context
	for (nI = 0; nI < sizeof(TWOFISHCTX); nI++)	*pDel++ = 0;

	return CIPHER_ERROR_NOERROR;
}




void Twofish_EncryptBuffer
(void* pContext,
 const void* pSource,
 void* pTarget,
 WORD32 lNumOfBytes)
{
	WORD32 lI, lJ;
	WORD32 blk[4];
	WORD8* pbIn = (WORD8*) pSource;
	WORD8* pbOut = (WORD8*) pTarget;
	TWOFISHCTX* pCtx = (TWOFISHCTX*) pContext;

	// work through all blocks
	for (lI = 0; lI < (lNumOfBytes / TWOFISH_BLOCKSIZE); lI++)
	{
		// get and and chain the actual block
		blk[0] = BYTES_TO_WORD32_X86(pbIn     ) ^ pCtx->cbc_iv[0];
		blk[1] = BYTES_TO_WORD32_X86(pbIn +  4) ^ pCtx->cbc_iv[1];
		blk[2] = BYTES_TO_WORD32_X86(pbIn +  8) ^ pCtx->cbc_iv[2];
		blk[3] = BYTES_TO_WORD32_X86(pbIn + 12) ^ pCtx->cbc_iv[3];

		// encrypt the block
		twofish_blockEncrypt(pCtx, blk);

		// set the new cbc iv
		for (lJ = 0; lJ < 4; lJ++)
			pCtx->cbc_iv[lJ] = blk[lJ];

		// copy the block back
		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)

		// next block
		pbIn += TWOFISH_BLOCKSIZE;
		pbOut += TWOFISH_BLOCKSIZE;
	}
}


void Twofish_DecryptBuffer
(void* pContext,
 const void* pSource,
 void* pTarget,
 WORD32 lNumOfBytes,
 const void* pPreviousBlock)
{
	WORD32 lI, lJ;
	WORD8* pbIn = (WORD8*) pSource;
	WORD8* pbOut = (WORD8*) pTarget;
	WORD32 blk[4];
	WORD32 save_iv[4];
	TWOFISHCTX* pCtx = (TWOFISHCTX*) pContext;

	// load a new CBC IV, if necessary
	if (pPreviousBlock != CIPHER_NULL)
	{
		for (lI = 0; lI < 4; lI++)
			pCtx->cbc_iv[lI] = ((WORD32*)pPreviousBlock)[lI];
	}

	// work through all blocks
	for (lI = 0; lI < (lNumOfBytes / TWOFISH_BLOCKSIZE); lI++)
	{
		// get and save the block
		save_iv[0] = blk[0] = BYTES_TO_WORD32_X86(pbIn);
		save_iv[1] = blk[1] = BYTES_TO_WORD32_X86(pbIn + 4);
		save_iv[2] = blk[2] = BYTES_TO_WORD32_X86(pbIn + 8);
		save_iv[3] = blk[3] = BYTES_TO_WORD32_X86(pbIn + 12);

		// decrypt the block
		twofish_blockDecrypt(pCtx, blk);

		// unchain the block
		for (lJ = 0; lJ < 4; lJ++)
		{
			blk[lJ] ^= pCtx->cbc_iv[lJ];
		}

		// save it and set the new IV
		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)

		for (lJ = 0; lJ < 4; lJ++)
		{
			pCtx->cbc_iv[lJ] = save_iv[lJ];
		}

		// next block
		pbIn += TWOFISH_BLOCKSIZE;
		pbOut += TWOFISH_BLOCKSIZE;
	}
}

⌨️ 快捷键说明

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