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

📄 cast256.cpp

📁 采用CAST-256位加密的Back Orifice 2000(BO2000)插件
💻 CPP
字号:
/*	CAST-256 Block Cypher Implementation
	Copyright (C) 1999, Daniel Roethlisberger

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

	The author of this program may be contacted at admin@roe.ch.
*/

#include "cast256.h"
#include "cast256s.h"

// ========================================================================
//  Support defines
// ------------------------------------------------------------------------
#define DWORD unsigned long

// Rotate Left operation
#define ROTL(x,n)	(((x) << (n)) | ((x) >> (32 - (n))))

// Extract the nth BYTE from a DWORD
#define EXT_A(x)	((int)((x >> 24) & 0xFF))
#define EXT_B(x)	((int)((x >> 16) & 0xFF))
#define EXT_C(x)	((int)((x >>  8) & 0xFF))
#define EXT_D(x)	((int)((x)       & 0xFF))

// Five least significant bits
#define FIVE_LSB(x) ((x) & (DWORD)0x0000001F)

// Fill in the rotation subkey from KAPPA
#define Kr_FILL(i,k) \
	Kr[i].A = FIVE_LSB(k.A); \
	Kr[i].B = FIVE_LSB(k.C); \
	Kr[i].C = FIVE_LSB(k.E); \
	Kr[i].D = FIVE_LSB(k.G)

// Fill in the mask subkey from KAPPA
#define Km_FILL(i,k) \
	Km[i].A = k.H; \
	Km[i].B = k.F; \
	Km[i].C = k.D; \
	Km[i].D = k.B

// ========================================================================
//  The global rotation and mask round subkey generation tables
// ------------------------------------------------------------------------
KAPPA g_Tr[24];
KAPPA g_Tm[24];

// ========================================================================
//  The F-Functions
// ------------------------------------------------------------------------
DWORD __inline f1(DWORD D, DWORD Kri, DWORD Kmi)
{
	DWORD I = ROTL((Kmi + D), Kri);
	return ((S1[EXT_A(I)] ^ S2[EXT_B(I)]) - S3[EXT_C(I)]) + S4[EXT_D(I)];
}
DWORD __inline f2(DWORD D, DWORD Kri, DWORD Kmi)
{
	DWORD I = ROTL((Kmi ^ D), Kri);
	return ((S1[EXT_A(I)] - S2[EXT_B(I)]) + S3[EXT_C(I)]) ^ S4[EXT_D(I)];
}
DWORD __inline f3(DWORD D, DWORD Kri, DWORD Kmi)
{
	DWORD I = ROTL((Kmi - D), Kri);
	return ((S1[EXT_A(I)] + S2[EXT_B(I)]) ^ S3[EXT_C(I)]) - S4[EXT_D(I)];
}

// ========================================================================
//  The Quad-Round and Reverse Quad Round
// ------------------------------------------------------------------------
BETA __inline Q(int round, BETA data, BETA* Kr, BETA* Km)
{

	data.C = data.C ^ f1(data.D, Kr[round].A, Km[round].A);
	data.B = data.B ^ f2(data.C, Kr[round].B, Km[round].B);
	data.A = data.A ^ f3(data.B, Kr[round].C, Km[round].C);
	data.D = data.D ^ f1(data.A, Kr[round].D, Km[round].D);

	return data;
}
BETA __inline QBAR(int round, BETA data, BETA* Kr, BETA* Km)
{
	data.D = data.D ^ f1(data.A, Kr[round].D, Km[round].D);
	data.A = data.A ^ f3(data.B, Kr[round].C, Km[round].C);
	data.B = data.B ^ f2(data.C, Kr[round].B, Km[round].B);
	data.C = data.C ^ f1(data.D, Kr[round].A, Km[round].A);

	return data;
}

// ========================================================================
//  The Forward Octave
// ------------------------------------------------------------------------
KAPPA __inline W(int round, KAPPA data, KAPPA* Tr, KAPPA* Tm)
{
	data.G = data.G ^ f1(data.H, Tr[round].A, Tm[round].A);
	data.F = data.F ^ f2(data.G, Tr[round].B, Tm[round].B);
	data.E = data.E ^ f3(data.F, Tr[round].C, Tm[round].C);
	data.D = data.D ^ f1(data.E, Tr[round].D, Tm[round].D);
	data.C = data.C ^ f2(data.D, Tr[round].E, Tm[round].E);
	data.B = data.B ^ f3(data.C, Tr[round].F, Tm[round].F);
	data.A = data.A ^ f1(data.B, Tr[round].G, Tm[round].G);
	data.H = data.H ^ f2(data.A, Tr[round].H, Tm[round].H);
	
	return data;
}

// ========================================================================
//  Encrypt a 128bit block
// ------------------------------------------------------------------------
void CAST256Encrypt(BETA *Kr, BETA *Km, BETA *pData)
{
	for(int i = 0; i < 6; i++)
		*pData = Q(i, *pData, Kr, Km);
	for(i = 6; i < 12; i++)
		*pData = QBAR(i, *pData, Kr, Km);
}

// ========================================================================
//  Decrypt a 128bit block
// ------------------------------------------------------------------------
void CAST256Decrypt(BETA *Kr, BETA *Km, BETA *pData)
{
	for(int i = 11; i >= 6; i--)
		*pData = Q(i, *pData, Kr, Km);
	for(i = 5; i >= 0; i--)
		*pData = QBAR(i, *pData, Kr, Km);
}

// ========================================================================
//  Initialize the mask and rotation round subkey sets from a given user key
// ------------------------------------------------------------------------
void CAST256KeyInit(BETA *Kr, BETA *Km, KAPPA userKey)
{
	for(int i = 0; i < 12; i++)
	{
		userKey = W(2*i, userKey, g_Tr, g_Tm);
		userKey = W(2*i+1, userKey, g_Tr, g_Tm);
		Kr_FILL(i, userKey);
		Km_FILL(i, userKey);
	}
}

// ========================================================================
//  Initialize the tables used for key initialization / expansion
// ------------------------------------------------------------------------
void CAST256TableInit(void)
{
	DWORD Cm = 0x5A827999;
	DWORD Mm = 0x6ED9EBA1;
	DWORD Cr = 19;
	DWORD Mr = 17;
	for(int i = 0; i < 24; i++)
	{
		g_Tm[i].A = Cm;
		Cm += Mm;
		g_Tm[i].B = Cm;
		Cm += Mm;
		g_Tm[i].C = Cm;
		Cm += Mm;
		g_Tm[i].D = Cm;
		Cm += Mm;
		g_Tm[i].E = Cm;
		Cm += Mm;
		g_Tm[i].F = Cm;
		Cm += Mm;
		g_Tm[i].G = Cm;
		Cm += Mm;
		g_Tm[i].H = Cm;
		Cm += Mm;
		g_Tr[i].A = Cr;
		Cr = FIVE_LSB(Cr + Mr);
		g_Tr[i].B = Cr;
		Cr = FIVE_LSB(Cr + Mr);
		g_Tr[i].C = Cr;
		Cr = FIVE_LSB(Cr + Mr);
		g_Tr[i].D = Cr;
		Cr = FIVE_LSB(Cr + Mr);
		g_Tr[i].E = Cr;
		Cr = FIVE_LSB(Cr + Mr);
		g_Tr[i].F = Cr;
		Cr = FIVE_LSB(Cr + Mr);
		g_Tr[i].G = Cr;
		Cr = FIVE_LSB(Cr + Mr);
		g_Tr[i].H = Cr;
		Cr = FIVE_LSB(Cr + Mr);
	}
}

// ========================================================================
//  CAST-256 Test Code
// ------------------------------------------------------------------------
/*
#include <stdio.h>
#include <string.h>
#include <conio.h>

void main(void)
{
	printf("CAST-256 Block Cypher Implementation\nCopyright (C) 1999, Daniel Roethlisberger <admin@roe.ch>\n\nThis program is free software under the GNU license.\nLet me know if you use it.\n\n");

	BETA Kr[CAST_ROUNDS];
	BETA Km[CAST_ROUNDS];

	// Simple encryption/decryption test

	printf("Block Encryption/Decryption Test: ");
	
	KAPPA uKey = {0x01234567, 0x89ABCDEF, 0x01234567, 0x89ABCDEF, 0x01234567, 0x89ABCDEF, 0x01234567, 0x89ABCDEF};
	BETA Plain = {0xDEAFDEAF, 0xDEAFDEAF, 0xDEAFDEAF, 0xDEAFDEAF};
	BETA Cypher = {0xDEAFDEAF, 0xDEAFDEAF, 0xDEAFDEAF, 0xDEAFDEAF};

	// Initialize tables and keys
	CAST256TableInit();
	CAST256KeyInit(Kr, Km, uKey);

	// Encrypt and decrypt Cypher
	CAST256Encrypt(Kr, Km, &Cypher);
	CAST256Decrypt(Kr, Km, &Cypher);

	// Check result. Cypher must be equal to Plain
	if(!memcmp(&Plain, &Cypher, 16))
		printf("PASSED\n");
	else
		printf("FAILED\n");


	// RFC2612's defined reference vector test

	printf("RFC 2612 Reference Vector Test:   ");

	// Defined user key
	uKey.A = 0x2342bb9e;
	uKey.B = 0xfa38542c;
	uKey.C = 0xbed0ac83;
	uKey.D = 0x940ac298;
	uKey.E = 0x8d7c47ce;
	uKey.F = 0x26490846;
	uKey.G = 0x1cc1b513;
	uKey.H = 0x7ae6b604;

	// Defined plaintext
	Plain.A = 0x00000000;
	Plain.B = 0x00000000;
	Plain.C = 0x00000000;
	Plain.D = 0x00000000;

	// Defined corresponding cyphertext
	Cypher.A = 0x4f6a2038;
	Cypher.B = 0x286897b9;
	Cypher.C = 0xc9870136;
	Cypher.D = 0x553317fa;

	// Initialize tables and keys
	CAST256TableInit();
	CAST256KeyInit(Kr, Km, uKey);

	// Encrypt the test vector (=Plain)
	CAST256Encrypt(Kr, Km, &Plain);

	// Check whether Plain encrypted to the correct cyphertext (=Cypher)
	if(!memcmp(&Plain, &Cypher, 16))
		printf("PASSED\n");
	else
		printf("FAILED\n");

	printf("\nPress any key to return...\n\n");
	getch();
}
/**/

⌨️ 快捷键说明

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