You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

360 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <iostream>
#include <vector>
#include <array>
#include<string>
#include<algorithm>
using namespace std;
// AES S盒完整256个值
const array<uint8_t, 256> 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
};
// 轮常数
const array<uint8_t, 10> rcon = {
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
};
using State = array<array<uint8_t, 4>, 4>;
using RoundKey = array<uint8_t, 16>;
// 辅助函数:字节转字
uint32_t bytes_to_word(const array<uint8_t, 4>& bytes) {
return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
}
// 辅助函数:字转字节
array<uint8_t, 4> word_to_bytes(uint32_t word) {
return {
static_cast<uint8_t>(word >> 24),
static_cast<uint8_t>((word >> 16) & 0xFF),
static_cast<uint8_t>((word >> 8) & 0xFF),
static_cast<uint8_t>(word & 0xFF)
};
}
// 密钥扩展
vector<RoundKey> key_expansion(const RoundKey& key) {
vector<RoundKey> round_keys(11);
round_keys[0] = key;
for (int i = 1; i <= 10; ++i) {
RoundKey new_key;
array<uint8_t, 4> temp;
// 获取前一个密钥的最后4字节
for (int j = 0; j < 4; ++j)
temp[j] = round_keys[i - 1][j + 12];
// RotWord
uint8_t tmp = temp[0];
temp[0] = temp[1];
temp[1] = temp[2];
temp[2] = temp[3];
temp[3] = tmp;
// SubWord
for (int j = 0; j < 4; ++j)
temp[j] = s_box[temp[j]];
// 异或Rcon
temp[0] ^= rcon[i - 1];
// 生成新的轮密钥
for (int j = 0; j < 4; ++j)
new_key[j] = round_keys[i - 1][j] ^ temp[j];
for (int j = 4; j < 16; ++j)
new_key[j] = new_key[j - 4] ^ round_keys[i - 1][j];
round_keys[i] = new_key;
}
return round_keys;
}
// 字节替换
void sub_bytes(State& state) {
for (auto& row : state)
for (auto& b : row)
b = s_box[b];
}
// 行移位
void shift_rows(State& state) {
// 第1行左移1字节
uint8_t temp = state[1][0];
state[1][0] = state[1][1];
state[1][1] = state[1][2];
state[1][2] = state[1][3];
state[1][3] = temp;
// 第2行左移2字节
swap(state[2][0], state[2][2]);
swap(state[2][1], state[2][3]);
// 第3行左移3字节
temp = state[3][3];
state[3][3] = state[3][2];
state[3][2] = state[3][1];
state[3][1] = state[3][0];
state[3][0] = temp;
}
// 有限域乘法
uint8_t gf_mult(uint8_t a, uint8_t b) {
uint8_t res = 0;
uint8_t hi_bit;
for (int i = 0; i < 8; ++i) {
if (b & 1) res ^= a;
hi_bit = a & 0x80;
a <<= 1;
if (hi_bit) a ^= 0x1B; // 模x^8 + x^4 + x^3 + x + 1
b >>= 1;
}
return res;
}
// 列混合
void mix_columns(State& state) {
for (int col = 0; col < 4; ++col) {
uint8_t a = state[0][col];
uint8_t b = state[1][col];
uint8_t c = state[2][col];
uint8_t d = state[3][col];
state[0][col] = gf_mult(a, 0x02) ^ gf_mult(b, 0x03) ^ c ^ d;
state[1][col] = a ^ gf_mult(b, 0x02) ^ gf_mult(c, 0x03) ^ d;
state[2][col] = a ^ b ^ gf_mult(c, 0x02) ^ gf_mult(d, 0x03);
state[3][col] = gf_mult(a, 0x03) ^ b ^ c ^ gf_mult(d, 0x02);
}
}
// 轮密钥加
void add_round_key(State& state, const RoundKey& key) {
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
state[i][j] ^= key[i + 4 * j];
}
// PKCS7填充
vector<uint8_t> pkcs7_pad(const vector<uint8_t>& data) {
size_t pad_len = 16 - (data.size() % 16);
vector<uint8_t> padded(data);
padded.insert(padded.end(), pad_len, static_cast<uint8_t>(pad_len));
return padded;
}
// AES加密主函数
vector<uint8_t> aes_encrypt(const vector<uint8_t>& plaintext, const RoundKey& key) {
auto round_keys = key_expansion(key);
vector<uint8_t> ciphertext;
for (size_t i = 0; i < plaintext.size(); i += 16) {
State state;
// 初始化状态矩阵
for (int row = 0; row < 4; ++row)
for (int col = 0; col < 4; ++col)
state[row][col] = plaintext[i + row + 4 * col];
// 初始轮密钥加
add_round_key(state, round_keys[0]);
// 10轮加密
for (int round = 1; round <= 10; ++round) {
sub_bytes(state);
shift_rows(state);
if (round != 10) mix_columns(state);
add_round_key(state, round_keys[round]);
}
// 写入密文
for (int row = 0; row < 4; ++row)
for (int col = 0; col < 4; ++col)
ciphertext.push_back(state[row][col]);
}
return ciphertext;
}
// 逆S盒
const array<uint8_t, 256> inv_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
};
// 逆字节替换
void inv_sub_bytes(State& state) {
for (auto& row : state)
for (auto& b : row)
b = inv_s_box[b];
}
// 逆行移位
void inv_shift_rows(State& state) {
// 第1行右移1字节
uint8_t temp = state[1][3];
state[1][3] = state[1][2];
state[1][2] = state[1][1];
state[1][1] = state[1][0];
state[1][0] = temp;
// 第2行右移2字节
swap(state[2][0], state[2][2]);
swap(state[2][1], state[2][3]);
// 第3行右移3字节
temp = state[3][0];
state[3][0] = state[3][1];
state[3][1] = state[3][2];
state[3][2] = state[3][3];
state[3][3] = temp;
}
// 逆列混合
void inv_mix_columns(State& state) {
for (int col = 0; col < 4; ++col) {
uint8_t a = state[0][col];
uint8_t b = state[1][col];
uint8_t c = state[2][col];
uint8_t d = state[3][col];
state[0][col] = gf_mult(a, 0x0e) ^ gf_mult(b, 0x0b) ^ gf_mult(c, 0x0d) ^ gf_mult(d, 0x09);
state[1][col] = gf_mult(a, 0x09) ^ gf_mult(b, 0x0e) ^ gf_mult(c, 0x0b) ^ gf_mult(d, 0x0d);
state[2][col] = gf_mult(a, 0x0d) ^ gf_mult(b, 0x09) ^ gf_mult(c, 0x0e) ^ gf_mult(d, 0x0b);
state[3][col] = gf_mult(a, 0x0b) ^ gf_mult(b, 0x0d) ^ gf_mult(c, 0x09) ^ gf_mult(d, 0x0e);
}
}
// PKCS7去填充
vector<uint8_t> pkcs7_unpad(const vector<uint8_t>& data) {
if (data.empty()) return data;
uint8_t pad_len = data.back();
if (pad_len > 16 || pad_len == 0) return data;
for (size_t i = data.size() - pad_len; i < data.size(); ++i)
if (data[i] != pad_len) return data;
return vector<uint8_t>(data.begin(), data.end() - pad_len);
}
// AES解密主函数
vector<uint8_t> aes_decrypt(const vector<uint8_t>& ciphertext, const RoundKey& key) {
auto round_keys = key_expansion(key);
vector<uint8_t> plaintext;
for (size_t i = 0; i < ciphertext.size(); i += 16) {
State state;
// 初始化状态矩阵
for (int row = 0; row < 4; ++row)
for (int col = 0; col < 4; ++col)
state[row][col] = ciphertext[i + row + 4 * col];
// 初始轮密钥加(使用最后一个轮密钥)
add_round_key(state, round_keys[10]);
// 10轮解密
for (int round = 9; round >= 0; --round) {
inv_shift_rows(state);
inv_sub_bytes(state);
add_round_key(state, round_keys[round]);
if (round > 0) inv_mix_columns(state);
}
// 写入明文
for (int row = 0; row < 4; ++row)
for (int col = 0; col < 4; ++col)
plaintext.push_back(state[row][col]);
}
// 去除填充
return pkcs7_unpad(plaintext);
}
// 用户交互界面
void user_interface() {
RoundKey key = {
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
};
while (true) {
cout << "\n=== AES-128 加解密系统 ==="
<< "\n1. 加密"
<< "\n2. 解密"
<< "\n0. 退出"
<< "\n请选择操作:";
int choice;
cin >> choice;
cin.ignore(); // 清除输入缓冲
if (choice == 0) break;
string input;
vector<uint8_t> data;
switch (choice) {
case 1: {
cout << "请输入要加密的明文:";
getline(cin, input);
data = vector<uint8_t>(input.begin(), input.end());
data = pkcs7_pad(data);
auto cipher = aes_encrypt(data, key);
cout << "\n加密结果HEX";
for (auto b : cipher) printf("%02x", b);
cout << endl;
break;
}
case 2: {
cout << "请输入要解密的密文HEX";
getline(cin, input);
// 转换HEX字符串到字节流
data.clear();
for (size_t i = 0; i < input.length(); i += 2) {
string byte = input.substr(i, 2);
data.push_back(static_cast<uint8_t>(stoul(byte, nullptr, 16)));
}
auto plain = aes_decrypt(data, key);
cout << "\n解密结果:";
for (auto b : plain) cout << static_cast<char>(b);
cout << endl;
break;
}
default:
cout << "无效选择!" << endl;
}
}
}
int main() {
user_interface();
return 0;
}