LINUX.ORG.RU

ГОСТ 28147-89 помогите разобраться

 28147, , ,


0

1

Нужно реализовать сабж на СИ, но убей не могу понять алгоритм. Можете объяснить на пальцах: «Берём файл, считываем блок данных размером 64 бита» и так далее? Заранее спасибо.

★★★★

Он же простой как две копейки. Берём ГОСТ, читаем. Берём гугл читаем про ГОСТ. Реализуем. Там даже подсказывать нечего. Ну можно ещё глянуть в реализацию mcrypt- ничего так, годно сделано. Можно кстати лучше..

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

А я не могу распарсить маны сумрачного советского гения

fero ★★★★
() автор топика

берешь 64 бита данных, делишь пополам, одну половину ксоришь с ключом, прогоняешь через таблицу подстановки, сдвигаешь, ксоришь со второй, меняешь их местами, повторяешь ещё 31 раз. Как на картинке в википедии.

anonymous
()
#include <stdio.h>


unsigned key[8]= {2542612654, 13689323, 1518563127, 3489012892, 2519843475, 3183980271, 1013633557, 104063607};
   
unsigned tab[8][16]=
   {{14, 4, 13, 13, 8, 15, 12, 0, 14, 8, 14, 6, 4, 0, 7, 15},
   {4, 8, 15, 4, 14, 10, 6, 1, 4, 5, 2, 3, 11, 12, 12, 3},
   {10, 3, 11, 7, 9, 15, 6, 0, 11, 0, 8, 2, 15, 7, 1, 10},
   {1, 11, 7, 3, 15, 13, 1, 3, 0, 10, 5, 1, 2, 10, 12, 12},
   {11, 15, 7, 11, 12, 15, 0, 1, 8, 5, 3, 11, 0, 1, 15, 3},
   {9, 4, 10, 4, 3, 14, 13, 5, 15, 7, 5, 12, 15, 14, 7, 9},
   {14, 11, 11, 10, 8, 14, 10, 1, 7, 15, 1, 0, 8, 4, 9, 5},
   {9, 12, 0, 5, 2, 7, 6, 13, 2, 5, 10, 11, 13, 13, 1, 12}};

//поблочная замена по таблице 
unsigned subst(unsigned N1)
 {
    unsigned i, t;
    unsigned mask= 0, umask;

    mask--;
    mask=15; //11111111111111111111111111110000
    umask= ~mask; //00000000000000000000000000001111

    for(i= 0; i < 8; ++i)
     {
       t= N1 >> 4*i; 
       t&= mask;
      
       t=tab[i][t];
       N1&= ~(umask << 4*i);
       N1|= t << 4*i;
       
     }
    return N1;
 }
//циклический сдвиг на 11 бит влево
unsigned shr(unsigned N1)
 {
    unsigned t= N1;

    N1= N1 << 11;
    N1|= t >> 21;

    return N1;
 }

void main_step(unsigned* pN1, unsigned* pN2, unsigned X)
 {
    unsigned S, N1, N2;

    N1= *pN1;
    N2= *pN2;
 
    S=N1+X;

    S= subst(S);
    S= shr(S);
    S^= N2;

    *pN1= S;
    *pN2= N1;
 }
//цикл зашифрования
void base_loop(unsigned* pN1, unsigned* pN2)
 {
    
    unsigned N1, N2;
    int i,j;

    N1= *pN1;
    N2= *pN2;

    for(i= 0; i < 3; ++i)
     {
        for(j= 0; j < 8; ++j) main_step(&N1,&N2, key[j]);
     }
    
    for(i= 7; i>= 0; --i) main_step(&N1,&N2, key[i]);

    *pN1= N1;
    *pN2= N2;
 }
//цикл расшифрования
void dbase_loop(unsigned* pN1, unsigned* pN2)
 {
    
    unsigned N1, N2;
    int i,j;

    N1= *pN1;
    N2= *pN2;

    for(i= 0; i < 8; ++i) main_step(&N1,&N2, key[i]);

    for(i= 0; i < 3; ++i)
     {
        for(j= 7; j >= 0; --j) main_step(&N1,&N2, key[j]);
     }
    
    *pN1= N1;
    *pN2= N2;
 }
int main()
 {

    unsigned N1, N2;
    FILE *xxx;
    xxx= fopen("xxx", "w+");
  
    char a[]= "abc";
    char b[]= "123";

    N1= (unsigned)a;
    N2= (unsigned)b; 

    base_loop(&N1,&N2);
    dbase_loop(&N1,&N2);

    fwrite(N1, 4, 1, xxx);
    fwrite(N2, 4, 1, xxx);


    return 0;
 }

Стыдно но пощу. Вещь тестовая, таблица и ключ намертво заварены в файл и пока что она шифрует/расшифрует один блок и то с помощью закомментирования :) Прошу посмотреть по диагонали, указать в каких местах я отстреливаю себе ноги и дать советов мудрых.

fero ★★★★
() автор топика
Последнее исправление: fero (всего исправлений: 1)

Помогите разобраться: три раза перечитал текст, так и не понял, чего надо ТСу.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Сначала я долго не мог распарисить что написано в ГОСТе, теперь распарсил но реализовать не могу. Вроде 1 блок зашифровать смог. Или нет? Прошу проверить и подсказать.

fero ★★★★
() автор топика
Ответ на: комментарий от fero

Ладно, в педивикии уже нашел. Дофига там написано, лень читать. Там внизу ссылочки, так вот в книжечке по ссылочке попроще как-то. В общем, тупняк: сдвигаешь/ксоришь... Что тут сложного-то?

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Сделал и вроде работает. Как мне теперь похитрее читать блоки по 64 бита и бить на два? Пробовал писать что-то вроде этого:

    unsigned N1, N2;
    char buf64[8];
    FILE *in, *out;
...

    while(fread(buf64,8,1,in))
     {
          memcpy(&N1, buf64, 4);
          memcpy(&N2, buf64+4, 4);
          base_loop(&N1,&N2);

          memcpy( buf64, &N1, 4);
          memcpy( buf64+4, &N2, 4);
          fwrite(buf64,8,1,out);
  
     }

Но видимо что-то я намудачил с указателями и вообще вудупрограммирую.

fero ★★★★
() автор топика
Ответ на: комментарий от Eddy_Em

Можно пример? Не понимаю, как мне это поможет. Да, можно будет читать сразу 64 бита, но обращаться к первым и вторым 4 байтам один чёрт геморойно. Или я чего-то не понимаю.

fero ★★★★
() автор топика
Ответ на: комментарий от fero

что-то вроде

typedef union{
  uint64_t all;
  uint32_t parts[2];
} data_struct;

а потом считывать сразу в all, работать же с parts[0] и parts[1].

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от fero

Да не за что. Только, как я уже говорил, осторожно надо быть с выравниванием: если оно будет по 8 байт, получится "фикус".

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от fero

Вот, наклепал коротенький примерчик:

cat 1.c 
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>

typedef union{
	uint64_t all;
	uint32_t parts[2];
} data_struct;


int main(int argc, char **argv){
	int fdin, fdout;
	data_struct Data, SWP;
	if(argc != 3) return(-1);
	umask(0);
	fdin = open(argv[1], O_RDONLY);
	fdout = open(argv[2], O_WRONLY | O_CREAT, 0666);
	if(fdin < 0 || fdout < 0) return(-1);
	while(read(fdin, &Data.all, 8) == 8){
		SWP.parts[1] = Data.parts[0];
		SWP.parts[0] = Data.parts[1];
		if(write(fdout, &SWP.all, 8) != 8) return(-1);
	}
	close(fdin);
	close(fdout);
	return 0;
}

gcc -Wall -Werror 1.c -o test && ./test testfile outfile

cat testfile 
12345678abcdefgh

cat outfile  
56781234efghabcd
Eddy_Em ☆☆☆☆☆
()
#include <stdio.h>
#include <fcntl.h>

typedef union
 {
    uint64_t all;
    uint32_t parts[2];
 }data_struct;


unsigned key[8]= {2542612654, 13689323, 1518563127, 3489012892, 2519843475, 3183980271, 1013633557, 104063607};

unsigned tab[8][16]=
   {{14, 4, 13, 13, 8, 15, 12, 0, 14, 8, 14, 6, 4, 0, 7, 15},
   {4, 8, 15, 4, 14, 10, 6, 1, 4, 5, 2, 3, 11, 12, 12, 3},
   {10, 3, 11, 7, 9, 15, 6, 0, 11, 0, 8, 2, 15, 7, 1, 10},
   {1, 11, 7, 3, 15, 13, 1, 3, 0, 10, 5, 1, 2, 10, 12, 12},
   {11, 15, 7, 11, 12, 15, 0, 1, 8, 5, 3, 11, 0, 1, 15, 3},
   {9, 4, 10, 4, 3, 14, 13, 5, 15, 7, 5, 12, 15, 14, 7, 9},
   {14, 11, 11, 10, 8, 14, 10, 1, 7, 15, 1, 0, 8, 4, 9, 5},
   {9, 12, 0, 5, 2, 7, 6, 13, 2, 5, 10, 11, 13, 13, 1, 12}};

unsigned subst(unsigned N1)
 {
    unsigned i, t;
    unsigned mask;

    mask=15;  //00000000000000000000000000001111

    for(i= 0; i < 8; ++i)
     {
       t= N1 >> 4*i;
       t&= mask;

       t=tab[i][t];
       N1&= ~(mask << 4*i);
       N1|= t << 4*i;

     }
    return N1;
 }

unsigned shr(unsigned N1)
 {
    unsigned t= N1;

    N1= N1 << 11;
    N1|= t >> 21;

    return N1;
 }

void main_step(unsigned* pN1, unsigned* pN2, unsigned X)
 {
    unsigned S, N1, N2;

    N1= *pN1;
    N2= *pN2;

    S=N1+X;

    S= subst(S);
    S= shr(S);
    S^= N2;

    *pN2= N1;
    *pN1= S;
 }
//Шифруем
void base_loop(unsigned* pN1, unsigned* pN2)
 {

    unsigned N1, N2;
    int i,j;

    N1= *pN1;
    N2= *pN2;

    for(i= 0; i < 3; ++i)
     {
        for(j= 0; j < 8; ++j) main_step(&N1,&N2, key[j]);
     }

    for(i= 7; i>= 0; --i) main_step(&N1,&N2, key[i]);

    *pN1= N1;
    *pN2= N2;
 }
//Дешифруем
void dbase_loop(unsigned* pN1, unsigned* pN2)
 {

    unsigned N1, N2;
    int i,j;

    N1= *pN1;
    N2= *pN2;

    for(i= 0; i < 8; ++i) main_step(&N1,&N2, key[i]);

    for(i= 0; i < 3; ++i)
     {
        for(j= 7; j >= 0; --j) main_step(&N1,&N2, key[j]);
     }

    *pN1= N1;
    *pN2= N2;
 }
int main()
 {

    data_struct Data;

    memcpy(&Data,"abcdef7", 8);


    base_loop(&Data.parts[0],&Data.parts[1]);
    dbase_loop(&Data.parts[0],&Data.parts[1]);

    return 0;
 }

Нашел ошибку в subst, с маской накосячил, но один чёрт не работает. Зато у меня получился переводчик с транслита на чешский :(

fero ★★★★
() автор топика
Ответ на: комментарий от fero

А ты попробуй, не используя выравнивания, записать какую-нибудь бинарную структуру в файл на 32-битной машине, а потом на 64-битной ее прочесть ;)

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от fero

Смешались в кучу люди, кони...

Ты хоть не мешай типы данных! Используй на всякий пожарный только строгие типы uint32_t и uint64_t, а то фиг его знает, во что на твоей архитектуре этот unsigned развернется!

В код не вникал: лень.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Хорошо, позаменю всё, спасибо большое.

fero ★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.