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

📄 pgpdes3.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 2 页
字号:
			       ^ *(PGPUInt32 *)((char *)SP0+((s >> 16) & 0x3fc))
			       ^ *(PGPUInt32 *)((char *)SP0+((s >> 24) & 0x0fc))
			       ^ *(PGPUInt32 *)((char *)SP1+( t        & 0x3fc))
			       ^ *(PGPUInt32 *)((char *)SP1+((t >> 8 ) & 0x3fc))
			       ^ *(PGPUInt32 *)((char *)SP1+((t >> 16) & 0x3fc))
			       ^ *(PGPUInt32 *)((char *)SP1+((t >> 24) & 0x0fc));

			s  = (leftt & 0xfcfcfcfc) ^ keys[2];
			t  = (((leftt >> 28) | (leftt << 4)) & 0xfcfcfcfc)
				^ keys[3];
			right ^= *(PGPUInt32 *)((char *)SP0+( s        & 0x3fc))
			       ^ *(PGPUInt32 *)((char *)SP0+((s >> 8 ) & 0x3fc))
			       ^ *(PGPUInt32 *)((char *)SP0+((s >> 16) & 0x3fc))
			       ^ *(PGPUInt32 *)((char *)SP0+((s >> 24) & 0x0fc))
			       ^ *(PGPUInt32 *)((char *)SP1+( t        & 0x3fc))
			       ^ *(PGPUInt32 *)((char *)SP1+((t >> 8 ) & 0x3fc))
			       ^ *(PGPUInt32 *)((char *)SP1+((t >> 16) & 0x3fc))
			       ^ *(PGPUInt32 *)((char *)SP1+((t >> 24) & 0x0fc));
			keys += 4;
		}
	} while (--iterate);

	/* Inverse IP */
	leftt = ((leftt << 1) | (leftt >> 31));
	t = (leftt ^ right) & 0x55555555L;
	leftt ^= t;
	right ^= t;
	right = ((right << 1) | (right >> 31));
	t = ((leftt >> 8) ^ right) & 0x00ff00ffL;
	right ^= t;
	leftt ^= (t << 8);
	t = ((leftt >> 2) ^ right) & 0x33333333L;
	right ^= t;
	leftt ^= (t << 2);
	t = ((right >> 16) ^ leftt) & 0x0000ffffL;
	leftt ^= t;
	right ^= (t << 16);
	t = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
	leftt ^= t;
	right ^= (t << 4);

	outblock[0] = (PGPByte)(right >> 24);
	outblock[1] = (PGPByte)(right >> 16);
	outblock[2] = (PGPByte)(right >>  8);
	outblock[3] = (PGPByte)(right      );
	outblock[4] = (PGPByte)(leftt >> 24);
	outblock[5] = (PGPByte)(leftt >> 16);
	outblock[6] = (PGPByte)(leftt >>  8);
	outblock[7] = (PGPByte)(leftt      );
	return;
}

/*** Externally called functions ***/

static void
des3Key (void *priv, void const *key)
{
	/* Do key schedule at encrypt/decrypt time; just store key for now */
	*((PGPByte *)priv + DES3_MODE_OFFSET) = DES3_UNDEFINED_MODE;
	/* Keep a copy of the unscheduled key for Washing purposes */
	memcpy ((PGPByte *)priv + DES3_KEYBYTES, key, DES3_USERKEYBYTES);
}

static void
scheduleKey (void *priv, PGPUInt32 mode)
{
	if (mode == DES3_ENCRYPTION_MODE) {
		if (*((PGPByte *)priv + DES3_MODE_OFFSET) != DES3_ENCRYPTION_MODE) {
			/* EDE triple-DES */
			PGPByte *key = (PGPByte *)priv + DES3_KEYBYTES;
			deskey (key   , 0, (PGPUInt32 *)priv);
			deskey (key+ 8, 1, (PGPUInt32 *)priv + DES_KEYWORDS);
			deskey (key+16, 0, (PGPUInt32 *)priv + 2*DES_KEYWORDS);
			*((PGPByte *)priv + DES3_MODE_OFFSET) = DES3_ENCRYPTION_MODE;
		}
	} else {
#if !UNITTEST
		pgpAssert (mode == DES3_DECRYPTION_MODE);
#endif
		if (*((PGPByte *)priv + DES3_MODE_OFFSET) != DES3_DECRYPTION_MODE) {
			/* EDE triple-DES */
			/* To decrypt, do DED with the keys in the opposite order */
			PGPByte *key = (PGPByte *)priv + DES3_KEYBYTES;
			deskey (key+16, 1, (PGPUInt32 *)priv);
			deskey (key+ 8, 0, (PGPUInt32 *)priv + DES_KEYWORDS);
			deskey (key   , 1, (PGPUInt32 *)priv + 2*DES_KEYWORDS);
			*((PGPByte *)priv + DES3_MODE_OFFSET) = DES3_DECRYPTION_MODE;
		}
	}
}

static void
des3Encrypt (void *priv, void const *in, void *out)
{
	/* Make sure key schedule is in the right mode */
	scheduleKey (priv, DES3_ENCRYPTION_MODE);
	des3DES ((const PGPByte *) in, (PGPByte *) out, (PGPUInt32 const *)priv);
}

static void
des3Decrypt (void *priv, void const *in, void *out)
{
	/* Make sure key schedule is in the right mode */
	scheduleKey (priv, DES3_DECRYPTION_MODE);
	des3DES ((const PGPByte *) in, (PGPByte *) out, (PGPUInt32 const *)priv);
}

/*
 * Do one 64-bit step of a Triple Tandem Davies-Meyer hash computation.
 * The hash buffer is 32 bytes long and contains H (0..7), then G (8..15),
 * then F (16..23), then 8 bytes of scratch space.  The buf is 8 bytes long.
 * xkey is a temporary key schedule buffer, with room for *4* DES
 * keys, i.e. 4*DESKEYWORDS words.
 * 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 des3Wash, so the interface can be a bit
 * specialized.)
 *
 * What is triple Tandem Davies-Meyer?  Well, it's a simple
 * extension of (double) Tandem Davies-Meyer, which goes
 * like this, to hash (H,G) with message block M:
 * H' = E_{G,M}(H)
 * G' = E_{M,H'}(G)
 * H ^= H'
 * G ^= G'
 *
 * The extension, to a triple-width hash (H,G,F) is just:
 * H' = E_{F,G,M}(H)
 * G' = E_{F,M,H'}(G)
 * F' = E_(M,G',H'}(F)
 * H ^= H'
 * G ^= G'
 * F ^= F'
 *
 * This schedules individual DES keys to avoid having to copy the
 * bits to contiguous buffers and to re-use the already-scheduled
 * leys.  F and H' are used twice in the same spot, and M is scheduled
 * twice for encryption.
 */
static void
des3StepTripleDM(PGPByte *hash, PGPByte const *buf, PGPUInt32 *xkey)
{
	int i;

	/* Set up triple-DES with F, G, M */
	deskey(hash+16, 0, xkey);
	deskey(hash+ 8, 1, xkey + DES_KEYWORDS);
	deskey(buf,     0, xkey + 2*DES_KEYWORDS);

	/* Compute H' and new H */
	des3DES(hash, hash+24, xkey);
	for (i = 0; i < 8; i++)
		hash[i] ^= hash[i+24];
	/* Copy encryption schedule for M out of harm's way */
	memcpy(xkey +3*DES_KEYWORDS, xkey+2*DES_KEYWORDS, DES_KEYBYTES);

	/* Set up triple-DES with F, M, H' */
	deskey(buf,     1, xkey + DES_KEYWORDS);
	deskey(hash+24, 0, xkey + 2*DES_KEYWORDS);

	/* Compute G' and new G */
	des3DES(hash+8, hash+24, xkey);
	for (i = 0; i < 8; i++)
		hash[i+8] ^= hash[i+24];

	/* Set up triple-DES with M, G', H' */
	memcpy(xkey, xkey+3*DES_KEYWORDS, DES_KEYBYTES);
	deskey(hash+24, 1, xkey + DES_KEYWORDS);

	/* Compute F' and new F */
	des3DES(hash+16, hash+24, xkey);
	for (i = 0; i < 8; i++)
		hash[i+16] ^= hash[i+24];
}

/*
 * 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 triple-Tandem Davies-Meyer hash of the bytes,
 * and uses the output as the new key.
 */
static void
des3Wash(void *priv, void const *bufIn, PGPSize len)
{
	PGPSize 	i;
	PGPByte 	temp[8];
	PGPUInt32 	xkey[4*DES_KEYWORDS];
	PGPByte		*buf = (PGPByte *) bufIn;
	
	/* The key is used as the IV for the hash */

	/* Do the initial blocks of the hash */
	i = len;
	while (i >= 8) {
		des3StepTripleDM((PGPByte *)priv+DES3_KEYBYTES, 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, as long as the length is there.
	 */
	/* Do the first partial block - i <= 7 */
	memcpy(temp, buf, i);
	temp[i++] = 0x80;
	if (i > 6) {
		pgpClearMemory(temp+i, 8-i);
		des3StepTripleDM((PGPByte *)priv+DES3_KEYBYTES, temp, xkey);
		i = 0;
	}
	pgpClearMemory(temp+i, 6-i);
	temp[6] = (PGPByte)(len >> 8);
	temp[7] = (PGPByte)len;
	des3StepTripleDM((PGPByte *)priv+DES3_KEYBYTES, temp, xkey);

	/* Re-schedule the key */
	*((PGPByte *)priv + DES3_MODE_OFFSET) = DES3_UNDEFINED_MODE;
	scheduleKey (priv, DES3_ENCRYPTION_MODE);

	pgpClearMemory( temp,  sizeof(temp));
	pgpClearMemory( xkey,  sizeof(xkey));
}

/*
 * Define a Cipher for the generic cipher.  This is the only real
 * exported symbol -- everything else can be static, since everything
 * is referenced through function pointers!
 */
PGPCipherVTBL const cipher3DES = {
	"3DES",
	kPGPCipherAlgorithm_3DES,
	8,			/* Blocksize */
	DES3_USERKEYBYTES,	/* Keysize */
	DES3_KEYBYTES + DES3_USERKEYBYTES + 1,
	alignof(PGPUInt32),
	des3Key,
	des3Encrypt,
	des3Decrypt,
	des3Wash
};

#if UNITTEST
/* Validation set:
 *
 * Double-length key, single-length plaintext -
 * Key    : 0123 4567 89ab cdef fedc ba98 7654 3210
 * Plain  : 0123 4567 89ab cde7
 * Cipher : 7f1d 0a77 826b 8aff
 *
 ***************************************************/

#include <stdio.h>
#include <time.h>

static void
printhex(unsigned char const *buf, unsigned len)
{
	while (len--) {
		printf("%02X", *buf++);
		putchar(len ? ' ' : '\n');
	}
}

int
main(void)
{
	unsigned i;
	clock_t c;

	static unsigned char const key[24] = {
		0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
		0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
		0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
	};
	static unsigned char const plain[8] = {
		0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7
	};
	static unsigned char const cipher[8] = {
		0x7f, 0x1d, 0x0a, 0x77, 0x82, 0x6b, 0x8a, 0xff
	};
	unsigned char out[8];

	PGPByte priv[DES3_KEYBYTES + DES3_USERKEYBYTES + 1];

	des3Key(priv, key);
	des3Encrypt(priv, plain, out);
	printf("   key=");
	printhex(key, 24);
	printf(" plain=");
	printhex(plain, 8);
	printf("   out=");
	printhex(out, 8);
	printf("cipher=");
	printhex(cipher, 8);
	if (memcmp(cipher, out, 8) == 0)
		printf("Encryption successful\n");
	else
		printf("### ENCRYPTION ERROR\n");

	des3Decrypt(priv, cipher, out);
	printf("cipher=");
	printhex(cipher, 8);
	printf("   out=");
	printhex(out, 8);
	printf(" plain=");
	printhex(plain, 8);
	if (memcmp(plain, out, 8) == 0)
		printf("Decryption successful\n");
	else
		printf("### DECRYPTION ERROR\n");

	printf("Doing test encryptions\n");
	c = clock();
	for (i = 0; i < 100000; i++)
		des3Encrypt(priv, out, out);
	c = clock() - c;
	printf("%u encryptions required %lu ticks\n",
		i, (unsigned long)c);
	return 0;
}

#endif

#endif /* ] PGP_DES3 */



/*__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 + -