
GOST 28147-89 (Part 2. Simple replacement mode)
This article is a continuation of the article on GOST 28147-89 . As mentioned earlier, GOST 28147-89 supports four operating modes, but perhaps the main one is the simple replacement mode, which is used both independently and as an integral part of other modes.
The article provides c ++ code that implements this mode.
To understand how GOST 28147-89 works in this mode, it is necessary to consider the following scheme:
Actually, the essence
Encryption
- Open data is divided into blocks of 64 bits.
- Next, enter the first block into drives N 1 and N 2 . In this case, the bits of open information are entered as follows: the 1st bit of open information - in the 1st discharge of drive N 1 , ..., 32nd - in the 32nd discharge of drive N 1 , the 33rd - in the 1st discharge of drive N 2 and so on until the 64th bit of open information is entered into the 32nd bit of drive N 2 .
- A 256-bit key is entered into the memory in the way described in GOST 28147-89 (Part 1. Introduction and general principles) .
Open data is encrypted in simple replacement mode (in 32 cycles):
- In the first cycle, the contents of register N 1 is summed up with filling X 0 from the RAM modulo 2 32 in the adder CM 1 .
- In the substitution block K, 32 bits of information received from the adder CM 1 are replaced according to the rules considered in the first article .
- In the shift register R , a cyclic shift of 11 is performed toward the higher order.
- Information from the shift register R and drive N 2 is summed modulo 2 in the adder CM 2 .
- The old filling of drive N 1 is overwritten into drive N 2 .
- The result from the output of the adder CM 2 is transferred to the drive N 1 .
- The first cycle ends.
- Subsequent cycles are similar to the first, with the only difference being that the key X 1 is entered in the 2nd cycle , X 7 in the 8th, X 0 in the 9th, and so on in the same order up to 24 cycles. From 25 to 32 cycles, the key is entered in the reverse order: X 7 - in the 25th, X 0 - in the 32nd.
- After the 32nd cycle, information is stored in N 1 , but the result from the output of the adder CM 2 is rewritten in N 2 .
- Filling N 1 and N 2 is the first block of encrypted data.
- The following blocks are encrypted in the same way.
Decryption
Decryption is carried out according to the same algorithm as encryption, only the input of drives N 1 and N 2 receives encrypted data divided into blocks of 64 bits. An important difference is that the key is in direct order (from X 0 to X 7 ) It is introduced only in the first 8 RPG cycles, in the rest - in the reverse (from X 7 to X 0 ). And so, after passing 32 cycles in the drives N 1 and N 2 contains blocks of open data.Explain all of the above with C ++ code
This code was written in console mode in C ++ Builder 6 for a long time and does not claim to be the best, so do not hit hard, there is no time to optimize. It just works, and quite quickly.gost28147.cpp
// ------------------------------------------------ --------------------------- #include#include #include // ------------------------------------------------ --------------------------- // taken from the help, determine the file size long filesize (FILE * stream) { long curpos, length; curpos = ftell (stream); fseek (stream, 0L, SEEK_END); length = ftell (stream); fseek (stream, curpos, SEEK_SET); return length; } // function that implements the work of GOST 28147-89 in the simple replacement mode void rpz (int rezh, char * opener, char * saver) { FILE * f_begin, * f_end; // streams for source and destination files // replacement table byte Tab_Z [8] [16] = { 0x0.0x1.0x2.0x3.0x4.0x5.0x6.0x7.0x8.0x9.0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0.0x1.0x2.0x3.0x4.0x5.0x6.0x7.0x8.0x9.0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0.0x1.0x2.0x3.0x4.0x5.0x6.0x7.0x8.0x9.0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0.0x1.0x2.0x3.0x4.0x5.0x6.0x7.0x8.0x9.0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0.0x1.0x2.0x3.0x4.0x5.0x6.0x7.0x8.0x9.0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0.0x1.0x2.0x3.0x4.0x5.0x6.0x7.0x8.0x9.0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0.0x1.0x2.0x3.0x4.0x5.0x6.0x7.0x8.0x9.0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0.0x1.0x2.0x3.0x4.0x5.0x6.0x7.0x8.0x9.0xA, 0xB, 0xC, 0xD, 0xE, 0xF }; // key unsigned long key [8] = { 0x0123, 0x4567, 0x89AB, 0xCDEF, 0x0123, 0x4567, 0x89AB, 0xCDEF }; char N [4]; // 32-bit drive unsigned long n1 = 0, n2 = 0, SUM232 = 0; // drives N1, N2, and the adder // open files f_begin = fopen (opener, "rb"); f_end = fopen (saver, "wb"); // define the number of blocks float blokoff; blokoff = 8 * filesize (f_begin); blokoff = blokoff / 64; int block = blokoff; if (blokoff-block> 0) block ++; int sh; if (filesize (f_begin)> = 4) sh = 4; else sh = filesize (f_begin); int sh1 = 0; int flag = 0; // start reading and converting blocks // there are checks for completeness of blocks to read only the required number of bits for (int i = 0; i = 0; q--) { zam_symbol = * ((byte *) & SUM232 + q); first_byte = (zam_symbol & 0xF0) >> 4; second_byte = (zam_symbol & 0x0F); first_byte = Tab_Z [n] [first_byte]; n--; second_byte = Tab_Z [n] [second_byte]; n--; zam_symbol = (first_byte << 4) | second_byte; * ((byte *) & SUM232 + q) = zam_symbol; } SUM232 = (SUM232 << 11) | (SUM232 >> 21); // cyclic shift by 11 SUM232 = n2 ^ SUM232; // add in the adder CM2 if (k <31) { n2 = n1; n1 = SUM232; } if (rezh == 1) { if (k <24) { c ++; if (c> 7) c = 0; } else { c--; if (c <0) c = 7; } } else { if (k <8) { c ++; if (c> 7) c = 0; } else { c--; if (c <0) c = 7; } } } n2 = SUM232; // output the result to a file char sym_rez; for (int q = 0; q <= 3; q ++) { sym_rez = * ((byte *) & n1 + q); fprintf (f_end, "% c", sym_rez); } for (int q = 0; q <= 3; q ++) { sym_rez = * ((byte *) & n2 + q); fprintf (f_end, "% c", sym_rez); } } fclose (f_begin); fclose (f_end); } // ------------------------------------------------ --------------------------- int main () { // select encryption or decryption int rezhim = 0; do { printf ("Select the mode of operation: \ n Encryption - 1 \ nDecryption - 2 \ n"); scanf ("% d", & rezhim); } while ((rezhim! = 1) && (rezhim! = 2)); // repeat until 1 or // select the source and destination files (slash '\' in the path to write as '\\') char open_str [50], save_str [50]; printf ("\ nEnter the path to the source file \ n"); scanf ("% s", & open_str); printf ("\ nEnter the path to the file where you want to write the result \ n"); scanf ("% s", & save_str); rpz (rezhim, open_str, save_str); // run RPZ return 0; } // ------------------------------------------------ ---------------------------
Note the advantages and disadvantages of this mode.
Advantages:
- Excludes the effect of cipher overlap on encryption strength.
- It is possible to decrypt any block regardless of its location in the cryptogram.
- Easy to sync.
Disadvantages:
- Message statistics penetrate cryptogram statistics.
- One error of the type “sign replacement” in the cryptogram leads to the complete destruction of the block during decryption.