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

    1. Open data is divided into blocks of 64 bits.
    2. 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 .
    3. A 256-bit key is entered into the memory in the way described in GOST 28147-89 (Part 1. Introduction and general principles) .
    4. Open data is encrypted in simple replacement mode (in 32 cycles):

      1. 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 .
      2. 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 .
      3. In the shift register R , a cyclic shift of 11 is performed toward the higher order.
      4. Information from the shift register R and drive N 2 is summed modulo 2 in the adder CM 2 .
      5. The old filling of drive N 1 is overwritten into drive N 2 .
      6. The result from the output of the adder CM 2 is transferred to the drive N 1 .
      7. The first cycle ends.
    5. 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.
    6. 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 .
    7. Filling N 1 and N 2 is the first block of encrypted data.
    8. 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.

    Application.

    This mode is used in the other three modes of GOST 28147-89, in GOST R34.11-94 when performing a mixing conversion, as well as for processing keys. It is not recommended to use it for encryption / decryption, there are more advanced modes, which will be discussed in the following parts.

    Also popular now: