AES advanced encryption standard

复制代码
// advanced encryption standard
// author: karl malbrain, malbrain@yahoo.com

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 ();
}
复制代码

 

posted @   IAmAProgrammer  阅读(815)  评论(0编辑  收藏  举报
(评论功能已被禁用)
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
历史上的今天:
2013-06-16 A SCSI command code -- SIMPLIFIED DIRECT-ACCESS DEVICE (RBC)
2013-06-16 How to match between physical usb device and its drive letter?
2013-06-16 A SCSI command code quick reference
2013-06-16 Inprove the speed of the "Mass storage" as u disk
点击右上角即可分享
微信分享提示