韩国国家加密算法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] = 
    {
        {
            
0x630x7c0x770x7b0xf20x6b0x6f0xc50x300x010x670x2b0xfe0xd70xab0x76,
            
0xca0x820xc90x7d0xfa0x590x470xf00xad0xd40xa20xaf0x9c0xa40x720xc0,
            
0xb70xfd0x930x260x360x3f0xf70xcc0x340xa50xe50xf10x710xd80x310x15,
            
0x040xc70x230xc30x180x960x050x9a0x070x120x800xe20xeb0x270xb20x75,
            
0x090x830x2c0x1a0x1b0x6e0x5a0xa00x520x3b0xd60xb30x290xe30x2f0x84,
            
0x530xd10x000xed0x200xfc0xb10x5b0x6a0xcb0xbe0x390x4a0x4c0x580xcf,
            
0xd00xef0xaa0xfb0x430x4d0x330x850x450xf90x020x7f0x500x3c0x9f0xa8,
            
0x510xa30x400x8f0x920x9d0x380xf50xbc0xb60xda0x210x100xff0xf30xd2,
            
0xcd0x0c0x130xec0x5f0x970x440x170xc40xa70x7e0x3d0x640x5d0x190x73,
            
0x600x810x4f0xdc0x220x2a0x900x880x460xee0xb80x140xde0x5e0x0b0xdb,
            
0xe00x320x3a0x0a0x490x060x240x5c0xc20xd30xac0x620x910x950xe40x79,
            
0xe70xc80x370x6d0x8d0xd50x4e0xa90x6c0x560xf40xea0x650x7a0xae0x08,
            
0xba0x780x250x2e0x1c0xa60xb40xc60xe80xdd0x740x1f0x4b0xbd0x8b0x8a,
            
0x700x3e0xb50x660x480x030xf60x0e0x610x350x570xb90x860xc10x1d0x9e,
            
0xe10xf80x980x110x690xd90x8e0x940x9b0x1e0x870xe90xce0x550x280xdf,
            
0x8c0xa10x890x0d0xbf0xe60x420x680x410x990x2d0x0f0xb00x540xbb0x16
        },
        {
            
0xe20x4e0x540xfc0x940xc20x4a0xcc0x620x0d0x6a0x460x3c0x4d0x8b0xd1,
            
0x5e0xfa0x640xcb0xb40x970xbe0x2b0xbc0x770x2e0x030xd30x190x590xc1,
            
0x1d0x060x410x6b0x550xf00x990x690xea0x9c0x180xae0x630xdf0xe70xbb,
            
0x000x730x660xfb0x960x4c0x850xe40x3a0x090x450xaa0x0f0xee0x100xeb,
            
0x2d0x7f0xf40x290xac0xcf0xad0x910x8d0x780xc80x950xf90x2f0xce0xcd,
            
0x080x7a0x880x380x5c0x830x2a0x280x470xdb0xb80xc70x930xa40x120x53,
            
0xff0x870x0e0x310x360x210x580x480x010x8e0x370x740x320xca0xe90xb1,
            
0xb70xab0x0c0xd70xc40x560x420x260x070x980x600xd90xb60xb90x110x40,
            
0xec0x200x8c0xbd0xa00xc90x840x040x490x230xf10x4f0x500x1f0x130xdc,
            
0xd80xc00x9e0x570xe30xc30x7b0x650x3b0x020x8f0x3e0xe80x250x920xe5,
            
0x150xdd0xfd0x170xa90xbf0xd40x9a0x7e0xc50x390x670xfe0x760x9d0x43,
            
0xa70xe10xd00xf50x680xf20x1b0x340x700x050xa30x8a0xd50x790x860xa8,
            
0x300xc60x510x4b0x1e0xa60x270xf60x350xd20x6e0x240x160x820x5f0xda,
            
0xe60x750xa20xef0x2c0xb20x1c0x9f0x5d0x6f0x800x0a0x720x440x9b0x6c,
            
0x900x0b0x5b0x330x7d0x5a0x520xf30x610xa10xf70xb00xd60x3f0x7c0x6d,
            
0xed0x140xe00xa50x3d0x220xb30xf80x890xde0x710x1a0xaf0xba0xb50x81
        },
        {
            
0x520x090x6a0xd50x300x360xa50x380xbf0x400xa30x9e0x810xf30xd70xfb,
            
0x7c0xe30x390x820x9b0x2f0xff0x870x340x8e0x430x440xc40xde0xe90xcb,
            
0x540x7b0x940x320xa60xc20x230x3d0xee0x4c0x950x0b0x420xfa0xc30x4e,
            
0x080x2e0xa10x660x280xd90x240xb20x760x5b0xa20x490x6d0x8b0xd10x25,
            
0x720xf80xf60x640x860x680x980x160xd40xa40x5c0xcc0x5d0x650xb60x92,
            
0x6c0x700x480x500xfd0xed0xb90xda0x5e0x150x460x570xa70x8d0x9d0x84,
            
0x900xd80xab0x000x8c0xbc0xd30x0a0xf70xe40x580x050xb80xb30x450x06,
            
0xd00x2c0x1e0x8f0xca0x3f0x0f0x020xc10xaf0xbd0x030x010x130x8a0x6b,
            
0x3a0x910x110x410x4f0x670xdc0xea0x970xf20xcf0xce0xf00xb40xe60x73,
            
0x960xac0x740x220xe70xad0x350x850xe20xf90x370xe80x1c0x750xdf0x6e,
            
0x470xf10x1a0x710x1d0x290xc50x890x6f0xb70x620x0e0xaa0x180xbe0x1b,
            
0xfc0x560x3e0x4b0xc60xd20x790x200x9a0xdb0xc00xfe0x780xcd0x5a0xf4,
            
0x1f0xdd0xa80x330x880x070xc70x310xb10x120x100x590x270x800xec0x5f,
            
0x600x510x7f0xa90x190xb50x4a0x0d0x2d0xe50x7a0x9f0x930xc90x9c0xef,
            
0xa00xe00x3b0x4d0xae0x2a0xf50xb00xc80xeb0xbb0x3c0x830x530x990x61,
            
0x170x2b0x040x7e0xba0x770xd60x260xe10x690x140x630x550x210x0c0x7d
        },
        {
            
0x300x680x990x1b0x870xb90x210x780x500x390xdb0xe10x720x090x620x3c,
            
0x3e0x7e0x5e0x8e0xf10xa00xcc0xa30x2a0x1d0xfb0xb60xd60x200xc40x8d,
            
0x810x650xf50x890xcb0x9d0x770xc60x570x430x560x170xd40x400x1a0x4d,
            
0xc00x630x6c0xe30xb70xc80x640x6a0x530xaa0x380x980x0c0xf40x9b0xed,
            
0x7f0x220x760xaf0xdd0x3a0x0b0x580x670x880x060xc30x350x0d0x010x8b,
            
0x8c0xc20xe60x5f0x020x240x750x930x660x1e0xe50xe20x540xd80x100xce,
            
0x7a0xe80x080x2c0x120x970x320xab0xb40x270x0a0x230xdf0xef0xca0xd9,
            
0xb80xfa0xdc0x310x6b0xd10xad0x190x490xbd0x510x960xee0xe40xa80x41,
            
0xda0xff0xcd0x550x860x360xbe0x610x520xf80xbb0x0e0x820x480x690x9a,
            
0xe00x470x9e0x5c0x040x4b0x340x150x790x260xa70xde0x290xae0x920xd7,
            
0x840xe90xd20xba0x5d0xf30xc50xb00xbf0xa40x3b0x710x440x460x2b0xfc,
            
0xeb0x6f0xd50xf60x140xfe0x7c0x700x5a0x7d0xfd0x2f0x180x830x160xa5,
            
0x910x1f0x050x950x740xa90xc10x5b0x4a0x850x6d0x130x070x4f0x4e0x45,
            
0xb20x0f0xc90x1c0xa60xbc0xec0x730x900x7b0xcf0x590x8f0xa10xf90x2d,
            
0xf20xb10x000x940x370x9f0xd00x2e0x9c0x6e0x280x3f0x800xf00x3d0xd3,
            
0x250x8a0xb50xe70x420xb30xc70xea0xf70x4c0x110x330x030xa20xac0x60
        }
    };

    
const static unsigned char DIFFUSE_OPERATION[DIFFUSE_TIMES][DIFFUSE_XOR_OPRAND_TIMES] = 
    {
        { 
0x030x040x060x080x090x0D0x0E },
        { 
0x020x050x070x080x090x0C0x0F },
        { 
0x010x040x060x0A0x0B0x0C0x0F },
        { 
0x000x050x070x0A0x0B0x0D0x0E },
        { 
0x000x020x050x080x0B0x0E0x0F },
        { 
0x010x030x040x090x0A0x0E0x0F },
        { 
0x000x020x070x090x0A0x0C0x0D },
        { 
0x010x030x060x080x0B0x0C0x0D },
        { 
0x000x010x040x070x0A0x0D0x0F },
        { 
0x000x010x050x060x0B0x0C0x0E },
        { 
0x020x030x050x060x080x0D0x0F },
        { 
0x020x030x040x070x090x0C0x0E },
        { 
0x010x020x060x070x090x0B0x0C },
        { 
0x000x030x060x070x080x0A0x0D },
        { 
0x000x030x040x050x090x0B0x0E },
        { 
0x010x020x040x050x080x0A0x0F }
    };

    
// 为了和文档兼容,这里增加了一个 0 行
    const static unsigned char CK[CK_NUM][CK_SECTION_LENGTH] =
    {
        { 
0x000x000x000x000x000x000x000x000x000x000x000x000x000x000x000x00 },
        { 
0x510x7c0xc10xb70x270x220x0a0x940xfe0x130xab0xe80xfa0x9a0x6e0xe0 },
        { 
0x6d0xb10x4a0xcc0x9e0x210xc80x200xff0x280xb10xd50xef0x5d0xe20xb0 },
        { 
0xdb0x920x370x1d0x210x260xe90x700x030x240x970x750x040xe80xc90x0e }
    };

    
const static unsigned char CK_ORDER[4][3= 
    {
        { 
000 },
        { 
123 },
        { 
231 },
        { 
312 }
    };

    
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, 
00, NOP, 00 },        // 0

        { NOP, 
00, RIGHT, 119 },    // 1
        { NOP, 10, RIGHT, 219 },    // 2
        { NOP, 20, RIGHT, 319 },    // 3
        { RIGHT, 019, NOP, 30 },    // 4

        { NOP, 
00, RIGHT, 131 },    // 5
        { NOP, 10, RIGHT, 231 },    // 6
        { NOP, 20, RIGHT, 331 },    // 7
        { RIGHT, 031, NOP, 30 },    // 8

        { NOP, 
00, LEFT, 161 },        // 9
        { NOP, 10, LEFT, 261 },        // 10
        { NOP, 20, LEFT, 361 },        // 11
        { LEFT, 061, NOP, 30 },        // 12

        { NOP, 
00, LEFT, 131  },    // 13
        { NOP, 10, LEFT, 231 },        // 14
        { NOP, 20, LEFT, 331 },        // 15
        { LEFT, 031, NOP, 30 },        // 16
        
        { NOP, 
00, LEFT, 119 }        // 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] =
    {
        { 
346891314 },
        { 
257891215 },
        { 
14610111215 },
        { 
05710111314 },
        { 
0258111415 },
        { 
1349101415 },
        { 
0279101213 },
        { 
1368111213 },
        { 
0147101315 },
        { 
0156111214 },
        { 
235681315 },
        { 
234791214 },
        { 
126791112 },
        { 
036781013 },
        { 
034591114 },
        { 
124581015 }
    };

}
#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[] = { 0x000x110x220x330x440x550x660x770x880x990xaa0xbb0xcc0xdd0xee0xff };

    unsigned 
char plaintext[] = { 0x110x110x110x110xaa0xaa0xaa0xaa0x110x110x110x110xbb0xbb0xbb0xbb };

    unsigned 
char plaintest[] = { 0x300x260xB20x750x8E0x660xCF0x110xA60xD90xAA0x000x620xCE0x6C0xD4 };

    
/*
    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;
}