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