SHARE
TWEET

Untitled

a guest Dec 1st, 2015 112 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top