300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > AES-128 加解密算法实现

AES-128 加解密算法实现

时间:2021-06-12 19:49:21

相关推荐

AES-128 加解密算法实现

本文中的代码仅实现了AES-128单个分组的加密算法和解密算法,不涉及填充和分组加密的工作模式(如CBC、CTR)

编写环境和工具

OS:Windows 10

IDE:Clion

mingw64(x86_64-8.1.0-posix-seh-rt_v6-rev0)

加解密算法实现

实际上代码都是C风格的,稍微改一改头文件就是C了

AES.hpp

#ifndef AES_H_INCLUDED#define AES_H_INCLUDED#include <cinttypes>/*** 编写日期:-6-10* 编写内容:AES-128单个分组加解密相关的* 主要函数、涉及常量和数据类型的定义* 修改日期:-6-13*//// ! 仅实现AES-128 ! ////// 类型定义和常量const uint8_t BLOCKSIZE = 16;const uint8_t KEYSIZE = 16;const uint8_t MAXROUND = 10;typedef uint8_t round;typedef uint8_t state[4][4];typedef uint32_t exkey[44];typedef char orikey[KEYSIZE + 1];typedef char block[BLOCKSIZE + 1];const uint8_t SBOX[16][16] = {{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}};const uint8_t INV_SBOX[16][16] = {{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}};/// AES分组的加解密void AES_BlockEncrypt(block pt, exkey w, block ct);void AES_BlockDecrypt(block ct, exkey w, block pt);void KeyExpansion(const orikey k, exkey w); /// 密钥扩展(生成轮密钥)/// AES分组加解密中共同用到的操作void block2state(block blc, state s); /// 将字符串(明文/密文)转为状态矩阵void state2block(state s, block blc); /// 将状态矩阵 转为字符串(明文/密文)void AddRoundKey(state s, exkey w, round r); /// 轮密钥加/// AES分组加密中用到的其他操作void SubBytes(state s); /// 经过S盒void ShiftRows(state s); /// 行移位void MixColumns(state s); /// 列混淆 (最后一轮这里是轮密钥加)/// AES分组解密中用到的其他操作void InvShiftRows(state s); /// 逆行移位void InvSubBytes(state s); /// 经过逆S盒void InvMixColumns(state s); /// 逆列混淆 (最后一轮这里是轮密钥加)#endif // AES_H_INCLUDED

AES.cpp

#include "AES.hpp"/*** 编写日期:-6-12* 编写内容:AES-128分组加解密实现* 修改日期:-6-15*/void AES_BlockEncrypt(block pt, exkey w, block ct) {state s;block2state(pt, s);AddRoundKey(s, w, 0);// 第一轮到第九轮for (int round = 1; round < 10; ++round) {SubBytes(s);ShiftRows(s);MixColumns(s);AddRoundKey(s, w, round);}// 第十轮SubBytes(s);ShiftRows(s);AddRoundKey(s, w, 10);state2block(s, ct);}void AES_BlockDecrypt(block ct, exkey w, block pt) {state s;block2state(ct, s);AddRoundKey(s, w, 10);for (int round = 9; round > 0; --round){InvShiftRows(s);InvSubBytes(s);AddRoundKey(s, w, round);InvMixColumns(s);}InvShiftRows(s);InvSubBytes(s);AddRoundKey(s, w, 0);state2block(s, pt);}/// 用于密钥扩展uint32_t SubWord(uint32_t in);uint32_t RotWord(uint32_t in);static const uint32_t Rcon[11] = {0x0, 0x01000000, 0x02000000, // 0x0 unused here0x04000000, 0x08000000,0x10000000, 0x20000000,0x40000000, 0x80000000,0x1b000000, 0x36000000 };/// 密钥扩展(生成轮密钥)void KeyExpansion(const orikey key, exkey w) {uint32_t tmp;int i = 0;// AES-128 ,Nk = 4while (i < 4) {uint32_t one = ((uint32_t)key[4*i] & 0xFF) << 24;uint32_t two = ((uint32_t)key[4*i+1] & 0xFF) << 16;uint32_t three = ((uint32_t)key[4*i+2] & 0xFF) << 8;uint32_t four = (uint32_t)key[4*i+3] & 0xFF;w[i] = one | two | three | four;i++;}i = 4;// AES-128while (i < 44) {tmp = w[i-1];if (i % 4 == 0){tmp = SubWord(RotWord(tmp));tmp ^= Rcon[i/4];}// For AES-128 only herew[i] = w[i - 4] ^ tmp;i++;}i = 4;}uint32_t SubWord(uint32_t in) {uint8_t tmp[4];uint8_t row,col;uint32_t res = 0;for (int i = 0; i < 4; ++i) {tmp[i] = (in >> (3 - i) * 8) & 0xFF;row = (tmp[i] >> 4) & 0x0F;col = tmp[i] & 0x0F;tmp[i] = SBOX[row][col];}uint32_t one = ((uint32_t)tmp[0] & 0xFF) << 24;uint32_t two = ((uint32_t)tmp[1] & 0xFF) << 16;uint32_t three = ((uint32_t)tmp[2] & 0xFF) << 8;uint32_t four = (uint32_t)tmp[3] & 0xFF;res = one | two | three | four;return res;}uint32_t RotWord(uint32_t in){return (in << 8) | (in >> 24);}/// AES分组加解密中共同用到的操作/// 轮密钥加void AddRoundKey(state s, exkey w, round r) {uint8_t tmp;for (int c = 0; c < 4; c++) {tmp = (uint8_t) ((w[r * 4 + c] & 0xFF000000) >> 24);s[0][c] ^= tmp;tmp = (uint8_t) ((w[r * 4 + c] & 0x00FF0000) >> 16);s[1][c] ^= tmp;tmp = (uint8_t) ((w[r * 4 + c] & 0x0000FF00) >> 8);s[2][c] ^= tmp;tmp = (uint8_t)(w[r * 4 + c] & 0x000000FF);s[3][c] ^= tmp;}}/// 将字符串(明文/密文)转为状态矩阵void block2state(block blc, state s) {for (int row = 0; row < 4; row++) {for (int col = 0; col < 4; col++) {s[row][col] = blc[4 * col + row];}}}/// 将状态矩阵 转为字符串(明文/密文)void state2block(state s, block blc) {for (int row = 0; row < 4; row++) {for (int col = 0; col < 4; col++) {blc[4 * col + row] = s[row][col];}}blc[BLOCKSIZE] = '\0';}/// AES分组加密中用到的其他操作/// 经过S盒void SubBytes(state s) {uint8_t row, col;for (int i = 0; i < 4; ++i) {for (int j = 0; j < 4; ++j) {row = (s[i][j] >> 4) & 0x0F;col = s[i][j] & 0x0F;s[i][j] = SBOX[row][col];}}}/// 行移位void ShiftRows(state s) {uint32_t tmp;// 第0行不用移for (int i = 1; i < 4; ++i) {uint32_t one = ((uint32_t)s[i][0] & 0xFF) << 24;uint32_t two = ((uint32_t)s[i][1] & 0xFF) << 16;uint32_t three = ((uint32_t)s[i][2] & 0xFF) << 8;uint32_t four = (uint32_t)s[i][3] & 0xFF;tmp = one | two | three | four;// 循环左移 8r 位tmp = (tmp << (8 * i)) | (tmp >> (32 - 8 * i));// 取数s[i][0] = (uint8_t)(tmp >> 24) & 0xFF;s[i][1] = (uint8_t)(tmp >> 16) & 0xFF;s[i][2] = (uint8_t)(tmp >> 8) & 0xFF;s[i][3] = (uint8_t)(tmp & 0xFF);}}/// GF(2^8)上的乘法,用于列混淆和逆列混淆/// 选取不可约多项式 p(x) 为 x^8 + x^4 + x^3 + x + 1.uint8_t GMul(uint8_t a, uint8_t b) {uint8_t res = 0;uint8_t tmp;res ^= (a & 0x1) ? b : 0;for (int i = 1; i < 8; ++i) {// 计算a(x)的i次项乘以b(x)的结果,并与当前结果相加(异或)if ((a >> i) & 0x1) {tmp = b;for (int timeMulx = 1; timeMulx <= i; ++timeMulx) {// 计算 x乘以b(x)的结果if (tmp & 0x80) {// 若deg(tmp(x)) = 7 则 x·tmp(x) 为8次多项式,需要模一下(减一下)p(x)tmp = (tmp << 1) ^ 0x1B; // 而减法就是加法,因此 加(XOR)0x1B即为减去p(x)} else {tmp = tmp << 1; }}res ^= tmp;}}return res;// for (int i = 0; i < 8; ++i) {// if (a & 0x01) {// res ^= b;// }// /// if deg(f) < 7 , then x·f(x) = byte[f(x)] << 1// /// if deg(f) = 7 , then x·f(x) = x·f(x) - p(x) = x·f(x) - (x^4 + x^3 + x + 1) = (byte[f(x)] << 1) ^ 0x1B// uint8_t flag = (b & 0x80);// b <<= 1;// if (flag) {// b ^= 0x1B;// }//// a >>= 1;// }// return res;}/// 列混淆void MixColumns(state s) {uint8_t tmp[4];for (int c = 0; c < 4; ++c) {for (int i = 0; i < 4; ++i) {tmp[i] = s[i][c];}s[0][c] = GMul(0x02, tmp[0]) ^ GMul(0x03, tmp[1]) ^ tmp[2] ^ tmp[3];s[1][c] = tmp[0] ^ GMul(0x02, tmp[1]) ^ GMul(0x03, tmp[2]) ^ tmp[3];s[2][c] = tmp[0] ^ tmp[1] ^ GMul(0x02, tmp[2]) ^ GMul(0x03, tmp[3]);s[3][c] = GMul(0x03, tmp[0]) ^ tmp[1] ^ tmp[2] ^ GMul(0x02, tmp[3]);}}/// AES分组解密中用到的其他操作/// 逆行移位void InvShiftRows(state s) {uint32_t tmp;// 第0行不用移for (int i = 1; i < 4; ++i) {uint32_t one = ((uint32_t)s[i][0] & 0xFF) << 24;uint32_t two = ((uint32_t)s[i][1] & 0xFF) << 16;uint32_t three = ((uint32_t)s[i][2] & 0xFF) << 8;uint32_t four = (uint32_t)s[i][3] & 0xFF;tmp = one | two | three | four;// 循环右移 8r 位tmp = (tmp >> (8 * i)) | (tmp << (32 - 8 * i));// 取数s[i][0] = (uint8_t)(tmp >> 24) & 0xFF;s[i][1] = (uint8_t)(tmp >> 16) & 0xFF;s[i][2] = (uint8_t)(tmp >> 8) & 0xFF;s[i][3] = (uint8_t)(tmp & 0xFF);}}/// 经过逆S盒void InvSubBytes(state s) {uint8_t row, col;// TODO: debugfor (int i = 0; i < 4; ++i) {for (int j = 0; j < 4; ++j) {row = (s[i][j] >> 4) & 0x0F;col = s[i][j] & 0x0F;s[i][j] = INV_SBOX[row][col];}}}/// 逆列混淆void InvMixColumns(state s) {uint8_t tmp[4];for (int c = 0; c < 4; ++c) {for (int i = 0; i < 4; ++i) {tmp[i] = s[i][c];}s[0][c] = GMul(0x0E, tmp[0]) ^ GMul(0x0B, tmp[1]) ^ GMul(0x0D, tmp[2]) ^ GMul(0x09, tmp[3]);s[1][c] = GMul(0x09, tmp[0]) ^ GMul(0x0E, tmp[1]) ^ GMul(0x0B, tmp[2]) ^ GMul(0x0D, tmp[3]);s[2][c] = GMul(0x0D, tmp[0]) ^ GMul(0x09, tmp[1]) ^ GMul(0x0E, tmp[2]) ^ GMul(0x0B, tmp[3]);s[3][c] = GMul(0x0B, tmp[0]) ^ GMul(0x0D, tmp[1]) ^ GMul(0x09, tmp[2]) ^ GMul(0x0E, tmp[3]);}}

测试用例

test_AES.hpp

#ifndef AES_DES_CBC_TEST_AES_HPP#define AES_DES_CBC_TEST_AES_HPPvoid test_AES_BlockEncrypt();void test_AES_BlockDecrypt();#endif //AES_DES_CBC_TEST_AES_HPP

test_AES.cpp

#include <cstdio>#include "AES.hpp"#include "test_AES.hpp"#include "AES.cpp"void test_AES_BlockEncrypt() {/*** plainText: 3243f6a8885a308d313198a2e0370734* key: 2b7e151628aed2a6abf7158809cf4f3c* expect cipherText:3925841d02dc09fbdc118597196a0b32*/block pt = "\x32\x43\xf6\xa8\x88\x5a\x30\x8d\x31\x31\x98\xa2\xe0\x37\x07\x34";block ct = "\0";orikey key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c";exkey w = {0};uint8_t *p;KeyExpansion(key, w);AES_BlockEncrypt(pt, w, ct);printf("The cipherText is:\n");p = (uint8_t*)ct;for (int i = 0; i < 16; ++i) {printf("%02x ", *p);p++;}printf("\n");}void test_AES_BlockDecrypt() {/*** cipherText: 39 25 84 1d 02 dc 09 fb dc 11 85 97 19 6a 0b 32* key: 2b 7e 15 16 28 ae d2 a6 ab f7 15 88 09 cf 4f 3c* expect plainText: 32 43 f6 a8 88 5a 30 8d 31 31 98 a2 e0 37 07 34*/block ct = "\x39\x25\x84\x1d\x02\xdc\x09\xfb\xdc\x11\x85\x97\x19\x6a\x0b\x32";block pt = "\0";orikey key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c";exkey w = {0};uint8_t *p;KeyExpansion(key, w);AES_BlockDecrypt(ct, w, pt);printf("The plainText is:\n");p = (uint8_t*)pt;for (int i = 0; i < 16; ++i) {printf("%02x ", *p);p++;}printf("\n");}

main.cpp

#define TEST_AES#ifdef TEST_AES#include "test_AES.hpp"int main(){test_AES_BlockEncrypt();test_AES_BlockDecrypt();return 0;}#endif

参考资料

/soreatu/Cryptography (python)

Announcing the ADVANCED ENCRYPTION STANDARD (AES)

(Federal Information Processing Standards Publication 197 November 26, 2001)

AES加密算法的详细介绍与实现

AES算法描述及C语言实现

后记

这次实验并没有我想象的那么简单,遇到了很多坑,也发现了自己的问题(比如说位运算各种写错)。为了解决链接时的一个奇怪的问题,代码中使用了一些邪恶的手段(没错,就是 #include “AES.cpp”)

犯了一些难以发现的低级错误,调试调吐了。等以后有时间,再多多练习编程。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。