逆向中曾与你擦肩而过的那些加密详解

Sher10ck 发布于 2026-03-20 183 次阅读


一、哪些是“真加密”,哪些不是

1、真正的密码算法

对称分组密码:AES、DES、TEA/XTEA/XXTEA、SM4等

流密码:RC4等

非对称密码:RSA

哈希 / MAC / KDF:MD5、SHA-1、SHA-2、SHA-3

2、哪些是“真加密”,哪些不是

编码:Base16/32/58/62/64/85、URL Encode、UUEncode

简单位运算混淆:XOR、ADD/SUB、ROL/ROR、字节交换、位重排、查表替换

压缩:zlib、gzip

约束 / 验证:迷宫、矩阵、线性方程组、Z3

虚拟机壳 / 自定义字节码:VM、解释器、调度器

3、迷宫、Z3 的定位

迷宫:本质是路径约束 / 状态转移 / 图搜索

Z3:本质是 SMT 求解器,不是加密算法,而是拿来解“验证关系”

Z3 官方文档把它定义为定理证明器 / SMT 求解器,用来判断逻辑公式在某些理论下是否可满足。逆向里它最常见的用途是:把校验逻辑翻成 bit-vector 约束后直接求解

二、逆向识别总方法:先看这 10 件事

2.1 看输入输出长度关系

这是最快的第一判断:

  • 长度变成 2 倍:像 hex / Base16
  • 3 字节变 4 字符:像 Base64
  • 4 字节变 5 字符:像 Base85
  • 输出长度与输入相同:像 XOR、流密码、分组密码某些模式
  • 固定输出 16/20/32/64 字节:像 MD5 / SHA1 / SHA256 / SHA512

2.2 看字符集

  • 0-9A-Fa-f:hex
  • A-Z2-7=:Base32
  • A-Za-z0-9+/=:Base64
  • A-Za-z0-9-_=:URL-safe Base64

2.3 看“块大小”

  • 8 字节块:DES /TEA 家族常见
  • 16 字节块:AES / SM4 常见
  • 不分块、逐字节/逐字输出:流密码或编码

2.4 看循环轮数

很多算法有非常鲜明的轮数味道:

  • AES:10 / 12 / 14 轮
  • DES:16 轮
  • TEA:常见 32 cycles(很多实现写成 32 次循环)
  • SM4:32 轮
  • SHA-1:80 步
  • SHA-256:64 步
  • MD5:64 步

2.5 看常量

常量是逆向识别最值钱的东西。

[Base]
Base64 table: A-Z a-z 0-9 + /
Base64 URL-safe: A-Z a-z 0-9 - _
Base32: A-Z 2-7
Base58: 无 0 O I l

[TEA]
delta = 0x9E3779B9
sum(dec start) = 0xC6EF3720
常见操作: <<4, >>5, +, ^

[XTEA]
k[sum & 3]
k[(sum >> 11) & 3]

[RC4]
S[256]
for i in 0..255 S[i]=i
KSA/PRGA + swap

[AES]
S-box 开头: 63 7C 77 7B F2 6B 6F C5
Rcon: 01 02 04 08 10 20 40 80 1B 36
AES-NI: aesenc/aesdec/aeskeygenassist

[DES]
8-byte block
16 rounds
大量置换表 + 8 个 S-box

[ChaCha20]
61707865 3320646e 79622d32 6b206574
rotation: 16,12,8,7

[Salsa20]
类似 16-word ARX
rotation: 7,9,13,18

[MD5]
IV:
67452301 EFCDAB89 98BADCFE 10325476

[SHA1]
IV:
67452301 EFCDAB89 98BADCFE 10325476 C3D2E1F0
K:
5A827999 6ED9EBA1 8F1BBCDC CA62C1D6

[SHA256]
IV:
6A09E667 BB67AE85 3C6EF372 A54FF53A
510E527F 9B05688C 1F83D9AB 5BE0CD19

[SM3]
IV:
7380166F 4914B2B9 172442D7 DA8A0600
A96F30BC 163138AA E38DEE4D B0FB0E4E
Tj:
79CC4519 / 7A879D8A

[HMAC]
ipad = 0x36
opad = 0x5C

[RSA]
e = 65537

2.6 看数据结构尺寸

一些算法的内部状态很有辨识度:

  • RC4:S[256]
  • AES:16-byte state,或 256 项 S-box / 4 张 T-table
  • SHA-256:8 个 32-bit state + 64 个 round constant
  • SHA-3/Keccak:5×5 lane 状态
  • RSA/ECC:大量大整数 limb 运算

2.7 看操作形状

  • 大量 xor + rol/ror + add:ARX 家族,常见于 TEA / XTEA
  • 大量查表:AES S-box、DES S-box、RC4 S 数组、Base 表
  • 大量位置换 / 掩码:DES、bitslice AES、CRC、哈希
  • 大整数乘模 / 平方模:RSA

2.8 看模式和 padding

很多题不是“算法本体”,而是“算法 + 模式 + padding”:

  • ECB:重复块明文会出现重复密文块
  • CBC:每块先 xor 前一密文块 / IV
  • CTR:无 padding,计数器递增
  • GCM:CTR + GHASH
  • PKCS#7:尾部 01/02/03...
  • Zero padding:末尾全 0

2.9 看硬件指令 / API

  • x86 aesenc/aesdec/aeskeygenassist:AES-NI
  • x86 pclmulqdq:GHASH / GCM 很常见
  • x86 SHA 扩展:SHA-1 / SHA-256
  • ARM AESE/AESMC/AESD/AESIMC:ARM Crypto Extension
  • CUDA / OpenCL / HIP:GPU 并行核

Intel 官方文档说明 AES-NI 包含 6 条核心指令;Intel SHA Extensions 为 SHA-1 和 SHA-256 提供 7 条 SSE 指令;ARM A64 加密指令运行在 128-bit Advanced SIMD 寄存器上;CUDA/PTX/OpenCL/ROCm 官方文档都把 GPU/异构设备暴露成数据并行模型。

三、所有常见加解密方法代码详解

base64(任意形式改变解密)

import base64
# 自定义Base64字符表
custom_table='6789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345'
#原编码
std_table ='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
# 密文
encoded_str = '1231231231'

# 字符映射和填充
translation = str.maketrans(custom_table, std_table)
translated_str = encoded_str.translate(translation)
pad_len = (-len(translated_str)) % 4
padded_str = translated_str + '=' * pad_len
try:
    data = base64.b64decode(padded_str)
    print("解码后的十六进制:", data.hex())
    
    # 尝试UTF-8解码
    
    flag = data.decode('utf-8')
    print("UTF-8解码成功:", flag)

except Exception as e:
    print("解码失败:", e)

TEA家族加解密

TEA

DELTA = 0x9E3779B9
MASK = 0xFFFFFFFF


def tea_encrypt(v, k):
    v0, v1 = v
    sum_ = 0
    for _ in range(32):
        sum_ = (sum_ + DELTA) & MASK
        v0 = (v0 + (((v1 << 4) + k[0]) ^ (v1 + sum_) ^ ((v1 >> 5) + k[1]))) & MASK
        v1 = (v1 + (((v0 << 4) + k[2]) ^ (v0 + sum_) ^ ((v0 >> 5) + k[3]))) & MASK
    return v0, v1


def tea_decrypt(v, k):
    v0, v1 = v
    sum_ = (DELTA * 32) & MASK
    for _ in range(32):
        v1 = (v1 - (((v0 << 4) + k[2]) ^ (v0 + sum_) ^ ((v0 >> 5) + k[3]))) & MASK
        v0 = (v0 - (((v1 << 4) + k[0]) ^ (v1 + sum_) ^ ((v1 >> 5) + k[1]))) & MASK
        sum_ = (sum_ - DELTA) & MASK
    return v0, v1


if __name__ == "__main__":
    # 一组数据块:2 个 32 位整数
    v = (0x12345678, 0x9ABCDEF0)

    # 128-bit key:4 个 32 位整数
    k = (0x11111111, 0x22222222, 0x33333333, 0x44444444)

    enc = tea_encrypt(v, k)
    dec = tea_decrypt(enc, k)

    print("原文: ", [hex(x) for x in v])
    print("加密: ", [hex(x) for x in enc])
    print("解密: ", [hex(x) for x in dec])

XTEA

MASK = 0xffffffff
u32 = lambda x: x & MASK

def encipher(num_rounds, v, key):
    v0, v1 = u32(v[0]), u32(v[1])
    delta = 0x9E3779B9
    sum_ = u32(0)
    for _ in range(num_rounds):
        t1 = u32(((v1 << 4) ^ (v1 >> 5)) + v1)
        k1 = u32(sum_ + key[sum_ & 3])
        v0 = u32(v0 + (t1 ^ k1))

        sum_ = u32(sum_ + delta)

        t2 = u32(((v0 << 4) ^ (v0 >> 5)) + v0)
        k2 = u32(sum_ + key[(sum_ >> 11) & 3])
        v1 = u32(v1 + (t2 ^ k2))

    v[0], v[1] = v0, v1

def decipher(num_rounds, v, key):
    v0, v1 = u32(v[0]), u32(v[1])
    delta = 0x9E3779B9
    sum_ = u32(delta * num_rounds)
    for _ in range(num_rounds):
        t2 = u32(((v0 << 4) ^ (v0 >> 5)) + v0)
        k2 = u32(sum_ + key[(sum_ >> 11) & 3])
        v1 = u32(v1 - (t2 ^ k2))

        sum_ = u32(sum_ - delta)

        t1 = u32(((v1 << 4) ^ (v1 >> 5)) + v1)
        k1 = u32(sum_ + key[sum_ & 3])
        v0 = u32(v0 - (t1 ^ k1))

    v[0], v[1] = v0, v1

if __name__ == "__main__":
    v = [1, 2]
    k = [2, 2, 3, 4]
    r = 32

    print("加密前原始数据:{} {}".format(v[0], v[1]))
    encipher(r, v, k)
    print("加密后的数据:{} {}".format(v[0], v[1]))
    decipher(r, v, k)
    print("解密后的数据:{} {}".format(v[0], v[1]))

XXTEA

def shift(z, y, x, k, p, e):
    return ((((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((x ^ y) + (k[(p & 3) ^ e] ^ z)))
def encrypt(v, k):
    delta = 0x9E3779B9
    n = len(v)
    rounds = 6 + 52 / n
    x = 0
    z = v[n - 1]
    for i in range(rounds):
        x = (x + delta) & 0xFFFFFFFF
        e = (x >> 2) & 3
        for p in range(n - 1):
            y = v[p + 1]
            v[p] = (v[p] + shift(z, y, x, k, p, e)) & 0xFFFFFFFF
            z = v[p]
        p += 1
        y = v[0]
        v[n - 1] = (v[n - 1] + shift(z, y, x, k, p, e)) & 0xFFFFFFFF
        z = v[n - 1]
    return v
def decrypt(v, k):
    delta = 0x9E3779B9
    n = len(v)
    rounds = 6 + 52 / n
    x = (rounds * delta) & 0xFFFFFFFF
    y = v[0]
    for i in range(rounds):
        e = (x >> 2) & 3
        for p in range(n - 1, 0, -1):
            z = v[p - 1]
            v[p] = (v[p] - shift(z, y, x, k, p, e)) & 0xFFFFFFFF
            y = v[p]
        p -= 1
        z = v[n - 1]
        v[0] = (v[0] - shift(z, y, x, k, p, e)) & 0xFFFFFFFF
        y = v[0]
        x = (x - delta) & 0xFFFFFFFF
    return v
if __name__ == '__main__':
    plain = [1, 2]
    key = [2, 2, 3, 4]
    encrypted = encrypt(plain, key)
    print(encrypted)
    decrypted = decrypt(encrypted, key)
    print(decrypted)

SM4

# 最简单 SM4 ECB 板子
# 适合 CTF 里直接解一块/多块数据

SBOX = [
    0xD6,0x90,0xE9,0xFE,0xCC,0xE1,0x3D,0xB7,0x16,0xB6,0x14,0xC2,0x28,0xFB,0x2C,0x05,
    0x2B,0x67,0x9A,0x76,0x2A,0xBE,0x04,0xC3,0xAA,0x44,0x13,0x26,0x49,0x86,0x06,0x99,
    0x9C,0x42,0x50,0xF4,0x91,0xEF,0x98,0x7A,0x33,0x54,0x0B,0x43,0xED,0xCF,0xAC,0x62,
    0xE4,0xB3,0x1C,0xA9,0xC9,0x08,0xE8,0x95,0x80,0xDF,0x94,0xFA,0x75,0x8F,0x3F,0xA6,
    0x47,0x07,0xA7,0xFC,0xF3,0x73,0x17,0xBA,0x83,0x59,0x3C,0x19,0xE6,0x85,0x4F,0xA8,
    0x68,0x6B,0x81,0xB2,0x71,0x64,0xDA,0x8B,0xF8,0xEB,0x0F,0x4B,0x70,0x56,0x9D,0x35,
    0x1E,0x24,0x0E,0x5E,0x63,0x58,0xD1,0xA2,0x25,0x22,0x7C,0x3B,0x01,0x21,0x78,0x87,
    0xD4,0x00,0x46,0x57,0x9F,0xD3,0x27,0x52,0x4C,0x36,0x02,0xE7,0xA0,0xC4,0xC8,0x9E,
    0xEA,0xBF,0x8A,0xD2,0x40,0xC7,0x38,0xB5,0xA3,0xF7,0xF2,0xCE,0xF9,0x61,0x15,0xA1,
    0xE0,0xAE,0x5D,0xA4,0x9B,0x34,0x1A,0x55,0xAD,0x93,0x32,0x30,0xF5,0x8C,0xB1,0xE3,
    0x1D,0xF6,0xE2,0x2E,0x82,0x66,0xCA,0x60,0xC0,0x29,0x23,0xAB,0x0D,0x53,0x4E,0x6F,
    0xD5,0xDB,0x37,0x45,0xDE,0xFD,0x8E,0x2F,0x03,0xFF,0x6A,0x72,0x6D,0x6C,0x5B,0x51,
    0x8D,0x1B,0xAF,0x92,0xBB,0xDD,0xBC,0x7F,0x11,0xD9,0x5C,0x41,0x1F,0x10,0x5A,0xD8,
    0x0A,0xC1,0x31,0x88,0xA5,0xCD,0x7B,0xBD,0x2D,0x74,0xD0,0x12,0xB8,0xE5,0xB4,0xB0,
    0x89,0x69,0x97,0x4A,0x0C,0x96,0x77,0x7E,0x65,0xB9,0xF1,0x09,0xC5,0x6E,0xC6,0x84,
    0x18,0xF0,0x7D,0xEC,0x3A,0xDC,0x4D,0x20,0x79,0xEE,0x5F,0x3E,0xD7,0xCB,0x39,0x48,
]

FK = [0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC]

CK = [
    0x00070E15,0x1C232A31,0x383F464D,0x545B6269,0x70777E85,0x8C939AA1,0xA8AFB6BD,0xC4CBD2D9,
    0xE0E7EEF5,0xFC030A11,0x181F262D,0x343B4249,0x50575E65,0x6C737A81,0x888F969D,0xA4ABB2B9,
    0xC0C7CED5,0xDCE3EAF1,0xF8FF060D,0x141B2229,0x30373E45,0x4C535A61,0x686F767D,0x848B9299,
    0xA0A7AEB5,0xBCC3CAD1,0xD8DFE6ED,0xF4FB0209,0x10171E25,0x2C333A41,0x484F565D,0x646B7279,
]

MASK = 0xFFFFFFFF


def rol32(x, n):
    """32 位循环左移"""
    x &= MASK
    return ((x << n) & MASK) | (x >> (32 - n))


def tau(x):
    """非线性变换:4 个字节分别过 SBOX"""
    return (
        (SBOX[(x >> 24) & 0xFF] << 24) |
        (SBOX[(x >> 16) & 0xFF] << 16) |
        (SBOX[(x >>  8) & 0xFF] <<  8) |
        SBOX[x & 0xFF]
    )


def L(x):
    """加解密轮函数里的线性变换"""
    return x ^ rol32(x, 2) ^ rol32(x, 10) ^ rol32(x, 18) ^ rol32(x, 24)


def L_key(x):
    """密钥扩展里的线性变换"""
    return x ^ rol32(x, 13) ^ rol32(x, 23)


def T(x):
    """轮函数 T = L(tau(x))"""
    return L(tau(x))


def T_key(x):
    """密钥扩展 T' = L'(tau(x))"""
    return L_key(tau(x))


def bytes_to_words(b):
    """16 字节 -> 4 个大端 32 位整数"""
    return [int.from_bytes(b[i:i+4], "big") for i in range(0, 16, 4)]


def words_to_bytes(words):
    """4 个 32 位整数 -> 16 字节"""
    return b"".join((x & MASK).to_bytes(4, "big") for x in words)


def expand_key(key16):
    """生成 32 个轮密钥"""
    if len(key16) != 16:
        raise ValueError("key 长度必须是 16 字节")

    mk = bytes_to_words(key16)
    K = [0] * 36

    for i in range(4):
        K[i] = mk[i] ^ FK[i]

    rk = []
    for i in range(32):
        K[i + 4] = K[i] ^ T_key(K[i + 1] ^ K[i + 2] ^ K[i + 3] ^ CK[i])
        rk.append(K[i + 4] & MASK)

    return rk


def sm4_block(block16, rk, decrypt=False):
    """SM4 单块处理:输入必须是 16 字节"""
    if len(block16) != 16:
        raise ValueError("单块长度必须是 16 字节")

    X = bytes_to_words(block16) + [0] * 32

    # 解密就是轮密钥倒序
    round_keys = rk[::-1] if decrypt else rk

    for i in range(32):
        X[i + 4] = X[i] ^ T(X[i + 1] ^ X[i + 2] ^ X[i + 3] ^ round_keys[i])

    return words_to_bytes([X[35], X[34], X[33], X[32]])


def sm4_ecb(data, key16, decrypt=False):
    """
    SM4 ECB 模式
    注意:这里不自动补齐,长度必须是 16 的倍数
    """
    if len(data) % 16 != 0:
        raise ValueError("ECB 数据长度必须是 16 的倍数")

    rk = expand_key(key16)
    out = b""

    for i in range(0, len(data), 16):
        out += sm4_block(data[i:i+16], rk, decrypt=decrypt)

    return out


if __name__ == "__main__":
    key = bytes.fromhex("ac46fb610b313b4f32fc642d8834b456")
    ct  = bytes.fromhex("49b351855f211b85bd012f80ce8ed5b3")  # 当前只有 1 块 = 16 字节

    # 解密
    pt = sm4_ecb(ct, key, decrypt=True)
    print("PT =", pt.hex())
    print("PT(raw) =", pt)

    # 回加密校验
    ct_check = sm4_ecb(pt, key, decrypt=False)
    print("RE-ENC MATCH:", ct_check == ct)

RC4

class RC4:
    def __init__(self, key: bytes):
        """
        初始化 RC4 类
        :param key: 密钥,字节类型
        """
        self.key = key
        self.s = list(range(256))  # 初始化 S 数组
        self._ksa()  # 执行密钥调度算法

    def _ksa(self):
        """
        密钥调度算法 (Key Scheduling Algorithm, KSA)
        """
        j = 0
        key_length = len(self.key)
        for i in range(256):
            j = (j + self.s[i] + self.key[i % key_length]) % 256
            self.s[i], self.s[j] = self.s[j], self.s[i]  # 交换 S[i] 和 S[j]

    def _prga(self):
        """
        伪随机数生成算法 (Pseudo-Random Generation Algorithm, PRGA)
        :yield: 生成的伪随机字节
        """
        i = j = 0
        while True:
            i = (i + 1) % 256
            j = (j + self.s[i]) % 256
            self.s[i], self.s[j] = self.s[j], self.s[i]  # 交换 S[i] 和 S[j]
            yield self.s[(self.s[i] + self.s[j]) % 256]

    def encrypt(self, plaintext: bytes) -> bytes:
        """
        加密明文
        :param plaintext: 明文,字节类型
        :return: 密文,字节类型
        """
        keystream = self._prga()
        return bytes([p ^ next(keystream) for p in plaintext])

    def decrypt(self, ciphertext: bytes) -> bytes:
        """
        解密密文
        :param ciphertext: 密文,字节类型
        :return: 明文,字节类型
        """
        # RC4 的加密和解密过程相同
        return self.encrypt(ciphertext)
key = b"s3c4etKey"
plaintext = b"flag{9ec326a6c0ba06d824c52f2ad8602659}"

# 初始化 RC4 类
rc4 = RC4(key)

# 加密
ciphertext = rc4.encrypt(plaintext)
print("Ciphertext:", ciphertext)

# 解密
decrypted = rc4.decrypt(ciphertext)
print("Decrypted:", decrypted)
    

AES_128(AES只写简单的128了,其他的可以在此基础上自己加入)

SBOX = [
    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
]

RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36]


def pkcs7_pad(data: bytes, block_size: int = 16) -> bytes:
    """PKCS#7 补位"""
    pad_len = block_size - (len(data) % block_size)
    return data + bytes([pad_len] * pad_len)


def xor_bytes(a, b):
    return [x ^ y for x, y in zip(a, b)]


def xtime(x: int) -> int:
    """GF(2^8) 上乘 2"""
    return (((x << 1) ^ 0x1B) & 0xFF) if (x & 0x80) else ((x << 1) & 0xFF)


def sub_bytes(state):
    """字节替换"""
    return [SBOX[b] for b in state]


def shift_rows(state):
    """
    行移位
    这里 state 按 AES 标准使用列优先布局:
    state[r + 4*c]
    """
    out = state[:]
    for r in range(4):
        row = [state[r + 4 * c] for c in range(4)]
        row = row[r:] + row[:r]  # 左移 r 位
        for c in range(4):
            out[r + 4 * c] = row[c]
    return out


def mix_columns(state):
    """列混合"""
    out = state[:]
    for c in range(4):
        i = 4 * c
        a0, a1, a2, a3 = state[i:i + 4]
        t = a0 ^ a1 ^ a2 ^ a3
        out[i + 0] = a0 ^ t ^ xtime(a0 ^ a1)
        out[i + 1] = a1 ^ t ^ xtime(a1 ^ a2)
        out[i + 2] = a2 ^ t ^ xtime(a2 ^ a3)
        out[i + 3] = a3 ^ t ^ xtime(a3 ^ a0)
    return [x & 0xFF for x in out]


def add_round_key(state, round_key):
    """轮密钥异或"""
    return [(a ^ b) & 0xFF for a, b in zip(state, round_key)]


def rot_word(word):
    """字循环:abcd -> bcda"""
    return word[1:] + word[:1]


def sub_word(word):
    """对 4 字节字做 SBOX 替换"""
    return [SBOX[b] for b in word]


def key_expansion(key: bytes):
    """
    AES-128 密钥扩展
    输入:16字节 key
    输出:11 轮轮密钥,每轮 16 字节
    """
    if len(key) != 16:
        raise ValueError("AES-128 的 key 必须是 16 字节")

    key_bytes = list(key)
    words = [key_bytes[i:i + 4] for i in range(0, 16, 4)]  # 先拆成4个字

    for i in range(4, 44):
        temp = words[i - 1][:]
        if i % 4 == 0:
            temp = sub_word(rot_word(temp))
            temp[0] ^= RCON[i // 4]
        new_word = [(words[i - 4][j] ^ temp[j]) & 0xFF for j in range(4)]
        words.append(new_word)

    round_keys = []
    for r in range(11):
        rk = []
        for i in range(4):
            rk.extend(words[4 * r + i])
        round_keys.append(rk)

    return round_keys


def aes128_encrypt_block(block: bytes, round_keys):
    """
    AES-128 单块加密
    输入必须是 16 字节
    """
    if len(block) != 16:
        raise ValueError("单块长度必须是 16 字节")

    state = list(block)

    # 初始轮
    state = add_round_key(state, round_keys[0])

    # 中间 9 轮
    for rnd in range(1, 10):
        state = sub_bytes(state)
        state = shift_rows(state)
        state = mix_columns(state)
        state = add_round_key(state, round_keys[rnd])

    # 最后一轮:没有 MixColumns
    state = sub_bytes(state)
    state = shift_rows(state)
    state = add_round_key(state, round_keys[10])

    return bytes(state)


def aes128_ecb_encrypt(data: bytes, key: bytes) -> bytes:
    """
    AES-128 ECB 加密
    自动做 PKCS#7 补位
    """
    round_keys = key_expansion(key)
    data = pkcs7_pad(data, 16)

    out = b""
    for i in range(0, len(data), 16):
        block = data[i:i + 16]
        out += aes128_encrypt_block(block, round_keys)
    return out


if __name__ == "__main__":
    key = b"1234567890abcdef"   # 16字节
    pt  = b"hello aes reverse"

    ct = aes128_ecb_encrypt(pt, key)

    print("key =", key)
    print("pt  =", pt)
    print("ct(hex) =", ct.hex())

其他

Z3和迷宫以及一些爆破脚本没有固定板子,掌握运用方法即可在各类题型中乱杀了

此作者没有提供个人介绍。
最后更新于 2026-03-20