📄 qfdes.c
字号:
0x08020020, 0x08000000, 0x00020000, 0x08000820,0x00000000, 0x08020820, 0x00020020, 0x08000020,0x08020000, 0x08000800, 0x08000820, 0x00000000,0x08020820, 0x00020800, 0x00020800, 0x00000820,0x00000820, 0x00020020, 0x08000000, 0x08020800};#define INITIAL_PERMUTATION(t, regL, regR) \ INITIAL_PERMUTATION_AUX(t[0], t[1], regL, regR)#define FINAL_PERMUTATION(regR, regL, t) \ FINAL_PERMUTATION_AUX(regR, regL, t[0], t[1])#define PC1(k, regC, regD) \ PC1_AUX(k[0], k[1], regC, regD)#define PC2(regC, regD, k) \ PC2_AUX(regC, regD, k[0], k[1])unsigned char G_padChar = (char) 0; /* Default pad charcater */static Word ROTATE_LEFT(Word x) { Word a; a = (x & 0x80000000) >> 27; return (x << 1) | a;}static Word ROTATE_RIGHT(Word x) { Word a; a = x & 0x00000010; return (x >> 1) | (a << 27);}/*** The S Box transformations and the permutation P are combined in the vectors** s_p0 - s_p7. Permutation E and the MOD 2 addition with the intermediate key** are then done "inline" on each round. The intermediate key is already in a** a 8x6bit form because of the modified permuation PC2 used.*/#if !defined(WORDS_BIGENDIAN)#define DES(t, ik) \{ \ register Word l, r, reg32, round; \ register unsigned char *bb; \ INITIAL_PERMUTATION(t, l, r); \ for(bb = (unsigned char *) ik, round = 0x8000; round; bb += 8, round >>= 1) { \ register Word w = (r << 1) | (r >> 31); \ reg32 = s_p7[( w & 0x3f) ^ bb[4]]; \ reg32 |= s_p6[((w >>= 4) & 0x3f) ^ bb[5]]; \ reg32 |= s_p5[((w >>= 4) & 0x3f) ^ bb[6]]; \ reg32 |= s_p4[((w >>= 4) & 0x3f) ^ bb[7]]; \ reg32 |= s_p3[((w >>= 4) & 0x3f) ^ bb[0]]; \ reg32 |= s_p2[((w >>= 4) & 0x3f) ^ bb[1]]; \ reg32 |= s_p1[((w >> 4) & 0x3f) ^ bb[2]]; \ reg32 |= s_p0[(((r & 0x1) << 5) | ((r & 0xf8000000) >> 27)) ^ bb[3]]; \ reg32 ^= l; \ l = r; \ r = reg32; \ } \ FINAL_PERMUTATION(r, l, t); \}#define MAKE_LITTLE_ENDIAN(t, s) \{ \ register unsigned int z, l = s/4; \ register Word *tp = (Word *) t; \ for(z = 0; z < l; ++z) tp[z] = htonl(tp[z]); \}#else /* WORDS_BIGENDIAN */#define DES(t, ik) \{ \ register Word l, r, reg32, round; \ register unsigned char *bb; \ INITIAL_PERMUTATION(t, l, r); \ for(bb = (unsigned char *) ik, round = 0x8000; round; bb += 8, round >>= 1) { \ register Word w = (r << 1) | (r >> 31); \ reg32 = s_p7[( w & 0x3f) ^ bb[7]]; \ reg32 |= s_p6[((w >>= 4) & 0x3f) ^ bb[6]]; \ reg32 |= s_p5[((w >>= 4) & 0x3f) ^ bb[5]]; \ reg32 |= s_p4[((w >>= 4) & 0x3f) ^ bb[4]]; \ reg32 |= s_p3[((w >>= 4) & 0x3f) ^ bb[3]]; \ reg32 |= s_p2[((w >>= 4) & 0x3f) ^ bb[2]]; \ reg32 |= s_p1[((w >> 4) & 0x3f) ^ bb[1]]; \ reg32 |= s_p0[(((r & 0x1) << 5) | ((r & 0xf8000000) >> 27)) ^ bb[0]]; \ reg32 ^= l; \ l = r; \ r = reg32; \ } \ FINAL_PERMUTATION(r, l, t); \}#endif /* WORDS_BIGENDIAN */intqfDES(unsigned char *key, unsigned char *data, unsigned int size,const QFDES_what what,const QFDES_mode mode, unsigned char *initVec){ /* Store some info to optimise for multiple calls ... */ static unsigned char desKey[8], desKeys[128]; static Word *oldKey = (Word *) desKey, *keys = (Word *) desKeys; static QFDES_what oldWhat; static QFDES_mode oldMode; unsigned char b0[8], b1[8]; /* feedback blocks */ Word *newKey = (Word *) key, /* key from user */ *text, /* text to be [en|de]crypted */ *cb = (Word *) b0, /* the chained block in CBC mode */ *cb1 = (Word *) b1; /* a copy for use when decrypting */#if !defined(WORDS_BIGENDIAN) unsigned int origSize = size; MAKE_LITTLE_ENDIAN(key, 8); MAKE_LITTLE_ENDIAN(data, origSize);#endif /* ** Check new key against old key ** and set up intermediate keys. */ if (newKey[0] != oldKey[0] || newKey[1] != oldKey[1]) { Word c, d; /* C and D registers */ oldKey[0] = newKey[0]; oldKey[1] = newKey[1]; oldWhat = what; oldMode = mode; PC1(newKey, c, d); if ((what == qfDES_encrypt) || (mode == qfDES_cfb) || (mode == qfDES_ofb)) { int z; Word r; Word *k = keys; Word rol[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1}; for(z = 0; z < 16; z++, k += 2) { for (r = 0; r < rol[z]; r++) { c = ROTATE_LEFT(c); d = ROTATE_LEFT(d); } PC2(c, d, k); } } else { int z; Word r; Word *k = keys; Word ror[16] = {0, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1}; for(z = 0; z < 16; z++, k += 2) { r = 0; while (ror[z] > r) { r++; c = ROTATE_RIGHT(c); d = ROTATE_RIGHT(d); } PC2(c, d, k); } } } else if ((what != oldWhat) && ((mode == qfDES_ecb) || (mode == qfDES_cbc))) { /* ** Same key but different direction. ** Reverse intermediate key sequence (ECB and CBC). */ Word *ik1, *ik2, ik3[2]; for(ik1 = keys, ik2 = &(keys[30]); ik1 < ik2; ik1 += 2, ik2 -= 2) { ik3[0] = ik1[0]; ik3[1] = ik1[1]; ik1[0] = ik2[0]; ik1[1] = ik2[1]; ik2[0] = ik3[0]; ik2[1] = ik3[1]; } oldWhat = what; } /* Set up initilaisation vector */ if (mode != qfDES_ecb) { if (initVec) { { cb[0] = ((Word *) initVec)[0]; cb[1] = ((Word *) initVec)[1]; } } else { cb[0] = 0; cb[1] = 0; }#if !defined(WORDS_BIGENDIAN) MAKE_LITTLE_ENDIAN(cb, 8);#endif } /* ** Lots of gotos and code duplication follow (arrgh) but it speeds ** it up a wee bit! ** What would be more useful is looking more carefully at the DES ** permutations to produce more efficient versions of the macros ** of the "auto-generated" versions used in qfDES-aux.c. */ size >>= 3; /* this is always a multpile of 8 */ if (what == qfDES_encrypt) { switch ((int) mode) { case ((int) qfDES_ecb): goto _ECB_; case ((int) qfDES_cbc): goto _CBC_encrypt_; case ((int) qfDES_cfb): goto _CFB_encrypt_; case ((int) qfDES_ofb): goto _OFB_; } } else { switch ((int) mode) { case ((int) qfDES_ecb): goto _ECB_; case ((int) qfDES_cbc): goto _CBC_decrypt_; case ((int) qfDES_cfb): goto _CFB_decrypt_; case ((int) qfDES_ofb): goto _OFB_; } }_ECB_: /* ECB */ for(text = (Word *) data; size; --size, text += 2) { DES(text, keys); } goto _exit_qfDES_;_CBC_encrypt_: /* CBC Encryption */ for(text = (Word *) data; size; --size, text += 2) { /* chaining block */ text[0] ^= cb[0]; text[1] ^= cb[1]; DES(text, keys); /* set up chaining block for next round */ cb[0] = text[0]; cb[1] = text[1]; } goto _initVec_;_CBC_decrypt_: /* CBC Decryption */ for(text = (Word *) data; size; --size, text += 2) { /* set up chaining block */ /* ** The decryption is done in place so I need ** to copy this text block for the next round. */ cb1[0] = text[0]; cb1[1] = text[1]; DES(text, keys); /* chaining block for next round */ text[0] ^= cb[0]; text[1] ^= cb[1]; /* ** Copy back the saved encrypted text - this makes ** CBC decryption slower than CBC encryption. */ cb[0] = cb1[0]; cb[1] = cb1[1]; } goto _initVec_;_CFB_encrypt_: /* CFB Encryption */ for(text = (Word *) data; size; --size, text += 2) { /* use cb as the feedback block */ DES(cb, keys); text[0] ^= cb[0]; text[1] ^= cb[1]; /* set up feedback block for next round */ cb[0] = text[0]; cb[1] = text[1]; } goto _initVec_;_CFB_decrypt_: /* CFB Decryption */ for(text = (Word *) data; size; --size, text += 2) { /* set up feedback block */ /* ** The decryption is done in place so I need ** to copy this text block for the next round. */ cb1[0] = text[0]; cb1[1] = text[1]; /* use cb as the feedback block */ DES(cb, keys); text[0] ^= cb[0]; text[1] ^= cb[1]; /* set up feedback block for next round */ cb[0] = cb1[0]; cb[1] = cb1[1]; } goto _initVec_;_OFB_: /* OFB */ for(text = (Word *) data; size; --size, text += 2) { /* use cb as the feed back block */ DES(cb, keys); text[0] ^= cb[0]; text[1] ^= cb[1]; }_initVec_: /* ** Copy the final chained block back to initVec (CBC, CFB and OFB). ** This allows the [en|de]cryption of large amounts of data in small ** chunks. */ if (initVec) { ((Word *) initVec)[0] = cb[0]; ((Word *) initVec)[1] = cb[1];#if !defined(WORDS_BIGENDIAN) MAKE_LITTLE_ENDIAN(initVec, 8);#endif }_exit_qfDES_:#if !defined(WORDS_BIGENDIAN) MAKE_LITTLE_ENDIAN(key, 8); MAKE_LITTLE_ENDIAN(data, origSize);#endif return 0;}/*** This function sets bit 8 of each byte to odd or even parity as requested.** It is assumed that the right-most bit of each byte is the parity bit.** Although this is really only used by the two key generation functions below,** it may be useful to someone.*/void qfDES_setParity(unsigned char *ptr, unsigned int size, const QFDES_parity parity){ unsigned int i, mask, bits; for(i = 0; i < size; ++i, ++ptr) { for(mask = 0x80, bits = 0; mask > 0x01; mask >>= 1) if (((unsigned int) *ptr) & mask) ++bits; *ptr |= bits % 2 == (unsigned int) parity ? 0x00 : 0x01; }}unsigned int qfDES_checkParity(unsigned char *ptr, unsigned int size, const QFDES_parity parity){ unsigned int i, mask, bits, parityBit, parityErrors = 0; for(i = 0; i < size; ++i, ++ptr) { for(mask = 0x80, bits = 0; mask > 0x01; mask >>= 1) if (((unsigned int) *ptr) & mask) ++bits; parityBit = bits % 2 == (unsigned int) parity ? 0 : 1; if ((((unsigned int) *ptr) & 0x1) != parityBit) ++parityErrors; } return parityErrors;}staticunsigned char weakKeys[18][8] ={{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, {0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe}, {0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e}, {0xe0, 0xe0, 0xe0, 0xe0, 0xf1, 0xf1, 0xf1, 0xf1}, {0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe}, {0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01}, {0x1f, 0xe0, 0x1f, 0xe0, 0x0e, 0xf1, 0x0e, 0xf1}, {0xe0, 0x1f, 0xe0, 0x1f, 0xf1, 0x0e, 0xf1, 0x0e}, {0x01, 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1}, {0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1, 0x01}, {0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe}, {0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e}, {0x01, 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e}, {0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e, 0x01}, {0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1, 0xfe}, {0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1}};/*** Although this is really only used by the key generation function below,** it may be handy to someone.*/int qfDES_checkWeakKeys(unsigned char *key){ unsigned char *bp; int i; for(bp = weakKeys[i = 0]; i < 18; bp = weakKeys[++i]) if (memcmp((void *) key, (void *) bp, 8) == 0) return -1; return 0;}/*** The following function attempts to genreate a random key or IV.** It relies on the randomness of the of the random(3) function. Although** it is probably not particularly fast, keys and IV will most probably be** generated off-line so it does not matter too much.*/unsigned char *qfDES_generate(const QFDES_generate what){ static unsigned char buffer[8]; static int flag = 0; unsigned char *bp; long mask = what == qfDES_key ? 0xfe : 0xff; /* Set up a seed - 42 is the answer ... */ if (!flag) { lbl_srandom((int) (getpid() * 42) ^ (int) time((time_t *) 0)); flag = 1; } do { for(bp = buffer; bp <= &(buffer[7]); *bp++ = (unsigned char) (lbl_random() & mask)); if (what == qfDES_key) qfDES_setParity(buffer, 8, qfDES_odd); } while(what == qfDES_key ? qfDES_checkWeakKeys(buffer) : 0); return buffer;}unsigned charqfDES_setPad(unsigned char pad){ unsigned char b = G_padChar; G_padChar = pad; return b; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -