韩国国家加密算法ARIA,Cpp实现

constant.h
#ifndef _CONSTANT_H_
#define  _CONSTANT_H_

namespace  triod
{
    
const   static  unsigned  short  NUM_OF_ROUND_KEY             =   18 ;
    
const   static  unsigned  short  SECTION_LEN                     =   128   /   8 ;
    
const   static  unsigned  short  MAX_KEY_WIDTH                 =   256   /   8 ;
    
const   static  unsigned  short  DIFFUSE_TIMES                 =   16 ;
    
const   static  unsigned  short  DIFFUSE_XOR_OPRAND_TIMES     =   7 ;
    
const   static  unsigned  short  CK_NUM                         =   4 ;
    
const   static  unsigned  short  CK_SECTION_LENGTH             =   128   /   8 ;
    
const   static  unsigned  short  SBOX_TYPES                     =   4 ;
    
const   static  unsigned  short  SBOX_ELEMENTS_NUM             =   0x100 ;
    
const   static  unsigned  short  ERROR_AFFECTED_BYTE_NUM         =   7 ;

    
const   static  unsigned  short  SUB_SECTION_LEN                 =   2 ;        

    
    
enum  { SBOX1, SBOX2, SBOX1_REVERSE, SBOX2_REVERSE };
    
enum  { LEFT, RIGHT, NOP };
    
enum  { MIN_LEN  =   16 , MID_LEN  =   24 , MAX_LEN  =   32  };
    
enum  { MIN_ROUND  =   12 , MID_ROUND  =   14 , MAX_ROUND  =   16  };

    
const   static  unsigned  char  SBOX[SBOX_TYPES][SBOX_ELEMENTS_NUM]  =  
    {
        {
            
0x63 0x7c 0x77 0x7b 0xf2 0x6b 0x6f 0xc5 0x30 0x01 0x67 0x2b 0xfe 0xd7 0xab 0x76 ,
            
0xca 0x82 0xc9 0x7d 0xfa 0x59 0x47 0xf0 0xad 0xd4 0xa2 0xaf 0x9c 0xa4 0x72 0xc0 ,
            
0xb7 0xfd 0x93 0x26 0x36 0x3f 0xf7 0xcc 0x34 0xa5 0xe5 0xf1 0x71 0xd8 0x31 0x15 ,
            
0x04 0xc7 0x23 0xc3 0x18 0x96 0x05 0x9a 0x07 0x12 0x80 0xe2 0xeb 0x27 0xb2 0x75 ,
            
0x09 0x83 0x2c 0x1a 0x1b 0x6e 0x5a 0xa0 0x52 0x3b 0xd6 0xb3 0x29 0xe3 0x2f 0x84 ,
            
0x53 0xd1 0x00 0xed 0x20 0xfc 0xb1 0x5b 0x6a 0xcb 0xbe 0x39 0x4a 0x4c 0x58 0xcf ,
            
0xd0 0xef 0xaa 0xfb 0x43 0x4d 0x33 0x85 0x45 0xf9 0x02 0x7f 0x50 0x3c 0x9f 0xa8 ,
            
0x51 0xa3 0x40 0x8f 0x92 0x9d 0x38 0xf5 0xbc 0xb6 0xda 0x21 0x10 0xff 0xf3 0xd2 ,
            
0xcd 0x0c 0x13 0xec 0x5f 0x97 0x44 0x17 0xc4 0xa7 0x7e 0x3d 0x64 0x5d 0x19 0x73 ,
            
0x60 0x81 0x4f 0xdc 0x22 0x2a 0x90 0x88 0x46 0xee 0xb8 0x14 0xde 0x5e 0x0b 0xdb ,
            
0xe0 0x32 0x3a 0x0a 0x49 0x06 0x24 0x5c 0xc2 0xd3 0xac 0x62 0x91 0x95 0xe4 0x79 ,
            
0xe7 0xc8 0x37 0x6d 0x8d 0xd5 0x4e 0xa9 0x6c 0x56 0xf4 0xea 0x65 0x7a 0xae 0x08 ,
            
0xba 0x78 0x25 0x2e 0x1c 0xa6 0xb4 0xc6 0xe8 0xdd 0x74 0x1f 0x4b 0xbd 0x8b 0x8a ,
            
0x70 0x3e 0xb5 0x66 0x48 0x03 0xf6 0x0e 0x61 0x35 0x57 0xb9 0x86 0xc1 0x1d 0x9e ,
            
0xe1 0xf8 0x98 0x11 0x69 0xd9 0x8e 0x94 0x9b 0x1e 0x87 0xe9 0xce 0x55 0x28 0xdf ,
            
0x8c 0xa1 0x89 0x0d 0xbf 0xe6 0x42 0x68 0x41 0x99 0x2d 0x0f 0xb0 0x54 0xbb 0x16
        },
        {
            
0xe2 0x4e 0x54 0xfc 0x94 0xc2 0x4a 0xcc 0x62 0x0d 0x6a 0x46 0x3c 0x4d 0x8b 0xd1 ,
            
0x5e 0xfa 0x64 0xcb 0xb4 0x97 0xbe 0x2b 0xbc 0x77 0x2e 0x03 0xd3 0x19 0x59 0xc1 ,
            
0x1d 0x06 0x41 0x6b 0x55 0xf0 0x99 0x69 0xea 0x9c 0x18 0xae 0x63 0xdf 0xe7 0xbb ,
            
0x00 0x73 0x66 0xfb 0x96 0x4c 0x85 0xe4 0x3a 0x09 0x45 0xaa 0x0f 0xee 0x10 0xeb ,
            
0x2d 0x7f 0xf4 0x29 0xac 0xcf 0xad 0x91 0x8d 0x78 0xc8 0x95 0xf9 0x2f 0xce 0xcd ,
            
0x08 0x7a 0x88 0x38 0x5c 0x83 0x2a 0x28 0x47 0xdb 0xb8 0xc7 0x93 0xa4 0x12 0x53 ,
            
0xff 0x87 0x0e 0x31 0x36 0x21 0x58 0x48 0x01 0x8e 0x37 0x74 0x32 0xca 0xe9 0xb1 ,
            
0xb7 0xab 0x0c 0xd7 0xc4 0x56 0x42 0x26 0x07 0x98 0x60 0xd9 0xb6 0xb9 0x11 0x40 ,
            
0xec 0x20 0x8c 0xbd 0xa0 0xc9 0x84 0x04 0x49 0x23 0xf1 0x4f 0x50 0x1f 0x13 0xdc ,
            
0xd8 0xc0 0x9e 0x57 0xe3 0xc3 0x7b 0x65 0x3b 0x02 0x8f 0x3e 0xe8 0x25 0x92 0xe5 ,
            
0x15 0xdd 0xfd 0x17 0xa9 0xbf 0xd4 0x9a 0x7e 0xc5 0x39 0x67 0xfe 0x76 0x9d 0x43 ,
            
0xa7 0xe1 0xd0 0xf5 0x68 0xf2 0x1b 0x34 0x70 0x05 0xa3 0x8a 0xd5 0x79 0x86 0xa8 ,
            
0x30 0xc6 0x51 0x4b 0x1e 0xa6 0x27 0xf6 0x35 0xd2 0x6e 0x24 0x16 0x82 0x5f 0xda ,
            
0xe6 0x75 0xa2 0xef 0x2c 0xb2 0x1c 0x9f 0x5d 0x6f 0x80 0x0a 0x72 0x44 0x9b 0x6c ,
            
0x90 0x0b 0x5b 0x33 0x7d 0x5a 0x52 0xf3 0x61 0xa1 0xf7 0xb0 0xd6 0x3f 0x7c 0x6d ,
            
0xed 0x14 0xe0 0xa5 0x3d 0x22 0xb3 0xf8 0x89 0xde 0x71 0x1a 0xaf 0xba 0xb5 0x81
        },
        {
            
0x52 0x09 0x6a 0xd5 0x30 0x36 0xa5 0x38 0xbf 0x40 0xa3 0x9e 0x81 0xf3 0xd7 0xfb ,
            
0x7c 0xe3 0x39 0x82 0x9b 0x2f 0xff 0x87 0x34 0x8e 0x43 0x44 0xc4 0xde 0xe9 0xcb ,
            
0x54 0x7b 0x94 0x32 0xa6 0xc2 0x23 0x3d 0xee 0x4c 0x95 0x0b 0x42 0xfa 0xc3 0x4e ,
            
0x08 0x2e 0xa1 0x66 0x28 0xd9 0x24 0xb2 0x76 0x5b 0xa2 0x49 0x6d 0x8b 0xd1 0x25 ,
            
0x72 0xf8 0xf6 0x64 0x86 0x68 0x98 0x16 0xd4 0xa4 0x5c 0xcc 0x5d 0x65 0xb6 0x92 ,
            
0x6c 0x70 0x48 0x50 0xfd 0xed 0xb9 0xda 0x5e 0x15 0x46 0x57 0xa7 0x8d 0x9d 0x84 ,
            
0x90 0xd8 0xab 0x00 0x8c 0xbc 0xd3 0x0a 0xf7 0xe4 0x58 0x05 0xb8 0xb3 0x45 0x06 ,
            
0xd0 0x2c 0x1e 0x8f 0xca 0x3f 0x0f 0x02 0xc1 0xaf 0xbd 0x03 0x01 0x13 0x8a 0x6b ,
            
0x3a 0x91 0x11 0x41 0x4f 0x67 0xdc 0xea 0x97 0xf2 0xcf 0xce 0xf0 0xb4 0xe6 0x73 ,
            
0x96 0xac 0x74 0x22 0xe7 0xad 0x35 0x85 0xe2 0xf9 0x37 0xe8 0x1c 0x75 0xdf 0x6e ,
            
0x47 0xf1 0x1a 0x71 0x1d 0x29 0xc5 0x89 0x6f 0xb7 0x62 0x0e 0xaa 0x18 0xbe 0x1b ,
            
0xfc 0x56 0x3e 0x4b 0xc6 0xd2 0x79 0x20 0x9a 0xdb 0xc0 0xfe 0x78 0xcd 0x5a 0xf4 ,
            
0x1f 0xdd 0xa8 0x33 0x88 0x07 0xc7 0x31 0xb1 0x12 0x10 0x59 0x27 0x80 0xec 0x5f ,
            
0x60 0x51 0x7f 0xa9 0x19 0xb5 0x4a 0x0d 0x2d 0xe5 0x7a 0x9f 0x93 0xc9 0x9c 0xef ,
            
0xa0 0xe0 0x3b 0x4d 0xae 0x2a 0xf5 0xb0 0xc8 0xeb 0xbb 0x3c 0x83 0x53 0x99 0x61 ,
            
0x17 0x2b 0x04 0x7e 0xba 0x77 0xd6 0x26 0xe1 0x69 0x14 0x63 0x55 0x21 0x0c 0x7d
        },
        {
            
0x30 0x68 0x99 0x1b 0x87 0xb9 0x21 0x78 0x50 0x39 0xdb 0xe1 0x72 0x09 0x62 0x3c ,
            
0x3e 0x7e 0x5e 0x8e 0xf1 0xa0 0xcc 0xa3 0x2a 0x1d 0xfb 0xb6 0xd6 0x20 0xc4 0x8d ,
            
0x81 0x65 0xf5 0x89 0xcb 0x9d 0x77 0xc6 0x57 0x43 0x56 0x17 0xd4 0x40 0x1a 0x4d ,
            
0xc0 0x63 0x6c 0xe3 0xb7 0xc8 0x64 0x6a 0x53 0xaa 0x38 0x98 0x0c 0xf4 0x9b 0xed ,
            
0x7f 0x22 0x76 0xaf 0xdd 0x3a 0x0b 0x58 0x67 0x88 0x06 0xc3 0x35 0x0d 0x01 0x8b ,
            
0x8c 0xc2 0xe6 0x5f 0x02 0x24 0x75 0x93 0x66 0x1e 0xe5 0xe2 0x54 0xd8 0x10 0xce ,
            
0x7a 0xe8 0x08 0x2c 0x12 0x97 0x32 0xab 0xb4 0x27 0x0a 0x23 0xdf 0xef 0xca 0xd9 ,
            
0xb8 0xfa 0xdc 0x31 0x6b 0xd1 0xad 0x19 0x49 0xbd 0x51 0x96 0xee 0xe4 0xa8 0x41 ,
            
0xda 0xff 0xcd 0x55 0x86 0x36 0xbe 0x61 0x52 0xf8 0xbb 0x0e 0x82 0x48 0x69 0x9a ,
            
0xe0 0x47 0x9e 0x5c 0x04 0x4b 0x34 0x15 0x79 0x26 0xa7 0xde 0x29 0xae 0x92 0xd7 ,
            
0x84 0xe9 0xd2 0xba 0x5d 0xf3 0xc5 0xb0 0xbf 0xa4 0x3b 0x71 0x44 0x46 0x2b 0xfc ,
            
0xeb 0x6f 0xd5 0xf6 0x14 0xfe 0x7c 0x70 0x5a 0x7d 0xfd 0x2f 0x18 0x83 0x16 0xa5 ,
            
0x91 0x1f 0x05 0x95 0x74 0xa9 0xc1 0x5b 0x4a 0x85 0x6d 0x13 0x07 0x4f 0x4e 0x45 ,
            
0xb2 0x0f 0xc9 0x1c 0xa6 0xbc 0xec 0x73 0x90 0x7b 0xcf 0x59 0x8f 0xa1 0xf9 0x2d ,
            
0xf2 0xb1 0x00 0x94 0x37 0x9f 0xd0 0x2e 0x9c 0x6e 0x28 0x3f 0x80 0xf0 0x3d 0xd3 ,
            
0x25 0x8a 0xb5 0xe7 0x42 0xb3 0xc7 0xea 0xf7 0x4c 0x11 0x33 0x03 0xa2 0xac 0x60
        }
    };

    
const   static  unsigned  char  DIFFUSE_OPERATION[DIFFUSE_TIMES][DIFFUSE_XOR_OPRAND_TIMES]  =  
    {
        { 
0x03 0x04 0x06 0x08 0x09 0x0D 0x0E  },
        { 
0x02 0x05 0x07 0x08 0x09 0x0C 0x0F  },
        { 
0x01 0x04 0x06 0x0A 0x0B 0x0C 0x0F  },
        { 
0x00 0x05 0x07 0x0A 0x0B 0x0D 0x0E  },
        { 
0x00 0x02 0x05 0x08 0x0B 0x0E 0x0F  },
        { 
0x01 0x03 0x04 0x09 0x0A 0x0E 0x0F  },
        { 
0x00 0x02 0x07 0x09 0x0A 0x0C 0x0D  },
        { 
0x01 0x03 0x06 0x08 0x0B 0x0C 0x0D  },
        { 
0x00 0x01 0x04 0x07 0x0A 0x0D 0x0F  },
        { 
0x00 0x01 0x05 0x06 0x0B 0x0C 0x0E  },
        { 
0x02 0x03 0x05 0x06 0x08 0x0D 0x0F  },
        { 
0x02 0x03 0x04 0x07 0x09 0x0C 0x0E  },
        { 
0x01 0x02 0x06 0x07 0x09 0x0B 0x0C  },
        { 
0x00 0x03 0x06 0x07 0x08 0x0A 0x0D  },
        { 
0x00 0x03 0x04 0x05 0x09 0x0B 0x0E  },
        { 
0x01 0x02 0x04 0x05 0x08 0x0A 0x0F  }
    };

    
//  为了和文档兼容,这里增加了一个 0 行
     const   static  unsigned  char  CK[CK_NUM][CK_SECTION_LENGTH]  =
    {
        { 
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00  },
        { 
0x51 0x7c 0xc1 0xb7 0x27 0x22 0x0a 0x94 0xfe 0x13 0xab 0xe8 0xfa 0x9a 0x6e 0xe0  },
        { 
0x6d 0xb1 0x4a 0xcc 0x9e 0x21 0xc8 0x20 0xff 0x28 0xb1 0xd5 0xef 0x5d 0xe2 0xb0  },
        { 
0xdb 0x92 0x37 0x1d 0x21 0x26 0xe9 0x70 0x03 0x24 0x97 0x75 0x04 0xe8 0xc9 0x0e  }
    };

    
const   static  unsigned  char  CK_ORDER[ 4 ][ 3 =  
    {
        { 
0 0 0  },
        { 
1 2 3  },
        { 
2 3 1  },
        { 
3 1 2  }
    };

    
const   static  unsigned  char  ROUNDS_BY_KEY_LENGTH[]  =  {  0 , MIN_ROUND, MID_ROUND, MAX_ROUND };


    
const   static  unsigned  short  ROUND_KEY_OP_ARRAY[NUM_OF_ROUND_KEY][ 6 =  
    {
        { NOP, 
0 0 , NOP,  0 0  },         //  0

        { NOP, 
0 0 , RIGHT,  1 19  },     //  1
        { NOP,  1 0 , RIGHT,  2 19  },     //  2
        { NOP,  2 0 , RIGHT,  3 19  },     //  3
        { RIGHT,  0 19 , NOP,  3 0  },     //  4

        { NOP, 
0 0 , RIGHT,  1 31  },     //  5
        { NOP,  1 0 , RIGHT,  2 31  },     //  6
        { NOP,  2 0 , RIGHT,  3 31  },     //  7
        { RIGHT,  0 31 , NOP,  3 0  },     //  8

        { NOP, 
0 0 , LEFT,  1 61  },         //  9
        { NOP,  1 0 , LEFT,  2 61  },         //  10
        { NOP,  2 0 , LEFT,  3 61  },         //  11
        { LEFT,  0 61 , NOP,  3 0  },         //  12

        { NOP, 
0 0 , LEFT,  1 31   },     //  13
        { NOP,  1 0 , LEFT,  2 31  },         //  14
        { NOP,  2 0 , LEFT,  3 31  },         //  15
        { LEFT,  0 31 , NOP,  3 0  },         //  16
        
        { NOP, 
0 0 , LEFT,  1 19  }         //  17

/*
        { RIGHT, 0, 7, LEFT, 1, 11 },
        { LEFT, 1, 22, NOP, 2, 0 },
        { RIGHT, 2, 17, LEFT, 3, 16 },
        { RIGHT, 0, 14, LEFT, 3, 32 },
        { RIGHT, 0, 21, RIGHT, 2, 34 },
        { LEFT, 1, 33, LEFT, 3, 48 },
        { LEFT, 1, 44, RIGHT, 2, 51 },
        { RIGHT, 0, 28, LEFT, 3, 64 },
        { LEFT, 1, 55, LEFT, 3, 80 },
        { RIGHT, 0, 35, RIGHT, 2, 68 },
        { RIGHT, 0, 42, LEFT, 1, 66 },
        { LEFT, 1, 77, RIGHT, 2, 85 },
        { RIGHT, 0, 49, RIGHT, 2, 102  },
        { RIGHT, 2, 119, LEFT, 3, 112 },
        { RIGHT, 0, 56, LEFT, 1, 8 }
*/
    };


    
const   static  unsigned  char  ODD_LAYER_BOX[]  =  
    {
        SBOX1, SBOX2, SBOX1_REVERSE, SBOX2_REVERSE, 
        SBOX1, SBOX2, SBOX1_REVERSE, SBOX2_REVERSE, 
        SBOX1, SBOX2, SBOX1_REVERSE, SBOX2_REVERSE, 
        SBOX1, SBOX2, SBOX1_REVERSE, SBOX2_REVERSE
    };

    
const   static  unsigned  char  EVEN_LAYER_BOX[]  =  
    {
        SBOX1_REVERSE, SBOX2_REVERSE, SBOX1, SBOX2, 
        SBOX1_REVERSE, SBOX2_REVERSE, SBOX1, SBOX2, 
        SBOX1_REVERSE, SBOX2_REVERSE, SBOX1, SBOX2, 
        SBOX1_REVERSE, SBOX2_REVERSE, SBOX1, SBOX2
    };

    
const   static  size_t ERROR_AT[SECTION_LEN][ERROR_AFFECTED_BYTE_NUM]  =
    {
        { 
3 4 6 8 9 13 14  },
        { 
2 5 7 8 9 12 15  },
        { 
1 4 6 10 11 12 15  },
        { 
0 5 7 10 11 13 14  },
        { 
0 2 5 8 11 14 15  },
        { 
1 3 4 9 10 14 15  },
        { 
0 2 7 9 10 12 13  },
        { 
1 3 6 8 11 12 13  },
        { 
0 1 4 7 10 13 15  },
        { 
0 1 5 6 11 12 14  },
        { 
2 3 5 6 8 13 15  },
        { 
2 3 4 7 9 12 14  },
        { 
1 2 6 7 9 11 12  },
        { 
0 3 6 7 8 10 13  },
        { 
0 3 4 5 9 11 14  },
        { 
1 2 4 5 8 10 15  }
    };

}
#endif

aira.h
#ifndef _ARIA_H_
#define  _ARIA_H_

#include 
< cstdio >
#include 
< cstring >

#include 
" constant.h "

#define  TEST 0

namespace  triod
{
    template
< int  key_length >
    
class  ARIA
    {
    
public :
        typedef 
const  unsigned  char         ( & const_block)    [key_length];
        typedef unsigned 
char             ( & block)        [key_length];

        ARIA( const_block key );
        
        
        
void  encrypt( const_block text, block cipher );     //  注意rounds_比实际的加密需要的轮数少一轮,用于最后一步的不做diffuse的运算
        
        
        
void  decrypt( const_block cipher, block text );


    
    
/*  ----------------------------------------------------------------------------------------  */
    
protected :
        
virtual   void  function ( size_t round, block input, const_block round_key );
        
virtual   void  function_last_round ( block input, const_block round_key );
        
        
void  generate_round_key();  //  生成轮密钥函数
         void  diffuse( block input );          //  The Diffusion Layer Function

        
static   void  key_xor ( const_block lhs, const_block rhs, block output );     //  针对 128 bit 的序列专门设计的异或函数
         static   void  rotate_key ( unsigned  short  types, const_block input, size_t move_bits, block output );  //  针对 128 bit 的序列专门设计的循环移位函数
         static   void  print_block( const_block text );
        
static   bool  compare_section(  const  unsigned  char *  lhs,  const  unsigned  char *  rhs, size_t len );

        unsigned 
char  key_[MAX_KEY_WIDTH];                                         //  主密钥, 256 bit
        unsigned  char  encrypt_round_key_[NUM_OF_ROUND_KEY][SECTION_LEN];         //  16 个加密轮密钥,每个 128 bit
        unsigned  char  decrypt_round_key_[NUM_OF_ROUND_KEY][SECTION_LEN];         //  16 个解密轮密钥,每个 128 bit

        size_t rounds_;
    };
}

/*  --------------------------------------------------------------------------------------------------------------------------------  */
namespace  triod
{
    template
< int  key_length >
    ARIA
< key_length > ::ARIA( const_block key )
    {
        
//  一个小小技巧,用于在编译期防止 key_length 非法
         char  guard[(key_length  ==  MIN_LEN  ||  key_length  ==  MID_LEN  ||  key_length  ==  MAX_LEN)  ?   1  :  - 1 =  {  0  };

        
//  另一个技巧,计算加密解密轮数
        rounds_  =  ROUNDS_BY_KEY_LENGTH[key_length  /   10 ];

        memset( key_, 
0 , MAX_KEY_WIDTH );

        
for  ( size_t i  =   0 ; i  <  NUM_OF_ROUND_KEY;  ++ i )
        {
            memset( encrypt_round_key_[i], 
0 , SECTION_LEN );
            memset( decrypt_round_key_[i], 
0 , SECTION_LEN );
        }

        
//  不用 memcpy
         for  ( size_t i  =   0 ; i  <  key_length;  ++ i )
            key_[i] 
=  key[i];

        
this -> generate_round_key();
    }


    
    template
< int  key_length >
    
void  ARIA < key_length > ::encrypt( const_block text, block cipher )     //  注意rounds_比实际的加密需要的轮数少一轮,用于最后一步的不做diffuse的运算
    {
        memcpy ( cipher, text, SECTION_LEN );    
        
        
for  ( size_t i  =   1 ; i  <  rounds_;  ++ i )
        {
            
this -> function( i, cipher, encrypt_round_key_[i] );

            
#if  TEST
            
this -> print_block( cipher );
            
#endif
        }

        
this -> function_last_round( cipher, encrypt_round_key_[rounds_] );
        
this -> key_xor( cipher, encrypt_round_key_[rounds_  +   1 ], cipher );

        
#if  TEST
        
this -> print_block( cipher );
        printf( 
" Encrypt TEXT\n\n " );
        
#endif
    }

    
    template
< int  key_length >
    
void  ARIA < key_length > ::decrypt( const_block cipher, block text )
    {
        
//  注意rounds_比实际的加密需要的轮数少一轮,用于最后一步的不做diffuse的运算
        memcpy ( text, cipher, SECTION_LEN );
        
        
for  ( size_t i  =   1 ; i  <  rounds_;  ++ i )
        {
            
this -> function( i  %   2   ==   1 , text, decrypt_round_key_[i] );

            
#if  TEST
            
for  ( size_t j  =   0 ; j  <  SECTION_LEN;  ++ j )
                printf( 
" %02x  " , text[j] );
            printf( 
" \n " );
            
#endif
        }

        
this -> function_last_round( text, decrypt_round_key_[rounds_] );
        
this -> key_xor( text, decrypt_round_key_[rounds_  +   1 ], text );

        
#if  TEST
        
for  ( size_t j  = 0 ; j  <  SECTION_LEN;  ++ j )
            printf( 
" %02x  " , text[j] );
        printf( 
" \nDecrypt TEXT\n\n " );
        
#endif
    }



/*  ----------------------------------------------------------------------------------------  */
    template
< int  key_length >
    
void  ARIA < key_length > ::function ( size_t round, block input, const_block round_key )
    {
        
bool  is_odd_layer  =  ( round  %   2   ==   1  );
        
        
//  第一步,XOR
         this -> key_xor( input, round_key, input );

        
//  第二步,S-box layer
         for  ( size_t i  =   0 ; i  <  SECTION_LEN;  ++ i )
        {
            input[i] 
=  SBOX[ is_odd_layer  ?  ODD_LAYER_BOX[i] : EVEN_LAYER_BOX[i] ][ input[i] ];
        }

        
//  第三步,diffusion layer
         this -> diffuse( input );
    }


    template
< int  key_length >
    
void  ARIA < key_length > ::function_last_round ( block input, const_block round_key )
    {

        
this -> key_xor( input, round_key, input );                         //  第一步,XOR

        
for  ( size_t i  =   0 ; i  <  SECTION_LEN;  ++ i )                         //  第二步,S-box layer
            input[i]  =  SBOX[EVEN_LAYER_BOX[i]][input[i]];
    }


    template
< int  key_length >
    
void  ARIA < key_length > ::generate_round_key()  //  生成轮密钥函数
    {
        
//  W 共有 4 个,每个 128 bit
        unsigned  char  W[ 4 ][SECTION_LEN];
        
        
//  kR,即 main key 的右 128 bits
        unsigned  char  KR[SECTION_LEN];
        memcpy ( KR, key_ 
+  SECTION_LEN, SECTION_LEN );

        
/*  ------------------- 首先初始化 W 数组 -------------------  */
        
//  W[0] = KL,即 main key 的左 128 bits
        memcpy ( W[ 0 ], key_, SECTION_LEN );

        
//  这里采用查表的方法:CK[ CK_ORDER[key_length / 10][0] ]
        
//  来处理密钥长度不同时,CK不同的情况
        memcpy( W[ 1 ], W[ 0 ], SECTION_LEN );
        
this -> function(  true , W[ 1 ], CK[ CK_ORDER[key_length  /   10 ][ 0 ] ] );
        
this -> key_xor( W[ 1 ], KR, W[ 1 ] );

        memcpy( W[
2 ], W[ 1 ], SECTION_LEN );
        
this -> function(  false , W[ 2 ], CK[ CK_ORDER[key_length  /   10 ][ 1 ] ] );
        
this -> key_xor( W[ 2 ], W[ 0 ], W[ 2 ] );

        memcpy( W[
3 ], W[ 2 ], SECTION_LEN );
        
this -> function(  true , W[ 3 ], CK[ CK_ORDER[key_length  /   10 ][ 2 ] ] );
        
this -> key_xor( W[ 3 ], W[ 1 ], W[ 3 ] );

        
#if  TEST  //  测试输出 W[k]
        
for  ( size_t i  =   0 ; i  <   4 ++ i )
        {
            
for  ( size_t j  =   0 ; j  <   16 ++ j )
                printf(
" %02x  " , W[i][j]);
            printf(
" \n " );
        }
        printf(
" W[k] END\n\n " );
        
#endif


        
/*  ------------------- 然后计算 encrypt_round_key_ -------------------  */     

        
//  中间操作需要两个临时的数组
        unsigned  char  temp[ 2 ][SECTION_LEN];

        
for  ( size_t i  =   1 ; i  <  NUM_OF_ROUND_KEY;  ++ i )
        {
            
this -> rotate_key( ROUND_KEY_OP_ARRAY[i][ 0 ], W[ ROUND_KEY_OP_ARRAY[i][ 1 ] ], ROUND_KEY_OP_ARRAY[i][ 2 ], temp[ 0 ] );
            
this -> rotate_key( ROUND_KEY_OP_ARRAY[i][ 3 ], W[ ROUND_KEY_OP_ARRAY[i][ 4 ] ], ROUND_KEY_OP_ARRAY[i][ 5 ], temp[ 1 ] );
            
this -> key_xor( temp[ 0 ], temp[ 1 ], encrypt_round_key_[i] );
        }

        
#if  TEST  //  测试输出 encrypt round key
        
for  ( size_t i  =   1 ; i  <  NUM_OF_ROUND_KEY;  ++ i )
        {
            
for  ( size_t j  =   0 ; j  <  SECTION_LEN;  ++ j )
                printf(
" %02x  " , encrypt_round_key_[i][j]);
            printf(
" \n " );
        }
        printf(
" ENCRYPT ROUND KEY END\n\n " );
        
#endif

        
/*  ------------------- 然后计算 decrypt_round_key_ -------------------  */     
        memcpy( decrypt_round_key_[
1 ], encrypt_round_key_[rounds_  +   1 ], SECTION_LEN );
        memcpy( decrypt_round_key_[rounds_ 
+   1 ], encrypt_round_key_[ 1 ], SECTION_LEN );
        
        
for  ( size_t i  =   2 ; i  <=  rounds_;  ++ i )
        {
            memcpy( decrypt_round_key_[i], encrypt_round_key_[rounds_ 
+   2   -  i], SECTION_LEN );
            
this -> diffuse( decrypt_round_key_[i] );
        }

        
#if  TEST  //  测试输出 decrypt round key
        
for  ( size_t i  =   1 ; i  <  NUM_OF_ROUND_KEY;  ++ i )
        {
            
for  ( size_t j  =   0 ; j  <  SECTION_LEN;  ++ j )
                printf(
" %02x  " , decrypt_round_key_[i][j]);
            printf(
" \n " );
        }
        printf(
" DECRYPT ROUND KEY END\n\n " );
        
#endif
    }
    
    template
< int  key_length >
    
void  ARIA < key_length > ::diffuse( block input )          //  The Diffusion Layer Function
    {
        unsigned 
char  temp[SECTION_LEN];
        memcpy ( temp, input, SECTION_LEN );

        
for  ( size_t i  =   0 ; i  <  SECTION_LEN;  ++ i )
        {
            input[i] 
=  
                temp[ DIFFUSE_OPERATION[i][
0 ] ]  ^
                temp[ DIFFUSE_OPERATION[i][
1 ] ]  ^
                temp[ DIFFUSE_OPERATION[i][
2 ] ]  ^
                temp[ DIFFUSE_OPERATION[i][
3 ] ]  ^
                temp[ DIFFUSE_OPERATION[i][
4 ] ]  ^
                temp[ DIFFUSE_OPERATION[i][
5 ] ]  ^
                temp[ DIFFUSE_OPERATION[i][
6 ] ];
        }
    }



    
/*  ------------------- 下面是一些针对内存块的功能函数 -------------------  */
    template
< int  key_length >
    
void  ARIA < key_length > ::key_xor ( const_block lhs, const_block rhs, block output )     //  针对 128 bit 的序列专门设计的异或函数
    {
        
for  ( size_t i  =   0 ; i  <  SECTION_LEN;  ++ i )
            output[i] 
=  lhs[i]  ^  rhs[i];
    }

    
    
    template
< int  key_length >
    
void  ARIA < key_length > ::rotate_key ( unsigned  short  types, const_block input, size_t move_bits, block output )  //  针对 128 bit 的序列专门设计的循环移位函数
    {
        size_t move_bytes 
=  move_bits  /   8 ;
        size_t remain_bits 
=  move_bits  %   8 ;
        
        unsigned 
char  higher_bit;
        unsigned 
char  lower_bit;

        
if  ( LEFT  ==  types )
        {
            memcpy ( output, input 
+  move_bytes, SECTION_LEN  -  move_bytes );
            memcpy ( output 
+  SECTION_LEN  -  move_bytes, input, move_bytes );

            
for  ( size_t i  =   0 ; i  <  remain_bits;  ++ i )
            {
                higher_bit 
=  (output[ 0 &   0x80 >>   7 ;     //  保存最高位
                 for  ( size_t j  =   0 ; j  <  SECTION_LEN  -   1 ++ j )
                {
                    output[j] 
<<=   1 ;                             //  左移之后,最低位用 0 补齐
                    lower_bit  =  (output[j  +   1 &   0x80 >>   7 ;
                    output[j] 
|=  lower_bit;                         //  0 | lower_bit = lower_bit
                }

                output[SECTION_LEN 
-   1 <<=   1 ;
                output[SECTION_LEN 
-   1 |=  higher_bit;
            }

            
return ;
        }

        
if  ( RIGHT  ==  types )
        {
            memcpy ( output, input 
+  SECTION_LEN  -  move_bytes, move_bytes );
            memcpy ( output 
+  move_bytes, input, SECTION_LEN  -  move_bytes );

            
for  ( size_t i  =   0 ; i  <  remain_bits;  ++ i )
            {
                lower_bit 
=  (output[ 0 &   0x01 <<   7 ;
                higher_bit 
=  (output[SECTION_LEN  -   1 &   0x01 <<   7 ;     //  保存最低位
                output[ 0 >>=   1 ;                                                         //  右移之后,最高位用 0 补齐
                output[ 0 |=  higher_bit;                                             //  0 | lower_bit = lower_bit

                
for  ( size_t j  =   1 ; j  <  SECTION_LEN;  ++ j )
                {
                    higher_bit 
=  lower_bit;
                    lower_bit 
=  (output[j]  &   0x01 <<   7 ;
                    output[j] 
>>=   1 ;                                 //  右移之后,最高位用 0 补齐
                    output[j]  |=  higher_bit;                     //  0 | higher_bit = higher_bit
                }
            }
        }

        
if  ( NOP  ==  types )
        {
            memcpy ( output, input, SECTION_LEN );
        }
    }

    template
< int  key_length >
    
void  ARIA < key_length > ::print_block( const_block text )
    {
        
for  ( size_t i  =   0 ; i  <  SECTION_LEN;  ++ i )
        {
            printf( 
" %02x  " , text[i] );
        }
        printf( 
" \n "  );
    }

    template
< int  key_length >
    
bool  ARIA < key_length > ::compare_section(  const  unsigned  char *  lhs,  const  unsigned  char *  rhs, size_t len )
    {
        
for  ( size_t i  =   0 ; i  <  len;  ++ i )
        {
            
if  ( lhs[i]  !=  rhs[i] )
                
return   false ;
        }

        
return   true ;
    }

/*  --------------------------------------------------------------------------------------------------------------------------------  */
}


#endif

test.cpp
#include  " ARIA.h "

#define  NUM 16

int  main()
{
    
using  triod::ARIA;

    
//  unsigned char key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
    unsigned  char  key[]  =  {  0x00 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 0x99 0xaa 0xbb 0xcc 0xdd 0xee 0xff  };

    unsigned 
char  plaintext[]  =  {  0x11 0x11 0x11 0x11 0xaa 0xaa 0xaa 0xaa 0x11 0x11 0x11 0x11 0xbb 0xbb 0xbb 0xbb  };

    unsigned 
char  plaintest[]  =  {  0x30 0x26 0xB2 0x75 0x8E 0x66 0xCF 0x11 0xA6 0xD9 0xAA 0x00 0x62 0xCE 0x6C 0xD4  };

    
/*
    unsigned char key[] = 
    {
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77
    };
    
*/

    
/*
    unsigned char key[] = 
    {    
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
    };
    
*/


    ARIA
< sizeof (key) >  test(key);

    unsigned 
char  cipher[ 2 ][NUM];

    test.encrypt( plaintext, cipher[
0 ] );
    test.encrypt( plaintest, cipher[
1 ] );
    unsigned 
char  t[NUM];
    test.decrypt( cipher[
1 ], t );

    
for  ( size_t j  =   0 ; j  <  NUM;  ++ j )
        printf( 
" %2x  " , t[j] );

    
return   0 ;
}