Encryption and decryption process based on CBC and DES

1, Introduction 1. Password classification: ...
1, Introduction 1. Password classification:

According to whether there is a key or not, the current cipher algorithms can be divided into keyless cipher and keyless cipher. Keyless cipher mainly includes hash function and message digest, while keyed cipher can be divided into symmetric cipher and asymmetric cipher, also known as private key cipher and public key cipher. For example, RSA algorithm belongs to public key cryptosystem, and the most important part of private key cipher is block cipher.

2. Group password:

Because the length of plaintext is uncertain, it is unrealistic to encrypt all plaintext directly with a certain algorithm, so we divide an arbitrary plaintext into several plaintext blocks with length of b bits, so we can encrypt each plaintext block with a certain standardized algorithm and then realize the encryption of all plaintext.

3. Design principle of block cipher:

**1) Diffusion: * * make each bit in the plaintext affect many bits in the ciphertext, that is, one bit in the ciphertext is affected by many bits in the plaintext, and each bit in the key affects many bits in the ciphertext. The basic operation is permutation.
**2) Obfuscation: * * eliminate statistical characteristics, so that the dependence between plaintext key and ciphertext becomes as complex as possible, and complex nonlinear substitution transformation will produce better obfuscation effect. The basic operation is to replace substitution.

4. DES encryption algorithm:

As a symmetric cryptosystem, the plaintext is grouped by 64 bits, and the key is 64 bits long. In fact, the key is 56 bits participating in DES operation (the 8th, 16th, 24th, 32nd, 40th, 48th, 56th and 64th bits are check bits, so that each key has an odd number of 1s. After grouping, the plaintext group and the 56 bit key are replaced or exchanged by bits to form a ciphertext group encryption method.

2, Algorithm flow chart

The figure below shows the overall framework of the algorithm. The plaintext is read in as a file, and the key is user-defined.
DES encryption algorithm uses the feistel structure, and the packet length is 64 bits.
For a 64 bit plaintext, an IP permutation is performed first. For example, the first 58 in the table means to move the 58th bit of plaintext to the first.
This only plays a role in disrupting the plaintext, and hardly improves the security.

The following figure shows the 16 round cyclic encryption algorithm flow. First, the plaintext to be encrypted is divided into left and right blocks, and the block on the right is directly used as the left input of the next round. At the same time, we use a round function with round key to process the block on the right, and perform an exclusive or operation between the result obtained and the input on the left of the previous round (if the first round is plaintext). The result is obtained As input to the right of the next round.

3, Source code

The project is divided into three documents: main.cpp ,des.h, des.cpp

//des.h #ifndef DES_H_INCLUDED #define DES_H_INCLUDED #include <iostream> #include <string> using namespace std; typedef const unsigned char TABLE; // Initial replacement IP table static TABLE IP_Table[64] = { 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 }; // Table of inverse initial displacement IP1 static TABLE IP1_Table[64] = { 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29, 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25 }; // Extended permutation table E static TABLE EXTENSION_Table[48] = { 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1 }; // S box design static TABLE S_Box[8][4][16] = { // S box 1 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13, // S box 2 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9, // S box 3 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12, // Box 4 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14, // S box 5 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3, // S box 6 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13, // S box 7 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12, // Box 8 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 }; // P box replacement table static TABLE P_Table[32] = { 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 }; // Key replacement table static TABLE PC1_Table[56] = { 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 }; // Compression replacement table static TABLE PC2_Table[48] = { 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 }; // Number of bits moved per round static TABLE SHIFT_Table[16] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 }; string byte2bit(string byte); string bit2byte(string bit); void get_roundkey(string* roundkey, string key); string transform(string bit, TABLE* table, int length); string B2C(string B, int i); #endif // DES_H_INCLUDED //des.cpp #include "des.h" string byte2bit(string byte) {//String to bit string int length = byte.length(); string bit(length * 8, 0); for (int i = 0; i < length; i++) { for (int j = 0; j < 8; j++) { bit[i * 8 + j] = (byte[i] >> (7 - j)) & 1; } } return bit; } string bit2byte(string bit) {//Bit string to string int length = bit.length() / 8; string byte(length, 0); for (int i = 0; i < length; i++) { byte[i] = 0; for (int j = 0; j < 8; j++) byte[i] = (byte[i] << 1) + bit[i * 8 + j]; } return byte; } string transform(string bit, TABLE* table, int length) { //Matrix permutation string tmp(length, 0); for (int i = 0; i < length; i++) tmp[i] = bit[table[i] - 1]; return tmp; } void get_roundkey(string* roundkey, string key) {//Get subkey string bit_key = byte2bit(key); string transformed_key = transform(bit_key, PC1_Table, 56);//PC1 is a process of selecting and rearranging 64 bit data string C(transformed_key, 0, 28); string D(transformed_key, 28, 28); for (int i = 0; i < 16; i++)//Rotate the data to the left. The specific shift is related to the number of encryption rounds { C = C.substr(SHIFT_Table[i]) + C.substr(0, SHIFT_Table[i]); D = D.substr(SHIFT_Table[i]) + D.substr(0, SHIFT_Table[i]); roundkey[i] = transform(C + D, PC2_Table, 48);//After the left shift, we mix the two parts of data, and use PC2's table to make a replacement, that is, we get 48 bit round key } } string B2C(string B,int i)//Use S box { int row=B[0]*2+B[5]; int col=B[1]*8+B[2]*4+B[3]*2+B[4]; int s=S_Box[i][row - 1][col - 1]; string C; for(i=3;i>=0;i--) C+=(int(s>>i)&1);//6 in 4 out S box return C; } //main.cpp #include <iostream> #include <fstream> #include <sstream> #include <string> #include "des.h" #include "des.cpp" enum MODE{encrypt,decrypt}mode;//Identify whether to encrypt or decrypt using namespace std; string enfunction(string R,string K); string encryption(string L,string R,string* K); string des(string data,string key); string CBC(string data,string key,string init_vector); string stringxor(string a,string b); string hex_to_bit(string hex); string bit_to_hex(string bit); void output(string s); string roundkey[16];//Round key string hex_to_bit(string hex)//Hexadecimal string to bit string { int length=hex.length(); string bit(length*4,0); for (int i=0;i<length;i++) { hex[i]-=48; if (hex[i]>9) hex[i]-=7; for (int j=0;j<4;j++) bit[i*4+j]=(hex[i]>>(3-j))&1; } return bit; } string bit_to_hex(string bit)//Bit string to sixteen base string { int length=bit.length()/4; string hex(length,0); for(int i=0;i<length;i++) { hex[i]=0; for(int j=0;j<4;j++) hex[i]=(hex[i]<<1)+bit[i*4+j]; hex[i]+=48; if (hex[i]>57) hex[i]+=7; } return hex; } void output(string s)//Output binary string { cout<<s.length()<<"\t"; for(int i=0;i<(int)s.length();i++) { if(s[i]==1) cout<<1; else cout<<0; } cout<<endl; } string stringxor(string a,string b)//String exclusive or, combining the binary exclusive or of each character { for (int i=0;i<(int)a.length();i++) a[i]^=b[i]; return a; } string enfunction(string R,string K)//f function { string ER=transform(R,EXTENSION_Table,48);//E-expansion, expanding a 32-bit data to 48 bits string BS=stringxor(ER,K);//Exclusive or with round key string f; for(int i=0;i<8;i++) { string B(BS.substr(i*6,6));//Take 6 bits string C=B2C(B,i);//C is 4 bits. S box converts 6 bits of data into 4 bits f+=C; } return f;//F cycle 8 rounds, change to 32-bit data } string encryption(string L,string R,string* K)//16 iterations { if(mode==encrypt) { for(int i=0;i<16;i++) { string tmp(L);//Save left L=R;//Assign right to left R=stringxor(tmp,enfunction(R,K[i]));//Right side is exclusive or with left side after encryption through S box // cout << "L" << i + 1 << ":\t"; // output(L); // cout << "R" << i + 1 << ":\t"; // output(R); } } else { for(int i=15;i>=0;i--) { string tmp(R); R=L; L=stringxor(tmp,enfunction(L,K[i])); // cout << "L" << 16 - i << ":\t"; // output(L); // cout << "R" << 16 - i << ":\t"; // output(R); } } return transform(L+R,IP1_Table,64);//IP1 replacement is the reverse process of IP replacement cout<<endl; } string des(string data,string key)//DES implementation of single block encryption and decryption { string bit_data; if (mode==encrypt)//Convert information to binary strings bit_data=byte2bit(data); else bit_data=hex_to_bit(data); // Cout < < information binary:; // output(bit_data); bit_data =transform(bit_data,IP_Table,64);//For a 64 bit plaintext, we first perform an IP permutation // Cout < < displacement binary:; // output(bit_data); string L(bit_data,0,32); string R(bit_data,32,32); string result=encryption(L,R,roundkey); if (mode==encrypt) return bit_to_hex(result); else return bit2byte(result); } string CBC(string data,string key,string init_vector)//Group link mode { string result; string block; string tmp; string initvector(init_vector); if(mode==encrypt) { for(int i=0;i<int(data.length()>>3);i++)//Move 3 bits to the right, i.e. divide by 8 { block=data.substr(i*8,8);//Get the 8-length string starting from the i * 8 bit in the string cout<<"The first"<<i+1<<"Block plaintext:"<<block<<"\t "; tmp=des(stringxor(block,initvector),key);//XOR string and key cout<<"The first"<<i+1<<"Block ciphertext:"<<tmp<<endl; initvector = bit2byte(hex_to_bit(tmp));//Modify vector result+=tmp; } cout<<"Complete ciphertext:"; } else { for(int i=0;i<int(data.length()>>4);i++)//16 in a group { tmp=data.substr(i*16,16); cout<<"The first"<<i+1<<"Block ciphertext:"<<tmp<<"\t "; block=stringxor(des(tmp,key),initvector); cout<<"The first"<<i+1<<"Block plaintext:"<<block<<endl; initvector=bit2byte(hex_to_bit(tmp)); result+=block; } cout<<"Complete clear text:"<<endl; } cout<<result<<endl<<endl; return result; } int main() { ifstream datafile("text.txt");//Create FileStream objects ostringstream buf;//Read the file into the ostringstream character stream object buf buf<<datafile.rdbuf();// Enter characters from the file stream into the string stream string plaintext=buf.str();//Returns the string associated with the stream object buf cout<<"Clear text:"; cout<<plaintext<<endl; string key("abc10101");//Set key get_roundkey(roundkey, key);//Round key, 16 round keys are generated from the original key, and 16 round keys are the same when each single block is encrypted. // for(int y=0;y<16;y++) // { // cout<<"roundkey "<<y+1<<": "; // output(roundkey[y]); // } char c=0; while(plaintext.length()%8!=0)//Auto fill 0 if the plaintext is less than 8 bits plaintext+=c; string ciphertext; string init_vector=key; //Set initial vector for grouping links mode=encrypt;//Start encryption ciphertext=CBC(plaintext,key,init_vector); mode=decrypt;//Indicates start decryption plaintext=CBC(ciphertext,key,init_vector); return 0; }
4, Test of experimental results

18 June 2020, 07:04 | Views: 7445

Add new comment

For adding a comment, please log in
or create account

0 comments