
// ------------------------------------------------ ---------------------------
#include <vcl.h>
#include <stdio.h>
#include <conio.h>
// ------------------------------------------------ ---------------------------
// 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 adder
// open files
f_begin = fopen (opener, "rb");
f_end = fopen (saver, "wb");
// determine 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 the completeness of the blocks to read only the required number of bits
for (int i = 0; i <block; i ++)
{
// write to drive N1
for (int q = 0; q <4; q ++) * ((byte *) & N + q) = 0x00;
if ((sh1 + sh) <filesize (f_begin))
{
fread (N, sh, 1, f_begin);
sh1 + = sh;
}
else
{
sh = filesize (f_begin) -sh1;
fread (N, sh, 1, f_begin);
flag = 1;
}
n1 = * ((unsigned long *) & N);
// write to N2 drive
for (int q = 0; q <4; q ++) * ((byte *) & N + q) = 0x00;
if ((sh1 + sh) <filesize (f_begin))
{
fread (N, sh, 1, f_begin);
sh1 + = sh;
}
else
{
if (flag == 0)
{
sh = filesize (f_begin) -sh1;
fread (N, sh, 1, f_begin);
}
}
n2 = * ((unsigned long *) & N);
// 32 simple replacement cycles
// read the key in the required GOST order
int c = 0;
for (int k = 0; k <32; k ++)
{
if (rezh == 1) {if (k == 24) c = 7; }
else {if (k == 8) c = 7; }
// sum in the adder CM1
SUM232 = key [c] + n1;
// replace by replacement table
byte first_byte = 0, second_byte = 0, zam_symbol = 0;
int n = 7;
for (int q = 3; q> = 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 result to 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 ()
{
// choose encryption or decryption
int rezhim = 0;
do
{
printf ("Select the mode of operation: \ nCrypting - 1 \ nCoding - 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 the RPP
return 0;
}
// ------------------------------------------------ ---------------------------
Source: https://habr.com/ru/post/81032/
All Articles