void DataBlockEncryptor::Encrypt( unsigned char *input, int inputLength, unsigned char *output, int *outputLength ) { unsigned index, byteIndex, lastBlock; unsigned long checkSum; unsigned char paddingBytes; unsigned char encodedPad; unsigned char randomChar; CheckSum checkSumCalculator; #ifdef _DEBUG assert( keySet ); #endif assert( input && inputLength ); // randomChar will randomize the data so the same data sent twice will not look the same randomChar = ( unsigned char ) randomMT(); // 16-(((x-1) % 16)+1) // # of padding bytes is 16 -(((input_length + extra_data -1) % 16)+1) paddingBytes = ( unsigned char ) ( 16 - ( ( ( inputLength + sizeof( randomChar ) + sizeof( checkSum ) + sizeof( encodedPad ) - 1 ) % 16 ) + 1 ) ); // Randomize the pad size variable encodedPad = ( unsigned char ) randomMT(); encodedPad <<= 4; encodedPad |= paddingBytes; *outputLength = inputLength + sizeof( randomChar ) + sizeof( checkSum ) + sizeof( encodedPad ) + paddingBytes; // Write the data first, in case we are overwriting ourselves if ( input == output ) memmove( output + sizeof( checkSum ) + sizeof( randomChar ) + sizeof( encodedPad ) + paddingBytes, input, inputLength ); else memcpy( output + sizeof( checkSum ) + sizeof( randomChar ) + sizeof( encodedPad ) + paddingBytes, input, inputLength ); // Write the random char memcpy( output + sizeof( checkSum ), ( char* ) & randomChar, sizeof( randomChar ) ); // Write the pad size variable memcpy( output + sizeof( checkSum ) + sizeof( randomChar ), ( char* ) & encodedPad, sizeof( encodedPad ) ); // Write the padding for ( index = 0; index < paddingBytes; index++ ) *( output + sizeof( checkSum ) + sizeof( randomChar ) + sizeof( encodedPad ) + index ) = ( unsigned char ) randomMT(); // Calculate the checksum on the data checkSumCalculator.add( output + sizeof( checkSum ), inputLength + sizeof( randomChar ) + sizeof( encodedPad ) + paddingBytes ); checkSum = checkSumCalculator.get(); // Write checksum memcpy( output, ( char* ) & checkSum, sizeof( checkSum ) ); // AES on the first block secretKeyAES128.encrypt16( output ); lastBlock = 0; // Now do AES on every other block from back to front for ( index = *outputLength - 16; index >= 16; index -= 16 ) { for ( byteIndex = 0; byteIndex < 16; byteIndex++ ) output[ index + byteIndex ] ^= output[ lastBlock + byteIndex ]; secretKeyAES128.encrypt16( output + index ); lastBlock = index; } }
bool DataBlockEncryptor::Decrypt( unsigned char *input, int inputLength, unsigned char *output, int *outputLength ) { unsigned index, byteIndex, lastBlock; unsigned long checkSum; unsigned char paddingBytes; unsigned char encodedPad; unsigned char randomChar; CheckSum checkSumCalculator; #ifdef _DEBUG assert( keySet ); #endif if ( input == 0 || inputLength < 16 || ( inputLength % 16 ) != 0 ) { return false; } // Unchain in reverse order for ( index = 16; ( int ) index <= inputLength - 16;index += 16 ) { secretKeyAES128.decrypt16( input + index ); for ( byteIndex = 0; byteIndex < 16; byteIndex++ ) { if ( index + 16 == ( unsigned ) inputLength ) input[ index + byteIndex ] ^= input[ byteIndex ]; else input[ index + byteIndex ] ^= input[ index + 16 + byteIndex ]; } lastBlock = index; }; // Decrypt the first block secretKeyAES128.decrypt16( input ); // Read checksum memcpy( ( char* ) & checkSum, input, sizeof( checkSum ) ); // Read the pad size variable memcpy( ( char* ) & encodedPad, input + sizeof( randomChar ) + sizeof( checkSum ), sizeof( encodedPad ) ); // Ignore the high 4 bytes paddingBytes = encodedPad & 0x0F; // Get the data length *outputLength = inputLength - sizeof( randomChar ) - sizeof( checkSum ) - sizeof( encodedPad ) - paddingBytes; // Calculate the checksum on the data. checkSumCalculator.add( input + sizeof( checkSum ), *outputLength + sizeof( randomChar ) + sizeof( encodedPad ) + paddingBytes ); if ( checkSum != checkSumCalculator.get() ) return false; // Read the data if ( input == output ) memmove( output, input + sizeof( randomChar ) + sizeof( checkSum ) + sizeof( encodedPad ) + paddingBytes, *outputLength ); else memcpy( output, input + sizeof( randomChar ) + sizeof( checkSum ) + sizeof( encodedPad ) + paddingBytes, *outputLength ); return true; }