AES加密算法是对称加密算法(symmetric-key algorithm)的一种。对称加密就意味着加密,解密中使用的key是相同的。从实现的算法来看,在加密解密的过程中,不需要动态分配内存,算法比较简捷,对于嵌入式系统来说好处多多。
这里主要是针对128-bit的AES加密算法的分析与实现。
- 原理
请先看下面一段flash(来自http://www.formaestudio.com/rijndaelinspector/archivos/Rijndael_Animation_v4_eng.swf)
NOTE:
- 演示中的数值可能存在错误,具体请看:http://coolshell.cn/articles/3161.html#comment-114419
Key Schedule 这一步里面,Round key 2 的第三列错了。
23,a3,39,39 应该为 59,25,80,7a;前面的步骤出现过正确的值,可以对照。
- P3中的State表示的是明文,而Cipher key表示的是16字节(128-bit的密钥)
对于128-bit的加密算法来说, 16字节的Cipher key会通过Key Schedule扩展成176字节,具体的扩展方法请看:http://www.samiam.org/key-schedule.html, 当然在进行Key扩展时,会使用到:
a. S-box – https://en.wikipedia.org/wiki/Rijndael_S-box
b. Rcon – https://en.wikipedia.org/wiki/Rijndael_key_schedule
c. Finite field arithmetic – https://en.wikipedia.org/wiki/Finite_field_arithmetic#Rijndael.27s_finite_field
权威文档:http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
中文文档请看:http://www.cnblogs.com/luop/p/4334160.html
- 加密算法C语言实现 – 辅助定义
#define AES_MAXNR 14 #define ROTL8(x,shift) ((uint8_t) ((x) << (shift)) | ((x) >> (8 - (shift)))) #undef ROTATE #if defined(_MSC_VER) || defined(__ICC) # define ROTATE(a,n) _lrotl(a,n) #elif defined(__GNUC__) && __GNUC__>=2 # if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) # define ROTATE(a,n) ({ register unsigned int ret; \ asm ( \ "roll %1,%0" \ : "=r"(ret) \ : "I"(n), "0"(a) \ : "cc"); \ ret; \ }) # endif #endif typedef struct { uint32_t rd_key[4 * (AES_MAXNR + 1)]; int32_t rounds; uint8_t sbox[256]; } AES_KEY;
- 加密算法C语言实现 – 加密过程
1. 计算sbox
// https://en.wikipedia.org/wiki/Rijndael_S-box static void initialize_aes_sbox(uint8_t *sbox) { /* loop invariant: p * q == 1 in the Galois field */ uint8_t p = 1, q = 1; do { /* multiply p by x+1 */ p = p ^ (p << 1) ^ (p & 0x80 ? 0x1B : 0); /* divide q by x+1 */ q ^= q << 1; q ^= q << 2; q ^= q << 4; q ^= q & 0x80 ? 0x09 : 0; /* compute the affine transformation */ sbox[p] = 0x63 ^ q ^ ROTL8(q, 1) ^ ROTL8(q, 2) ^ ROTL8(q, 3) ^ ROTL8(q, 4); } while (p != 1); /* 0 is a special case since it has no inverse */ sbox[0] = 0x63; }
2. Rcon实现
static uint8_t rcon(uint8_t i) { uint8_t c; for (c = 1; i != 1; i--) c = c << 1 ^ (c & 0x80 ? 0x1b : 0); return c; }
3. 乘法运算实现
// https://en.wikipedia.org/wiki/Finite_field_arithmetic /* Multiply two numbers in the GF(2^8) finite field defined * by the polynomial x^8 + x^4 + x^3 + x + 1 = 0 * using the Russian Peasant Multiplication algorithm * (the other way being to do carry-less multiplication followed by a modular reduction) */ static uint8_t gmul(uint8_t a, uint8_t b) { uint8_t p = 0; /* the product of the multiplication */ while (b) { if (b & 1) /* if b is odd, then add the corresponding a to p (final product = sum of all a's corresponding to odd b's) */ p ^= a; /* since we're in GF(2^m), addition is an XOR */ if (a & 0x80) /* GF modulo: if a >= 128, then it will overflow when shifted left, so reduce */ a = (a << 1) ^ 0x11b; /* XOR with the primitive polynomial x^8 + x^4 + x^3 + x + 1 (0b1_0001_1011) -- you can change it but it must be irreducible */ else a <<= 1; /* equivalent to a*2 */ b >>= 1; /* equivalent to b // 2 */ } return p; }
4. 加密使用的key扩展
int AES_set_encrypt_key(const uint8_t *userKey, const uint32_t bits, AES_KEY *key) { uint32_t i, v1, v2, v3, v4, v5; if (bits != 128) return -1; key->rounds = 10; initialize_aes_sbox(key->sbox); v1 = key->rd_key[0] = *(uint32_t *)(userKey + 0); v2 = key->rd_key[1] = *(uint32_t *)(userKey + 4); v3 = key->rd_key[2] = *(uint32_t *)(userKey + 8); v4 = key->rd_key[3] = *(uint32_t *)(userKey + 12); uint8_t *sbox = key->sbox; for (i = 1; i <= key->rounds; i++) { v5 = sbox[(v4 >> 24) & 0xff] << 0 | sbox[(v4 >> 16) & 0xff] << 24 | sbox[(v4 >> 8) & 0xff] << 16 | sbox[(v4 >> 0) & 0xff] << 8; v1 = rcon(i) << 24 ^ v5 ^ v1; v2 = v1 ^ v2; v3 = v2 ^ v3; v4 = v3 ^ v4; key->rd_key[4 * i + 0] = v1; key->rd_key[4 * i + 1] = v2; key->rd_key[4 * i + 2] = v3; key->rd_key[4 * i + 3] = v4; } return 0; }
NOTE:
这里加密所使用的rcon并非标准:
unsigned char rcon[256] = { 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d }
而是将对应的数值向左移了24位,所以经过这个算法加密的数据,不能通过openssl这种标准的算法来进行解密。
与标准算法的区别请看这篇:
5. 加密算法
void AES_encrypt(const uint8_t *text, uint8_t *cipher, const AES_KEY *key) { uint32_t v1, v2, v3, v4; uint32_t v11, v12, v13, v14; uint32_t v17, v18, v20; v1 = key->rd_key[0] ^ *(uint32_t *)(text + 0); v2 = key->rd_key[1] ^ *(uint32_t *)(text + 4); v3 = key->rd_key[2] ^ *(uint32_t *)(text + 8); v4 = key->rd_key[3] ^ *(uint32_t *)(text + 12); const uint8_t *sbox = key->sbox; for (v20 = 1; v20 < 10; v20++) { v11 = sbox[(v1 >> 24) & 0xFF] << 24 | sbox[(v2 >> 16) & 0xFF] << 16 | sbox[(v3 >> 8) & 0xFF] << 8 | sbox[(v4 >> 0) & 0xFF] << 0; v12 = sbox[(v1 >> 0) & 0xFF] << 0 | sbox[(v2 >> 24) & 0xFF] << 24 | sbox[(v3 >> 16) & 0xFF] << 16 | sbox[(v4 >> 8) & 0xFF] << 8; v13 = sbox[(v1 >> 8) & 0xFF] << 8 | sbox[(v2 >> 0) & 0xFF] << 0 | sbox[(v3 >> 24) & 0xFF] << 24 | sbox[(v4 >> 16) & 0xFF] << 16; v14 = sbox[(v1 >> 16) & 0xFF] << 16 | sbox[(v2 >> 8) & 0xFF] << 8 | sbox[(v3 >> 0) & 0xFF] << 0 | sbox[(v4 >> 24) & 0xFF] << 24; /***************************************************************************** v1 = [ a1 a2 a3 a4 ] <- 0xa1a2a3a4 v2 = [ b1 b2 b3 b4 ] <- 0xb1b2b3b4 v3 = [ c1 c2 c3 c4 ] <- 0xc1c2c3c4 v4 = [ d1 d2 d3 d4 ] <- 0xd1d2d3d4 v11 = [ a1 b2 c3 d4 ] <- 0xa1b2c3d4 v12 = [ b1 c2 d3 a4 ] <- 0xb1c2d3a4 v13 = [ c1 d2 a3 b4 ] <- 0xc1d2a3b4 v14 = [ d1 a2 b3 c4 ] <- 0xd1a2b3c4 v1 = \ [ 02 03 01 01 ] [ a1 ] [ 01 02 03 01 ] [ b2 ] [ 01 01 02 03 ] [ c3 ] [ 03 01 01 02 ] [ d4 ] = \ (02*a1 ^ 03*b2 ^ 01*c3 ^ 01*d4) << 24 | <- (02*a1 ^ 03*b2 ^ 01*c3 ^ 01*d4) << 24 (01*a1 ^ 02*b2 ^ 03*c3 ^ 01*d4) << 16 | <- (02*b2 ^ 03*c3 ^ 01*d1 ^ 01*a1) << 16 (01^a1 ^ 01*b2 ^ 02*c3 ^ 03*d4) << 8 | <- (02*c3 ^ 03*d4 ^ 01*a1 ^ 01*b2) << 8 (03*a1 ^ 01*b2 ^ 01*c3 ^ 02*d4) << 0 <- (02*d4 ^ 03*a1 ^ 01*b2 ^ 01*c3) << 0 -------------------------------------------------------------------------------------------- [ 0e 0b 0d 09 ] [ 02 03 01 01 ] [ 01 00 00 00 ] [ 09 0e 0b 0d ] [ 01 02 03 01 ] [ 00 01 00 00 ] = [ 0d 09 0e 0b ] [ 01 01 02 03 ] [ 00 00 01 00 ] [ 0b 0d 09 0e ] [ 03 01 01 02 ] [ 00 00 00 01 ] *****************************************************************************/ v17 = ROTATE(v11, 16); v18 = ROTATE(v11, 24); v1 = key->rd_key[4 * v20 + 0] ^ 0x1B * ((v11 >> 7) & 0x1010101) ^ 2 * (v11 & 0xFF7F7F7F) ^ ((2 * (v11 & 0x7F000000) ^ 0x1B * ((v11 >> 7) & 0x1010101) ^ v11) >> 24 | (0x1B * ((v11 >> 7) & 0x10101) ^ 2 * (v11 & 0xFFFF7F7F) ^ v11) << 8) ^ v18 ^ v17; v17 = ROTATE(v12, 16); v18 = ROTATE(v12, 24); v2 = key->rd_key[4 * v20 + 1] ^ 0x1B * ((v12 >> 7) & 0x1010101) ^ 2 * (v12 & 0xFF7F7F7F) ^ ((2 * (v12 & 0x7F000000) ^ 0x1B * ((v12 >> 7) & 0x1010101) ^ v12) >> 24 | (0x1B * ((v12 >> 7) & 0x10101) ^ 2 * (v12 & 0xFFFF7F7F) ^ v12) << 8) ^ v18 ^ v17; v17 = ROTATE(v13, 16); v18 = ROTATE(v13, 24); v3 = key->rd_key[4 * v20 + 2] ^ 0x1B * ((v13 >> 7) & 0x1010101) ^ 2 * (v13 & 0xFF7F7F7F) ^ ((2 * (v13 & 0x7F000000) ^ 0x1B * ((v13 >> 7) & 0x1010101) ^ v13) >> 24 | (0x1B * ((v13 >> 7) & 0x10101) ^ 2 * (v13 & 0xFFFF7F7F) ^ v13) << 8) ^ v18 ^ v17; v17 = ROTATE(v14, 16); v18 = ROTATE(v14, 24); v4 = key->rd_key[4 * v20 + 3] ^ 0x1B * ((v14 >> 7) & 0x1010101) ^ 2 * (v14 & 0xFF7F7F7F) ^ ((2 * (v14 & 0x7F000000) ^ 0x1B * ((v14 >> 7) & 0x1010101) ^ v14) >> 24 | (0x1B * ((v14 >> 7) & 0x10101) ^ 2 * (v14 & 0xFFFF7F7F) ^ v14) << 8) ^ v18 ^ v17; } // v1 v2, v3, v4 *(uint32_t *)(cipher + 0) = key->rd_key[4 * v20 + 0] ^ (sbox[(v1 >> 24) & 0xFF] << 24 | sbox[(v2 >> 16) & 0xFF] << 16 | sbox[(v3 >> 8) & 0xFF] << 8 | sbox[(v4 >> 0) & 0xFF] << 0); *(uint32_t *)(cipher + 4) = key->rd_key[4 * v20 + 1] ^ (sbox[(v1 >> 0) & 0xFF] << 0 | sbox[(v2 >> 24) & 0xFF] << 24 | sbox[(v3 >> 16) & 0xFF] << 16 | sbox[(v4 >> 8) & 0xFF] << 8); *(uint32_t *)(cipher + 8) = key->rd_key[4 * v20 + 2] ^ (sbox[(v1 >> 8) & 0xFF] << 8 | sbox[(v2 >> 0) & 0xFF] << 0 | sbox[(v3 >> 24) & 0xFF] << 24 | sbox[(v4 >> 16) & 0xFF] << 16); *(uint32_t *)(cipher + 12) = key->rd_key[4 * v20 + 3] ^ (sbox[(v1 >> 16) & 0xFF] << 16 | sbox[(v2 >> 8) & 0xFF] << 8 | sbox[(v3 >> 0) & 0xFF] << 0 | sbox[(v4 >> 24) & 0xFF] << 24); }
- 加密算法C语言实现 – 解密过程
1. 计算inv_sbox
static void initialize_aes_inv_sbox(uint8_t *inv_sbox) { uint8_t sbox[256]; int32_t i; initialize_aes_sbox(sbox); for (i = 0; i < 256; i++) inv_sbox[sbox[i]] = i; }
NOTE: 通过已知的sbox计算出inv sbox
2. 解密所需的key扩展
int AES_set_decrypt_key(const uint8_t *userKey, const uint32_t bits, AES_KEY *key) { uint32_t i, v1, v2, v3, v4, v5; if (bits != 128) return -1; key->rounds = 10; initialize_aes_sbox(key->sbox); v1 = key->rd_key[0] = *(uint32_t *)(userKey + 0); v2 = key->rd_key[1] = *(uint32_t *)(userKey + 4); v3 = key->rd_key[2] = *(uint32_t *)(userKey + 8); v4 = key->rd_key[3] = *(uint32_t *)(userKey + 12); uint8_t *sbox = key->sbox; for (i = 1; i <= key->rounds; i++) { v5 = sbox[(v4 >> 24) & 0xff] << 0 | sbox[(v4 >> 16) & 0xff] << 24 | sbox[(v4 >> 8) & 0xff] << 16 | sbox[(v4 >> 0) & 0xff] << 8; v1 = rcon(i) << 24 ^ v5 ^ v1; v2 = v1 ^ v2; v3 = v2 ^ v3; v4 = v3 ^ v4; key->rd_key[4 * i + 0] = v1; key->rd_key[4 * i + 1] = v2; key->rd_key[4 * i + 2] = v3; key->rd_key[4 * i + 3] = v4; } initialize_aes_inv_sbox(key->sbox); return 0; }
3. 解密算法
void AES_decrypt(const uint8_t *cipher, uint8_t *text, const AES_KEY *key) { uint32_t v1, v2, v3, v4, v11, v12, v13, v14; const uint8_t *inv_sbox = key->sbox; uint32_t v20 = key->rounds; v11 = *(uint32_t *)(cipher + 0) ^ key->rd_key[v20 * 4 + 0]; v12 = *(uint32_t *)(cipher + 4) ^ key->rd_key[v20 * 4 + 1]; v13 = *(uint32_t *)(cipher + 8) ^ key->rd_key[v20 * 4 + 2]; v14 = *(uint32_t *)(cipher + 12) ^ key->rd_key[v20 * 4 + 3]; v1 = inv_sbox[(v11 >> 24) & 0xff] << 24 | inv_sbox[(v14 >> 16) & 0xff] << 16 | inv_sbox[(v13 >> 8) & 0xff] << 8 | inv_sbox[(v12 >> 0) & 0xff] << 0; v2 = inv_sbox[(v12 >> 24) & 0xff] << 24 | inv_sbox[(v11 >> 16) & 0xff] << 16 | inv_sbox[(v14 >> 8) & 0xff] << 8 | inv_sbox[(v13 >> 0) & 0xff] << 0; v3 = inv_sbox[(v13 >> 24) & 0xff] << 24 | inv_sbox[(v12 >> 16) & 0xff] << 16 | inv_sbox[(v11 >> 8) & 0xff] << 8 | inv_sbox[(v14 >> 0) & 0xff] << 0; v4 = inv_sbox[(v14 >> 24) & 0xff] << 24 | inv_sbox[(v13 >> 16) & 0xff] << 16 | inv_sbox[(v12 >> 8) & 0xff] << 8 | inv_sbox[(v11 >> 0) & 0xff] << 0; for (v20--; v20 >= 1; v20--) { uint32_t *v30[4] = { &v1, &v2, &v3, &v4 }; uint8_t a1, a2, a3, a4; int32_t i; /************************************************************************ v1 = 0xa1a2a3a4 v11 = \ [ 0e 0b 0d 09 ] [ a1 ] [ 09 0e 0b 0d ] [ a2 ] [ 0d 09 0e 0b ] [ a3 ] [ 0b 0d 09 0e ] [ a4 ] = \ (0e*a1 ^ 0b*a2 ^ 0d*a3 ^ 09*a4) << 24 | (09*a1 ^ 0e*a2 ^ 0b*a3 ^ 0d*a4) << 16 | (0d*a1 ^ 09*a2 ^ 0e*a3 ^ 0b*a4) << 8 | (0b*a1 ^ 0d*a2 ^ 09*a3 ^ 0e*a4) << 0 *************************************************************************/ for (i = 0; i < 4; i++) { uint32_t *v = v30[i]; *v ^= key->rd_key[4 * v20 + i]; a1 = (*v >> 24) & 0xff; a2 = (*v >> 16) & 0xff; a3 = (*v >> 8) & 0xff; a4 = (*v >> 0) & 0xff; *v = (gmul(a1, 0x0e) ^ gmul(a2, 0x0b) ^ gmul(a3, 0x0d) ^ gmul(a4, 0x09)) << 24 | (gmul(a1, 0x09) ^ gmul(a2, 0x0e) ^ gmul(a3, 0x0b) ^ gmul(a4, 0x0d)) << 16 | (gmul(a1, 0x0d) ^ gmul(a2, 0x09) ^ gmul(a3, 0x0e) ^ gmul(a4, 0x0b)) << 8 | (gmul(a1, 0x0b) ^ gmul(a2, 0x0d) ^ gmul(a3, 0x09) ^ gmul(a4, 0x0e)) << 0; } v11 = inv_sbox[(v1 >> 24) & 0xff] << 24 | inv_sbox[(v4 >> 16) & 0xff] << 16 | inv_sbox[(v3 >> 8) & 0xff] << 8 | inv_sbox[(v2 >> 0) & 0xff] << 0; v12 = inv_sbox[(v2 >> 24) & 0xff] << 24 | inv_sbox[(v1 >> 16) & 0xff] << 16 | inv_sbox[(v4 >> 8) & 0xff] << 8 | inv_sbox[(v3 >> 0) & 0xff] << 0; v13 = inv_sbox[(v3 >> 24) & 0xff] << 24 | inv_sbox[(v2 >> 16) & 0xff] << 16 | inv_sbox[(v1 >> 8) & 0xff] << 8 | inv_sbox[(v4 >> 0) & 0xff] << 0; v14 = inv_sbox[(v4 >> 24) & 0xff] << 24 | inv_sbox[(v3 >> 16) & 0xff] << 16 | inv_sbox[(v2 >> 8) & 0xff] << 8 | inv_sbox[(v1 >> 0) & 0xff] << 0; v1 = v11; v2 = v12; v3 = v13; v4 = v14; } *(uint32_t *)(text + 0) = key->rd_key[0] ^ v1; *(uint32_t *)(text + 4) = key->rd_key[1] ^ v2; *(uint32_t *)(text + 8) = key->rd_key[2] ^ v3; *(uint32_t *)(text + 12) = key->rd_key[3] ^ v4; }
- 加密算法C语言实现 – 演示
1. 代码
int main(int argc, char *argv[]) { // http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf // Expansion of a 128-bit Cipher Key uint8_t userKey[] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; uint8_t text[] = { 'w', 'w', 'w', '.', 'b', 'r', 'o', 'b', 'w', 'i', 'n', 'd', '.', 'c', 'o', 'm' }; uint8_t cipher[16]; AES_KEY aes_key; memset(&aes_key, 0x00, sizeof(aes_key)); AES_set_encrypt_key(userKey, 128, &aes_key); printf(" --------------------- AES 128 ENC EXPANDED KEY -------------------------\n"); hexdump(aes_key.rd_key, sizeof(aes_key.rd_key), 0, NULL); AES_encrypt(text, cipher, &aes_key); printf(" --------------------- AES 128 ENC - CIPHER -----------------------------\n"); hexdump(cipher, sizeof(cipher), 0, NULL); AES_set_decrypt_key(userKey, 128, &aes_key); printf(" --------------------- AES 128 DEC EXPANDED KEY -------------------------\n"); hexdump(aes_key.rd_key, sizeof(aes_key.rd_key), 0, NULL); memset(text, 0x00, sizeof(text)); AES_decrypt(cipher, text, &aes_key); printf(" --------------------- AES 128 DEC - TEXT -------------------------------\n"); hexdump(text, sizeof(text), 0, NULL); return 0; }
2. 结果
--------------------- AES 128 ENC EXPANDED KEY ------------------------- 00000000: 2b 7e 15 16 28 ae d2 a6 ab f7 15 88 09 cf 4f 3c +~..(.........O< 00000010: c0 7f 9f 93 e8 d1 4d 35 43 26 58 bd 4a e9 17 81 ......M5C&X.J... 00000020: cc a9 81 61 24 78 cc 54 67 5e 94 e9 2d b7 83 68 ...a$x.Tg^..-..h 00000030: 89 71 28 89 ad 09 e4 dd ca 57 70 34 e7 e0 f3 5c .q(......Wp4...\ 00000040: c3 e5 c9 8c 6e ec 2d 51 a4 bb 5d 65 43 5b ae 39 ....n.-Q..]eC[.9 00000050: d1 ff f0 78 bf 13 dd 29 1b a8 80 4c 58 f3 2e 75 ...x...)...LX..u 00000060: 4c 95 fd 69 f3 86 20 40 e8 2e a0 0c b0 dd 8e 79 L..i.. @.......y 00000070: fa 72 3c 30 09 f4 1c 70 e1 da bc 7c 51 07 32 05 .r<0...p...|Q.2. 00000080: 91 a3 f9 93 98 57 e5 e3 79 8d 59 9f 28 8a 6b 9a .....W..y.Y.(.k. 00000090: 29 97 87 f7 b1 c0 62 14 c8 4d 3b 8b e0 c7 50 11 ).....b..M;...P. 000000a0: ab 76 41 92 1a b6 23 86 d2 fb 18 0d 32 3c 48 1c .vA...#.....2<H. 000000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ --------------------- AES 128 ENC - CIPHER ----------------------------- 00000000: b6 08 04 bc 5f 65 f2 b3 d7 16 f7 6f d6 6a a2 27 ...._e.....o.j.' --------------------- AES 128 DEC EXPANDED KEY ------------------------- 00000000: 2b 7e 15 16 28 ae d2 a6 ab f7 15 88 09 cf 4f 3c +~..(.........O< 00000010: c0 7f 9f 93 e8 d1 4d 35 43 26 58 bd 4a e9 17 81 ......M5C&X.J... 00000020: cc a9 81 61 24 78 cc 54 67 5e 94 e9 2d b7 83 68 ...a$x.Tg^..-..h 00000030: 89 71 28 89 ad 09 e4 dd ca 57 70 34 e7 e0 f3 5c .q(......Wp4...\ 00000040: c3 e5 c9 8c 6e ec 2d 51 a4 bb 5d 65 43 5b ae 39 ....n.-Q..]eC[.9 00000050: d1 ff f0 78 bf 13 dd 29 1b a8 80 4c 58 f3 2e 75 ...x...)...LX..u 00000060: 4c 95 fd 69 f3 86 20 40 e8 2e a0 0c b0 dd 8e 79 L..i.. @.......y 00000070: fa 72 3c 30 09 f4 1c 70 e1 da bc 7c 51 07 32 05 .r<0...p...|Q.2. 00000080: 91 a3 f9 93 98 57 e5 e3 79 8d 59 9f 28 8a 6b 9a .....W..y.Y.(.k. 00000090: 29 97 87 f7 b1 c0 62 14 c8 4d 3b 8b e0 c7 50 11 ).....b..M;...P. 000000a0: ab 76 41 92 1a b6 23 86 d2 fb 18 0d 32 3c 48 1c .vA...#.....2<H. 000000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ --------------------- AES 128 DEC - TEXT ------------------------------- 00000000: 77 77 77 2e 62 72 6f 62 77 69 6e 64 2e 63 6f 6d www.brobwind.com
- 加密算法C语言实现 – 源代码
完整的代码可以从这里下载:
$ git clone https://github.com/brobwind/bro_aes.git
代码结构:
bro_aes +-- Makefile +-- README.md +-- bro_aes.c +-- bro_aes.h +-- bro_util.c +-- bro_util.h `-- main.c
使用Makefile编译系统。
- 相关的参考文档:
- http://crypto.stackexchange.com/questions/2418/how-to-use-rcon-in-key-expansion-of-128-bit-advanced-encryption-standard
- http://www.cnblogs.com/luop/p/4334160.html
- http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
- http://www.samiam.org/key-schedule.html
- http://www.formaestudio.com/rijndaelinspector/archivos/Rijndael_Animation_v4_eng.swf
- http://www.adamberent.com/documents/AESbyExample.htm
- http://www.efgh.com/software/rijndael.htm
分析的很详细。
http://extranet.cryptomathic.com/aescalc/index?key=2b7e151628aed2a6abf7158809cf4f3c&iv=00000000000000000000000000000000&input=7777772e62726f6277696e642e636f6d&mode=ecb&action=Encrypt&output=
Key : 2B7E151628AED2A6ABF7158809CF4F3C
Input Data : 7777772E62726F6277696E642E636F6D <– www.brobwind.com
Output Data : 7607B8E394C51976AB885254AC658D22
http://testprotect.com/appendix/AEScalc
和上面相同
http://aes.online-domain-tools.com/
Input Data : www.brobwind.com
Key : 2B7E151628AED2A6ABF7158809CF4F3C
Output Data : 7607B8E394C51976AB885254AC658D22
和你加密的结果对不住?
b6 08 04 bc 5f 65 f2 b3 d7 16 f7 6f d6 6a a2 27
是应为文中提到的原因吗?
NOTE:
这里加密所使用的rcon并非标准:
而是将对应的数值向左移了24位,所以经过这个算法加密的数据,
不能通过openssl这种标准的算法来进行解密。
http://extranet.cryptomathic.com/aescalc/index?key=2b7e151628aed2a6abf7158809cf4f3c&iv=00000000000000000000000000000000&input=7777772e62726f6277696e642e636f6d&mode=ecb&action=Encrypt&output=
Key : 2B7E151628AED2A6ABF7158809CF4F3C
Input Data : 7777772E62726F6277696E642E636F6D <– http://www.brobwind.com
Output Data : 7607B8E394C51976AB885254AC658D22
http://testprotect.com/appendix/AEScalc
相同
http://aes.online-domain-tools.com/
Input Data : http://www.brobwind.com
Key : 2B7E151628AED2A6ABF7158809CF4F3C
Output Data : 7607B8E394C51976AB885254AC658D22
和你加密的结果对不住?
b6 08 04 bc 5f 65 f2 b3 d7 16 f7 6f d6 6a a2 27
是因为文中提到的原因吗?
NOTE:
这里加密所使用的rcon并非标准:
而是将对应的数值向左移了24位,所以经过这个算法加密的数据,
不能通过openssl这种标准的算法来进行解密。
可以说这个并不是AES 128-bit的标准实现,主要是为了将来可以会实现一个能够与ST-LINK/V2-1 bootloader相兼容的bootloader。
请仔细看这篇文档:https://www.brobwind.com/archives/1133
在http://www.taylorkillian.com/2013/01/retrieving-st-linkv2-firmware-from.htm上有提到固件的加密算法为AES 128-bit, 而加密的key为”I am key, wawawa”, 所以:
--------------------- AES 128 ENC EXPANDED KEY -------------------------
00000000: 49 20 61 6d 20 6b 65 79 2c 20 77 61 77 61 77 61 I am key, wawawa <- Encryption key
00000010: a6 d5 8e 99 86 be eb e0 aa 9e 9c 81 dd ff eb e0 ................
00000020: 47 14 98 72 c1 aa 73 92 6b 34 ef 13 b6 cb 04 f3 G..r..s.k4......
00000030: 4a 5a 87 84 8b f0 f4 16 e0 c4 1b 05 56 0f 1f f6 JZ..........V...
00000040: 08 eb f1 4c 83 1b 05 5a 63 df 1e 5f 35 d0 01 a9 ...L...Zc.._5...
00000050: db 7d 81 20 58 66 84 7a 3b b9 9a 25 0e 69 9b 8c .}. Xf.z;..%.i..
00000060: bf d6 78 14 e7 b0 fc 6e dc 09 66 4b d2 60 fd c7 ..x....n..fK.
..
00000070: 79 63 a8 00 9e d3 54 6e 42 da 32 25 90 ba cf e2 yc....TnB.2%....
00000080: e1 03 5c 0a 7f d0 08 64 3d 0a 3a 41 ad b0 f5 a3 ..\....d=.:A....
00000090: eb 96 bb f7 94 46 b3 93 a9 4c 89 d2 04 fc 7c 71 .....F...L....|q
000000a0: 48 64 0b d1 dc 22 b8 42 75 6e 31 90 71 92 4d e1 Hd...".Bun1.q.M.
--------------------- AES 128 ENC - CIPHER -----------------------------
00000000: f6 5c 83 b1 d2 cf 3e e2 0c 3d 6d 17 e4 0d f1 60 .\....>..=m....
<- Device encryption key
--------------------- AES 128 DEC EXPANDED KEY -------------------------
00000000: 49 20 61 6d 20 6b 65 79 2c 20 77 61 77 61 77 61 I am key, wawawa
00000010: a6 d5 8e 99 86 be eb e0 aa 9e 9c 81 dd ff eb e0 ................
00000020: 47 14 98 72 c1 aa 73 92 6b 34 ef 13 b6 cb 04 f3 G..r..s.k4......
00000030: 4a 5a 87 84 8b f0 f4 16 e0 c4 1b 05 56 0f 1f f6 JZ..........V...
00000040: 08 eb f1 4c 83 1b 05 5a 63 df 1e 5f 35 d0 01 a9 ...L...Zc.._5...
00000050: db 7d 81 20 58 66 84 7a 3b b9 9a 25 0e 69 9b 8c .}. Xf.z;..%.i..
00000060: bf d6 78 14 e7 b0 fc 6e dc 09 66 4b d2 60 fd c7 ..x....n..fK.
..
00000070: 79 63 a8 00 9e d3 54 6e 42 da 32 25 90 ba cf e2 yc....TnB.2%....
00000080: e1 03 5c 0a 7f d0 08 64 3d 0a 3a 41 ad b0 f5 a3 ..\....d=.:A....
00000090: eb 96 bb f7 94 46 b3 93 a9 4c 89 d2 04 fc 7c 71 .....F...L....|q
000000a0: 48 64 0b d1 dc 22 b8 42 75 6e 31 90 71 92 4d e1 Hd...".Bun1.q.M.
--------------------- AES 128 DEC - TEXT -------------------------------
00000000: 40 00 ff ff 52 ff 6c 06 49 72 51 49 15 42 16 87 @...R.l.IrQI.B.. <- Unique device ID
我本来以为只是在计算expand key的时候使用的rcon不同,所以最终的结果也不同。现在看来,在进行文本加密时,使用的算法可能也与标准的AES算法不同,有时间再进行进一步分析。
不过这个算法与AES的标准算法还是很接近的,都有
- SubBytes transformation
-ShiftRows transformation
-MixColumns transformation
-AddRoundKey Transformation
https://android.googlesource.com/platform/external/openssl/+/android-5.1.1_r38/crypto/aes/aes_x86core.c 虽说可以当作AES C参考实现,个人觉得学习的难度有点大。
也就是说只是定制算法,类似于AES但是又不是纯正的AES。
它们的区别请看这篇文档:STM32: 实现AES 128-BIT加密算法 - 标准实现
https://www.brobwind.com/archives/1255
# elif defined(__arm__)
// ftp://ftp.dca.fee.unicamp.br/pub/docs/ea871/ARM/ARMGCCInlineAssemblerCookbook.pdf
# define ROTATE(a,n) ({ register unsigned int ret; \
asm ( \
“ror %0,%0,%1” \
: “=r”(ret) \
: “I”(32 – n), “0”(a) \
: “cc”); \
ret; \
})
# endif
使用这个在stm32 mdk编译时会报bro_aes.c(293): error: #29: expected an expression
请问该怎么解决?
/** \brief Rotate Right in unsigned value (32 bit)
This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
\param [in] value Value to rotate
\param [in] value Number of Bits to rotate
\return Rotated value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
{
__ASM volatile (“ror %0, %0, %1” : “+r” (op1) : “r” (op2) );
return(op1);
}
能不能详细的说一下计算S盒那部分,看的不太明白,为什么p要*3,q要/3,还有最后为什么要异或0X63,每一步看的云里雾里的,希望楼主解答一下,谢谢。。。
你参考这两篇文档看看,我也没搞懂:
http://www.samiam.org/s-box.html
http://www.samiam.org/galois.html
恩。。好的,谢谢