📄 pgpdes3.c
字号:
^ *(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 + -