pgpdes3.c

来自「著名的加密软件的应用于电子邮件中」· C语言 代码 · 共 607 行 · 第 1/2 页

C
607
字号
/*
* pgpDES3.c - TripleDES EDE Encryptor
*
* Copyright (C) 1996,1997 Pretty Good Privacy, Inc. All rights reserved.
*
* pgpDES3.c 95/09/11 23:29:03 EDT by Richard Outerbridge
*
* $Id: pgpDES3.c,v 1.1.2.1 1997/06/07 09:49:52 mhw Exp $
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "pgpCipher.h"
#include "pgpDES3.h"
#include "pgpMem.h"
#include "pgpUsuals.h"

/* The size of a scheduled DES key */
#define DES_KEYWORDS 32
#define DES_KEYBYTES (sizeof(word32)*DES_KEYWORDS)
#define DES3_KEYWORDS (3*DES_KEYWORDS)
#define DES3_KEYBYTES (sizeof(word32)*DES3_KEYWORDS)

#define DES3_USERKEYBYTES 24

static word32 const 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	};

/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */

static byte const 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 byte const totrot[16] = {
	1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 };

static byte const 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 };

/*
* This is a less-that-brilliant key scheduling routine.
* It could stand optimization some time.
*
* cookey "cooks" the key into the desired form, from the basic one that
* has the keys for S-boxes 1 through 8 in adjacent words of the
* "raw" array. I.e. the bits start out like this:
* xxxxxxxx111111222222333333444444
* xxxxxxxx555555666666777777888888
* We actually want the keys to look like this:
* 111111xx333333xx555555xx777777xx
* 222222xx444444xx666666xx888888xx
* Where the "xx" patterns are set to 01020300 for use by the s-box
* lookup code in the main encrypt loop.
*/
static void
cookey (word32 *raw, word32 *cooked)
{
		int i;

		for (i = 0; i < 16; i++, raw += 2, cooked += 2) {
				cooked[0] = (raw[0] & 0x00fc0000L) << 8;
				cooked[0] |= (raw[0] & 0x00000fc0L) << 12;
				cooked[0] |= (raw[1] & 0x00fc0000L) >> 8;
				cooked[0] |= (raw[1] & 0x00000fc0L) >> 4;
				cooked[0] |= 0x01020300;
				cooked[1] = (raw[0] & 0x0003f000L) << 14;
				cooked[1] |= (raw[0] & 0x0000003fL) << 18;
				cooked[1] |= (raw[1] & 0x0003f000L) >> 2;
				cooked[1] |= (raw[1] & 0x0000003fL) << 2;
				cooked[1] |= 0x01020300;
		}
		return;
}
	
static void
deskey (byte const *key, int decryptf, word32 *outbuf)
{
		int i, j, l, m, n;
		byte pc1m[56], pcr[56];
		word32 kn[32];
	
		for (j = 0; j < 56; j++) {
			l = pc1[j];
			m = l & 07;
			pc1m[j] = ( key[l >> 3] >> (~l & 7) ) & 1;
		}
		for (i = 0; i < 16; i++ ) {
				m = (decryptf ? 15-i : i) << 1;
				n = m + 1;
				kn[m] = kn[n] = 0L;
				for (j = 0; j < 28; j++) {
						l = j + totrot[i];
						if (l >= 28)
							l -= 28;
						pcr[j] = pc1m[l];
				}
				for (j = 28; j < 56; j++) {
						l = j + totrot[i];
						if (l >= 56)
							l -= 28;
						pcr[j] = pc1m[l];
				}
				for (j = 0; j < 24; j++) {
						if (pcr[pc2[j]])
							kn[m] |= bigbyte[j];
						if (pcr[pc2[j+24]])
								kn[n] |= bigbyte[j];
				}
		}
		cookey(kn, outbuf);
		return;
}

/* S-boxes 1, 3, 5, 7, plus P permutation, rotated */
static word32 const SP0[512] = {
		0x00404100, 0x00000000, 0x00004000, 0x00404101,
		0x00404001, 0x00004101, 0x00000001, 0x00004000,
		0x00000100, 0x00404100, 0x00404101, 0x00000100,
		0x00400101, 0x00404001, 0x00400000, 0x00000001,
		0x00000101, 0x00400100, 0x00400100, 0x00004100,
		0x00004100, 0x00404000, 0x00404000, 0x00400101,
		0x00004001, 0x00400001, 0x00400001, 0x00004001,
		0x00000000, 0x00000101, 0x00004101, 0x00400000,
		0x00004000, 0x00404101, 0x00000001, 0x00404000,
		0x00404100, 0x00400000, 0x00400000, 0x00000100,
		0x00404001, 0x00004000, 0x00004100, 0x00400001,
		0x00000100, 0x00000001, 0x00400101, 0x00004101,
		0x00404101, 0x00004001, 0x00404000, 0x00400101,
		0x00400001, 0x00000101, 0x00004101, 0x00404100,
		0x00000101, 0x00400100, 0x00400100, 0x00000000,
		0x00004001, 0x00004100, 0x00000000, 0x00404001,

		0x00000082, 0x02008080, 0x00000000, 0x02008002,
		0x02000080, 0x00000000, 0x00008082, 0x02000080,
		0x00008002, 0x02000002, 0x02000002, 0x00008000,
		0x02008082, 0x00008002, 0x02008000, 0x00000082,
		0x02000000, 0x00000002, 0x02008080, 0x00000080,
		0x00008080, 0x02008000, 0x02008002, 0x00008082,
		0x02000082, 0x00008080, 0x00008000, 0x02000082,
		0x00000002, 0x02008082, 0x00000080, 0x02000000,
		0x02008080, 0x02000000, 0x00008002, 0x00000082,
		0x00008000, 0x02008080, 0x02000080, 0x00000000,
		0x00000080, 0x00008002, 0x02008082, 0x02000080,
		0x02000002, 0x00000080, 0x00000000, 0x02008002,
		0x02000082, 0x00008000, 0x02000000, 0x02008082,
		0x00000002, 0x00008082, 0x00008080, 0x02000002,
		0x02008000, 0x02000082, 0x00000082, 0x02008000,
		0x00008082, 0x00000002, 0x02008002, 0x00008080,

		0x00000040, 0x00820040, 0x00820000, 0x10800040,
		0x00020000, 0x00000040, 0x10000000, 0x00820000,
		0x10020040, 0x00020000, 0x00800040, 0x10020040,
		0x10800040, 0x10820000, 0x00020040, 0x10000000,
		0x00800000, 0x10020000, 0x10020000, 0x00000000,
		0x10000040, 0x10820040, 0x10820040, 0x00800040,
		0x10820000, 0x10000040, 0x00000000, 0x10800000,
		0x00820040, 0x00800000, 0x10800000, 0x00020040,
		0x00020000, 0x10800040, 0x00000040, 0x00800000,
		0x10000000, 0x00820000, 0x10800040, 0x10020040,
		0x00800040, 0x10000000, 0x10820000, 0x00820040,
		0x10020040, 0x00000040, 0x00800000, 0x10820000,
		0x10820040, 0x00020040, 0x10800000, 0x10820040,
		0x00820000, 0x00000000, 0x10020000, 0x10800000,
		0x00020040, 0x00800040, 0x10000040, 0x00020000,
		0x00000000, 0x10020000, 0x00820040, 0x10000040,

		0x00080000, 0x81080000, 0x81000200, 0x00000000,
		0x00000200, 0x81000200, 0x80080200, 0x01080200,
		0x81080200, 0x00080000, 0x00000000, 0x81000000,
		0x80000000, 0x01000000, 0x81080000, 0x80000200,
		0x01000200, 0x80080200, 0x80080000, 0x01000200,
		0x81000000, 0x01080000, 0x01080200, 0x80080000,
		0x01080000, 0x00000200, 0x80000200, 0x81080200,
		0x00080200, 0x80000000, 0x01000000, 0x00080200,
		0x01000000, 0x00080200, 0x00080000, 0x81000200,
		0x81000200, 0x81080000, 0x81080000, 0x80000000,
		0x80080000, 0x01000000, 0x01000200, 0x00080000,
		0x01080200, 0x80000200, 0x80080200, 0x01080200,
		0x80000200, 0x81000000, 0x81080200, 0x01080000,
		0x00080200, 0x00000000, 0x80000000, 0x81080200,
		0x00000000, 0x80080200, 0x01080000, 0x00000200,
		0x81000000, 0x01000200, 0x00000200, 0x80080000 };

/* S-boxes 2, 4, 6, 8, plus P permutation, rotated */
static word32 const SP1[512] = {
		0x20042008, 0x20002000, 0x00002000, 0x00042008,
		0x00040000, 0x00000008, 0x20040008, 0x20002008,
		0x20000008, 0x20042008, 0x20042000, 0x20000000,
		0x20002000, 0x00040000, 0x00000008, 0x20040008,
		0x00042000, 0x00040008, 0x20002008, 0x00000000,
		0x20000000, 0x00002000, 0x00042008, 0x20040000,
		0x00040008, 0x20000008, 0x00000000, 0x00042000,
		0x00002008, 0x20042000, 0x20040000, 0x00002008,
		0x00000000, 0x00042008, 0x20040008, 0x00040000,
		0x20002008, 0x20040000, 0x20042000, 0x00002000,
		0x20040000, 0x20002000, 0x00000008, 0x20042008,
		0x00042008, 0x00000008, 0x00002000, 0x20000000,
		0x00002008, 0x20042000, 0x00040000, 0x20000008,
		0x00040008, 0x20002008, 0x20000008, 0x00040008,
		0x00042000, 0x00000000, 0x20002000, 0x00002008,
		0x20000000, 0x20040008, 0x20042008, 0x00042000,

		0x40200800, 0x40000820, 0x40000820, 0x00000020,
		0x00200820, 0x40200020, 0x40200000, 0x40000800,
		0x00000000, 0x00200800, 0x00200800, 0x40200820,
		0x40000020, 0x00000000, 0x00200020, 0x40200000,
		0x40000000, 0x00000800, 0x00200000, 0x40200800,
		0x00000020, 0x00200000, 0x40000800, 0x00000820,
		0x40200020, 0x40000000, 0x00000820, 0x00200020,
		0x00000800, 0x00200820, 0x40200820, 0x40000020,
		0x00200020, 0x40200000, 0x00200800, 0x40200820,
		0x40000020, 0x00000000, 0x00000000, 0x00200800,
		0x00000820, 0x00200020, 0x40200020, 0x40000000,
		0x40200800, 0x40000820, 0x40000820, 0x00000020,
		0x40200820, 0x40000020, 0x40000000, 0x00000800,
		0x40200000, 0x40000800, 0x00200820, 0x40200020,
		0x40000800, 0x00000820, 0x00200000, 0x40200800,
		0x00000020, 0x00200000, 0x00000800, 0x00200820,

			0x08000004, 0x08100000, 0x00001000, 0x08101004,
			0x08100000, 0x00000004, 0x08101004, 0x00100000,
			0x08001000, 0x00101004, 0x00100000, 0x08000004,
			0x00100004, 0x08001000, 0x08000000, 0x00001004,
			0x00000000, 0x00100004, 0x08001004, 0x00001000,
			0x00101000, 0x08001004, 0x00000004, 0x08100004,
			0x08100004, 0x00000000, 0x00101004, 0x08101000,
			0x00001004, 0x00101000, 0x08101000, 0x08000000,
			0x08001000, 0x00000004, 0x08100004, 0x00101000,
			0x08101004, 0x00100000, 0x00001004, 0x08000004,
			0x00100000, 0x08001000, 0x08000000, 0x00001004,
			0x08000004, 0x08101004, 0x00101000, 0x08100000,
			0x00101004, 0x08101000, 0x00000000, 0x08100004,
			0x00000004, 0x00001000, 0x08100000, 0x00101004,
			0x00001000, 0x00100004, 0x08001004, 0x00000000,
			0x08101000, 0x08000000, 0x00100004, 0x08001004,

			0x04000410, 0x00000400, 0x00010000, 0x04010410,
			0x04000000, 0x04000410, 0x00000010, 0x04000000,
			0x00010010, 0x04010000, 0x04010410, 0x00010400,
			0x04010400, 0x00010410, 0x00000400, 0x00000010,
			0x04010000, 0x04000010, 0x04000400, 0x00000410,
			0x00010400, 0x00010010, 0x04010010, 0x04010400,
			0x00000410, 0x00000000, 0x00000000, 0x04010010,
			0x04000010, 0x04000400, 0x00010410, 0x00010000,
			0x00010410, 0x00010000, 0x04010400, 0x00000400,
			0x00000010, 0x04010010, 0x00000400, 0x00010410,
			0x04000400, 0x00000010, 0x04000010, 0x04010000,
			0x04010010, 0x04000000, 0x00010000, 0x04000410,
			0x00000000, 0x04010410, 0x00010010, 0x04000010,
			0x04010000, 0x04000400, 0x04000410, 0x00000000,
			0x04010410, 0x00010400, 0x00010400, 0x00000410,
			0x00000410, 0x00010010, 0x04000000, 0x04010400 };

/*
* This encryption function is fairly clever in the way it does its
* s-box lookup. The S-boxes are indexed by bytes, rather than
* words, because that's faster on many machines, and shifting
* everything two bits to do the multiply by 4 is trivial.
* Then, the indexing into the various S boxes is done by
* adding the appropriate offset bits into the key array, so the
* addition is done by the XOR with the key rather than having to
* be done explicitly here.
*/
static void
des3DES (byte const inblock[8], byte outblock[8], word32 const *keys)
{
		word32 s, t, right, leftt;
		int round, iterate;
	
		leftt	 = ((word32)inblock[0] << 24)
	| ((word32)inblock[1] << 16)
	| ((word32)inblock[2] << 8)
	| (word32)inblock[3];
		right	 = ((word32)inblock[4] << 24)
	| ((word32)inblock[5] << 16)
	| ((word32)inblock[6] << 8)
	| (word32)inblock[7];

		/* Initial permutation IP */
		t = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
		right ^= t;
		leftt ^= (t << 4);
		t = ((leftt >> 16) ^ right) & 0x0000ffffL;
		right ^= t;
		leftt ^= (t << 16);
		t = ((right >> 2) ^ leftt) & 0x33333333L;
		leftt ^= t;
		right ^= (t << 2);
		t = ((right >> 8) ^ leftt) & 0x00ff00ffL;
		leftt ^= t;
		right ^= (t << 8);

⌨️ 快捷键说明

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