adamj@web5h.berkeley.edu (Adam J. Richter) (02/10/88)
Here's a note for you cryptography wizards out there. Assuming that there isn't some kind of bug in the program I used to deduce this, I think I've found an interesting property of the S-boxes. I have no idea how this might be useful and I have no idea whether this property is a strength of DES, a weakness of DES, an irrelevant artifact of DES, or a bug in my program. (Source code is at the end.) Consider the following question. For s-box S, input bit I, and output bit O, how many input bit combinations that have input bit I set result in output bit O being set, for s-box S? (Or, "how many input-ouptput pairs for s-box S have both input bit I and output bit O set?") The average should be 16. Half of the 64 6-bit inputs will have input bit I set and an average of half of those comibinations should result in output bit O being one; half will result in output bit O being zero. It seems that the last two input bits of *ALL* the s-boxes follow this prediction exactly, as does the 3rd-to-the-last input bit of the last s-box and the first bit of the second. There are plenty of other combinations for which there is a 50/50 chance of input bit I being set, given that output bit O of s-box S is also set. However, there are no other places where all output bits for some input bit, or all input bits for some output bit, have this property. The next page is the output of my program, editted for readability. I've seperated the last two input bits to illustrate my point. The page after the next is the source code to the program that generated the table. (I've edited the output a bit.) A bug in the program is not unlikely. I played with DES a few months ago and then found other things to do. --Adam J. Richter adamj@widow.berkeley.edu In how many of the possible input combinations are both input bit I and output bit O set? Input bit (I): 0 1 2 3 4 5 S-box 0: output bit 0: 15 17 18 17 16 16 output bit 1: 15 15 15 17 16 16 output bit 2: 15 15 13 15 16 16 output bit 3: 17 15 14 16 16 16 S-box 1: output bit 0: 16 15 16 16 16 16 output bit 1: 16 17 17 14 16 16 output bit 2: 16 17 15 16 16 16 output bit 3: 16 16 15 16 16 16 S-box 2: output bit 0: 17 14 16 16 16 16 output bit 1: 15 16 19 17 16 16 output bit 2: 16 17 16 17 16 16 output bit 3: 16 16 15 17 16 16 S-box 3: output bit 0: 16 15 14 15 16 16 output bit 1: 18 15 16 15 16 16 output bit 2: 18 15 16 17 16 16 output bit 3: 16 17 18 15 16 16 S-box 4: output bit 0: 18 17 16 17 16 16 output bit 1: 15 15 17 15 16 16 output bit 2: 15 16 16 16 16 16 output bit 3: 18 16 15 16 16 16 S-box 5: output bit 0: 16 16 17 17 16 16 output bit 1: 16 17 15 16 16 16 output bit 2: 17 17 14 16 16 16 output bit 3: 17 17 17 14 16 16 S-box 6: output bit 0: 16 16 14 15 16 16 output bit 1: 17 17 16 17 16 16 output bit 2: 18 16 15 16 16 16 output bit 3: 17 18 14 15 16 16 S-box 7: output bit 0: 17 15 16 16 16 16 output bit 1: 16 15 17 16 16 16 output bit 2: 15 16 16 16 16 16 output bit 3: 15 17 15 16 16 16 [The rest of this posting is source code. Hitting "n" now would be a good idea.] ------------------------------ CUT HERE ------------------------------------ static char S[8][64] = { 14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7, 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8, 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, 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, 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, 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, 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, 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, 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, 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, }; static char flagTable[64][16]; /* from,to */ static char numOnes[6][4]; /* frombit, tobit */ void ClearOnesTable () { int frombit, tobit; for (frombit = 0; frombit < 6; frombit++) for (tobit = 0; tobit < 4; tobit++) numOnes[frombit][tobit] = '\0'; } void BuildOnesTable (sbox) int sbox; { int frombit, tobit; int from; for (frombit = 0; frombit < 6; frombit++) { int frommask = 1 << frombit; for (tobit = 0; tobit < 4; tobit++) { int tomask = 1 << tobit; for (from = 0; from < 64; from++) if ((from & frommask) && (S[sbox][from] & tomask)) numOnes[frombit][tobit]++; } } } void PrintOnesTable_Vertically () { int frombit, tobit; for (frombit = 0; frombit < 6; frombit++) { int total_to = -64; printf ("from bit %d: ", frombit); for (tobit = 0; tobit < 4; tobit++) { printf (" %d", numOnes[frombit][tobit]); total_to += numOnes [frombit][tobit]; } printf (" (%d)", total_to); printf ("\n"); } } void PrintOnesTable_Horizontally () { int frombit, tobit; for (tobit = 0; tobit < 4; tobit++) { int total_from = -16*6; printf ("output bit %d: ", tobit); for (frombit = 0; frombit < 6; frombit++) { printf (" %d", numOnes[frombit][tobit]); total_from += numOnes [frombit][tobit]; } printf (" (%2d)", total_from); printf ("\n"); } } void DoOnesTable (sbox) int sbox; { ClearOnesTable (); BuildOnesTable (sbox); printf ("S-box %d:\n", sbox); PrintOnesTable_Horizontally (); } void ClearFlagTable () { int from, to; for (from = 0; from < 64; from++) for (to = 0; to < 16; to++) flagTable[from][to] = 0; } void AddFlagTable (boxNum) int boxNum; { int from, to; for (from = 0; from < 64; from++) { to = S [boxNum][from]; flagTable [from][to]++; } } void DisplayVertically () { int from, to; for (from = 0; from < 64; from++) { if (from < 10) printf (" %d: ", from); else printf ("%d: ", from); for (to = 0; to < 16; to++) if (flagTable[from][to]) printf ("%x", flagTable[from][to]); else printf (" "); printf ("\n"); } } void DisplayHorizontally () { int from, to; for (to = 0; to < 16; to++) { if (to < 10) printf (" %d: ", to); else printf ("%d: ", to); for (from = 0; from < 64; from++) { if (flagTable[from][to]) printf ("%x", flagTable[from][to]); else printf (" "); } printf ("\n"); } } int TotalDistance (to) int to; { int from; int result = 0; for (from = 0; from < 64; from++) result += flagTable [from][to]*from; return result; } main (argc, argv) int argc; char **argv; { int sbox; for (sbox = 0; sbox < 8; sbox++) DoOnesTable (sbox); } Adam J. Richter adamj@widow.berkeley.edu ....!ucbvax!widow!adamj Home: (415)549-6377 Sun room: (415)642-7762
lindsay@kelpie.newcastle.ac.uk (Lindsay F. Marshall) (02/15/88)
One of the crytopgraphy gurus (I cant remember which one) published a paper on this last year. He showed the regularity, but couldnt find a way to compromise DES using it. Lindsay -- Lindsay F. Marshall, Computing Lab., U of Newcastle upon Tyne, Tyne & Wear, UK ARPA: lindsay%cheviot.newcastle@nss.cs.ucl.ac.uk JANET: lindsay@uk.ac.newcastle.cheviot UUCP: <UK>!ukc!cheviot!lindsay