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

📄 pgpcast5.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	PGPUInt32 l, r, t;

	r = (PGPUInt32)
		in[0]<<24 | (PGPUInt32)in[1]<<16 | (PGPUInt32)in[2]<<8 | in[3];
	l = (PGPUInt32)
		in[4]<<24 | (PGPUInt32)in[5]<<16 | (PGPUInt32)in[6]<<8 | in[7];

	t = F1(l, xkey, 15); r ^= G1(t);
	t = F3(r, xkey, 14); l ^= G3(t);
	t = F2(l, xkey, 13); r ^= G2(t);
	t = F1(r, xkey, 12); l ^= G1(t);
	/* Start here if only doing 12 rounds */
	t = F3(l, xkey, 11); r ^= G3(t);
	t = F2(r, xkey, 10); l ^= G2(t);
	t = F1(l, xkey,  9); r ^= G1(t);
	t = F3(r, xkey,  8); l ^= G3(t);
	t = F2(l, xkey,  7); r ^= G2(t);
	t = F1(r, xkey,  6); l ^= G1(t);
	t = F3(l, xkey,  5); r ^= G3(t);
	t = F2(r, xkey,  4); l ^= G2(t);
	t = F1(l, xkey,  3); r ^= G1(t);
	t = F3(r, xkey,  2); l ^= G3(t);
	t = F2(l, xkey,  1); r ^= G2(t);
	t = F1(r, xkey,  0); l ^= G1(t);

	out[0] = B0(l);
	out[1] = B1(l);
	out[2] = B2(l);
	out[3] = B3(l);
	out[4] = B0(r);
	out[5] = B1(r);
	out[6] = B2(r);
	out[7] = B3(r);
}


/*
 * Exported functions
 */

/* Expand 16 byte key into expanded key *priv */
static void
cast5Key(void *priv, void const *key)
{
	CAST5schedule((PGPUInt32 *)priv, (const PGPByte *) key);
}

/* Encrypt 8 bytes at *in into 8 bytes at *out using key sched from *priv */
static void
cast5Encrypt(void *priv, void const *in, void *out)
{
	CAST5encrypt((const PGPByte *) in, (PGPByte *) out, (PGPUInt32 *)priv);
}

/* Decrypt 8 bytes at *in into 8 bytes at *out using key sched from *priv */
static void
cast5Decrypt(void *priv, void const *in, void *out)
{
	CAST5decrypt( (const PGPByte *) in, (PGPByte *) out, (PGPUInt32 *)priv);
}



/*
 * Do one 64-bit step of a Tandem Davies-Meyer hash computation.
 * The hash buffer is 32 bytes long and contains H (0..7), then G (8..15),
 * then 16 bytes of scratch space.  The buf is 8 bytes long.
 * xkey is a temporary key schedule buffer.
 * This and the extra data in the hash buffer are allocated by the
 * caller to reduce the amount of buffer-wiping we have to do.
 * (It's only called from ideaWash, so the interface can be a bit
 * specialized.)
 */
static void
CAST5StepTandemDM(PGPByte *hash, PGPByte const *buf, PGPUInt32 *xkey)
{
	int i;

	/* key1 = G << 64 + M, remembering that CAST is big-endian */
	memcpy(hash+16, buf, 8);
	CAST5schedule(xkey, hash+8);
	/* W = E_key1(H), key2 = M << 64 + W */
	CAST5encrypt(hash, hash+24, xkey);
	CAST5schedule(xkey, hash+16);
	/* V = E_key2(G) */
	CAST5encrypt(hash+8, hash+16, xkey);
	/* H ^= W, G ^= V */
	for (i = 0; i < 8; i++) {
		hash[i] ^= hash[i+24];
		hash[i+8] ^= hash[i+16];
	}
}

/*
 * Munge the key of the CipherContext based on the supplied bytes.
 * This is for random-number generation, so the exact technique is
 * unimportant, but it happens to use the current key as the
 * IV for computing a tandem Davies-Meyer hash of the bytes,
 * and uses the output as the new key.
 */
static void
cast5Wash(void *priv, void const *bufIn, PGPSize len)
{
	PGPSize i;
	PGPByte hash[32];
	PGPUInt32 	*xkey = (PGPUInt32 *)priv;
	PGPByte		*buf = (PGPByte *) bufIn;
	
	/* Read out the key in canonical byte order for the IV */
	for (i = 0; i < 8; i++) {
		hash[2*i] = (PGPByte)(xkey[i]>>8);
		hash[2*i+1] = (PGPByte)xkey[i];
	}

	/* Do the initial blocks of the hash */
	i = len;
	while (i >= 8) {
		CAST5StepTandemDM(hash, buf, xkey);
		buf += 8;
		i -= 8;
	}
	/*
	 * At the end, we do Damgard-Merkle strengthening, just like
	 * MD5 or SHA.  Pad with 0x80 then 0 bytes to 6 mod 8, then
	 * add the length.  We use a 16-bit length in bytes instead
	 * of a 64-bit length in bits, but that is cryptographically
	 * irrelevant.
	 */
	/* Do the first partial block - i <= 7 */
	memcpy(hash+24, buf, i);
	hash[24 + i++] = 0x80;
	if (i > 6) {
		pgpClearMemory(hash+24+i, 8-i);
		CAST5StepTandemDM(hash, hash+24, xkey);
		i = 0;
	}
	pgpClearMemory(hash+24+i, 6-i);
	hash[30] = (PGPByte)(len >> 8);
	hash[31] = (PGPByte)len;
	CAST5StepTandemDM(hash, hash+24, xkey);

	/* Re-schedule the key */
	CAST5schedule(xkey, hash);

	pgpClearMemory( hash,  sizeof(hash));
}

/*
 * Define a Cipher for the generic cipher.  This is the only
 * real exported thing -- everything else can be static, since everything
 * is referenced through function pointers!
 */
PGPCipherVTBL const cipherCAST5 =
{
	"CAST5",
	kPGPCipherAlgorithm_CAST5,
	8,			/* Blocksize */
	16,			/* Keysize */
	CAST5_KEYBYTES,				/* Priv array size */
	alignof(PGPUInt32),
	cast5Key,
	cast5Encrypt,
	cast5Decrypt,
	cast5Wash
};





#if UNITTEST


/*
 * From RFC2144:
 *
 * Appendix B. Test Vectors
 * 
 *    This appendix provides test vectors for the CAST-128 cipher described
 *    this document.
 * 
 * B.1. Single Plaintext-Key-Ciphertext Sets
 * 
 *    In order to ensure that the algorithm is implemented correctly, the
 *    following test vectors can be used for verification (values given in
 *    hexadecimal notation).
 * 
 *    128-bit key         = 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A
 *            plaintext   = 01 23 45 67 89 AB CD EF
 *            ciphertext  = 23 8B 4F E5 84 7E 44 B2
 * 
 *    80-bit  key         = 01 23 45 67 12 34 56 78 23 45
 *                        = 01 23 45 67 12 34 56 78 23 45 00 00 00 00 00 00
 *            plaintext   = 01 23 45 67 89 AB CD EF
 *            ciphertext  = EB 6A 71 1A 2C 02 27 1B
 * 
 *    40-bit  key         = 01 23 45 67 12
 *                        = 01 23 45 67 12 00 00 00 00 00 00 00 00 00 00 00
 *            plaintext   = 01 23 45 67 89 AB CD EF
 *            ciphertext  = 7A C8 16 D1 6E 9B 30 2E
 * 
 * B.2. Full Maintenance Test
 * 
 *    A maintenance test for CAST-128 has been defined to verify the
 *    correctness of implementations.  It is defined in pseudo-code as
 *    follows, where a and b are 128-bit vectors, aL and aR are the
 *    leftmost and rightmost halves of a, bL and bR are the leftmost and
 *    rightmost halves of b, and encrypt(d,k) is the encryption in ECB mode
 *    of block d under key k.
 * 
 *    Initial a = 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A (hex)
 *    Initial b = 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A (hex)
 * 
 *    do 1,000,000 times
 *    {
 *        aL = encrypt(aL,b)
 *        aR = encrypt(aR,b)
 *        bL = encrypt(bL,a)
 *        bR = encrypt(bR,a)
 *    }
 * 
 * Verify a == EE A9 D0 A2 49 FD 3B A6 B3 43 6F B8 9D 6D CA 92 (hex)
 * Verify b == B2 C9 5E B0 0C 31 AD 71 80 AC 05 B8 E8 3D 69 6E (hex)
 * 
 */


/* Test vectors */
PGPByte K1[] = {
	0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
	0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A
};
PGPByte P1[] = {
	0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
};
PGPByte C1[] = {
	0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2
};

#if 0
/*
 * We do not support 80-bit and lower keys, which require 12 rather
 * than 16 rounds of encryption.
 */
PGPByte K2[] = {
	0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
	0x23, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
PGPByte P2[] = {
	0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
};
PGPByte C2[] = {
	0xEB, 0x6A, 0x71, 0x1A, 0x2C, 0x02, 0x27, 0x1B
};

PGPByte K3[] = {
	0x01, 0x23, 0x45, 0x67, 0x12, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
PGPByte P3[] = {
	0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
};
PGPByte C3[] = {
	0x7A, 0xC8, 0x16, 0xD1, 0x6E, 0x9B, 0x30, 0x2E
};
#endif


/* Maintenance test */
PGPByte A[] = {
	0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
	0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A
};
PGPByte B[] = {
	0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
	0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A
};
PGPByte VA[] = {
	0xEE, 0xA9, 0xD0, 0xA2, 0x49, 0xFD, 0x3B, 0xA6,
	0xB3, 0x43, 0x6F, 0xB8, 0x9D, 0x6D, 0xCA, 0x92
};
PGPByte VB[] = {
	0xB2, 0xC9, 0x5E, 0xB0, 0x0C, 0x31, 0xAD, 0x71,
	0x80, 0xAC, 0x05, 0xB8, 0xE8, 0x3D, 0x69, 0x6E
};


int
main(void)
{	/* Test driver for CAST cipher */
	int i;
	PGPByte priv[CAST5_KEYBYTES];
	PGPByte X[8], Y[8];

	/* First test */
	cast5Key(priv, K1);
	cast5Encrypt(priv, P1, X);
	if (memcmp(C1, X, sizeof(X)) == 0)
		printf ("Encryption test 1 passed\n");
	else
		printf ("ERROR ON ENCRYPTION TEST 1\n");
	cast5Decrypt(priv, C1, Y);
	if (memcmp(P1, Y, sizeof(Y)) == 0)
		printf ("Decryption test 1 passed\n");
	else
		printf ("ERROR ON DECRYPTION TEST 1\n");

	/* Maintenance test */
	printf ("Performing maintenance test...\n");
	for (i=0; i<1000000; ++i) {
		cast5Key(priv, B);
		cast5Encrypt(priv, A, A);
		cast5Encrypt(priv, A+8, A+8);
		cast5Key(priv, A);
		cast5Encrypt(priv, B, B);
		cast5Encrypt(priv, B+8, B+8);
	}
	if (memcmp(A, VA, sizeof(A)) == 0)
		printf ("Maintenance test A passed\n");
	else
		printf ("ERROR ON MAINTENANCE TEST A\n");
	if (memcmp(B, VB, sizeof(B)) == 0)
		printf ("Maintenance test B passed\n");
	else
		printf ("ERROR ON MAINTENANCE TEST B\n");

	return 0;	/* normal exit */
} /* main */

#endif /* UNITTEST */



#endif /* ] PGP_CAST5 */

/*__Editor_settings____

	Local Variables:
	tab-width: 4
	End:
	vi: ts=4 sw=4
	vim: si
_____________________*/

⌨️ 快捷键说明

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