voltage

gost89

Oct 21st, 2012
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.63 KB | None | 0 0
  1. /*
  2.   ГОСТ 28147-89 в режиме простой замены.
  3. */
  4.  
  5. #include <ctype.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <stdint.h>
  9.  
  10. /*
  11.   Функция преобразования символа в число.
  12.   Предполагается, что входной символ 0..9 или A..F.
  13. */
  14. static uint8_t char_to_dec(char c)
  15. {
  16.   return c < 'A' ? c - '0' : c - 'A' + 10;
  17. }
  18.  
  19. /*
  20.   Функция разбора hex-строки с ключом в массив байт.
  21.   Записывает ключ в pk.
  22.   Возвращает либо длину ключа в байтах, либо -1 в случае некорректной входной строки.
  23. */
  24. static int parse_key(char* ps, uint8_t* pk)
  25. {
  26.   int n = 0;
  27.   char *s = ps;
  28.   uint8_t *k = pk;
  29.  
  30.   /* строка заканчивается нулевым символом */
  31.   while(*s != '\0')
  32.   {    
  33.     /* наращиваем количество пройденных символов в строке */
  34.     n++;
  35.  
  36.     if(*s >= 'a' && *s <= 'f')
  37.     {
  38.       /* делаем из строчной буквы прописную */
  39.       *s = toupper(*s); /* подключается из ctype.h */
  40.     }
  41.     else if(*s < '0' || (*s > '9' && *s < 'A') || *s > 'F')
  42.     {
  43.       /* попался некорректный символ, строка не может быть разобрана */
  44.       return -1;
  45.     }
  46.  
  47.     if(n % 2 != 0)
  48.     {
  49.       /* записываем число, которое представляет собой символ, в старшие биты ключа */
  50.       *k = char_to_dec(*s) << 4;
  51.     }
  52.     else
  53.     {
  54.       /* пишем число в младшие биты ключа и переходим к следующему байту */
  55.       *k += char_to_dec(*s) & 0xF;
  56.       k++;
  57.     }
  58.  
  59.     /* переходим к следующему символу в строке */
  60.     s++;
  61.   }
  62.  
  63.   /* если длина входной строки не делится на два - всё плохо. */
  64.   return n % 2 != 0 ? -1 : k - pk;
  65. }
  66.  
  67. /*
  68.   Часть алгоритма ГОСТ 28147-89, вынесенная в отдельную функцию.
  69. */
  70. static uint32_t f(uint32_t x, uint8_t k)
  71. {
  72.   /* описание таблицы замен */
  73.   static const uint8_t s_table[][16] =
  74.   {
  75.     { 0x4, 0xA, 0x9, 0x2, 0xD, 0x8, 0x0, 0xE, 0x6, 0xB, 0x1, 0xC, 0x7, 0xF, 0x5, 0x3 },
  76.     { 0xE, 0xB, 0x4, 0xC, 0x6, 0xD, 0xF, 0xA, 0x2, 0x3, 0x8, 0x1, 0x0, 0x7, 0x5, 0x9 },
  77.     { 0x5, 0x8, 0x1, 0xD, 0xA, 0x3, 0x4, 0x2, 0xE, 0xF, 0xC, 0x7, 0x6, 0x0, 0x9, 0xB },
  78.     { 0x7, 0xD, 0xA, 0x1, 0x0, 0x8, 0x9, 0xF, 0xE, 0x4, 0x6, 0xC, 0xB, 0x2, 0x5, 0x3 },
  79.     { 0x6, 0xC, 0x7, 0x1, 0x5, 0xF, 0xD, 0x8, 0x4, 0xA, 0x9, 0xE, 0x0, 0x3, 0xB, 0x2 },
  80.     { 0x4, 0xB, 0xA, 0x0, 0x7, 0x2, 0x1, 0xD, 0x3, 0x6, 0x8, 0x5, 0x9, 0xC, 0xF, 0xE },
  81.     { 0xD, 0xB, 0x4, 0x1, 0x3, 0xF, 0x5, 0x9, 0x0, 0xA, 0xE, 0x7, 0x6, 0x8, 0x2, 0xC },
  82.     { 0x1, 0xF, 0xD, 0x0, 0x5, 0x7, 0xA, 0x4, 0x9, 0x2, 0x3, 0xE, 0x6, 0xB, 0x8, 0xC }
  83.   };
  84.   uint32_t mp;
  85.  
  86.   /* при сложении переполнение разрядной сетки отбрасывается, в mp остается сумма по модулю 32 */
  87.   mp = x + k;
  88.  
  89.   /* разбиваем mp на группы по 4 бита, прогоняем их через таблицы замены, затем склеиваем */
  90.   mp = (s_table[7][(mp >> 0 ) & 0xF] << 0 ) + (s_table[6][(mp >> 4 ) & 0xF] << 4 ) +
  91.        (s_table[5][(mp >> 8 ) & 0xF] << 8 ) + (s_table[4][(mp >> 12) & 0xF] << 12) +
  92.        (s_table[3][(mp >> 16) & 0xF] << 16) + (s_table[2][(mp >> 20) & 0xF] << 20) +
  93.        (s_table[1][(mp >> 24) & 0xF] << 24) + (s_table[0][(mp >> 28) & 0xF] << 28) ;
  94.  
  95.   /* циклически сдвигаем результат влево на 11 бит */
  96.   mp = (mp << 11) + (mp >> (sizeof(mp) * 8 - 11));
  97.  
  98.   return mp;
  99. }
  100.  
  101. /*
  102.   Основная функция обработки блока текста.
  103.   Используется и при зашифровании, и при расшифровании.
  104. */
  105. static void process_block(uint8_t* x, const uint8_t* k, const uint8_t* ki)
  106. {
  107.   const uint8_t* end = ki + 32;
  108.   uint32_t a, b, c;
  109.  
  110.   /* разбиваем входной 64-битный блок на группы по 32 бита */
  111.   memcpy(&a, x + sizeof(b), sizeof(a)); /* для memcpy и strcpy нужен string.h */
  112.   memcpy(&b, x, sizeof(b));
  113.  
  114.   /* 32 раунда шифрования */
  115.   for(; ki < end; ki++)
  116.   {
  117.     c = a;
  118.     a = b ^ f(a, k[*ki]);
  119.     b = c;
  120.   }
  121.  
  122.   /* склеиваем 32-битные группы в обратном порядке */
  123.   memcpy(x, &a, sizeof(a));
  124.   memcpy(x + sizeof(a), &b, sizeof(b));
  125. }
  126.  
  127. /*
  128.   Функция шифрования блока.
  129.   При шифровании используется прямой порядок подключей.
  130. */
  131. void encrypt_block(uint8_t* x, const uint8_t* k)
  132. {
  133.   /* массив индексов подключей */
  134.   static const uint8_t encrypt_ki[] =
  135.   {
  136.     0, 1, 2, 3, 4, 5, 6, 7,
  137.     0, 1, 2, 3, 4, 5, 6, 7,
  138.     0, 1, 2, 3, 4, 5, 6, 7,
  139.     7, 6, 5, 4, 3, 2, 1, 0
  140.   };
  141.  
  142.   process_block(x, k, encrypt_ki);
  143. }
  144.  
  145. /*
  146.   Функция расшифрования блока.
  147.   Порядок подключей инвертируется.
  148. */
  149. void decrypt_block(uint8_t* x, const uint8_t* k)
  150. {
  151.   /* массив индексов подключей */
  152.   static const uint8_t decrypt_ki[] =
  153.   {
  154.     0, 1, 2, 3, 4, 5, 6, 7,
  155.     7, 6, 5, 4, 3, 2, 1, 0,
  156.     7, 6, 5, 4, 3, 2, 1, 0,
  157.     7, 6, 5, 4, 3, 2, 1, 0
  158.   };
  159.  
  160.   process_block(x, k, decrypt_ki);
  161. }
  162.  
  163. /*
  164.   Точка входа в программу.
  165. */
  166. int main(int argc, char** argv)
  167. {
  168.   uint8_t key[8]; /* для типов uint8_t, uint32_t, ... нужен stdint.h */
  169.   char data[8 + 1]; /* восемь байт на блок, один - для нулевого символа */
  170.   int n;
  171.  
  172.   /* возврат, если не удалось прочитать ключ из аргументов, если не удалось его разобрать или он имеет неверную длину */
  173.   if(argc < 2 || (n = parse_key(argv[1], key)) < 0 || n != 8)
  174.   {
  175.     return -1;
  176.   }
  177.  
  178.   /* блок открытого текста помещается в буфер */
  179.   strcpy(data, "opentext");
  180.  
  181.   /* шифрование и расшифрование с выводом на консоль */
  182.  
  183.   encrypt_block((uint8_t*)data, key);
  184.   printf("enc: %s\n", data); /* для printf нужен stdio.h */
  185.  
  186.   decrypt_block((uint8_t*)data, key);
  187.   printf("dec: %s\n", data);
  188.  
  189.   return 0;
  190. }
Advertisement
Add Comment
Please, Sign In to add comment