AES advanced encryption standard

// advanced encryption standard
// author: karl malbrain, [email protected]

typedef unsigned char uchar;
#include <string.h>
#include <memory.h>

// AES only supports Nb=4
#define Nb 4            // number of columns in the state & expanded key

#define Nk 4            // number of columns in a key
#define Nr 10            // number of rounds in encryption

uchar Sbox[256] = {        // forward s-box
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};

uchar InvSbox[256] = {    // inverse s-box
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};

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

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

// modular multiplication tables
// based on:

// Xtime2[x] = (x & 0x80 ? 0x1b : 0) ^ (x + x)
// Xtime3[x] = x^Xtime2[x];

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

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

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

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

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

// exchanges columns in each of 4 rows
// row0 - unchanged, row1- shifted left 1,
// row2 - shifted left 2 and row3 - shifted left 3
void ShiftRows (uchar *state, uchar *out)
{
    // just substitute row 0
    out[0] = Sbox[state[0]], out[4] = Sbox[state[4]];
    out[8] = Sbox[state[8]], out[12] = Sbox[state[12]];

    // rotate row 1
    out[1] = Sbox[state[5]], out[5] = Sbox[state[9]];
    out[9] = Sbox[state[13]], out[13] = Sbox[state[1]];

    // rotate row 2
    out[2] = Sbox[state[10]], out[10] = Sbox[state[2]];
    out[6] = Sbox[state[14]], out[14] = Sbox[state[6]];

    // rotate row 3
    out[15] = Sbox[state[11]], out[11] = Sbox[state[7]];
    out[7] = Sbox[state[3]], out[3] = Sbox[state[15]];
}

// restores columns in each of 4 rows
// row0 - unchanged, row1- shifted right 1,
// row2 - shifted right 2 and row3 - shifted right 3
void InvShiftRows (uchar *state, uchar *out)
{
    // restore row 0
    out[0] = InvSbox[state[0]], out[4] = InvSbox[state[4]];
    out[8] = InvSbox[state[8]], out[12] = InvSbox[state[12]];

    // restore row 1
    out[13] = InvSbox[state[9]], out[9] = InvSbox[state[5]];
    out[5] = InvSbox[state[1]], out[1] = InvSbox[state[13]];

    // restore row 2
    out[2] = InvSbox[state[10]], out[10] = InvSbox[state[2]];
    out[6] = InvSbox[state[14]], out[14] = InvSbox[state[6]];

    // restore row 3
    out[3] = InvSbox[state[7]], out[7] = InvSbox[state[11]];
    out[11] = InvSbox[state[15]], out[15] = InvSbox[state[3]];
}

uchar Rcon[11] = {
0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};

// produce Nb bytes for each round
void ExpandKey (uchar *key, uchar *expkey)
{
uchar tmp0, tmp1, tmp2, tmp3, tmp4;
int idx;

    memcpy (expkey, key, Nk * 4);

    for( idx = Nk; idx < Nb * (Nr + 1); idx++ ) {
        tmp0 = expkey[4*idx - 4];
        tmp1 = expkey[4*idx - 3];
        tmp2 = expkey[4*idx - 2];
        tmp3 = expkey[4*idx - 1];
        if( !(idx % Nk) ) {
            tmp4 = tmp3;
            tmp3 = Sbox[tmp0];
            tmp0 = Sbox[tmp1] ^ Rcon[idx/Nk];
            tmp1 = Sbox[tmp2];
            tmp2 = Sbox[tmp4];
        } else if( Nk > 6 && idx % Nk == 4 ) {
            tmp0 = Sbox[tmp0];
            tmp1 = Sbox[tmp1];
            tmp2 = Sbox[tmp2];
            tmp3 = Sbox[tmp3];
        }

        expkey[4*idx+0] = expkey[4*idx - 4*Nk + 0] ^ tmp0;
        expkey[4*idx+1] = expkey[4*idx - 4*Nk + 1] ^ tmp1;
        expkey[4*idx+2] = expkey[4*idx - 4*Nk + 2] ^ tmp2;
        expkey[4*idx+3] = expkey[4*idx - 4*Nk + 3] ^ tmp3;
    }
}

// encrypt/decrypt columns of the key

#define AddRoundKey(state, key, out)do {    out[0] = state[0] ^ key[0];    out[1] = state[1] ^ key[1];    out[2] = state[2] ^ key[2];    out[3] = state[3] ^ key[3];    out[4] = state[4] ^ key[4];    out[5] = state[5] ^ key[5];    out[6] = state[6] ^ key[6];    out[7] = state[7] ^ key[7];    out[8] = state[8] ^ key[8];    out[9] = state[9] ^ key[9];    out[10] = state[10] ^ key[10];    out[11] = state[11] ^ key[11];    out[12] = state[12] ^ key[12];    out[13] = state[13] ^ key[13];    out[14] = state[14] ^ key[14];    out[15] = state[15] ^ key[15];} while(0)

// recombine and mix each row in a column
#define MixSubColumns(state, out, key)do {    /* mixing column 0*/    out[0] = Xtime2Sbox[state[0]] ^ Xtime3Sbox[state[5]] ^ Sbox[state[10]] ^ Sbox[state[15]] ^ key[0];    out[1] = Sbox[state[0]] ^ Xtime2Sbox[state[5]] ^ Xtime3Sbox[state[10]] ^ Sbox[state[15]] ^ key[1];    out[2] = Sbox[state[0]] ^ Sbox[state[5]] ^ Xtime2Sbox[state[10]] ^ Xtime3Sbox[state[15]] ^ key[2];    out[3] = Xtime3Sbox[state[0]] ^ Sbox[state[5]] ^ Sbox[state[10]] ^ Xtime2Sbox[state[15]] ^ key[3];    /* mixing column 1*/    out[4] = Xtime2Sbox[state[4]] ^ Xtime3Sbox[state[9]] ^ Sbox[state[14]] ^ Sbox[state[3]] ^ key[4];    out[5] = Sbox[state[4]] ^ Xtime2Sbox[state[9]] ^ Xtime3Sbox[state[14]] ^ Sbox[state[3]] ^ key[5];    out[6] = Sbox[state[4]] ^ Sbox[state[9]] ^ Xtime2Sbox[state[14]] ^ Xtime3Sbox[state[3]] ^ key[6];    out[7] = Xtime3Sbox[state[4]] ^ Sbox[state[9]] ^ Sbox[state[14]] ^ Xtime2Sbox[state[3]] ^ key[7];    /* mixing column 2*/    out[8] = Xtime2Sbox[state[8]] ^ Xtime3Sbox[state[13]] ^ Sbox[state[2]] ^ Sbox[state[7]] ^ key[8];    out[9] = Sbox[state[8]] ^ Xtime2Sbox[state[13]] ^ Xtime3Sbox[state[2]] ^ Sbox[state[7]] ^ key[9];    out[10]  = Sbox[state[8]] ^ Sbox[state[13]] ^ Xtime2Sbox[state[2]] ^ Xtime3Sbox[state[7]] ^ key[10];    out[11]  = Xtime3Sbox[state[8]] ^ Sbox[state[13]] ^ Sbox[state[2]] ^ Xtime2Sbox[state[7]] ^ key[11];    /* mixing column 3*/    out[12] = Xtime2Sbox[state[12]] ^ Xtime3Sbox[state[1]] ^ Sbox[state[6]] ^ Sbox[state[11]] ^ key[12];    out[13] = Sbox[state[12]] ^ Xtime2Sbox[state[1]] ^ Xtime3Sbox[state[6]] ^ Sbox[state[11]] ^ key[13];    out[14] = Sbox[state[12]] ^ Sbox[state[1]] ^ Xtime2Sbox[state[6]] ^ Xtime3Sbox[state[11]] ^ key[14];    out[15] = Xtime3Sbox[state[12]] ^ Sbox[state[1]] ^ Sbox[state[6]] ^ Xtime2Sbox[state[11]] ^ key[15];} while(0)

// encrypt one 128 bit block
void Encrypt (uchar *in, uchar *expkey, uchar *out)
{
uchar state[Nb * 4], tmp[Nb * 4];

    AddRoundKey (in, expkey, state);
    expkey += Nb * 4;

    MixSubColumns (state, tmp, expkey);
    expkey += Nb * 4;

    MixSubColumns (tmp, state, expkey);
    expkey += Nb * 4;

    MixSubColumns (state, tmp, expkey);
    expkey += Nb * 4;

    MixSubColumns (tmp, state, expkey);
    expkey += Nb * 4;

    MixSubColumns (state, tmp, expkey);
    expkey += Nb * 4;

    MixSubColumns (tmp, state, expkey);
    expkey += Nb * 4;

    MixSubColumns (state, tmp, expkey);
    expkey += Nb * 4;

    MixSubColumns (tmp, state, expkey);
    expkey += Nb * 4;

    MixSubColumns (state, tmp, expkey);
    expkey += Nb * 4;

#if (Nr > 10)
    MixSubColumns (tmp, state, expkey);
    expkey += Nb * 4;

    MixSubColumns (state, tmp, expkey);
    expkey += Nb * 4;
#endif

#if (Nr > 12)
    MixSubColumns (tmp, state, expkey);
    expkey += Nb * 4;

    MixSubColumns (state, tmp, expkey);
    expkey += Nb * 4;
#endif

    ShiftRows (tmp, state);
    AddRoundKey (state, expkey, out);
}

// restore and un-mix each row in a column
#define InvMixSubColumns(state, out, key)do {    /* restore column 0*/    t0 = state[0] ^ key[0];    t1 = state[1] ^ key[1];    t2 = state[2] ^ key[2];    t3 = state[3] ^ key[3];    out[0] = InvSbox[XtimeE[t0] ^ XtimeB[t1] ^ XtimeD[t2] ^ Xtime9[t3]];    out[5] = InvSbox[Xtime9[t0] ^ XtimeE[t1] ^ XtimeB[t2] ^ XtimeD[t3]];    out[10] = InvSbox[XtimeD[t0] ^ Xtime9[t1] ^ XtimeE[t2] ^ XtimeB[t3]];    out[15] = InvSbox[XtimeB[t0] ^ XtimeD[t1] ^ Xtime9[t2] ^ XtimeE[t3]];    /* restore column 1*/    t0 = state[4] ^ key[4];    t1 = state[5] ^ key[5];    t2 = state[6] ^ key[6];    t3 = state[7] ^ key[7];    out[4] = InvSbox[XtimeE[t0] ^ XtimeB[t1] ^ XtimeD[t2] ^ Xtime9[t3]];    out[9] = InvSbox[Xtime9[t0] ^ XtimeE[t1] ^ XtimeB[t2] ^ XtimeD[t3]];    out[14] = InvSbox[XtimeD[t0] ^ Xtime9[t1] ^ XtimeE[t2] ^ XtimeB[t3]];    out[3] = InvSbox[XtimeB[t0] ^ XtimeD[t1] ^ Xtime9[t2] ^ XtimeE[t3]];    /* restore column 2*/    t0 = state[8] ^ key[8];    t1 = state[9] ^ key[9];    t2 = state[10] ^ key[10];    t3 = state[11] ^ key[11];    out[8] = InvSbox[XtimeE[t0] ^ XtimeB[t1] ^ XtimeD[t2] ^ Xtime9[t3]];    out[13] = InvSbox[Xtime9[t0] ^ XtimeE[t1] ^ XtimeB[t2] ^ XtimeD[t3]];    out[2]  = InvSbox[XtimeD[t0] ^ Xtime9[t1] ^ XtimeE[t2] ^ XtimeB[t3]];    out[7]  = InvSbox[XtimeB[t0] ^ XtimeD[t1] ^ Xtime9[t2] ^ XtimeE[t3]];    /* restore column 3*/    t0 = state[12] ^ key[12];    t1 = state[13] ^ key[13];    t2 = state[14] ^ key[14];    t3 = state[15] ^ key[15];    out[12] = InvSbox[XtimeE[t0] ^ XtimeB[t1] ^ XtimeD[t2] ^ Xtime9[t3]];    out[1] = InvSbox[Xtime9[t0] ^ XtimeE[t1] ^ XtimeB[t2] ^ XtimeD[t3]];    out[6] = InvSbox[XtimeD[t0] ^ Xtime9[t1] ^ XtimeE[t2] ^ XtimeB[t3]];    out[11] = InvSbox[XtimeB[t0] ^ XtimeD[t1] ^ Xtime9[t2] ^ XtimeE[t3]];} while(0)

void Decrypt (uchar *in, uchar *expkey, uchar *out)
{
uchar state[Nb * 4], tmp[Nb * 4];
uchar t0, t1, t2, t3;

    expkey += Nr * Nb * 4;
    AddRoundKey (in, expkey, tmp);
    InvShiftRows(tmp, state);

    expkey -= Nb * 4;
    InvMixSubColumns (state, tmp, expkey);

    expkey -= Nb * 4;
    InvMixSubColumns (tmp, state, expkey);

    expkey -= Nb * 4;
    InvMixSubColumns (state, tmp, expkey);

    expkey -= Nb * 4;
    InvMixSubColumns (tmp, state, expkey);

    expkey -= Nb * 4;
    InvMixSubColumns (state, tmp, expkey);

    expkey -= Nb * 4;
    InvMixSubColumns (tmp, state, expkey);

    expkey -= Nb * 4;
    InvMixSubColumns (state, tmp, expkey);

    expkey -= Nb * 4;
    InvMixSubColumns (tmp, state, expkey);

    expkey -= Nb * 4;
    InvMixSubColumns (state, tmp, expkey);

#if (Nr > 10)
    expkey -= Nb * 4;
    InvMixSubColumns (tmp, state, expkey);

    expkey -= Nb * 4;
    InvMixSubColumns (state, tmp, expkey);
#endif

#if (Nr > 12)
    expkey -= Nb * 4;
    InvMixSubColumns (tmp, state, expkey);

    expkey -= Nb * 4;
    InvMixSubColumns (state, tmp, expkey);
#endif

    expkey -= Nb * 4;
    AddRoundKey (tmp, expkey, out);
}

#include <stdio.h>
#include <fcntl.h>
uchar in[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};

uchar key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f};

uchar out[16];

#ifndef unix
void rd_clock (__int64 *ans)
{
unsigned dwLow, dwHigh;

    __asm {
        rdtsc
        mov dwLow, eax
        mov dwHigh, edx
    }
    *ans = (__int64)dwHigh << 32 | (__int64)dwLow;
}
#else
typedef long long __int64;

void rd_clock (__int64 *ans)
{
unsigned long long dwBoth;

    __asm__ volatile(".byte 0x0f, 0x31" : "=A"(dwBoth));
    *ans = dwBoth;
}
#endif

uchar samplekey[] = {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab,
0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c};

uchar samplein[] = {0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31,
0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34};

void sample ()
{
uchar expkey[4 * Nb * (Nr + 1)];
int idx, diff;
__int64 start, stop;

    ExpandKey (samplekey, expkey);
    Encrypt (samplein, expkey, out);

    rd_clock(&start);

    Encrypt (samplein, expkey, out);

    rd_clock(&stop);
    diff = stop - start;
    printf ("encrypt time: %d, %d cycles per byte\n", diff, diff/16);

    for( idx = 0; idx < 16; idx++ )
        printf ("%.2x ", out[idx]);

    printf ("\n");
    Decrypt (out, expkey, in);
    rd_clock(&start);
    Decrypt (out, expkey, in);

    rd_clock(&stop);
    diff = stop - start;
    printf ("decrypt time: %d, %d cycles per byte\n", diff, diff/16);

    for( idx = 0; idx < 16; idx++ )
        printf ("%.2x ", in[idx]);

    printf ("\n");
}

void certify ()
{
uchar expkey[4 * Nb * (Nr + 1)];
int idx, diff;
__int64 start, stop;

    ExpandKey (key, expkey);
    Encrypt (in, expkey, out);

    rd_clock(&start);

    Encrypt (in, expkey, out);

    rd_clock(&stop);
    diff = stop - start;
    printf ("encrypt time: %d, %d cycles per byte\n", diff, diff/16);

    for( idx = 0; idx < 16; idx++ )
        printf ("%.2x ", out[idx]);

    printf ("\n");
    Decrypt (out, expkey, in);
    rd_clock(&start);
    Decrypt (out, expkey, in);

    rd_clock(&stop);
    diff = stop - start;
    printf ("decrypt time: %d, %d cycles per byte\n", diff, diff/16);

    for( idx = 0; idx < 16; idx++ )
        printf ("%.2x ", in[idx]);

    printf ("\n");
}

void decrypt (char *mykey, char *name)
{
uchar expkey[4 * Nb * (Nr + 1)];
FILE *fd = fopen (name, "rb");
int ch, idx = 0;

    strncpy (key, mykey, sizeof(key));
    ExpandKey (key, expkey);

    while( ch = getc(fd), ch != EOF ) {
        in[idx++] = ch;
        if( idx % 16 )
            continue;

        Decrypt (in, expkey, out);

        for( idx = 0; idx < 16; idx++ )
            putchar (out[idx]);
        idx = 0;
    }
}

void encrypt (char *mykey, char *name)
{
uchar expkey[4 * Nb * (Nr + 1)];
FILE *fd = fopen (name, "rb");
int ch, idx = 0;

    strncpy (key, mykey, sizeof(key));
    ExpandKey (key, expkey);

    while( ch = getc(fd), ch != EOF ) {
        in[idx++] = ch;
        if( idx % 16 )
            continue;

        Encrypt (in, expkey, out);

        for( idx = 0; idx < 16; idx++ )
            putchar (out[idx]);
        idx = 0;
    }

    if( idx )
      while( idx % 16 )
        in[idx++] = 0;
    else
      return;

    Encrypt (in, expkey, out);

    for( idx = 0; idx < 16; idx++ )
        putchar (out[idx]);
}

uchar expkey[4 * Nb * (Nr + 1)];
void mrandom (int, char *);
unsigned xrandom (void);

int aescycles ()
{
__int64 start, end;
int t;

    do {
        rd_clock(&start);
        Encrypt (in, expkey, out);
        rd_clock (&end);
        t = end - start;
    } while( t<= 0 || t>= 4000);
    return t;
}

int bestx (int b, int loops)
{
int bestx = 0, bestxt = 0;
int x, xt, i, j;

    for( x = 0; x < 256; x++ ) {
        xt = 0;
        for( i = 0; i < loops; i++ ) {
            for( j = 0; j < 16; j++ )
                in[j] = xrandom() >> 16;
            in[b] = x;
            xt += aescycles(); xt += aescycles(); xt += aescycles();
            xt += aescycles(); xt += aescycles();
        }
        if( xt > bestxt )
            bestx = x, bestxt = xt;
    }
    return bestx;
}

void bernstein (char *seed)
{
int loops, b, j, k;

    mrandom (strlen(seed), seed);

    for( loops = 4; loops <= 65536; loops *= 16) {
        for( b = 0; b < 16; b++ ) {
            printf ("%.2d, %.5d loops:", b, loops);
            for( k = 0; k < 10; k++ ) {
                for( j = 0; j < 16; j++ )
                    key[j] = xrandom() >> 16;
                ExpandKey (key, expkey);
                printf (" %.2x", bestx (b, loops) ^ key[b]);
                fflush (stdout);
            }
            printf ("\n");
        }
    }
}

void tables()
{
int i;

    for( i = 0; i < 256; i++)
    {
        printf("0x%.2x, ", Sbox[i] ^ Xtime2[Sbox[i]]);
        if( !((i+1) % 16) )
            printf("\n");
    }

    printf("\n");

    for( i = 0; i < 256; i++)
    {
        printf("0x%.2x, ", Xtime2[Sbox[i]]);
        if ( !((i+1) % 16) )
            printf("\n");
    }
}

int main (int argc, char *argv[])
{
#ifndef unix
extern int __cdecl _setmode (int, int);

    _setmode (_fileno(stdout), _O_BINARY);
#endif

    switch( argv[1][0] ) {
    case ‘c‘: certify(); break;
    case ‘e‘: encrypt(argv[2], argv[3]); break;
    case ‘d‘: decrypt(argv[2], argv[3]); break;
    case ‘b‘: bernstein(argv[2]);    break;
    case ‘s‘: sample(); break;
    case ‘t‘: tables(); break;
    }
}

/*
 * The package generates far better random numbers than a linear
 * congruential generator.  The random number generation technique
 * is a linear feedback shift register approach.  In this approach,
 * the least significant bit of all the numbers in the RandTbl table
 * will act as a linear feedback shift register, and will have period
 * of approximately 2^96 - 1.
 *
 */

#define RAND_order (7 * sizeof(unsigned))
#define RAND_size (96 * sizeof(unsigned))

uchar RandTbl[RAND_size + RAND_order];
int RandHead = 0;

/*
 * random:     x**96 + x**7 + x**6 + x**4 + x**3 + x**2 + 1
 *
 * The basic operation is to add to the number at the head index
 * the XOR sum of the lower order terms in the polynomial.
 * Then the index is advanced to the next location cyclically
 * in the table.  The value returned is the sum generated.
 *
 */

unsigned xrandom ()
{
register unsigned fact;

    if( (RandHead -= sizeof(unsigned)) < 0 ) {
        RandHead = RAND_size - sizeof(unsigned);
        memcpy (RandTbl + RAND_size, RandTbl, RAND_order);
    }

    fact = *(unsigned *)(RandTbl + RandHead + 7 * sizeof(unsigned));
    fact ^= *(unsigned *)(RandTbl + RandHead + 6 * sizeof(unsigned));
    fact ^= *(unsigned *)(RandTbl + RandHead + 4 * sizeof(unsigned));
    fact ^= *(unsigned *)(RandTbl + RandHead + 3 * sizeof(unsigned));
    fact ^= *(unsigned *)(RandTbl + RandHead + 2 * sizeof(unsigned));
    return *(unsigned *)(RandTbl + RandHead) += fact;
}

/*
 * mrandom:
 *         Initialize the random number generator based on the given seed.
 *
 */

void mrandom (int len, char *ptr)
{
unsigned short rand = *ptr;
int idx, bit = len * 4;

    memset (RandTbl, 0, sizeof(RandTbl));
    RandHead = 0;

    while( rand *= 20077, rand += 11, bit-- )
        if( ptr[bit >> 2] & (1 << (bit & 3)) )
            for (idx = 0; idx < 5; idx++) {
                rand *= 20077, rand += 11;
                RandTbl[rand % 96 << 2] ^= 1;
            }

    for( idx = 0; idx < 96 * 63; idx++ )
        xrandom ();
}
时间: 2024-08-25 12:07:38

AES advanced encryption standard的相关文章

AES advanced encryption standard 3

This optimized <../aesbench/> AES implementation conforms to FIPS-197. aes.h #ifndef _AES_H #define _AES_H #ifndef uint8 #define uint8 unsigned char #endif #ifndef uint32 #define uint32 unsigned long int #endif typedef struct { uint32 erk[64]; /* en

AES advanced encryption standard 2

/* * FIPS-197 compliant AES implementation * * Copyright (C) 2006-2007 Christophe Devine * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redi

java AES 加密解密工具(Advanced Encryption Standard)

1.通用方法 package com.qlkj.hzd.commom.utils; import javax.crypto.*; import java.io.UnsupportedEncodingException; import java.security.*; /** * RSA相关工具类 * * @author vampire * @date 2018/10/12 下午5:33 */ public class EncrypAES { //KeyGenerator 提供对称密钥生成器的功能

DES,3DES,AES这三种对称密钥的区别与联系

DES:Data Encryption Standard(数据加密标准,又美国国密局,选中的IBM的方案,密钥长度为56,标准提出是要使用64位长的密钥,但是实际中DES算法只用了64位中的56位密钥,这一点是容易出错的) 3DES:trip DES(3级DES,是DES的升级版,主要是为了应对快速发展的计算机能力,能够在24小时内暴力破解传统的56位长度密钥的DES,而3DES相当于对统一数据块采用3次DES,3次DES使用的密钥如果完全不同,则密钥长度可以达到168位,大大延长了被暴力破解的

关于httpd 2.x,mod_auth_mysql模块的安装配置以及对aes加密的支持

前言 在之前的一篇博文<Apache httpd2.2版本以及2.4版本部分实验>的实验二里面,提到了协议认证使用了mod_auth_mysql.so模块,本文将阐述该模块的安装,配置,以及对于aes加密特性的支持. 基于开发者文档的安装步骤 注:在笔者的CentOS7测试环境下并不支持aes加密 首先从模块提供的官方站点下载mod_auth_mysql-3.0.0.tar.gz,并下载对应的补丁mod_auth_mysql_3.0.0_patch_apache2.4.diff,解压缩之后,将

Qt使用AES加密算法对字符串进行加密

因工作需要,需要对字符串进行加密处理,在网上找了很长时间,终于找到了一个可以使用的aes加密算法.其源代码采用c++编写而成,但其头文件引用windows.h,经过修改部分代码,将#include<windows.h>去掉,这样可是使用与多个编译器.下面的代码中列出了测试用的代码(中文出现乱码现象): 点击(此处)折叠或打开 int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); TAesClass *aes = n

java-信息安全(二)-对称加密算法DES,3DES,AES,Blowfish,RC2,RC4

概述 信息安全基本概念: DES(Data Encryption Standard,数据加密标准) 3DES(Triple DES,三重数据加密算法(TDEA,Triple Data Encryption Algorithm)) AES(Advanced Encryption Standard,高级加密标准) Blowfish RC2 RC4 DES DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定

AES 加密算法的原理详解

AES 加密算法的原理详解 本教程摘选自 https://blog.csdn.net/qq_28205153/article/details/55798628 的原理部分. AES简介 高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的).对称加密算法也就是加密和解密用相同的密钥,具体的加密流程如下图: 下面简单介绍下各个部分的作用与意义: 明文P 没有经过加密的数据. 密钥K 用来加密明文的密码,在对称

python3 + Vue 应用 AES 数据加密

python3 + Vue 应用 AES 数据加密 高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的).对称加密算法也就是加密和解密用相同的密钥,具有以下几个特点: 1.最常用的对称加密算法 2.密钥建立时间短.灵敏性好.内存需求低 3.实际使用中,使用工作模式为CTR(最好用BC去实现),此工作模式需要引入IV参数(16位的字节数组) 4.密钥长度128/192/256,其中192与256需要配置无政