// 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()); }