📄 pgpdes3.c
字号:
/*
* pgpDES3.c - TripleDES EDE Encryptor
*
* pgpDES3.c 95/09/11 23:29:03 EDT by Richard Outerbridge
*
* $Id: pgpDES3.c,v 1.15 1997/10/14 01:48:17 heller Exp $
*/
#include "pgpSDKBuildFlags.h"
#ifndef PGP_DES3
#error you must define PGP_DES3 one way or the other
#endif
#if PGP_DES3 /* [ */
#include <string.h>
#include "pgpConfig.h"
#include "pgpSymmetricCipherPriv.h"
#include "pgpDES3.h"
#include "pgpMem.h"
/* The size of a scheduled DES key */
#define DES_KEYWORDS 32
#define DES_KEYBYTES (sizeof(PGPUInt32)*DES_KEYWORDS)
#define DES3_KEYWORDS (3*DES_KEYWORDS)
#define DES3_KEYBYTES (sizeof(PGPUInt32)*DES3_KEYWORDS)
#define DES3_USERKEYBYTES 24
/*
* Flags in priv array to record whether key schedule is in encrypt
* or decrypt mode
*/
#define DES3_MODE_OFFSET (DES3_KEYBYTES + DES3_USERKEYBYTES)
#define DES3_UNDEFINED_MODE 0x00
#define DES3_ENCRYPTION_MODE 0x11
#define DES3_DECRYPTION_MODE 0x22
static PGPUInt32 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 PGPByte 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 PGPByte const totrot[16] = {
1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 };
static PGPByte 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 (PGPUInt32 *raw, PGPUInt32 *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 (PGPByte const *key, int decryptf, PGPUInt32 *outbuf)
{
int i, j, l, m, n;
PGPByte pc1m[56], pcr[56];
PGPUInt32 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 PGPUInt32 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 PGPUInt32 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 (PGPByte const inblock[8], PGPByte outblock[8], PGPUInt32 const *keys)
{
PGPUInt32 s, t, right, leftt;
int round, iterate;
leftt = ((PGPUInt32)inblock[0] << 24)
| ((PGPUInt32)inblock[1] << 16)
| ((PGPUInt32)inblock[2] << 8)
| (PGPUInt32)inblock[3];
right = ((PGPUInt32)inblock[4] << 24)
| ((PGPUInt32)inblock[5] << 16)
| ((PGPUInt32)inblock[6] << 8)
| (PGPUInt32)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);
leftt = ((leftt >> 1) | (leftt << 31));
t = (leftt ^ right) & 0x55555555L;
leftt ^= t;
right ^= t;
right = ((right >> 1) | (right << 31));
/* The main encryption loop */
iterate = 3;
goto Des0;
do {
t = right;
right = leftt;
leftt = t;
Des0:
for (round = 0; round < 8; round++) {
s = (right & 0xfcfcfcfc) ^ keys[0];
t = (((right >> 28) | (right << 4)) & 0xfcfcfcfc)
^ keys[1];
leftt ^= *(PGPUInt32 *)((char *)SP0+( s & 0x3fc))
^ *(PGPUInt32 *)((char *)SP0+((s >> 8 ) & 0x3fc))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -