pgpdes3.c
来自「著名的加密软件的应用于电子邮件中」· C语言 代码 · 共 607 行 · 第 1/2 页
C
607 行
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 ^= *(word32 *)((char *)SP0+( s & 0x3fc))
^ *(word32 *)((char *)SP0+((s >> 8 ) & 0x3fc))
^ *(word32 *)((char *)SP0+((s >> 16) & 0x3fc))
^ *(word32 *)((char *)SP0+((s >> 24) & 0x0fc))
^ *(word32 *)((char *)SP1+( t & 0x3fc))
^ *(word32 *)((char *)SP1+((t >> 8 ) & 0x3fc))
^ *(word32 *)((char *)SP1+((t >> 16) & 0x3fc))
^ *(word32 *)((char *)SP1+((t >> 24) & 0x0fc));
s = (leftt & 0xfcfcfcfc) ^ keys[2];
t = (((leftt >> 28) | (leftt << 4)) & 0xfcfcfcfc)
^ keys[3];
right ^= *(word32 *)((char *)SP0+( s & 0x3fc))
^ *(word32 *)((char *)SP0+((s >> 8 ) & 0x3fc))
^ *(word32 *)((char *)SP0+((s >> 16) & 0x3fc))
^ *(word32 *)((char *)SP0+((s >> 24) & 0x0fc))
^ *(word32 *)((char *)SP1+( t & 0x3fc))
^ *(word32 *)((char *)SP1+((t >> 8 ) & 0x3fc))
^ *(word32 *)((char *)SP1+((t >> 16) & 0x3fc))
^ *(word32 *)((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] = (byte)(right >> 24);
outblock[1] = (byte)(right >> 16);
outblock[2] = (byte)(right >> 8);
outblock[3] = (byte)(right );
outblock[4] = (byte)(leftt >> 24);
outblock[5] = (byte)(leftt >> 16);
outblock[6] = (byte)(leftt >> 8);
outblock[7] = (byte)(leftt );
return;
}
/*** Externally called functions ***/
static void
des3Key (void *priv, byte const *key)
{
/* EDE triple-DES */
deskey (key , 0, (word32 *)priv);
deskey (key+ 8, 1, (word32 *)priv + DES_KEYWORDS);
deskey (key+16, 0, (word32 *)priv + 2*DES_KEYWORDS);
/* To decrypt, do DED with the keys in the opposite order */
/* Keep a copy of the unscheduled key for Washing purposes */
memcpy ((byte *)priv + DES3_KEYBYTES, key, DES3_USERKEYBYTES);
}
static void
des3Encrypt (void *priv, byte const *in, byte *out)
{
des3DES (in, out, (word32 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(byte *hash, byte const *buf, word32 *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, byte const *buf, unsigned len)
{
unsigned i;
byte temp[8];
word32 xkey[4*DES_KEYWORDS];
/* The key is used as the IV for the hash */
/* Do the initial blocks of the hash */
i = len;
while (i >= 8) {
des3StepTripleDM((byte *)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) {
memset(temp+i, 0, 8-i);
des3StepTripleDM((byte *)priv+DES3_KEYBYTES, temp, xkey);
i = 0;
}
memset(temp+i, 0, 6-i);
temp[6] = (byte)(len >> 8);
temp[7] = (byte)len;
des3StepTripleDM((byte *)priv+DES3_KEYBYTES, temp, xkey);
/* Re-schedule the key */
deskey ((byte *)priv+DES3_KEYBYTES , 0,
(word32 *)priv);
deskey ((byte *)priv+DES3_KEYBYTES+ 8, 1,
(word32 *)priv + DES_KEYWORDS);
deskey ((byte *)priv+DES3_KEYBYTES+16, 0,
(word32 *)priv + 2*DES_KEYWORDS);
memset(temp, 0, sizeof(temp));
memset(xkey, 0, sizeof(xkey));
}
/*
* Define a struct Cipher for the generic cipher. This is the only real
* exported symbol -- everything else can be static, since everything
* is referenced through function pointers!
*/
struct PgpCipher const cipher3DES = {
"3DES",
PGP_CIPHER_3DES,
8, /* Blocksize */
DES3_USERKEYBYTES, /* Keysize */
DES3_KEYBYTES + DES3_USERKEYBYTES,
alignof(word32),
des3Key,
des3Encrypt,
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>
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];
word32 xkey[DES3_KEYWORDS+6];
des3Key(xkey, key);
des3Encrypt(xkey, 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("Test successful\n");
else
printf("### ERROR\n");
printf("Doing test encryptions\n");
c = clock();
for (i = 0; i < 100000; i++)
des3Encrypt(xkey, out, out);
c = clock() - c;
printf("%u encryptions required %lu ticks\n",
i, (unsigned long)c);
return 0;
}
#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?