加密原理

AES 是一种分组对称加密算法标准分组长度为 128 16 字节),密钥长度可以是 128192  256 
核心流程
AES 的加密过程由多个”(Round组成对于 AES-128总共有 10 除了初始轮和最后一轮略有不同每一轮都包含以下四个步骤
1.1 字节代换 (SubBytes)
这是 AES 唯一的非线性变换每个字节通过一个固定的查表操作S-Box进行替换    特征如果你在程序里看到一个 256 字节的随机数组通常以 0x63, 0x7c, 0x77... 开头),那大概率就是 AES  S 

1.2 行移位 (ShiftRows)
将矩阵的每一行进行循环左移第一行不变第二行移 1 第三行移 2 第四行移 3     目的 打乱字节在列间的排列

1.3 列混淆 (MixColumns)
利用有限域 GF(28) 上的矩阵乘法对每一列进行线性变换    注意最后一轮Round 10没有这一步

1.4 轮密钥加 (AddRoundKey)
将当前的中间状态与该轮的轮密钥进行异或 (XOR) 操作这是加密逻辑真正依赖密钥的地方

2. 关键密钥扩展 (Key Expansion)
AES 不直接把你的原始密钥用到每一轮它会通过一个算法将原始密钥拉长成多个轮密钥Round Keys)。
AES 一次只能加密 16 字节如果明文很长就需要按照某种规则重复调用 AES 核心函数
ECB (Electronic Codebook) - 电子密码本模式
这是最简单的模式直接把明文切成 16 字节的一块块每一块独立加密
    逆向特征代码里没有初始向量IV),循环调用加密函数且输入输出直接对应
    缺点同样的明文块加密后密文完全相同 CTF 如果你看到密文有规律的重复基本就是 ECB

CBC (Cipher Block Chaining) - 密码分组链接模式
这是 CTF 中最常见的模式每一块明文在加密前先与前一块的密文进行 异或 (XOR)
    IV (Initialization Vector)第一块明文需要与一个随机的初始向量异或
    逆向特征代码中会出现一个 16 字节的 IV且在 Encrypt 函数执行前后有明显的异或操作

其他模式 (CTR, GCM, CFB)
    CTR (Counter) AES 当成流加密加密的是一个计数器然后把结果与明文异或逆向点 这种模式下加密和解密逻辑完全一样都是异或)。
    GCM带有认证能力的模式除了密文还会产出一个 Tag 用于校验数据是否被篡改
2. 填充方式 (Padding)
由于 AES 要求输入必须是 16 字节的整数倍如果你的明文比如 "Hello"不到 16 字节就必须凑数这就叫填充
PKCS#7 (最标准、最常见)
原理缺几个字节就填几个”。
     1 字节末尾填 01
     3 字节末尾填 03 03 03
    特例如果明文刚好是 16 字节的倍数必须再增加一个完整的 16 字节填充全部填 10),否则解密时无法区分是原始数据还是填充

Zero Padding
原理末尾全部补 00
    逆向点如果解密后的明文末尾有很多 \x00通常就是这种

ANSI X.923
原理末尾补 00但最后一个字节记录填充的总长度

代码实现

S盒密钥扩展核心加密逻辑ECB/CBC 模式选择以及 PKCS#7 填充
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>

// --- [1. 识别的关键点] ---
const uint8_t sbox[256] = {
    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 Rcon[11] = {0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};

// --- [2. 核心数学运算] ---
#define xtime(x) ((x << 1) ^ (((x >> 7) & 1) * 0x1b))

void KeyExpansion(uint8_t *key, uint8_t *w) {
    uint8_t temp[4];
    memcpy(w, key, 16);
    for (int i = 16; i < 176; i += 4) {
        memcpy(temp, w + i - 4, 4);
        if (i % 16 == 0) {
            uint8_t t = temp[0];
            temp[0] = sbox[temp[1]] ^ Rcon[i/16];
            temp[1] = sbox[temp[2]];
            temp[2] = sbox[temp[3]];
            temp[3] = sbox[t];
        }
        for (int j = 0; j < 4; j++) w[i + j] = w[i - 16 + j] ^ temp[j];
    }
}

// --- [3. AES 单块加密核心] ---
void aes_encrypt_block(uint8_t state[16], uint8_t *w) {
    // AddRoundKey (Round 0)
    for (int i = 0; i < 16; i++) state[i] ^= w[i];

    for (int round = 1; round <= 10; round++) {
        // 1. SubBytes
        for (int i = 0; i < 16; i++) state[i] = sbox[state[i]];

        // 2. ShiftRows
        uint8_t t[16];
        t[0]=state[0]; t[4]=state[4]; t[8]=state[8]; t[12]=state[12];
        t[1]=state[5]; t[5]=state[9]; t[9]=state[13]; t[13]=state[1];
        t[2]=state[10];t[6]=state[14];t[10]=state[2]; t[14]=state[6];
        t[3]=state[15];t[7]=state[3]; t[11]=state[7]; t[15]=state[11];
        memcpy(state, t, 16);

        // 3. MixColumns (Round 1-9 only)
        if (round < 10) {
            for (int i = 0; i < 4; i++) {
                uint8_t a = state[i*4], b = state[i*4+1], c = state[i*4+2], d = state[i*4+3];
                state[i*4]   = xtime(a^b) ^ b ^ c ^ d;
                state[i*4+1] = xtime(b^c) ^ c ^ d ^ a;
                state[i*4+2] = xtime(c^d) ^ d ^ a ^ b;
                state[i*4+3] = xtime(d^a) ^ a ^ b ^ c;
            }
        }
        // 4. AddRoundKey
        for (int i = 0; i < 16; i++) state[i] ^= w[round * 16 + i];
    }
}

// --- [4. 工作模式与填充] ---

// PKCS#7 填充
int pkcs7_pad(uint8_t *data, int len) {
    uint8_t pad = 16 - (len % 16);
    for (int i = 0; i < pad; i++) data[len + i] = pad;
    return len + pad;
}

// ECB 模式加密
void aes_ecb_encrypt(uint8_t *input, int len, uint8_t *key, uint8_t *output) {
    uint8_t w[176];
    KeyExpansion(key, w);
    for (int i = 0; i < len; i += 16) {
        memcpy(output + i, input + i, 16);
        aes_encrypt_block(output + i, w);
    }
}

// CBC 模式加密
void aes_cbc_encrypt(uint8_t *input, int len, uint8_t *key, uint8_t *iv, uint8_t *output) {
    uint8_t w[176], temp_iv[16];
    KeyExpansion(key, w);
    memcpy(temp_iv, iv, 16);
    for (int i = 0; i < len; i += 16) {
        for (int j = 0; j < 16; j++) output[i + j] = input[i + j] ^ temp_iv[j];
        aes_encrypt_block(output + i, w);
        memcpy(temp_iv, output + i, 16);
    }
}

// --- [5. 主函数测试] ---
int main() {
    uint8_t key[16] = "CTF_RE_STUDENT!!"; // 16字节Key
    uint8_t iv[16]  = "1234567887654321"; // 16字节IV
    char plain[]    = "Hello AES Mode!";   // 明文
    
    uint8_t buffer[64];
    memset(buffer, 0, 64);
    memcpy(buffer, plain, strlen(plain));

    // 1. 填充
    int padded_len = pkcs7_pad(buffer, strlen(plain));
    uint8_t encrypted[64];

    // 2. CBC 加密
    printf("Encrypted (CBC): ");
    aes_cbc_encrypt(buffer, padded_len, key, iv, encrypted);
    for (int i = 0; i < padded_len; i++) printf("%02X", encrypted[i]);
    printf("\n");

    // 3. ECB 加密 (无IV)
    printf("Encrypted (ECB): ");
    aes_ecb_encrypt(buffer, padded_len, key, encrypted);
    for (int i = 0; i < padded_len; i++) printf("%02X", encrypted[i]);
    printf("\n");

    return 0;
}