//--------------------------------------------------------------------------- #include #pragma hdrstop #include "des.h" //--------------------------------------------------------------------------- #pragma package(smart_init) //--------------------------------------------------------------------------- #define ps(n) ((unsigned char) (0x80 >> (n-1))) #define b(n,r) ((n > r || n < r-7) ? 0 : ps(n-(r-8))) #define P(n) b(n,8),b(n,16),b(n,24),b(n,32), \ b(n,40),b(n,48),b(n,56),b(n,64) #define Q(n) P((n)+4) struct ks { unsigned char ki[6]; }; struct LR { long Left; long Right; }; static struct ks keys[16]; unsigned char Pmask[] = { // Permutation Mask... P( 1),P( 2),P( 3),P( 4),P( 5),P( 6),P( 7),P( 8), P( 9),P(10),P(11),P(12),P(13),P(14),P(15),P(16), P(17),P(18),P(19),P(20),P(21),P(22),P(23),P(24), P(25),P(26),P(27),P(28),P(29),P(30),P(31),P(32), P(33),P(34),P(35),P(36),P(37),P(38),P(39),P(40), P(41),P(42),P(43),P(44),P(45),P(46),P(47),P(48), P(49),P(50),P(51),P(52),P(53),P(54),P(55),P(56), P(57),P(58),P(59),P(60),P(61),P(62),P(63),P(64) }; unsigned char IPtbl[] = { // Initail and inverse permuation tbl... P(58),P(50),P(42),P(34),P(26),P(18),P(10),P( 2), P(60),P(52),P(44),P(36),P(28),P(20),P(12),P( 4), P(62),P(54),P(46),P(38),P(30),P(22),P(14),P( 6), P(64),P(56),P(48),P(40),P(32),P(24),P(16),P( 8), P(57),P(49),P(41),P(33),P(25),P(17),P( 9),P( 1), P(59),P(51),P(43),P(35),P(27),P(19),P(11),P( 3), P(61),P(53),P(45),P(37),P(29),P(21),P(13),P( 5), P(63),P(55),P(47),P(39),P(31),P(23),P(15),P( 7) }; unsigned char Etbl[] = { // Permutation tbl for E and F function... P(32),P( 1),P( 2),P( 3),P( 4),P( 5), P( 4),P( 5),P( 6),P( 7),P( 8),P( 9), P( 8),P( 9),P(10),P(11),P(12),P(13), P(12),P(13),P(14),P(15),P(16),P(17), P(16),P(17),P(18),P(19),P(20),P(21), P(20),P(21),P(22),P(23),P(24),P(25), P(24),P(25),P(26),P(27),P(28),P(29), P(28),P(29),P(30),P(31),P(32),P( 1) }; unsigned char Ptbl[] = { // permutaion tbl for P and f function... P(16),P( 7),P(20),P(21),P(29),P(12),P(28),P(17), P( 1),P(15),P(23),P(26),P( 5),P(18),P(31),P(10), P( 2),P( 8),P(24),P(14),P(32),P(27),P( 3),P( 9), P(19),P(13),P(30),P( 6),P(22),P(11),P( 4),P(25) }; unsigned char stbl[8][4][16] = { // 6 & 4 bits stream... 14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7, // s1 8,15,7,4,14,2,13,1,10,6,12,11,9,5,3,0, 4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0, 15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13, 15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10, // s2 3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5, 0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15, 13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9, 10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8, // s3 13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1, 13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7, 1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12, 7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15, // s4 13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9, 10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4, 3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14, 2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9, // s5 14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6, 4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14, 11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3, 12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11, // s6 10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8, 9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6, 4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13, 4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1, // s7 13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6, 1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2, 6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12, 13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7, // s8 1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2, 7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8, 2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11 }; unsigned char PC1tbl[] = { // permuted choice 1 for key schedule calculation P(57),P(49),P(41),P(33),P(25),P(17),P( 9), P( 1),P(58),P(50),P(42),P(34),P(26),P(18), P(10),P( 2),P(59),P(51),P(43),P(35),P(27), P(19),P(11),P( 3),P(60),P(52),P(44),P(36), P( 0),P( 0),P( 0),P( 0), P(63),P(55),P(47),P(39),P(31),P(23),P(15), P( 7),P(62),P(54),P(46),P(38),P(30),P(22), P(14),P( 6),P(61),P(53),P(45),P(37),P(29), P(21),P(13),P( 5),P(28),P(20),P(12),P( 4), P( 0),P( 0),P( 0),P( 0) }; unsigned char PC2tbl[] = { // permuted choice 2 for key calc... P(14),P(17),P(11),P(24),P( 1),P( 5),P( 3),P(28), P(15),P( 6),P(21),P(10),P(23),P(19),P(12),P( 4), P(26),P( 8),P(16),P( 7),P(27),P(20),P(13),P( 2), Q(41),Q(52),Q(31),Q(37),Q(47),Q(55),Q(30),Q(40), Q(51),Q(45),Q(33),Q(48),Q(44),Q(49),Q(39),Q(56), Q(34),Q(53),Q(46),Q(42),Q(50),Q(36),Q(29),Q(32) }; unsigned char ex6[8][2][4] = { // For extracting 6bits from 64-bit stream 0,2,0,0x3f, // BYTE >>, << & 0,2,0,0x3f, // s = 8 0,0,4,0x30, // s = 7 1,4,0,0x0f, 1,0,2,0x3c, // s = 6 2,6,0,0x03, 2,0,0,0x3f, // s = 5 2,0,0,0x3f, 3,2,0,0x3f, // s = 4 3,2,0,0x3f, 3,0,4,0x30, // s = 3 4,4,0,0x0f, 4,0,2,0x3c, // s = 2 5,6,0,0x03, 5,0,0,0x3f, // s = 1 5,0,0,0x3f }; //--------------------------------------------------------------------------- static unsigned char oddparity(unsigned char s) { unsigned char c = s | 0x80; /// while ( s ) { if ( s & 1 ) c ^= 0x80; s = ( s >> 1 ) & 0x7f; } return c; } //--------------------------------------------------------------------------- static void setparity(unsigned char *key) { int i; for ( i = 0 ; i < 8 ; i++ ) *(key+i) = oddparity(*(key+i)); } //--------------------------------------------------------------------------- static void permute(long *op, long *ip, long *tbl, int n) { int i; long *pt = (long *)Pmask; *op = *(op+1) = 0; for ( i = 0 ; i < n ; i++) { if ((*ip & *tbl) || (*(ip+1) & *(tbl+1))) { *op |= *pt; *(op+1) |= *(pt+1); } tbl += 2; pt += 2; } } //--------------------------------------------------------------------------- static void rotate(unsigned char *c, int n) { int i; unsigned j,k; k = ((*c) & 0xff) >> (8 - n); for ( i = 3 ; i >= 0; --i) { j = ((*(c+i) << n) + k); k = (j >> 8) & 0xff; *(c+i) = j & 0xff; } if ( n == 2 ) *(c+3) = (*(c+3) & 0xc0) | ((*(c+3) << 4) & 0x30); else *(c+3) = (*(c+3) & 0xe0) | ((*(c+3) << 4) & 0x10); } //--------------------------------------------------------------------------- static struct ks KS(int n, unsigned char *key) { static unsigned char cd[8]; static int its[] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1}; union { struct ks kn; struct LR filter; } result; if ( n == 0 ) permute((long *)cd, (long *)key, (long *) PC1tbl,64); rotate(cd,its[n]); rotate(cd+4,its[n]); permute(&result.filter.Left,(long *)cd, (long *)PC2tbl,48); return result.kn; } //--------------------------------------------------------------------------- void initkey(unsigned char *key) { int i; for ( i = 0 ; i < 16 ; i++) keys[i] = KS(i,key); } //--------------------------------------------------------------------------- static void inverse_permute(long *op, long *ip, long *tbl, int n) { int i; long *pt = (long *)Pmask; *op = *(op+1) = 0; for ( i = 0 ; i < n; i++) { if ((*ip & *pt) || (*(ip+1) & *(pt+1))) { *op |= *tbl; *(op+1) |= *(tbl+1); } tbl += 2; pt += 2; } } //--------------------------------------------------------------------------- static void swapbyte(long *l) { unsigned char *cp = (unsigned char *) l; unsigned char t = *(cp + 3); *(cp + 3) = *cp; *cp = t; t = *(cp + 2); *(cp + 2) = *(cp + 1); *(cp + 1) = t; } //--------------------------------------------------------------------------- static sixbits(struct ks k, int s) { int op = 0; int n = s; int i; for ( i = 0 ; i < 2 ; i++ ) { int off =ex6[n][i][0]; unsigned char c = k.ki[off]; c >>= ex6[n][i][1]; c <<= ex6[n][i][2]; c &= ex6[n][i][3]; op |= c; } return op; } //--------------------------------------------------------------------------- static int fourbits(struct ks k, int s) { int i = sixbits(k,s); int row, col; row = ((i >> 4) & 2) | (i & 1); col = (i >> 1) & 0xf; return stbl[s][row][col]; } //--------------------------------------------------------------------------- static long f(long blk, struct ks key) { struct LR ir,or; union { struct LR f; struct ks kn; } tr = {0,0}, kr = {0,0}; int i; ir.Left = blk; ir.Right = 0; kr.kn = key; swapbyte(&ir.Left); swapbyte(&ir.Right); permute(&tr.f.Left,&ir.Left,(long *)Etbl, 48); tr.f.Left ^= kr.f.Left; tr.f.Right ^= kr.f.Right; ir.Left = 0; for ( i = 0 ; i < 8 ; i++) { long four = fourbits(tr.kn,i); ir.Left |= four << ((7 - i) * 4); } swapbyte(&ir.Left); ir.Right = or.Right = 0; permute(&or.Left,&ir.Left,(long *)Ptbl, 32); swapbyte(&or.Left); swapbyte(&or.Right); return or.Left; } //--------------------------------------------------------------------------- void __fastcall encrypt(unsigned char *key, unsigned char *blk) { struct LR ip, op; long temp; int n; setparity(key); initkey(key); memcpy(&ip,blk,sizeof(struct LR)); permute(&op.Left,&ip.Left,(long *)IPtbl,64); // Initial permuation... swapbyte(&op.Left); swapbyte(&op.Right); for ( n = 0 ; n < 16 ; n++) { // swap and key iteration... temp = op.Right; op.Right = op.Left ^ f(op.Right,keys[n]); op.Left = temp; } ip.Right = op.Left; ip.Left = op.Right; swapbyte(&ip.Left); swapbyte(&ip.Right); inverse_permute(&op.Left,&ip.Left,(long *)IPtbl, 64); memcpy(blk,&op,sizeof(struct LR)); } //--------------------------------------------------------------------------- void __fastcall decrypt(unsigned char *key, unsigned char *blk) { struct LR ip, op; long temp; int n; setparity(key); initkey(key); memcpy(&ip,blk,sizeof(struct LR)); permute(&op.Left,&ip.Left,(long *)IPtbl,64); // Initial permuation... swapbyte(&op.Left); swapbyte(&op.Right); ip.Right = op.Left; ip.Left = op.Right; for ( n = 15 ; n >= 0 ; --n) { // swap and key iteration... temp = ip.Left; ip.Left = ip.Right ^ f(ip.Left,keys[n]); ip.Right = temp; } swapbyte(&ip.Left); swapbyte(&ip.Right); // Inverse initial permute inverse_permute(&op.Left,&ip.Left,(long *)IPtbl, 64); memcpy(blk,&op,sizeof(struct LR)); } //---------------------------------------------------------------------------