• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

DataBlockEncryptor.cpp

Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 #include "DataBlockEncryptor.h"
00009 #include "CheckSum.h"
00010 #include "GetTime.h"
00011 #include "Rand.h"
00012 #include "RakAssert.h"
00013 #include <string.h>
00014 #include "Rijndael.h"
00015 //#include "Types.h"
00016 
00017 DataBlockEncryptor::DataBlockEncryptor()
00018 {
00019         keySet = false;
00020 }
00021 
00022 DataBlockEncryptor::~DataBlockEncryptor()
00023 {}
00024 
00025 bool DataBlockEncryptor::IsKeySet( void ) const
00026 {
00027         return keySet;
00028 }
00029 
00030 void DataBlockEncryptor::SetKey( const unsigned char key[ 16 ] )
00031 {
00032         keySet = true;
00033         //secretKeyAES128.set_key( key );
00034         makeKey(&keyEncrypt, DIR_ENCRYPT, 16, (char*)key);
00035         makeKey(&keyDecrypt, DIR_DECRYPT, 16, (char*)key);
00036         cipherInit(&cipherInst, MODE_ECB, 0); // ECB is not secure except that I chain manually farther down.
00037 }
00038 
00039 void DataBlockEncryptor::UnsetKey( void )
00040 {
00041         keySet = false;
00042 }
00043 
00044 void DataBlockEncryptor::Encrypt( unsigned char *input, unsigned int inputLength, unsigned char *output, unsigned int *outputLength, RakNetRandom *rnr )
00045 {
00046         unsigned index, byteIndex, lastBlock;
00047         unsigned int checkSum;
00048         unsigned char paddingBytes;
00049         unsigned char encodedPad;
00050         unsigned char randomChar;
00051         CheckSum checkSumCalculator;
00052 
00053 #ifdef _DEBUG
00054 
00055         RakAssert( keySet );
00056 #endif
00057 
00058         RakAssert( input && inputLength );
00059 
00060 
00061         // randomChar will randomize the data so the same data sent twice will not look the same
00062         randomChar = (unsigned char) rnr->RandomMT();
00063 
00064         // 16-(((x-1) % 16)+1)
00065 
00066         // # of padding bytes is 16 -(((input_length + extra_data -1) % 16)+1)
00067         paddingBytes = (unsigned char) ( 16 - ( ( ( inputLength + sizeof( randomChar ) + sizeof( checkSum ) + sizeof( encodedPad ) - 1 ) % 16 ) + 1 ) );
00068 
00069         // Randomize the pad size variable
00070         encodedPad = (unsigned char) rnr->RandomMT();
00071         encodedPad <<= 4;
00072         encodedPad |= paddingBytes;
00073 
00074         *outputLength = inputLength + sizeof( randomChar ) + sizeof( checkSum ) + sizeof( encodedPad ) + paddingBytes;
00075 
00076         // Write the data first, in case we are overwriting ourselves
00077 
00078         if ( input == output )
00079                 memmove( output + sizeof( checkSum ) + sizeof( randomChar ) + sizeof( encodedPad ) + paddingBytes, input, inputLength );
00080         else
00081                 memcpy( output + sizeof( checkSum ) + sizeof( randomChar ) + sizeof( encodedPad ) + paddingBytes, input, inputLength );
00082 
00083         // Write the random char
00084         memcpy( output + sizeof( checkSum ), ( char* ) & randomChar, sizeof( randomChar ) );
00085 
00086         // Write the pad size variable
00087         memcpy( output + sizeof( checkSum ) + sizeof( randomChar ), ( char* ) & encodedPad, sizeof( encodedPad ) );
00088 
00089         // Write the padding
00090         for ( index = 0; index < paddingBytes; index++ )
00091                 *( output + sizeof( checkSum ) + sizeof( randomChar ) + sizeof( encodedPad ) + index ) = (unsigned char) rnr->RandomMT();
00092 
00093         // Calculate the checksum on the data
00094         checkSumCalculator.Add( output + sizeof( checkSum ), inputLength + sizeof( randomChar ) + sizeof( encodedPad ) + paddingBytes );
00095 
00096         checkSum = checkSumCalculator.Get();
00097 
00098         // Write checksum
00099 #ifdef HOST_ENDIAN_IS_BIG
00100         output[0] = checkSum&0xFF;
00101         output[1] = (checkSum>>8)&0xFF;
00102         output[2] = (checkSum>>16)&0xFF;
00103         output[3] = (checkSum>>24)&0xFF;
00104 #else
00105         memcpy( output, ( char* ) & checkSum, sizeof( checkSum ) );
00106 #endif
00107 
00108         // AES on the first block
00109 //      secretKeyAES128.encrypt16( output );
00110         blockEncrypt(&cipherInst, &keyEncrypt, output, 16, output);
00111 
00112         lastBlock = 0;
00113 
00114         // Now do AES on every other block from back to front
00115         for ( index = *outputLength - 16; index >= 16; index -= 16 )
00116         {
00117                 for ( byteIndex = 0; byteIndex < 16; byteIndex++ )
00118                         output[ index + byteIndex ] ^= output[ lastBlock + byteIndex ];
00119 
00120                 //secretKeyAES128.encrypt16( output + index );
00121                 blockEncrypt(&cipherInst, &keyEncrypt, output+index, 16, output+index);
00122 
00123                 lastBlock = index;
00124         }
00125 }
00126 
00127 bool DataBlockEncryptor::Decrypt( unsigned char *input, unsigned int inputLength, unsigned char *output, unsigned int *outputLength )
00128 {
00129         unsigned index, byteIndex;
00130         unsigned int checkSum;
00131         unsigned char paddingBytes;
00132         unsigned char encodedPad;
00133         unsigned char randomChar;
00134         CheckSum checkSumCalculator;
00135 #ifdef _DEBUG
00136 
00137         RakAssert( keySet );
00138 #endif
00139 
00140         if ( input == 0 || inputLength < 16 || ( inputLength % 16 ) != 0 )
00141         {
00142                 return false;
00143         }
00144 
00145         // Unchain in reverse order
00146         for ( index = 16; index <= inputLength - 16;index += 16 )
00147         {
00148         //      secretKeyAES128.decrypt16( input + index );
00149                 blockDecrypt(&cipherInst, &keyDecrypt, input + index, 16, output + index);
00150 
00151                 for ( byteIndex = 0; byteIndex < 16; byteIndex++ )
00152                 {
00153                         if ( index + 16 == ( unsigned ) inputLength )
00154                                 output[ index + byteIndex ] ^= input[ byteIndex ];
00155                         else
00156                                 output[ index + byteIndex ] ^= input[ index + 16 + byteIndex ];
00157                 }
00158 
00159         //      lastBlock = index;
00160         };
00161 
00162         // Decrypt the first block
00163         //secretKeyAES128.decrypt16( input );
00164         blockDecrypt(&cipherInst, &keyDecrypt, input, 16, output);
00165 
00166         // Read checksum
00167 #ifdef HOST_ENDIAN_IS_BIG
00168         checkSum = (unsigned int)output[0] | (unsigned int)(output[1]<<8) |
00169                 (unsigned int)(output[2]<<16)|(unsigned int)(output[3]<<24);
00170 #else
00171         memcpy( ( char* ) & checkSum, output, sizeof( checkSum ) );
00172 #endif
00173 
00174         // Read the pad size variable
00175         memcpy( ( char* ) & encodedPad, output + sizeof( randomChar ) + sizeof( checkSum ), sizeof( encodedPad ) );
00176 
00177         // Ignore the high 4 bytes
00178         paddingBytes = encodedPad & 0x0F;
00179 
00180 
00181         // Get the data length
00182         *outputLength = inputLength - sizeof( randomChar ) - sizeof( checkSum ) - sizeof( encodedPad ) - paddingBytes;
00183 
00184         // Calculate the checksum on the data.
00185         checkSumCalculator.Add( output + sizeof( checkSum ), *outputLength + sizeof( randomChar ) + sizeof( encodedPad ) + paddingBytes );
00186 
00187         if ( checkSum != checkSumCalculator.Get() )
00188                 return false;
00189 
00190         // Read the data
00191         //if ( input == output )
00192                 memmove( output, output + sizeof( randomChar ) + sizeof( checkSum ) + sizeof( encodedPad ) + paddingBytes, *outputLength );
00193         //else
00194         //      memcpy( output, input + sizeof( randomChar ) + sizeof( checkSum ) + sizeof( encodedPad ) + paddingBytes, *outputLength );
00195 
00196         return true;
00197 }

Generated on Thu Sep 30 2010 01:27:22 for RakNet by  doxygen 1.7.1