Advertisement
Guest User

Untitled

a guest
Dec 1st, 2015
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 27.52 KB | None | 0 0
  1. aes.hpp
  2.  
  3. /**\addtogroup AES ****************************************************////@{
  4. /**\file*********************************************************************
  5.  *                                                                     \brief
  6.  *  Заголовочный файл класса #aes.
  7.  *
  8.  *  @author Serge Trusov
  9.  *  mailto: serge.trusov@gmail.com
  10.  *
  11.  ****************************************************************************
  12.  */
  13.  
  14.  
  15. #ifndef _AES_HPP
  16. #define _AES_HPP
  17.  
  18.  
  19. /**
  20.  *  Базовый тип данных обрабатываемый криптоалгоритмом.
  21.  */
  22. typedef unsigned char   byte;
  23.  
  24.  
  25. /////////////////////////////////////////////////////////////////////////////
  26.  
  27. /**
  28.  *  Класс обеспечивает шифрование блока данных
  29.  *  по стандартам AES-128, AES-192 и AES-256.
  30.  *
  31.  *  @note
  32.  *  При компиляции можно выбрать поддерживаемые варианты длины ключа
  33.  *  задав любую комбинацию макросов #AES_128, #AES_192 и #AES_256.
  34.  *  По умолчанию будут поддерживаться все возможные длины ключей.
  35.  */
  36. class   aes {
  37.  
  38. #if !defined(AES_128) && !defined(AES_192) && !defined(AES_256)
  39. /// Обеспечивает поддержку ключей длиной 128 бит.       @ingroup AES
  40. #define AES_128    
  41. /// Обеспечивает поддержку ключей длиной 192 бит.       @ingroup AES
  42. #define AES_192
  43. /// Обеспечивает поддержку ключей длиной 256 бит.       @ingroup AES
  44. #define AES_256
  45. #endif
  46.  
  47. /////////////////////////////////////////////////////////////////////////////
  48.  
  49. public:
  50.  
  51.     /**
  52.      *  Значения, возвращаемые методами.
  53.      *  Сигнализирует об успехе / ошибке.
  54.      */
  55.     enum   status   {
  56.         Ok                  = 0,    ///< нет ошибки.
  57.         wrong_key_lenght    = ~0    ///< неверная длина ключа.
  58.     };
  59.  
  60.     /**
  61.      *  Размер блока шифротекста в байтах.
  62.      *  По стандарту фиксирован.
  63.      *  Может быть использован во внешних алгоритмах
  64.      *  вызывающих методы класса.
  65.      */
  66.     static const unsigned  block_size = 16;
  67.  
  68.     /**
  69.      *  Шифрование блока данных.
  70.      *  @note   Входной и выходной блоки могут совпадать !
  71.      */
  72.     void
  73.       encrypt(
  74.         const byte      in[block_size], ///< Входной блок данных.
  75.         byte            out[block_size] ///< Выходной блок данных.  @see block_size
  76.         );
  77.  
  78.     /**
  79.      *  Расшифровывание блока данных.
  80.      *  @note   Входной и выходной блоки могут совпадать !
  81.      */
  82.     void
  83.       decrypt(
  84.         const byte      in[block_size], ///< Входной блок данных.
  85.         byte            out[block_size] ///< Выходной блок данных. @see block_size
  86.         );
  87.  
  88.     /**
  89.      *  Расширение ключа.
  90.      *  Для (де)шифрации обязательно используется расширенный ключ.
  91.      *  Необходимо вызвать метод перед первым encrypt() или decrypt()
  92.      *  @note   Допустимые размеры ключа:
  93.      *  128 бит (если определён макрос #AES_128),
  94.      *  192 бит (если определён макрос #AES_192),
  95.      *  256 бит (если определён макрос #AES_265).
  96.      */
  97.     status
  98.       expand_key(
  99.         const byte    * key,            ///< Ключ.
  100.         const unsigned  size            ///< Размер ключа в битах.
  101.         );
  102.    
  103. /////////////////////////////////////////////////////////////////////////////
  104.  
  105. protected:
  106.  
  107.     /**
  108.      *  Количество раундов шифрования.
  109.      *  Автоматически устанавливается в функции расширения ключа.
  110.      */
  111.     unsigned    rounds;
  112.  
  113.     /**
  114.      *  Криптоалгоритм обрабатывает блоки по 4 байта.
  115.      */
  116.     typedef unsigned long   u32;
  117.  
  118.     /**
  119.      *  Расширенные (раундовые) ключи.
  120.      *  Используются непосредственно для (де)шифрации текста.
  121.      */
  122.     u32     encryption_round_key[64],
  123.             decryption_round_key[64];
  124.  
  125.     /**
  126.      *  Таблицы замен.
  127.      */
  128.     static  u32 s_box[256];     ///< Прямая замена
  129.     static  u32 r_box[256];     ///< Обратная замена
  130.     static  u32 ft[4][256];     ///< Расширенная прямая замена
  131.     static  u32 rt[4][256];     ///< Расширенная обратная замена
  132.    
  133.     /**
  134.      *  Формирует таблицы замен.
  135.      */
  136.     void inline
  137.       init_tables();
  138.    
  139.     /**
  140.      *  Образующий полином (базис) поля GF(2**8).
  141.      *  определён так:     phi(x) = x**8 + x**4 + x**3 + x**1 + 1;
  142.      */
  143.     static const unsigned   basis = 1<<8 | 1<<4 | 1<<3 | 1<<1 | 1<<0;
  144.  
  145.     /**
  146.      *  Генератор Галуа (Linear Feedback Shift Register)
  147.      *  ненулевых элементов поля GF(2**8) в заданном базисе.
  148.      *  Выполняет умножение на x по модулю phi(x). (xTime)
  149.      */
  150.     byte static inline
  151.       lfsr2(
  152.         byte    a           ///< Предыдущее состойние генератора.
  153.         );
  154.  
  155.     /**
  156.      *  Циклический сдвиг двойного слова влево на байт.
  157.      */
  158.     u32 static inline
  159.       rot_left_8(
  160.         u32 value           ///< Сдвигаемое значение.
  161.         );
  162.  
  163.     /**
  164.      *  Преобразуете 4 байта в двойное слово (32бита).
  165.      */
  166.     u32 static inline
  167.       get(
  168.         const byte array[4] ///< Указатель на массив из 4-х байт.
  169.         );
  170.  
  171.     /**
  172.      *  Помещает двойное слово (32бита) в массив из четырёх байт.
  173.      */
  174.     void static inline
  175.       put(
  176.         u32  value,         ///< Исходные данные.
  177.         byte array[4]       ///< Указатель на массив из четырёх байт.
  178.         );
  179.  
  180.     /**
  181.      *  Вспомогательная функция прямой табличной замены.
  182.      *  Один из байт двойного слова используется в качестве индекса.
  183.      */
  184.     u32 static inline
  185.       fb(
  186.         u32 byte,           ///< Слово содержащее байт.
  187.         unsigned position   ///< Позиция байта в слове.
  188.         );
  189.  
  190.     /**
  191.      *  Вспомогательная функция обратной табличной замены.
  192.      *  Один из байт двойного слова используется в качестве индекса.
  193.      */
  194.     u32 static inline
  195.       rb(
  196.         u32 byte,           ///< Слово содержащее байт.
  197.         unsigned position   ///< Позиция байта в слове.
  198.         );
  199.  
  200. };//class   aes
  201.  
  202.  
  203. #endif//#ifndef _AES_HPP
  204.  
  205.  
  206. ///========================================================================//
  207. ///*} EOF
  208.  
  209.  
  210.  
  211. aes.cpp
  212.  
  213. /**\addtogroup AES Advanced Encryption Standard******************************
  214.  *
  215.  *  Advanced Encryption Standard (Rijndael) algorithm implementation.
  216.  *
  217.  *  @author Serge Trusov
  218.  *  mailto: serge.trusov@gmail.com
  219.  *
  220.  *  @version    0.5.05.21
  221.  *  @date       21 May 2005
  222.  *
  223.  *  @note   Для тестирования работы скомпилируйте файл aes.cpp
  224.  *          определив макрос AES_TEST   @see main()
  225.  *
  226.  *//**@{*/ /**  @file
  227.  *                                                                     \brief
  228.  *  Реализация класса #aes.
  229.  *  Обеспечивает (де)шифрацию блока данных по алгоритму Rijndael.
  230.  *  Реализованы варианты: AES-128, AES-192 и AES-256.            @copydoc AES
  231.  *
  232.  ****************************************************************************
  233.  */
  234.  
  235.  
  236. #include <stdlib.h>
  237. #include "aes.hpp"
  238.  
  239.  
  240. //=========================================================================//
  241. //
  242. //  Перед использованием необходимо сгенерировать
  243. //  расширенный ключ (из 128-ми, 192-ч или 256-ти битного)
  244. //
  245. aes::status aes::expand_key( const byte * key, const unsigned size )
  246. {
  247.     unsigned i;
  248.  
  249.     //  инициализированный s_box содержит здесь ненулевое значение
  250.     if( ! s_box[0] ) init_tables();
  251.  
  252.     //  Копируем ключ.
  253.  
  254.     u32   * ek = encryption_round_key;
  255.     for( i = 0; i < size / (8*sizeof(u32)); i++ )
  256.         ek[i] = get( &key[i * 4] );
  257.  
  258.     //  Создаём расширенный ключ для засшифровки
  259.  
  260.     u32 round_constant = 1;
  261.     switch( size )
  262.     {
  263.     default:
  264.         return  wrong_key_lenght;
  265.  
  266.     #ifdef AES_128
  267.     case 128:
  268.         for( i = 0; i < 10; i++, ek += 4 )
  269.         {
  270.             ek[4] = ek[0]
  271.                   ^ s_box[ ek[3] >>  0 & 0xFF ] << 24
  272.                   ^ s_box[ ek[3] >> 24        ] << 16
  273.                   ^ s_box[ ek[3] >> 16 & 0xFF ] <<  8
  274.                   ^ s_box[ ek[3] >>  8 & 0xFF ] <<  0
  275.                   ^ round_constant;
  276.             ek[5] = ek[1] ^ ek[4];
  277.             ek[6] = ek[2] ^ ek[5];
  278.             ek[7] = ek[3] ^ ek[6];
  279.             round_constant = lfsr2((byte)round_constant);
  280.         }
  281.         rounds = 10;
  282.         break;
  283.     #endif
  284.  
  285.     #ifdef AES_192
  286.     case 192:
  287.         for( i = 0; i < 8; i++, ek += 6 )
  288.         {
  289.             ek[6]  = ek[0]
  290.                    ^ s_box[ ek[5] >>  0 & 0xFF ] << 24
  291.                    ^ s_box[ ek[5] >> 24        ] << 16
  292.                    ^ s_box[ ek[5] >> 16 & 0xFF ] <<  8
  293.                    ^ s_box[ ek[5] >>  8 & 0xFF ] <<  0
  294.                    ^ round_constant;
  295.             ek[7]  = ek[1] ^ ek[6];
  296.             ek[8]  = ek[2] ^ ek[7];
  297.             ek[9]  = ek[3] ^ ek[8];
  298.             ek[10] = ek[4] ^ ek[9];
  299.             ek[11] = ek[5] ^ ek[10];
  300.             //  упростим lfsr2, т.к кол-во итераций цикла < 9
  301.             round_constant <<=1;// lfsr2( round_constant );
  302.         }
  303.         rounds = 12;
  304.         break;
  305.     #endif
  306.  
  307.     #ifdef AES_256
  308.     case 256:
  309.         for( i = 0; i < 7; i++, ek += 8 )
  310.         {
  311.             ek[8]  = ek[0]
  312.                    ^ s_box[ ek[7] >>  0 & 0xFF ] << 24
  313.                    ^ s_box[ ek[7] >> 24        ] << 16
  314.                    ^ s_box[ ek[7] >> 16 & 0xFF ] <<  8
  315.                    ^ s_box[ ek[7] >>  8 & 0xFF ] <<  0
  316.                    ^ round_constant;
  317.             ek[9]  = ek[1] ^ ek[8];
  318.             ek[10] = ek[2] ^ ek[9];
  319.             ek[11] = ek[3] ^ ek[10];
  320.             ek[12] = ek[4]
  321.                    ^ s_box[ ek[11] >> 24        ] << 24
  322.                    ^ s_box[ ek[11] >> 16 & 0xFF ] << 16
  323.                    ^ s_box[ ek[11] >>  8 & 0xFF ] <<  8
  324.                    ^ s_box[ ek[11] >>  0 & 0xFF ] <<  0;
  325.             ek[13] = ek[5] ^ ek[12];
  326.             ek[14] = ek[6] ^ ek[13];
  327.             ek[15] = ek[7] ^ ek[14];
  328.             //  упростим lfsr2, т.к кол-во итераций цикла < 9
  329.             round_constant <<=1;// lfsr2( round_constant );
  330.         }
  331.         rounds = 14;
  332.         break;
  333.     #endif
  334.     }
  335.  
  336.     //  Создаём расширенный ключ для расшифровки
  337.  
  338.     u32   * dk = decryption_round_key;
  339.     dk[0] = ek[0];  dk[1] = ek[1];  dk[2] = ek[2];  dk[3] = ek[3];
  340.  
  341.     for( i = 4 * (rounds-1); i; --i, dk++ )
  342.     {
  343.         //  Исходные данные расположены в таком порядке:
  344.         //  ..., 9, 10, 11, 12, 5, 6, 7, 8, 1, 2, 3, 4.
  345.         //  первый раз из 4х двигаем указатель "назад" на 7
  346.         //  остальные три - "вперёд" на 1
  347.         ek += i & 0x3 ? 1 : -7;
  348.         dk[4] = rt[0][ s_box[ ek[4-1] >>  0 & 0xFF ] ]
  349.               ^ rt[1][ s_box[ ek[4-1] >>  8 & 0xFF ] ]
  350.               ^ rt[2][ s_box[ ek[4-1] >> 16 & 0xFF ] ]
  351.               ^ rt[3][ s_box[ ek[4-1] >> 24        ] ];
  352.     }
  353.     dk[4] = ek[4-8];    dk[5] = ek[5-8];
  354.     dk[6] = ek[6-8];    dk[7] = ek[7-8];
  355.  
  356.     return Ok;
  357. }
  358.  
  359.  
  360. //=========================================================================//
  361. //
  362. //  Шифрование
  363. //
  364. void aes::encrypt( const byte in[block_size], byte out[block_size] )
  365. {
  366.     //  Указатель на раундовые константы
  367.     u32   * rk = encryption_round_key;
  368.  
  369.     //  Считываем блок и добавляем раундовый ключ.
  370.     u32     a0 = get( &in[ 0] ) ^ rk[0];
  371.     u32     a1 = get( &in[ 4] ) ^ rk[1];
  372.     u32     a2 = get( &in[ 8] ) ^ rk[2];
  373.     u32     a3 = get( &in[12] ) ^ rk[3];
  374.     u32     b0, b1, b2, b3;
  375.  
  376.     //  Раунды криптования (цикл развёрнут 2x)
  377.     for( int i = rounds; ; rk += 8 )  
  378.     {
  379.         b0 = fb(a0, 0) ^ fb(a1, 1) ^ fb(a2, 2) ^ fb(a3, 3) ^ rk[4];
  380.         b1 = fb(a1, 0) ^ fb(a2, 1) ^ fb(a3, 2) ^ fb(a0, 3) ^ rk[5];
  381.         b2 = fb(a2, 0) ^ fb(a3, 1) ^ fb(a0, 2) ^ fb(a1, 3) ^ rk[6];
  382.         b3 = fb(a3, 0) ^ fb(a0, 1) ^ fb(a1, 2) ^ fb(a2, 3) ^ rk[7];
  383.        
  384.         //  Сверхумный MSVC разворачивает цикл, что раздувает размер
  385.         //  и снижает (!) скорость на 10%.
  386.         //  приходится добавлять лишний байт :-(.
  387.         #if defined(_MSC_VER) && ! defined(__cplusplus_cli)
  388.             __asm nop
  389.         #endif
  390.  
  391.         if( ! (i -= 2) ) break;
  392.  
  393.         a0 = fb(b0, 0) ^ fb(b1, 1) ^ fb(b2, 2) ^ fb(b3, 3) ^ rk[8];
  394.         a1 = fb(b1, 0) ^ fb(b2, 1) ^ fb(b3, 2) ^ fb(b0, 3) ^ rk[9];
  395.         a2 = fb(b2, 0) ^ fb(b3, 1) ^ fb(b0, 2) ^ fb(b1, 3) ^ rk[10];
  396.         a3 = fb(b3, 0) ^ fb(b0, 1) ^ fb(b1, 2) ^ fb(b2, 3) ^ rk[11];
  397.     }
  398.      
  399.     //  Последний раунд (без перемешивания столбцов)
  400.     put(
  401.         rk[8]  ^ s_box[ b3 >> 24        ] << 24
  402.                ^ s_box[ b2 >> 16 & 0xFF ] << 16
  403.                ^ s_box[ b1 >>  8 & 0xFF ] <<  8
  404.                ^ s_box[ b0 >>  0 & 0xFF ] <<  0
  405.         , &out[ 0]
  406.         );
  407.     put(
  408.         rk[9]  ^ s_box[ b0 >> 24        ] << 24
  409.                ^ s_box[ b3 >> 16 & 0xFF ] << 16
  410.                ^ s_box[ b2 >>  8 & 0xFF ] <<  8
  411.                ^ s_box[ b1 >>  0 & 0xFF ] <<  0
  412.         , &out[ 4]
  413.         );  
  414.     put(
  415.         rk[10] ^ s_box[ b1 >> 24        ] << 24
  416.                ^ s_box[ b0 >> 16 & 0xFF ] << 16
  417.                ^ s_box[ b3 >>  8 & 0xFF ] <<  8
  418.                ^ s_box[ b2 >>  0 & 0xFF ] <<  0
  419.         , &out[ 8]
  420.         );  
  421.     put(
  422.         rk[11] ^ s_box[ b2 >> 24        ] << 24
  423.                ^ s_box[ b1 >> 16 & 0xFF ] << 16
  424.                ^ s_box[ b0 >>  8 & 0xFF ] <<  8
  425.                ^ s_box[ b3 >>  0 & 0xFF ] <<  0
  426.         , &out[12]
  427.         );
  428. }
  429.  
  430.  
  431. //=========================================================================//
  432. //
  433. //  Расшифровывание.
  434. //
  435. void aes::decrypt( const byte in[block_size], byte out[block_size] )
  436. {
  437.     //  Указатель на раундовые константы
  438.     u32   * rk = decryption_round_key;
  439.  
  440.     //  Считываем блок и добавляем раундовый ключ.
  441.     u32     a0 = get( &in[ 0] ) ^ rk[0];
  442.     u32     a1 = get( &in[ 4] ) ^ rk[1];
  443.     u32     a2 = get( &in[ 8] ) ^ rk[2];
  444.     u32     a3 = get( &in[12] ) ^ rk[3];
  445.     u32     b0, b1, b2, b3;
  446.  
  447.     //  Раунды разкриптования (цикл развёрнут 2x)
  448.     for( int i = rounds; ; rk += 8 )
  449.     {
  450.         b0 = rb(a0, 0) ^ rb(a3, 1) ^ rb(a2, 2) ^ rb(a1, 3) ^ rk[4];
  451.         b1 = rb(a1, 0) ^ rb(a0, 1) ^ rb(a3, 2) ^ rb(a2, 3) ^ rk[5];
  452.         b2 = rb(a2, 0) ^ rb(a1, 1) ^ rb(a0, 2) ^ rb(a3, 3) ^ rk[6];
  453.         b3 = rb(a3, 0) ^ rb(a2, 1) ^ rb(a1, 2) ^ rb(a0, 3) ^ rk[7];
  454.  
  455.         //  Сверхумный MSVC разворачивает цикл, что раздувает размер
  456.         //  и снижает (!) скорость.
  457.         //  приходится добавлять лишний байт :-(.
  458.         #if defined(_MSC_VER) && ! defined(__cplusplus_cli)
  459.             __asm nop
  460.         #endif
  461.  
  462.         if( ! (i -= 2) ) break;
  463.  
  464.         a0 = rb(b0, 0) ^ rb(b3, 1) ^ rb(b2, 2) ^ rb(b1, 3) ^ rk[8];
  465.         a1 = rb(b1, 0) ^ rb(b0, 1) ^ rb(b3, 2) ^ rb(b2, 3) ^ rk[9];
  466.         a2 = rb(b2, 0) ^ rb(b1, 1) ^ rb(b0, 2) ^ rb(b3, 3) ^ rk[10];
  467.         a3 = rb(b3, 0) ^ rb(b2, 1) ^ rb(b1, 2) ^ rb(b0, 3) ^ rk[11];
  468.     }
  469.    
  470.     //  Последний раунд (без перемешивания столбцов)
  471.     put(
  472.         rk[8]  ^ r_box[ b1 >> 24        ] << 24
  473.                ^ r_box[ b2 >> 16 & 0xFF ] << 16
  474.                ^ r_box[ b3 >>  8 & 0xFF ] <<  8
  475.                ^ r_box[ b0 >>  0 & 0xFF ] <<  0
  476.         , &out[ 0]
  477.         );
  478.     put(
  479.         rk[9]  ^ r_box[ b2 >> 24        ] << 24
  480.                ^ r_box[ b3 >> 16 & 0xFF ] << 16
  481.                ^ r_box[ b0 >>  8 & 0xFF ] <<  8
  482.                ^ r_box[ b1 >>  0 & 0xFF ] <<  0
  483.         , &out[ 4]
  484.         );
  485.     put(
  486.         rk[10] ^ r_box[ b3 >> 24        ] << 24
  487.                ^ r_box[ b0 >> 16 & 0xFF ] << 16
  488.                ^ r_box[ b1 >>  8 & 0xFF ] <<  8
  489.                ^ r_box[ b2 >>  0 & 0xFF ] <<  0
  490.         , &out[ 8]
  491.         );
  492.     put(
  493.         rk[11] ^ r_box[ b0 >> 24        ] << 24
  494.                ^ r_box[ b1 >> 16 & 0xFF ] << 16
  495.                ^ r_box[ b2 >>  8 & 0xFF ] <<  8
  496.                ^ r_box[ b3 >>  0 & 0xFF ] <<  0
  497.         , &out[12]
  498.         );
  499. }
  500.  
  501. //@}    protected:
  502.  
  503.  
  504. byte inline aes::lfsr2( byte a )
  505. {
  506.     return a & 0x80 ? a<<1 ^ (byte)basis    // вычитание по модулю 2
  507.                     : a<<1;                 // нет обратноё связи
  508. }
  509.  
  510.  
  511. //=========================================================================//
  512. /// !.
  513. /// Создаёт прямую и обратную таблицы замен (S-box)
  514. /// и расширенные таблицы замен/микширования -
  515. /// используются для оптимизации криптораундов по скорости.
  516. ///
  517. void aes::init_tables()
  518. {
  519.     //  Таблицы для быстрого умножения в поле GF(2**8)  
  520.     byte    pow[1<<8],  log[1<<8];
  521.  
  522.     //  Заполняем их.
  523.     unsigned    i = 0;      //  Начальная степень omega;
  524.     byte        a = 1;      //  omega**i в полиномиальной форме;
  525.     log[0] = 0;             //  Ой элемент нужен для генерации S-box
  526.     do
  527.     {
  528.         pow[i] = a;         //  omega**i = x7**7 + .. + x0**0;
  529.         log[a] = (byte)i;
  530.         //  следующий элемент таблицы выбирается
  531.         //  на основе полинома phi(x+1)
  532.         a ^= lfsr2(a);      //  a *= (x + 1)
  533.     }
  534.     while( (byte)++i );     //  2**8 итераций
  535.  
  536.     //  Что бы не инициализировать отдельно элементы [0x63, 0]
  537.     //  используем "лишнюю" итерацию цикла;
  538.     //   для этого модифицируем неиспользуемый элемент таблицы.
  539.     pow[ (1<<8) - 1 ] = 0;
  540.  
  541.     //  Генерируем прямой и обратный S-box'ы
  542.     i = 0;
  543.     do
  544.     {
  545.         byte    a = pow[(1<<8)-1 - log[i]];
  546.  
  547.         //  Умножаем на     x**4 + x**3 + x**2 + x + 1
  548.         a ^= a << 1 ^ a << 2 ^ a << 3 ^ a << 4  // a<<1|a>>7 == a<<1^a>>7 !
  549.           ^  a >> 4 ^ a >> 5 ^ a >> 6 ^ a >> 7  // переставим слагаемые
  550.                                                 // что бы помочь компилятору
  551.         //  и прибавляем    x**6 + x**5 + x**1 + x**0
  552.           ^                (1<<6 ^ 1<<5 ^ 1<<1 ^ 1<<0);  
  553.        
  554.         s_box[i] = a;
  555.         r_box[a] = i;
  556.     }
  557.     while( (byte)++i );     //  2**8 итераций
  558.  
  559.     //  Генерируем расширенные таблицы замен
  560.     for( i = 0; i < 256; i++ )
  561.     {
  562.         byte f = (byte)s_box[i];
  563.         byte f2 = lfsr2(f);
  564.         ft[0][i] = (f ^ f2) << 24 | f << 16 | f << 8 | f2;
  565.         ft[1][i] = rot_left_8( ft[0][i] );
  566.         ft[2][i] = rot_left_8( ft[1][i] );
  567.         ft[3][i] = rot_left_8( ft[2][i] );
  568.  
  569.         byte r = (byte)r_box[i];
  570.         //  Умножение выполняется по формуле:
  571.         //  pow[(log[x] + log[y]) % 255]    ( при x и y != 0 )
  572.         rt[0][i] = ! r ? r :
  573.                  (u32) pow[(0x68 + log[r]) % 255] << 24 // log[0x0B] == 0x68
  574.                ^ (u32) pow[(0xEE + log[r]) % 255] << 16 // log[0x0D] == 0xEE
  575.                ^ (u32) pow[(0xC7 + log[r]) % 255] <<  8 // log[0x09] == 0xC7
  576.                ^ (u32) pow[(0xDF + log[r]) % 255] <<  0;// log[0x0E] == 0xDF
  577.         rt[1][i] = rot_left_8( rt[0][i] );
  578.         rt[2][i] = rot_left_8( rt[1][i] );
  579.         rt[3][i] = rot_left_8( rt[2][i] );
  580.     }
  581. }
  582.  
  583.  
  584. aes::u32 inline aes::get( const byte array[4] )
  585. {
  586. #if (('1234' >> 24) == '1')     // little endian ?
  587.     return  *(u32 *)(array);
  588. #else
  589.     return  array[0] <<  0
  590.           | array[1] <<  8
  591.           | array[2] << 16
  592.           | array[3] << 24;
  593. #endif
  594. }
  595.  
  596.  
  597. void inline aes::put( u32 value, byte array[4] )
  598. {
  599. #if (('1234' >> 24) == '1')     // little endian ?
  600.     *(u32 *)(array) = value;
  601. #else
  602.     array[0] = value >>  0 & 0xFF;
  603.     array[1] = value >>  8 & 0xFF;
  604.     array[2] = value >> 16 & 0xFF;
  605.     array[3] = value >> 24       ;
  606. #endif
  607. }
  608.  
  609.  
  610. aes::u32 inline aes::fb(u32 byte, unsigned pos)
  611. {
  612.     return ft[pos][ byte >> pos*8 & 0xFF ];
  613. }
  614.  
  615.  
  616. aes::u32 inline aes::rb(u32 byte, unsigned pos)
  617. {
  618.     return rt[pos][ byte >> pos*8 & 0xFF ];
  619. }
  620.  
  621.  
  622. aes::u32    aes::s_box[256], aes::r_box[256];
  623. aes::u32    aes::ft[4][256], aes::rt[4][256];
  624.  
  625.  
  626. //=========================================================================//
  627. // Блок используется при тестировании.
  628. #ifdef AES_TEST
  629.     #ifdef LIBST
  630.         #include "libst.cpp"
  631.         typedef long clock_t;
  632.         clock_t clock(){ return GetTickCount(); }
  633.         const clock_t CLOCKS_PER_SEC = 1000;
  634.         extern "C" int _fltused = 0;
  635.     #else
  636.         #include <string.h>
  637.         #include <stdio.h>
  638.         #include <math.h>
  639.         #include <time.h>
  640.     #endif
  641. #endif
  642. //=========================================================================//
  643.  
  644.  
  645. aes::u32 inline aes::rot_left_8( u32 value )
  646. {
  647. #ifdef  _M_IX86
  648.     return  _rotl(value, 8);                // MSVC и Intel C++ делают ROL
  649. #else
  650.     return  value >> 24 | value << 8;
  651. #endif
  652. }
  653.  
  654.  
  655. //=========================================================================//
  656. // Блок используется при тестировании.
  657. #ifdef AES_TEST
  658. /**
  659.  *  Функция используется при компиляции тестового исполняемого файла.
  660.  *  При тестировании проверяется корректность (де)шифрации
  661.  *  и скорость различных методов класса aes при использовании
  662.  *  ключей 128, 192 и 256 бит.
  663.  */
  664. int main()
  665. {
  666.     /**
  667.      *  Данные для тестирования взяты из fips-197.pdf
  668.      *  http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
  669.      */
  670.    
  671.     static const byte plaintext[aes::block_size] =
  672.     {  
  673.         0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
  674.         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
  675.     };
  676.  
  677.     // Для "коротких" ключей используется начальная часть всего ключа.
  678.     static const byte key[] =
  679.     {
  680.         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  681.         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  682.         // 192 бит
  683.         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  684.         // 256 бит
  685.         0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
  686.     };
  687.  
  688.     static const byte ciphertext[3][aes::block_size] =
  689.     {
  690.         //  для ключа 128 бит
  691.         {0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
  692.          0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a},
  693.         //  для ключа 192 бит
  694.         {0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
  695.          0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91},
  696.         //  для ключа 256 бит
  697.         {0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
  698.          0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89}
  699.     };
  700.  
  701.     aes     crypto;
  702.     byte    buf[crypto.block_size];
  703.  
  704.     printf("\n AES test:\n");
  705.  
  706.     for( int i0  = 0; i0 <= 2; i0++ )
  707.     {
  708.         int key_length = 128 + 64 * i0;
  709.         printf("\n %d bit key... ", key_length);
  710.  
  711.         if( crypto.expand_key(key, key_length) != crypto.Ok )
  712.             printf("error: can't expand key.");
  713.         else
  714.         {
  715.             crypto.encrypt(plaintext, buf);
  716.             if( memcmp(&ciphertext[i0], buf, crypto.block_size) )
  717.                 printf("error: encryption failed.");
  718.             else
  719.             {
  720.                 crypto.decrypt(buf, buf);
  721.                 if( memcmp(plaintext, buf, crypto.block_size) )
  722.                     printf("error: decryption failed.");
  723.                 else
  724.                     printf("Ok.");
  725.             }
  726.         }
  727.     }
  728.        
  729.     printf("\n\n Speed test:");
  730.     printf("\n\n   key   | key expansions/sec | encryption, bytes/sec | decryption, bytes/sec");
  731.     for( int i1  = 0; i1 <= 2; i1++ )
  732.     {
  733.         const int times = 1024 * 1024;
  734.         int key_length = 128 + 64 * i1;
  735.         printf("\n %3d bit |", key_length);
  736.  
  737.         clock_t start = clock();
  738.         for( int t0 = times; t0; t0-- )
  739.         {
  740.             crypto.expand_key(key, key_length);
  741.         }
  742.         printf("    %10d      |",
  743.            (unsigned)((double)times  * CLOCKS_PER_SEC / (clock() - start))
  744.            );
  745.        
  746.         crypto.encrypt(plaintext, buf);
  747.  
  748.         start = clock();
  749.         for( int t1 = times; t1; t1-- )
  750.         {
  751.             crypto.encrypt(buf, buf);
  752.         }
  753.         printf("       %10d      |", (unsigned)
  754.            ((double)crypto.block_size * times * CLOCKS_PER_SEC / (clock() - start))
  755.            );
  756.  
  757.         start = clock();
  758.         for( int t2 = times; t2; t2-- )
  759.         {
  760.             crypto.decrypt(buf, buf);
  761.         }
  762.         printf("       %10d", (unsigned)
  763.            ((double)crypto.block_size * times * CLOCKS_PER_SEC / (clock() - start))
  764.            );
  765.  
  766.         crypto.decrypt(buf, buf);
  767.         if( memcmp(plaintext, buf, crypto.block_size) )
  768.         {
  769.             printf("\n\n error: Monte Carlo test failed.\n");
  770.             return ~0;
  771.         }
  772.     }
  773.     printf("\n\n Ok.\n");    
  774.     return 0;
  775. }
  776. #endif//#ifdef AES_TEST
  777. //=========================================================================//
  778.  
  779. ///========================================================================//
  780. /// EOF
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement