⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aes.h

📁 加密解密,安全工具!很有意思的代码
💻 H
字号:
#ifndef __AES_H
#define __AES_H

// I retain copyright in this code but I encourage its free use provided
// that I don't carry any responsibility for the results. I am especially 
// happy to see it used in free and open source software. If you do use 
// it I would appreciate an acknowledgement of its origin in the code or
// the product that results and I would also appreciate knowing a liitle
// about the use to which it is being put.
//
// Dr B. R. Gladman <brg@gladman.uk.net> 23rd January 2001.

// This is an implementation of the AES encryption algorithm (Rijndael)
// designed by Joan Daemen and Vincent Rijmen. This version is designed
// to provide both fixed and dynamic block and key lengths and can also 
// run with either big or little endian internal byte order (see aes.h). 
// It inputs block and key lengths in bytes with the legal values being 
// 16, 24 and 32.

// A. THE CIPHER INTERFACE
//
// byte                    (an unsigned 8-bit type)
// word                    (an unsigned 32-bit type)
// rval:                   (a signed 16 bit type for function return values)
//      aes_good            (value != 0, a good return)
//      aes_bad             (value == 0, an error return)
// enum aes_key:           (encryption direction)
//      enc                 (set key for encryption)
//      dec                 (set key for decryption)
//      both                (set key for both)
// class or struct aes     (structure for context)
//
// C subroutine calls:
//
// rval set_blk(const word n_bytes, aes *cx)   (if block size is variable)
// rval set_key(const byte key[], const word n_bytes, const enum aes_key f, aes *cx)
// rval encrypt(const byte in_blk[], byte out_blk[], const aes *cx)
// rval decrypt(const byte in_blk[], byte out_blk[], const aes *cx)
//
// C++ aes class subroutines:
//
// rval set_blk(const word n_bytes)            (if block size is variable)
// rval set_key(const byte key[], const word n_bytes, const aes_key f)
// rval encrypt(const byte in_blk[], byte out_blk[]) const
// rval decrypt(const byte in_blk[], byte out_blk[]) const
//
// The block length inputs to set_block and set_key are in numbers of
// BYTES, not bits.  The calls to subroutines must be made in the above 
// order but multiple calls can be made without repeating earlier calls
// if their parameters have not changed. If the cipher block length is
// variable but set_blk has not been called before cipher operations a
// value of 16 is assumed (that is, the AES block size). In contrast to 
// earlier versions the block and key length parameters are now checked
// for correctness and the encryption and decryption routines test to 
// ensure that an appropriate key has been set before their use.

// B. COMPILATION 
//
// To compile AES (Rijndael) in C
//  a. Rename aes.cpp to aes.c (if necessary) and compile as a C file
//  b. Exclude the AES_DLL define in aes.h
//  c. Disable the AES_IN_CPP define in aes.h
//
// To compile AES (Rijndael) in C++
//  a. Rename aes.c to aes.cpp (if necessary) and compile as a C++ file
//  b. Exclude the AES_DLL define in aes.h
//  c. Enable the AES_IN_CPP define in aes.h
//
// To compile AES (Rijndael) in C as a Dynamic Link Library
//  a. Rename aes.cpp to aes.c (if necessary) and compile as a C file
//  c. Include the AES_DLL define in aes.h
//  c. Disable the AES_IN_CPP define in aes.h
//  d. Compile the DLL.  If using the test files, exclude aes.c and 
//     aes.cpp from the test build project and compile it with same 
//     defines used for the DLL. Ensure that the DLL path section G 
//     below points to correct DLL directory.
//
// Note that parts of this header file can be removed if the testing code
// is not being used or if only the C or the C++ implementation is used.

#define BIG_ENDIAN      1   // do not change
#define LITTLE_ENDIAN   2   // do not change

// C. CONFIGURATION OPTIONS (see also aes.c and/or aes.cpp)

// 1. define BLOCK_SIZE_R to set the cipher block size (16, 24 or 32) or
//    leave this undefined for dynamically variable block size (this will
//    result in much slower code).
// 2. set AES_IN_CPP to compile in C++ rather than C (this define may
//    also occur in aes.c and aes.cpp).
// 3. set AES_DLL if AES (Rijndael) is to be compiled to a DLL
// 4. set INTERNAL_BYTE_ORDER to one of the above constants to set the
//    internal byte order (the order used within the algorithm code)
// 5. set EXTERNAL_BYTE_ORDER to one of the above constants to set the byte
//    order used at the external interfaces for the input, output and key
//    byte arrays.

// IMPORTANT NOTE: BLOCK_SIZE_R is in BYTES (16, 24, 32 or undefined). If left
// undefined a slower version providing variable block length is compiled   

#define BLOCK_SIZE_R  16
//#define AES_IN_CPP
//#define AES_DLL
#define INTERNAL_BYTE_ORDER LITTLE_ENDIAN
#define EXTERNAL_BYTE_ORDER LITTLE_ENDIAN

// End of configuration options, but see also aes.c, aes.cpp and sections G.

// D, COMMON C AND C++ DEFINITIONS

typedef unsigned char   byte;   // must be an 8-bit storage unit
typedef unsigned int    word;   // must be a 32-bit storage unit
typedef short int       rval;   // function return type

#define aes_good    1           // return value after success
#define aes_bad     0           // return value after failure


// rot1 changes [b0,b1,b2,b3] to [b3,b0,b1,b2]
// rot2 changes [b0,b1,b2,b3] to [b2,b3,b0,b1]
// rot3 changes [b0,b1,b2,b3] to [b1,b2,b3,b0]

#if(INTERNAL_BYTE_ORDER == LITTLE_ENDIAN)


// Circular byte rotates of 32-bit words

    #if defined(_MSC_VER)   // non-portable but gives a small gain in speed

        #include <stdlib.h>
        #pragma intrinsic(_lrotr,_lrotl)
        #define rot1(x)   _lrotl(x, 8)
        #define rot2(x)   _lrotl(x,16)
        #define rot3(x)   _lrotl(x,24)

    #else

        #define rot1(x) (((x) <<  8) | ((x) >> 24))
        #define rot2(x) (((x) << 16) | ((x) >> 16))
        #define rot3(x) (((x) << 24) | ((x) >>  8))

    #endif


// Extract bytes from a 32-bit words

    #define byte0(x)    ((byte) (x))
    #define byte1(x)    ((byte)((x) >>  8))
    #define byte2(x)    ((byte)((x) >> 16))
    #define byte3(x)    ((byte)((x) >> 24))

    #define bytes2word(b0, b1, b2, b3) ((word)(b3) << 24 | (word)(b2) << 16 | (word)(b1) << 8 | (b0))


// Invert byte order in a 32 bit variable

    #define byte_swap(x)    (rot1(x) & 0x00ff00ff | rot3(x) & 0xff00ff00)

#else


// Circular byte rotates of 32-bit words

    #define rot3(x) (((x) <<  8) | ((x) >> 24))
    #define rot2(x) (((x) << 16) | ((x) >> 16))
    #define rot1(x) (((x) << 24) | ((x) >>  8))


// Extract bytes from a 32-bit words

    #define byte3(x)    ((byte) (x))
    #define byte2(x)    ((byte)((x) >>  8))
    #define byte1(x)    ((byte)((x) >> 16))
    #define byte0(x)    ((byte)((x) >> 24))

    #define bytes2word(b0, b1, b2, b3)  \
    ((word)(b0) << 24 | (word)(b1) << 16 | (word)(b2) << 8 | (b3))


// Invert byte order in a 32 bit variable

    #define byte_swap(x)    (rot3(x) & 0x00ff00ff | rot1(x) & 0xff00ff00)

#endif

#if(INTERNAL_BYTE_ORDER == EXTERNAL_BYTE_ORDER)

    #define word_in(x)      *(word*)(x)
    #define word_out(x,v)   *(word*)(x) = (v)

#else

    #define word_in(x)      byte_swap(*(word*)(x))
    #define word_out(x,v)   *(word*)(x) = byte_swap(v)

#endif

enum aes_const
{
    Nrow =  4,  // the number of rows in the cipher state
    Mcol =  8,  // maximum number of columns in the state
    Mkbl = 15,  // maximum number of key schedule blocks
#if defined(BLOCK_SIZE_R)         // set up a statically defined block size
    Ncol =  BLOCK_SIZE_R / 4,  
    Shr1 =  1,  // the cyclic shift values for rows 1, 2 & 3
    Shr2 =  BLOCK_SIZE_R == 32 ? 3 : 2,
    Shr3 =  BLOCK_SIZE_R == 32 ? 4 : 3
#endif 
};

enum aes_key
{
    enc  =  1,  // set if encryption is needed
    dec  =  2,  // set if decryption is needed
    both =  3,  // set if both are needed
};

#if defined(AES_IN_CPP) // AES (Rijndael) compiled in C++


// E. DEFINITIONS FOR C++ IMPLEMENTATION

class   aes
{
private:
    word    Nkey;       // the number of words in the key input block
    word    Nrnd;       // the number of cipher rounds
#if !defined(BLOCK_SIZE_R)
    word    Ncol;       // the number of columns in the cipher state
    byte    shf1[8];    // row 1 forward shift table
    byte    shf2[8];    // row 2 forward shift table
    byte    shf3[8];    // row 3 forward shift table
    byte    shr1[8];    // row 1 reverse shift table
    byte    shr2[8];    // row 2 reverse shift table
    byte    shr3[8];    // row 3 reverse shift table
    word    e_key[128]; // the encryption key schedule
    word    d_key[128]; // the decryption key schedule
#else
    word    e_key[4 * BLOCK_SIZE_R];  // the encryption key schedule
    word    d_key[4 * BLOCK_SIZE_R];  // the decryption key schedule
#endif
    byte    mode;       // encrypt, decrypt or both
public:                 
#if !defined(BLOCK_SIZE_R)
    aes(word n_bytes = 4) : mode(0)
    {
        set_blk(n_bytes);
    };
    rval set_blk(const word n_bytes);
#endif
    rval    set_key(const byte key[], const word n_bytes, const aes_key f);
    rval    _encrypt(const byte in_blk[], byte out_blk[]) const;
    rval    _decrypt(const byte in_blk[], byte out_blk[]) const;
};

#else


// F. DEFINITIONS FOR C IMPLEMENTATION

    #if defined(__cplusplus)
extern "C"
{
#endif

    typedef struct          // note that Nkey = key_len_in_bits / 32
    {
        word    Nkey;       // the number of words in the key input block
        word    Nrnd;       // the number of cipher rounds
#if !defined(BLOCK_SIZE_R)
        word    Ncol;       // the number of columns in the cipher state
        byte    shf1[8];    // row 1 forward shift table
        byte    shf2[8];    // row 2 forward shift table
        byte    shf3[8];    // row 3 forward shift table
        byte    shr1[8];    // row 1 reverse shift table
        byte    shr2[8];    // row 2 reverse shift table
        byte    shr3[8];    // row 3 reverse shift table
        word    e_key[128]; // the encryption key schedule
        word    d_key[128]; // the decryption key schedule
#else
        word    e_key[4 * BLOCK_SIZE_R];  // the encryption key schedule
        word    d_key[4 * BLOCK_SIZE_R];  // the decryption key schedule
#endif
        byte    mode;       // encrypt, decrypt or both
    } aes;

// _stdcall is needed for Visual Basic DLLs but is not necessary for C/C++

#if defined(AES_DLL)
#define cf_dec  rval __declspec(dllexport) _stdcall
#else
#define cf_dec  rval
#endif

    cf_dec set_key(const byte key[], const word n_bytes, const enum aes_key f, aes *cx);
    cf_dec _encrypt(const byte in_blk[], byte out_blk[], const aes *cx);
    cf_dec _decrypt(const byte in_blk[], byte out_blk[], const aes *cx);
    cf_dec set_blk(const word n_bytes, aes *cx);

#if defined(__cplusplus)
};
    #endif

#endif  // defined(AES_IN_CPP)


// G. DEFINITIONS FOR TESTING ONLY

// The following definitions are required for testing only, They are not needed 
// for AES (Rijndael) implementation.  They are used to allow C, C++  and DLL 
// data acesses and subroutine calls to be expressed in the same form in the 
// testing code.

#define ref_path    "..\\testvals\\"				// path for test vector files
#define out_path    "..\\outvals\\"					// path for output files
#define dll_path    "..\\aes_dll\\release\\aes"     // path for DLL

#if defined(AES_IN_CPP)

    #define f_dat(a,b)          (b)
    #define f_set_key(a,b,c,d)  (a)->set_key((b),(c),(d))
    #define f_encrypt(a,b,c)    (a)->encrypt((b),(c))
    #define f_decrypt(a,b,c)    (a)->decrypt((b),(c))
    #define f_set_blk(a,b)      (a)->set_blk((b))

#elif !defined(AES_DLL)

    #define f_dat(a,b)          (a->b)
    #define f_set_key(a,b,c,d)  set_key((b),(c),(d),(a))
    #define f_encrypt(a,b,c)    _encrypt((b),(c),(a))
    #define f_decrypt(a,b,c)    _decrypt((b),(c),(a))
    #define f_set_blk(a,b)      set_blk((b),(a))

#else

typedef cf_dec f_ky(const byte key[], const word klen, const enum aes_key mode, aes *ctx);
typedef cf_dec f_ed(const byte in_blk[], byte out_blk[], const aes *ctx);
typedef cf_dec f_bl(const word blen, aes *ctx);

typedef struct  // initialised with subroutine addresses when the DLL is loaded
{
    f_ky    *fn_set_key;
    f_ed    *fn_encrypt;
    f_ed    *fn_decrypt;
    f_bl    *fn_set_blk;
} fn_ptrs;

    #define f_dat(a,b)          (a->b)
    #define f_set_key(a,b,c,d)  (fn.fn_set_key)((b),(c),(d),(a))
    #define f_encrypt(a,b,c)    (fn.fn_encrypt)((b),(c),(a))
    #define f_decrypt(a,b,c)    (fn.fn_decrypt)((b),(c),(a))
    #define f_set_blk(a,b)      (fn.fn_set_blk)((b),(a))

#endif
#endif //__AES_H

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -