// Decrypt data in vector void RC5Simple::RC5_Decrypt(vector<unsigned char> &in, vector<unsigned char> &out) { RC5_LOG(( "\nDecrypt\n" )); // Cleaning output vector out.clear(); out.resize(in.size(), 0); // No decrypt null data if(in.size()==0) return; // Get IV unsigned char iv[RC5_BLOCK_LEN]; for(int i=0; i<RC5_BLOCK_LEN; i++) iv[i]=in[i]; // Set secret key for decrypt RC5_Setup(rc5_key); // Decode by blocks from block with index 1 (from 0 block already read IV) unsigned int data_size=0; unsigned int block=1; while( (RC5_BLOCK_LEN*(block+1))<=in.size() ) { unsigned int shift=block*RC5_BLOCK_LEN; RC5_TWORD temp_word_1; RC5_TWORD temp_word_2; RC5_TWORD pt[RC5_WORDS_IN_BLOCK]; RC5_TWORD ct[RC5_WORDS_IN_BLOCK]; RC5_LOG(( "Block num %d, shift %d\n", block, shift )); temp_word_1=RC5_GetWordFromByte(in[shift], in[shift+1], in[shift+2], in[shift+3]); temp_word_2=RC5_GetWordFromByte(in[shift+RC5_WORD_LEN], in[shift+RC5_WORD_LEN+1], in[shift+RC5_WORD_LEN+2], in[shift+RC5_WORD_LEN+3]); pt[0]=temp_word_1; pt[1]=temp_word_2; // Decode RC5_DecryptBlock(pt, ct); // --------------------------- // Un XOR block with IV vector // --------------------------- // Convert block words to plain array unsigned char ct_part[RC5_BLOCK_LEN]; for(int i=0; i<RC5_WORD_LEN; i++) { ct_part[i]=RC5_GetByteFromWord(ct[0], i); ct_part[i+RC5_WORD_LEN]=RC5_GetByteFromWord(ct[1], i); } // Un XOR for(int i=0; i<RC5_BLOCK_LEN; i++) ct_part[i]^=iv[i]; if(block==1) { data_size=RC5_GetIntFromByte(ct_part[0], ct_part[1], ct_part[2], ct_part[3]); RC5_LOG(( "Decrypt data size: %d\n", data_size )); // Uncorrect decrypt data size if((unsigned int)data_size>(unsigned int)in.size()) return; } #if RC5_ENABLE_DEBUG_PRINT==1 RC5_LOG(( "Pt %.8X, %.8X\n", pt[0], pt[1] )); RC5_LOG(( "Ct %.8X, %.8X\n", ct[0], ct[1] )); #endif // Generate next IV for Cipher Block Chaining (CBC) for(int i=0; i<RC5_BLOCK_LEN; i++) iv[i]=in[shift+i]; // Save decrypt data for(int i=0; i<RC5_BLOCK_LEN; i++) out[shift-RC5_BLOCK_LEN+i]=ct_part[i]; block++; } // Cleaning IV for(int i=0; i<RC5_BLOCK_LEN; i++) iv[i]=0; // Remove from output first byte with length out.erase(out.begin(), out.begin()+RC5_BLOCK_LEN); // Remove from output last byte with random byte for aligning if(out.size()>data_size) out.erase(out.begin()+data_size, out.end()); }
// Decrypt data in vector void RC5Simple::RC5_Decrypt(vector<unsigned char> &in, vector<unsigned char> &out) { RC5_LOG(( "\nDecrypt\n" )); RC5_LOG(( "\nInput data size: %d\n", in.size() )); // No decrypt null data if(in.size()==0) { errorCode=RC5_ERROR_CODE_6; return; } // Detect format version unsigned int formatVersion=0; if(rc5_isSetFormatVersionForce==true) formatVersion=rc5_formatVersion; // If format set force, format not autodetected else { // Signature bytes const char *signature=RC5_SIMPLE_SIGNATURE; // Detect signature bool isSignatureCorrect=true; for(int i=0; i<(RC5_BLOCK_LEN-1); i++) if(in[i]!=signature[i]) isSignatureCorrect=false; // If not detect signature if(isSignatureCorrect==false) formatVersion=RC5_FORMAT_VERSION_1; // In first version can't signature else { // Get format version unsigned char readFormatVersion=in[RC5_BLOCK_LEN-1]; // If format version correct if(readFormatVersion>=RC5_FORMAT_VERSION_2 && readFormatVersion<=RC5_FORMAT_VERSION_CURRENT) formatVersion=readFormatVersion; else formatVersion=RC5_FORMAT_VERSION_1; // If version not correct, may be it format 1 ( probability 0.[hrendesyatih]1 ) } } unsigned int ivShift=0; unsigned int firstDataBlock=0; unsigned int removeBlocksFromOutput=0; unsigned int blockWithDataSize=0; if(formatVersion==RC5_FORMAT_VERSION_1) { ivShift=0; firstDataBlock=1; // Start decode from block with index 1 (from block 0 read IV) removeBlocksFromOutput=1; blockWithDataSize=1; } if(formatVersion==RC5_FORMAT_VERSION_2) { ivShift=RC5_BLOCK_LEN; firstDataBlock=2; // Start decode from block with index 2 (0 - signature and version, 1 - IV) removeBlocksFromOutput=2; // Random data block and size data block blockWithDataSize=3; } if(formatVersion==RC5_FORMAT_VERSION_3) { ivShift=RC5_BLOCK_LEN; firstDataBlock=2; // Start decode from block with index 2 (0 - signature and version, 1 - IV) removeBlocksFromOutput=3; // Two random data block and size data block blockWithDataSize=4; } // Get IV unsigned char iv[RC5_BLOCK_LEN]; for(int i=0; i<RC5_BLOCK_LEN; i++) iv[i]=in[i+ivShift]; // Set secret key for decrypt RC5_Setup(rc5_key); // Cleaning output vector out.clear(); out.resize(in.size(), 0); // Decode by blocks from started data block unsigned int data_size=0; unsigned int block=firstDataBlock; while( (RC5_BLOCK_LEN*(block+1))<=in.size() ) { unsigned int shift=block*RC5_BLOCK_LEN; RC5_TWORD temp_word_1; RC5_TWORD temp_word_2; RC5_TWORD pt[RC5_WORDS_IN_BLOCK]; RC5_TWORD ct[RC5_WORDS_IN_BLOCK]; RC5_LOG(( "Block num %d, shift %d\n", block, shift )); temp_word_1=RC5_GetWordFromByte(in[shift], in[shift+1], in[shift+2], in[shift+3]); temp_word_2=RC5_GetWordFromByte(in[shift+RC5_WORD_LEN], in[shift+RC5_WORD_LEN+1], in[shift+RC5_WORD_LEN+2], in[shift+RC5_WORD_LEN+3]); pt[0]=temp_word_1; pt[1]=temp_word_2; RC5_LOG(( "Block data. Word 1: %.2X, Word 2: %.2X\n", temp_word_1, temp_word_2 )); // Decode RC5_DecryptBlock(pt, ct); // --------------------------- // Un XOR block with IV vector // --------------------------- // Convert block words to plain array unsigned char ct_part[RC5_BLOCK_LEN]; for(int i=0; i<RC5_WORD_LEN; i++) { ct_part[i]=RC5_GetByteFromWord(ct[0], i); ct_part[i+RC5_WORD_LEN]=RC5_GetByteFromWord(ct[1], i); } // Un XOR for(int i=0; i<RC5_BLOCK_LEN; i++) ct_part[i]^=iv[i]; if(block==blockWithDataSize) { data_size=RC5_GetIntFromByte(ct_part[0], ct_part[1], ct_part[2], ct_part[3]); RC5_LOG(( "Decrypt data size: %d\n", data_size )); // Uncorrect decrypt data size if((unsigned int)data_size>(unsigned int)in.size()) { // RC5_LOG(( "Incorrect data size. Decrypt data size: %d, estimate data size: ~%d\n", data_size, in.size() )); errorCode=RC5_ERROR_CODE_7; return; } } #if RC5_ENABLE_DEBUG_PRINT==1 RC5_LOG(( "Pt %.8X, %.8X\n", pt[0], pt[1] )); RC5_LOG(( "Ct %.8X, %.8X\n", ct[0], ct[1] )); #endif // Generate next IV for Cipher Block Chaining (CBC) for(int i=0; i<RC5_BLOCK_LEN; i++) iv[i]=in[shift+i]; // Save decrypt data for(int i=0; i<RC5_BLOCK_LEN; i++) { RC5_LOG(( "Put decrypt data to vector out[%d] = %.2X\n", shift-(removeBlocksFromOutput*RC5_BLOCK_LEN)+i, ct_part[i] )); out[shift-(firstDataBlock*RC5_BLOCK_LEN)+i]=ct_part[i]; } block++; } // Cleaning IV for(int i=0; i<RC5_BLOCK_LEN; i++) iv[i]=0; // Remove from output a blocks with technical data (random blocks, size, etc...) out.erase(out.begin(), out.begin()+removeBlocksFromOutput*RC5_BLOCK_LEN); // Remove from output a last byte with random byte for aligning if(out.size()>data_size) out.erase(out.begin()+data_size, out.end()); }
// Encrypt data in vector void RC5Simple::RC5_Encrypt(vector<unsigned char> &in, vector<unsigned char> &out) { // Clear output vector out.clear(); // No crypt null data if(in.size()==0) return; // Save input data size unsigned int clean_data_size=in.size(); RC5_LOG(( "Input data size: %d\n", clean_data_size )); // IV block unsigned char iv[RC5_BLOCK_LEN]; for(int i=0; i<RC5_BLOCK_LEN; i++) iv[i]=(unsigned char)RC5_Rand(0, 0xFF); // Block with data size unsigned char data_size[RC5_BLOCK_LEN]; for(int i=0; i<RC5_BLOCK_LEN; i++) { data_size[i]=RC5_GetByteFromInt( clean_data_size, i ); RC5_LOG(( "Data size byte %d: %.2X\n", i, data_size[i] )); } // Insert data size to begin data in.insert( in.begin(), RC5_BLOCK_LEN, 0); for(int i=0; i<RC5_BLOCK_LEN; i++) in[i]=data_size[i]; // Align end of data to block size int last_unalign_len=clean_data_size%RC5_BLOCK_LEN; RC5_LOG(( "Last unalign len: %d\n", last_unalign_len )); if(last_unalign_len>0) { // Add random data to end for align to block size for(int i=0; i<(RC5_BLOCK_LEN-last_unalign_len); i++) { RC5_LOG(( "Add byte: %d\n", i )); in.push_back( (unsigned char)RC5_Rand(0, 0xFF) ); } } #if RC5_ENABLE_DEBUG_PRINT==1 RC5_LOG(( "Data size after crypt setup: %d\n", in.size() )); RC5_LOG(( "Plain byte after crypt setup: " )); for(int i=0; i<in.size(); i++) RC5_LOG(( "%.2X ", in[i] )); RC5_LOG(( "\n" )); #endif // ------ // Encode // ------ // Create cell in output vector out.resize(in.size()+RC5_BLOCK_LEN, 0); // Save start IV to first block in output data for(int i=0; i<RC5_BLOCK_LEN; i++) out[i]=iv[i]; // Set secret key for encrypt RC5_Setup(rc5_key); // Encode by blocks unsigned int block=0; while( (RC5_BLOCK_LEN*(block+1))<=in.size() ) { unsigned int shift=block*RC5_BLOCK_LEN; // Temp input buffer for dont modify input data unsigned char temp_in[RC5_BLOCK_LEN]; // XOR block with current IV for(int i=0; i<RC5_BLOCK_LEN; i++) temp_in[i]=in[shift+i] ^ iv[i]; RC5_TWORD temp_word_1; RC5_TWORD temp_word_2; RC5_TWORD pt[RC5_WORDS_IN_BLOCK]; RC5_TWORD ct[RC5_WORDS_IN_BLOCK]; RC5_LOG(( "Block num %d, shift %d\n", block, shift )); temp_word_1=RC5_GetWordFromByte(temp_in[0], temp_in[1], temp_in[2], temp_in[3]); temp_word_2=RC5_GetWordFromByte(temp_in[RC5_WORD_LEN+0], temp_in[RC5_WORD_LEN+1], temp_in[RC5_WORD_LEN+2], temp_in[RC5_WORD_LEN+3]); pt[0]=temp_word_1; pt[1]=temp_word_2; // Encode RC5_EncryptBlock(pt, ct); #if RC5_ENABLE_DEBUG_PRINT==1 RC5_LOG(( "Pt %.8X, %.8X\n", pt[0], pt[1] )); RC5_LOG(( "Ct %.8X, %.8X\n", ct[0], ct[1] )); #endif // Save crypt data for(int i=0; i<RC5_WORD_LEN; i++) { // Save crypt data with shift to RC5_BLOCK_LEN // btw. in first block putted IV out[RC5_BLOCK_LEN+shift+i]=RC5_GetByteFromWord(ct[0], i); out[RC5_BLOCK_LEN+shift+RC5_WORD_LEN+i]=RC5_GetByteFromWord(ct[1], i); } // Generate next IV for Cipher Block Chaining (CBC) for(int i=0; i<RC5_BLOCK_LEN; i++) iv[i]=out[RC5_BLOCK_LEN+shift+i]; block++; } // Cleaning IV for(int i=0; i<RC5_BLOCK_LEN; i++) iv[i]=0; // ----------------------------------- // Return input vector to firsted data // ----------------------------------- // Clear input vector from service data in.erase(in.begin(), in.begin()+RC5_BLOCK_LEN); // Remove from input vector last random byte for aligning if(in.size()>clean_data_size) in.erase(in.begin()+clean_data_size, in.end()); }
// Encrypt data in vector void RC5Simple::RC5_Encrypt(vector<unsigned char> &in, vector<unsigned char> &out) { // Clear output vector out.clear(); // No crypt null data if(in.size()==0) { errorCode=RC5_ERROR_CODE_5; return; } // Save input data size unsigned int clean_data_size=in.size(); RC5_LOG(( "Input data size: %d\n", clean_data_size )); // IV block unsigned char iv[RC5_BLOCK_LEN]; for(int i=0; i<RC5_BLOCK_LEN; i++) iv[i]=(unsigned char)RC5_Rand(0, 0xFF); // Block with data size unsigned char data_size[RC5_BLOCK_LEN]; for(int i=0; i<RC5_BLOCK_LEN; i++) { data_size[i]=RC5_GetByteFromInt( clean_data_size, i ); RC5_LOG(( "Data size byte %d: %.2X\n", i, data_size[i] )); } // Insert data size to begin data in.insert( in.begin(), RC5_BLOCK_LEN, 0); for(int i=0; i<RC5_BLOCK_LEN; i++) in[i]=data_size[i]; // Add firsted random data unsigned int firsRandomDataBlocks=0; if(rc5_formatVersion==RC5_FORMAT_VERSION_2) firsRandomDataBlocks=1; // At start at format version 2, in begin data add one block with random data if(rc5_formatVersion==RC5_FORMAT_VERSION_3) firsRandomDataBlocks=2; // At start at format version 3, in begin data add two blocks with random data (full width is 128 bit) if(firsRandomDataBlocks>0) for(unsigned int n=1; n<=firsRandomDataBlocks; n++) { in.insert( in.begin(), RC5_BLOCK_LEN, 0); for(int i=0; i<RC5_BLOCK_LEN; i++) in[i]=(unsigned char)RC5_Rand(0, 0xFF); } // Align end of data to block size int last_unalign_len=clean_data_size%RC5_BLOCK_LEN; RC5_LOG(( "Last unalign len: %d\n", last_unalign_len )); if(last_unalign_len>0) { // Add random data to end for align to block size for(int i=0; i<(RC5_BLOCK_LEN-last_unalign_len); i++) { RC5_LOG(( "Add byte: %d\n", i )); in.push_back( (unsigned char)RC5_Rand(0, 0xFF) ); } } #if RC5_ENABLE_DEBUG_PRINT==1 RC5_LOG(( "Data size after crypt setup: %d\n", in.size() )); RC5_LOG(( "Plain byte after crypt setup: " )); for(int i=0; i<in.size(); i++) RC5_LOG(( "%.2X ", in[i] )); RC5_LOG(( "\n" )); #endif // ------ // Encode // ------ // Create and fill cell in output vector unsigned int notCryptDataSize=0; // In format version 1 save only IV as open data in block 0 if(rc5_formatVersion==RC5_FORMAT_VERSION_1) { out.resize(in.size()+RC5_BLOCK_LEN, 0); // Save start IV to block 0 in output data for(int i=0; i<RC5_BLOCK_LEN; i++) out[i]=iv[i]; notCryptDataSize=RC5_BLOCK_LEN; } // In format version 2 or higth save format header (block 0) and IV (block 1) if(rc5_formatVersion>=RC5_FORMAT_VERSION_2) { out.resize(in.size()+RC5_BLOCK_LEN*2, 0); // Signature bytes in header const char *signature=RC5_SIMPLE_SIGNATURE; for(int i=0; i<(RC5_BLOCK_LEN-1); i++) out[i]=signature[i]; // Format version byte in header if(rc5_isSetFormatVersionForce) out[RC5_BLOCK_LEN-1]=rc5_formatVersion; else out[RC5_BLOCK_LEN-1]=RC5_FORMAT_VERSION_CURRENT; // Save start IV to second block in output data for(int i=0; i<RC5_BLOCK_LEN; i++) out[i+RC5_BLOCK_LEN]=iv[i]; notCryptDataSize=RC5_BLOCK_LEN*2; } // Set secret key for encrypt RC5_Setup(rc5_key); // Encode by blocks unsigned int block=0; while( (RC5_BLOCK_LEN*(block+1))<=in.size() ) { unsigned int shift=block*RC5_BLOCK_LEN; // Temp input buffer for dont modify input data unsigned char temp_in[RC5_BLOCK_LEN]; // XOR block with current IV for(int i=0; i<RC5_BLOCK_LEN; i++) temp_in[i]=in[shift+i] ^ iv[i]; RC5_TWORD temp_word_1; RC5_TWORD temp_word_2; RC5_TWORD pt[RC5_WORDS_IN_BLOCK]; RC5_TWORD ct[RC5_WORDS_IN_BLOCK]; RC5_LOG(( "Block num %d, shift %d\n", block, shift )); temp_word_1=RC5_GetWordFromByte(temp_in[0], temp_in[1], temp_in[2], temp_in[3]); temp_word_2=RC5_GetWordFromByte(temp_in[RC5_WORD_LEN+0], temp_in[RC5_WORD_LEN+1], temp_in[RC5_WORD_LEN+2], temp_in[RC5_WORD_LEN+3]); pt[0]=temp_word_1; pt[1]=temp_word_2; // Encode RC5_EncryptBlock(pt, ct); #if RC5_ENABLE_DEBUG_PRINT==1 RC5_LOG(( "Pt %.8X, %.8X\n", pt[0], pt[1] )); RC5_LOG(( "Ct %.8X, %.8X\n", ct[0], ct[1] )); #endif // Save crypt data for(int i=0; i<RC5_WORD_LEN; i++) { // Save crypt data with shift to RC5_BLOCK_LEN // btw. in first block putted IV out[notCryptDataSize+shift+i]=RC5_GetByteFromWord(ct[0], i); out[notCryptDataSize+shift+RC5_WORD_LEN+i]=RC5_GetByteFromWord(ct[1], i); } // Generate next IV for Cipher Block Chaining (CBC) for(int i=0; i<RC5_BLOCK_LEN; i++) iv[i]=out[notCryptDataSize+shift+i]; block++; } // Cleaning IV for(int i=0; i<RC5_BLOCK_LEN; i++) iv[i]=0; // ----------------------------------- // Return input vector to firsted data // ----------------------------------- // Remove size block (for all formats) in.erase(in.begin(), in.begin()+RC5_BLOCK_LEN); // Remove random data blocks if(firsRandomDataBlocks>0) for(unsigned int n=1; n<=firsRandomDataBlocks; n++) in.erase(in.begin(), in.begin()+RC5_BLOCK_LEN); // Remove from input vector last random byte for aligning if(in.size()>clean_data_size) in.erase(in.begin()+clean_data_size, in.end()); }