home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 1999 October / PCpro_1999_10.ISO / Tools / vbcrypt / Control / Source / DES_CLS.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-23  |  13.1 KB  |  441 lines

  1. #include "stdafx.h"
  2. /// DES
  3.  
  4. // Die erste Permutation vertauscht die Bits des zu verschlⁿsselnden Textes. Laut der
  5. // folgenden Tabelle mu▀ das Bit 0 an die Position 58, Bit 1 an die Position 50, Bit 3 an 
  6. // Position 42 etc.
  7.  
  8. static int iIniPerm[64]={ 57,49,41,33,25,17, 9, 1,59,51,43,35,27,19,11, 3,
  9.                           61,53,45,37,29,21,13, 5,63,55,47,39,31,23,15, 7,
  10.                           56,48,40,32,24,16, 8, 0,58,50,42,34,26,18,10, 2,
  11.                           60,52,44,36,28,20,12, 4,62,54,46,38,30,22,14, 6 };
  12.  
  13. DWORD dwIniPermMask[64][2];
  14.  
  15. // Anzahl der Bits, die die 28-Bit HΣlften des 56-Bit Key je Runde nach links zu rotieren sind
  16. static int iRoundRotate[16] = { 1,1,2,2,2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
  17.  
  18. // Die folgende Tabelle wird ben÷tigt, um aus dem 64-Bit Schlⁿssel einen 56-Bit Schlⁿssel
  19. // zu erzeugen. Jedes achte Bit wird ignoriert und au▀erdem werden die Bits vertuascht.
  20. // Die Tabelle ist wie folgt zu lesen:
  21. // Das 57-Bit im 64-Bit Key, kommt an Position 0 im 56-Bit Key. Bit 46(64-Bit Key) kommt an Position 1 (56-Bit Key)
  22.  
  23. // KeyPermutation
  24. static int iKeyPerm[56] = { 56,48,40,32,24,16, 8, 0,57,49,41,33,25,17,
  25.                              9, 1,58,50,42,34,26,18,10, 2,59,51,43,35,
  26.                             62,54,46,38,30,22,14, 6,61,53,45,37,29,21,
  27.                             13, 5,60,52,44,36,28,20,12, 4,27,19,11,3 };
  28. static DWORD dwKeyPermMask[56][2];
  29.  
  30.  
  31. // Welche der 56-Bits gehen in den 48-Bit Schlⁿssel ein?
  32. // Compression Permutation
  33. static int iComPerm[48] = { 13,16,10,23, 0, 4, 2,27,14, 5,20, 9,
  34.                             22,18,11, 3,25, 7,15, 6,26,19,12, 1,
  35.                             40,51,30,36,46,54,29,39,50,44,32,47,
  36.                             43,48,38,55,33,52,45,41,49,35,28,31 };
  37. static DWORD dwComPermMask[48][2];
  38.  
  39.  
  40. static int iExpPerm[48] = { 31, 0, 1, 2, 3, 4, 3, 4, 5, 6, 7, 8,
  41.                              7, 8, 9,10,11,12,11,12,13,14,15,16,
  42.                             15,16,17,18,19,20,19,20,21,22,23,24,
  43.                             23,24,25,26,27,28,27,28,29,30,31, 0 };
  44. static DWORD dwExpPermMask[48];
  45.  
  46. static char SBoxes[8][4][16] = { // S-Box 1
  47.                           { { 14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7 },
  48.                             {  0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8 },
  49.                             {  4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0 },
  50.                             { 15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13 } },
  51.                           // S-Box 2
  52.                           { { 15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10 },
  53.                             {  3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5 },
  54.                             {  0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15 },
  55.                             { 13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9 } },
  56.                           // S-Box 3
  57.                           { { 10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8 },
  58.                             { 13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1 },
  59.                             { 13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7 },
  60.                             {  1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12 } },
  61.                           // S-Box 4
  62.                           { {  7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15 },
  63.                             { 13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9 },
  64.                             { 10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4 },
  65.                             {  3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2, 14} },
  66.                           // S-Box 5
  67.                           { {  2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9},
  68.                             { 14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6},
  69.                             {  4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14},
  70.                             { 11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3} }, 
  71.                           // S-Box 6
  72.                           { { 12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11},
  73.                             { 10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8},
  74.                             {  9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6},
  75.                             {  4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13} },
  76.                           //S-Box 7
  77.                           { {  4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1},
  78.                             { 13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6},
  79.                             {  1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2},
  80.                             {  6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12} },
  81.                           // S-Box 8
  82.                           { { 13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7},
  83.                             {  1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2},
  84.                             {  7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8},
  85.                             {  2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11 } } };
  86.  
  87. static int iPBoxPerm[32] = { 15, 6,19,20,28,11,27,16, 0,14,22,25, 4,17,30, 9,
  88.                               1, 7,23,13,31,26, 2, 8,18,12,29, 5,21,10, 3,24};
  89. static DWORD dwPBoxPermMask[32];
  90.  
  91. void DES::BuildPermutationMasks()
  92. {
  93.   int i;
  94.  
  95.   for( i = 0; i < 64; i++ )
  96.   {
  97.     // Aus den Bitposition werden Bitmasken erzeugt, damit sich die Bits 
  98.     // einfacher vertauschen lassen. In InitialPermutation() wirden dazu 
  99.     // die zu vertauschenden Original-Bits durchlaufen, um einen neuen 
  100.     // 64-Bit Wert "zusammenzubasteln". Neben der InitialPermutation wird
  101.     // auf die FinalPermutation erzeugt.
  102.  
  103.     if( iIniPerm[i] >= 32 )
  104.     {
  105.       dwIniPermMask[i][0]= (1<<(iIniPerm[i]-32));
  106.       dwIniPermMask[i][1]= 0;
  107.     }
  108.     else
  109.     {
  110.       dwIniPermMask[i][0]= 0;
  111.       dwIniPermMask[i][1]= (1<<iIniPerm[i]);
  112.     }
  113.   }
  114.  
  115.   for( i = 0; i < 56; i++ )
  116.   {
  117.     if( iKeyPerm[i] >= 32 )
  118.     {
  119.       dwKeyPermMask[i][0]= (1<<(iKeyPerm[i]-32));
  120.       dwKeyPermMask[i][1]= 0;
  121.     }
  122.     else
  123.     {
  124.       dwKeyPermMask[i][0]= 0;
  125.       dwKeyPermMask[i][1]= (1<<iKeyPerm[i]);
  126.     }
  127.   }
  128.  
  129.   for( i = 0; i < 48; i++ )
  130.   {
  131.     if( iComPerm[i] >= 32 )
  132.     {
  133.       dwComPermMask[i][0]= (1<<(iComPerm[i]-32));
  134.       dwComPermMask[i][1]= 0;
  135.     }
  136.     else
  137.     {
  138.       dwComPermMask[i][0]= 0;
  139.       dwComPermMask[i][1]= (1<<iComPerm[i]);
  140.     }
  141.   }
  142.  
  143.   for( i = 0; i < 48; i++ )
  144.     dwExpPermMask[i] = (1<<iExpPerm[i]);
  145.  
  146.   for( i = 0; i < 32; i++ )
  147.     dwPBoxPermMask[i] = (1<<iPBoxPerm[i]);
  148. }
  149.  
  150. DES::~DES()
  151. {
  152.   memset( &RoundKeys, 0, sizeof( ROUNDKEYS ) );
  153. }
  154.  
  155. DES::DES()
  156. {
  157.   BuildPermutationMasks();  
  158. }
  159.  
  160. void DES::InitialPermutation( DWORD *PlainText, DWORD *dwPermutation )
  161. {
  162.   DWORD dwResult[2];
  163.   DWORD dwWorkingCopy[2];
  164.   int i;
  165.  
  166.   // Arbeitskopie des zu verschlⁿsselnden Textes anlegen
  167.   dwWorkingCopy[0]=PlainText[0];
  168.   dwWorkingCopy[1]=PlainText[1];
  169.  
  170.   // Ergebnis l÷schen
  171.   dwResult[0]=0;
  172.   dwResult[1]=0;
  173.  
  174.   for( i = 63; i >= 32; i-- )
  175.   {
  176.     if( ( ( dwWorkingCopy[0] & dwIniPermMask[i][0] ) == 
  177.                                dwIniPermMask[i][0] ) &&
  178.         ( ( dwWorkingCopy[1] & dwIniPermMask[i][1] ) == 
  179.                                dwIniPermMask[i][1] ) ) 
  180.       dwResult[0] |= (1<<(i-32));
  181.   }
  182.  
  183.   for( i = 31; i >= 0; i-- )
  184.   {
  185.     if( ( ( dwWorkingCopy[0] & dwIniPermMask[i][0] ) == 
  186.                                dwIniPermMask[i][0] ) &&
  187.         ( ( dwWorkingCopy[1] & dwIniPermMask[i][1] ) == 
  188.                                dwIniPermMask[i][1] ) ) 
  189.       dwResult[1] |= (1<<i);
  190.   }
  191.  
  192.   dwPermutation[0] = dwResult[0];
  193.   dwPermutation[1] = dwResult[1];
  194. }
  195.  
  196. void DES::FinalPermutation( DWORD *CryptText, DWORD *dwPermutation )
  197. {
  198.   DWORD dwResult[2];
  199.   DWORD dwWorkingCopy[2];
  200.   int i;
  201.  
  202.   // Arbeitskopie des zu verschlⁿsselnden Textes anlegen
  203.   dwWorkingCopy[0]=CryptText[0];
  204.   dwWorkingCopy[1]=CryptText[1];
  205.  
  206.   // Ergebnis l÷schen
  207.   dwResult[0]=0;
  208.   dwResult[1]=0;
  209.  
  210.  
  211.   for( i = 63; i >= 32; i-- )
  212.   {
  213.     if( dwWorkingCopy[0] & ( 1 << (i-32) ) )
  214.     {
  215.       dwResult[0] |= dwIniPermMask[i][0];
  216.       dwResult[1] |= dwIniPermMask[i][1];
  217.     }
  218.   }
  219.  
  220.   for( i = 31; i >= 0; i-- )
  221.   {
  222.     if( dwWorkingCopy[1] & ( 1 << i ) )
  223.     {
  224.       dwResult[0] |= dwIniPermMask[i][0];
  225.       dwResult[1] |= dwIniPermMask[i][1];
  226.     }
  227.   }
  228.  
  229.   dwPermutation[0] = dwResult[0];
  230.   dwPermutation[1] = dwResult[1];
  231. }
  232.  
  233.  
  234. void DES::KeyPermutation( DWORD *Key64, DWORD *Key56 )
  235. {
  236.   int i;
  237.   
  238.   // 56-Bit Schlⁿssel l÷schen    
  239.   Key56[0]=0;
  240.   Key56[1]=0;
  241.  
  242.  
  243.   for( i = 55; i >= 32; i-- )
  244.   {
  245.     if( ( ( Key64[0] & dwKeyPermMask[i][0] ) == 
  246.                        dwKeyPermMask[i][0] ) &&
  247.         ( ( Key64[1] & dwKeyPermMask[i][1] ) == 
  248.                        dwKeyPermMask[i][1] ) ) 
  249.       Key56[0] |= (1<<(i-32));
  250.   }
  251.  
  252.   for( i = 31; i >= 0; i-- )
  253.   {
  254.     if( ( ( Key64[0] & dwKeyPermMask[i][0] ) == 
  255.                        dwKeyPermMask[i][0] ) &&
  256.         ( ( Key64[1] & dwKeyPermMask[i][1] ) == 
  257.                        dwKeyPermMask[i][1] ) ) 
  258.       Key56[1] |= (1<<i);
  259.   }
  260. }
  261.  
  262. void DES::Compress( DWORD *Key56, DWORD *Key48 )
  263. {
  264.   int i;
  265.   
  266.   // 56-Bit Schlⁿssel l÷schen    
  267.   Key48[0]=0;
  268.   Key48[1]=0;
  269.  
  270.  
  271.   for( i = 47; i >= 32; i-- )
  272.   {
  273.     if( ( ( Key56[0] & dwComPermMask[i][0] ) == 
  274.                        dwComPermMask[i][0] ) &&
  275.         ( ( Key56[1] & dwComPermMask[i][1] ) == 
  276.                        dwComPermMask[i][1] ) ) 
  277.       Key48[0] |= (1<<(i-32));
  278.   }
  279.  
  280.   for( i = 31; i >= 0; i-- )
  281.   {
  282.     if( ( ( Key56[0] & dwComPermMask[i][0] ) == 
  283.                        dwComPermMask[i][0] ) &&
  284.         ( ( Key56[1] & dwComPermMask[i][1] ) == 
  285.                        dwComPermMask[i][1] ) ) 
  286.       Key48[1] |= (1 << i);
  287.   }
  288. }
  289.  
  290. void DES::CreateRoundKeys( ROUNDKEYS *keys, DWORD *dw56Key, BOOL bDecrypt )
  291. {     
  292.   DWORD dw28Left;   // Die linke und rechte 28-Bit HΣlfte des 56-Bit Schlⁿssels
  293.   DWORD dw28Right;
  294.   DWORD dw28LeftOverhang,
  295.         dw28RightOverhang;
  296.   DWORD dwUseKey56[2];
  297.   int i;
  298.   
  299.   // Die oberen 28 Bitt:
  300.   dw28Left = (dw56Key[0] << 4 ) | ( dw56Key[1] & 0xF0000000 ) >> 28;
  301.   // die unteren 28 Bit:
  302.   dw28Right= dw56Key[1] & 0x0FFFFFFF;
  303.   
  304.   for( i = 0; i < 16; i++ )
  305.   {
  306.     if( iRoundRotate[i] == 1 ) // IN Jeder Runde wird der halbe Schlⁿssel nur 1 oder 2 Bit rotiert
  307.     {
  308.       dw28LeftOverhang = (dw28Left & 0x01 ) << 27;
  309.       dw28RightOverhang = (dw28Right & 0x1 ) << 27;
  310.     }
  311.     else
  312.     {
  313.       dw28LeftOverhang = (dw28Left & 0x3 ) << 26;
  314.       dw28RightOverhang = (dw28Right & 0x3 ) << 26;
  315.     }
  316.  
  317.     dw28Left >>= iRoundRotate[i];
  318.     dw28Left |= dw28LeftOverhang;
  319.  
  320.     dw28Right >>= iRoundRotate[i];
  321.     dw28Right |= dw28RightOverhang;
  322.  
  323.     dwUseKey56[0] = dw28Left>>4;
  324.     dwUseKey56[1] = (dw28Left<<28) | dw28Right; 
  325.  
  326.     Compress( dwUseKey56, &keys->dwKeys48[bDecrypt?(15-i):i][0] );
  327.   }
  328. }
  329.  
  330. void DES::Expand( DWORD dw32Bit, DWORD *dw48Bit )
  331. {
  332.   int i;
  333.   
  334.   dw48Bit[0]=0;
  335.   dw48Bit[1]=0;
  336.  
  337.   for( i = 47; i >= 32; i-- )
  338.   {
  339.     if( ( dw32Bit & dwExpPermMask[i] ) ==  dwExpPermMask[i] )
  340.       dw48Bit[0] |= (1<<(i-32));
  341.   }
  342.  
  343.   for( i = 31; i >= 0; i-- )
  344.   {
  345.     if( ( dw32Bit & dwExpPermMask[i] ) ==  dwExpPermMask[i] )
  346.       dw48Bit[1] |= (1 << i);
  347.   }
  348. }
  349.  
  350. void DES::SBox( DWORD *dw48Bit, DWORD *dw32Bit )
  351. {
  352.   int s[8];
  353.   int i, row,col;
  354.   // Isoliere die 8 6-Bit Gruppen
  355.   for( i = 0; i < 8; i++ )
  356.   {
  357.     s[i] = dw48Bit[1] & 0x0000003F;
  358.     dw48Bit[1] >>= 6;
  359.     dw48Bit[1] |= (dw48Bit[0] & 0x0000003F) << 26;
  360.     dw48Bit[0] >>= 6;
  361.   }
  362.  
  363.   *dw32Bit = 0;
  364.   for( i = 7; i >= 0; i-- )
  365.   {
  366.     
  367.     row = ( s[i] & 0x20 ) >> 4;
  368.     row |= ( s[i] & 0x1 );
  369.  
  370.     col = ( s[i] & 0x1E ) >> 1;
  371.  
  372.     *dw32Bit <<= 4; // Platz fⁿr 4 But schaffen
  373.     *dw32Bit |= SBoxes[i][row][col]; // Sbox hinzu
  374.   }
  375. }
  376.  
  377. void DES::PBox( DWORD *dw32Bit )
  378. {
  379.   DWORD dwCopy;
  380.   int i;
  381.       
  382.   dwCopy = *dw32Bit;
  383.  
  384.   *dw32Bit = 0;
  385.   for( i=0; i < 32; i++ )
  386.     if( dwCopy & dwPBoxPermMask[i] )
  387.       *dw32Bit |= (1 << i);
  388. }
  389.  
  390. void DES::BuildEncryptionKey( DWORD *dw64Key )
  391. {
  392.   DWORD dw56Key[2];
  393.   
  394.   KeyPermutation( dw64Key, dw56Key );
  395.   CreateRoundKeys( &RoundKeys, dw56Key, FALSE ); // Achtung! Auch dwKey56 Σndert sich!
  396.   dw56Key[0]=0; // Nie was ⁿbriglassen
  397.   dw56Key[1]=0;
  398. }
  399.  
  400. void DES::BuildDecryptionKey( DWORD *dw64Key )
  401. {
  402.   DWORD dw56Key[2];
  403.  
  404.   KeyPermutation( dw64Key, dw56Key );
  405.   CreateRoundKeys( &RoundKeys, dw56Key, TRUE ); // Achtung! Auch dwKey56 Σndert sich!
  406.   dw56Key[0]=0; // Nie was ⁿbriglassen
  407.   dw56Key[1]=0;
  408. }
  409.  
  410. void DES::Codec( DWORD *dw64BitIn, DWORD *dw64BitOut )
  411. {
  412.   int i;
  413.   DWORD dwWorkingCopy[2];
  414.   DWORD left, right;
  415.   DWORD dw48Bit[2];
  416.   DWORD dwSaveRight;
  417.  
  418.   InitialPermutation( dw64BitIn, dwWorkingCopy );
  419.  
  420.   left = dwWorkingCopy[0];
  421.   right = dwWorkingCopy[1];
  422.  
  423.   for( i = 0; i < 16; i++ ) 
  424.   {
  425.     dwSaveRight = right;
  426.  
  427.     Expand( right, dw48Bit );
  428.     dw48Bit[0] ^= RoundKeys.dwKeys48[i][0];
  429.     dw48Bit[1] ^= RoundKeys.dwKeys48[i][1];
  430.  
  431.     SBox( dw48Bit, &right );
  432.     PBox( &right );
  433.     right ^= left;
  434.     left = dwSaveRight;
  435.   }
  436.  
  437.   dwWorkingCopy[0] = right;
  438.   dwWorkingCopy[1] = left;
  439.   FinalPermutation( dwWorkingCopy, dw64BitOut );
  440. }
  441.