CTF-RE 从0到N: TEA

TEA

TEA(Tiny Encryption Algorithm,轻量加密算法) 是一种简单、快速的对称加密算法。它是一个分组加密算法,通常用于加密 64 位的数据块,并使用 128 位的密钥。TEA 是一种"费斯妥结构"(Feistel structure)算法,具有 64 轮的加密过程,设计目标是简洁和高效。

TEA 加密算法原理

  1. 分组加密 :TEA 将明文分成 64 位(8 字节)块,每个块分为两个 32 位部分(v0v1)。
  2. 密钥结构 :TEA 使用 128 位密钥,分成 4 个 32 位的部分(k[0], k[1], k[2], k[3])。
  3. 加密轮数:TEA 通常运行 64 轮的加密(或者在某些实现中,使用 32 轮)。
  4. 加密过程 :通过对两个 32 位部分(v0v1)的混合和异或操作来增加密文的复杂性。

TEA 通过多轮迭代,利用简单的移位、加法和异或运算来实现数据加密。

标准 TEA 加密的 C 代码

以下是 TEA 的标准加密实现,使用 C 语言编写:

c 复制代码
// TEA 加密函数
void tea_encrypt(uint32_t v[2], const uint32_t k[4]) {
    // 初始化v0和v1为输入数据的两个32位块
    uint32_t v0 = v[0], v1 = v[1], sum = 0;
    
    // 常量delta,用于累加器的固定值
    uint32_t delta = 0x9E3779B9;

    // 进行32轮加密操作
    for (uint32_t i = 0; i < 32; i++) {
        // 累加器,sum每轮累加delta值
        sum += delta;

        // 对v0进行加密操作,涉及左移、右移、XOR和密钥k[0]和k[1]
        v0 += ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);

        // 对v1进行加密操作,类似v0,涉及k[2]和k[3]
        v1 += ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);
    }

    // 将加密后的v0和v1保存回输入数组
    v[0] = v0;
    v[1] = v1;
}

// TEA 解密函数
void tea_decrypt(uint32_t v[2], const uint32_t k[4]) {
    // 初始化v0和v1为输入数据的两个32位块
    uint32_t v0 = v[0], v1 = v[1];

    // 初始化累加器sum为最大值,用于解密过程
    uint32_t sum = 0xC6EF3720;

    // 常量delta,用于累加器的固定值
    uint32_t delta = 0x9E3779B9;

    // 进行32轮解密操作
    for (uint32_t i = 0; i < 32; i++) {
        // 对v1进行解密操作,与加密过程相反
        v1 -= ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);

        // 对v0进行解密操作,与加密过程相反
        v0 -= ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);

        // 累加器减少delta值
        sum -= delta;
    }

    // 将解密后的v0和v1保存回输入数组
    v[0] = v0;
    v[1] = v1;
}

代码解析

  1. 输入参数:

    • v 是一个包含两个 32 位整数的数组,代表 64 位数据块的两个部分(v0v1)。
    • k 是一个包含四个 32 位整数的数组,代表 128 位密钥的四个部分(k[0]k[3])。
  2. Delta 常量:

    • delta = 0x9E3779B9,它是黄金分割比的一个近似值,用于混合密钥和数据块。
  3. 加密过程:

    • 初始时,sum 置为 0。sum 是一个累加器,每轮加密时增加 delta,以确保每轮混合不同的密钥部分。
    • 每轮加密时,v0v1 通过移位、加法和异或操作相互混合,并与密钥的不同部分组合。
  4. 解密过程:

    • 初始时,sum 被设定为 32 轮加密时的最终值(即 0xC6EF3720)。
    • 解密过程是加密过程的逆过程,逐步减去 delta,并通过相同的移位和异或操作还原原始的明文。

特征

1. 双32位分组操作

TEA 处理的是 64 位数据块(分为两个 32 位整数 v0v1)。因此在伪代码中,你可能会看到两个主要变量,通常是 32 位整数,分别对应于 TEA 加密中的 v0v1

伪代码中的特征可能类似如下:

c 复制代码
v0 = data[0];
v1 = data[1];

2. 四个32位密钥

TEA 使用 128 位密钥,分成四个 32 位的部分 k[0], k[1], k[2], k[3]。如果在伪代码中看到四个整数数组元素反复用于加密过程,则很可能是 TEA 的密钥部分。

c 复制代码
uint32_t k[4] = { key1, key2, key3, key4 };

3. 多轮循环(典型为32轮或64轮)

TEA 的加密过程通常有 32 或 64 轮,每轮使用固定的 delta 值累加到 sum 变量中,通常循环结构会类似于如下形式:

c 复制代码
sum = 0;
for (i = 0; i < 32; i++) {  // 32轮循环
    sum += delta;
    v0 += 复杂的表达式;
    v1 += 复杂的表达式;
}

其中 delta 是常量 0x9E3779B9,在伪代码中可以直接看到这个值:

c 复制代码
delta = 0x9E3779B9;

4. 移位和异或操作

TEA 的核心是对 v0v1 进行移位、加法和异或操作。通过反编译的伪代码中,应该可以看到 <<, >>, ^, + 等符号交替出现:

c 复制代码
v0 += ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);
v1 += ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);

这里可以看出明显的移位和异或操作是 TEA 算法的一个标志性特征。

5. Delta 值和累加的 sum 变量

TEA 算法中使用的 delta 值为 0x9E3779B9,如果在伪代码中发现这个常量,并且被用来在每轮加密中累加到 sum 变量里,这也是 TEA 算法的一个强特征:

c 复制代码
sum += delta;

解密过程的 sum 初始化为 0xC6EF3720(即 0x9E3779B9 * 32),然后在每轮中减少 delta 值,这也是解密过程的一个特征。

6. 相同的加密和解密逻辑

由于 TEA 是对称加密算法,解密过程和加密过程非常相似,只是 sum 的初始化和循环方向不同。如果在逆向过程中发现类似的加密和解密逻辑,特别是基于 sum 的加减操作,这通常是 TEA 解密的迹象。

xTEA

XTEA(Extended Tiny Encryption Algorithm)是 TEA 的改进版本,设计用于克服 TEA 的一些已知安全性问题。它保持了 TEA 的简单性和高效性,但引入了一些增强的特性以提高其安全性。XTEA 是一种基于分组加密的对称加密算法,使用 128 位密钥加密 64 位的数据块。它通过多轮加密将密钥与数据进行复杂混合,通常进行 64 轮操作。XTEA 的核心操作包括移位(<<>>)、加法、异或和常数 delta 的使用。

XTEA 加密的主要特点

  1. 输入:64 位数据(通常拆分为两个 32 位块)和 128 位密钥(4 个 32 位整数)。
  2. 轮数:XTEA 进行 64 轮加密(比 TEA 的 32 轮更安全)。
  3. 核心操作 :移位、加法、异或运算通过密钥和常数 delta 的混合执行。
  4. delta 常量 :XTEA 使用的 delta 是一个固定常数,取值为 0x9E3779B9(源于黄金分割数)。

XTEA 加密的 C 代码

XTEA 将 64 位的数据块分为两个 32 位部分 v0v1,并依次使用 128 位密钥的四个部分 k[0], k[1], k[2], k[3]。加密过程如下:

c 复制代码
// XTEA 加密函数
void xtea_encrypt(uint32_t v[2], const uint32_t k[4]) {
    // 初始化 v0 和 v1 为输入的两个 32 位数据块
    uint32_t v0 = v[0], v1 = v[1], sum = 0;
    
    // 常量 delta,用于控制加密过程中的变化
    uint32_t delta = 0x9E3779B9;

    // XTEA 的加密循环执行 32 轮
    for (uint32_t i = 0; i < 32; i++) {
        // 对 v0 进行加密操作,使用 v1 和密钥进行复杂变换
        // 这里使用左移、右移、XOR 运算,以及累加器 sum 和密钥 k 的部分值(k[sum & 3])
        v0 += ((v1 << 4) ^ (v1 >> 5)) + v1 ^ (sum + k[sum & 3]);

        // 累加器 sum 增加 delta 值,每轮都累加,确保变化
        sum += delta;

        // 对 v1 进行加密操作,使用 v0 和密钥进行变换
        // 同样使用左移、右移、XOR 运算,并使用 sum 的另一部分值 (k[(sum >> 11) & 3])
        v1 += ((v0 << 4) ^ (v0 >> 5)) + v0 ^ (sum + k[(sum >> 11) & 3]);
    }

    // 将加密后的结果保存回原始数组中
    v[0] = v0;
    v[1] = v1;
}

// XTEA 解密函数
void xtea_decrypt(uint32_t v[2], const uint32_t k[4]) {
    // 初始化 v0 和 v1 为输入的两个 32 位数据块
    uint32_t v0 = v[0], v1 = v[1];

    // 初始化累加器 sum 为最大值,用于解密过程
    uint32_t sum = 0xC6EF3720;

    // 常量 delta,用于控制解密过程中的变化
    uint32_t delta = 0x9E3779B9;

    // XTEA 的解密循环执行 32 轮,与加密过程相反
    for (uint32_t i = 0; i < 32; i++) {
        // 对 v1 进行解密操作,使用与加密相反的公式
        v1 -= ((v0 << 4) ^ (v0 >> 5)) + v0 ^ (sum + k[(sum >> 11) & 3]);

        // 累加器 sum 减少 delta 值,与加密过程相反
        sum -= delta;

        // 对 v0 进行解密操作,使用与加密相反的公式
        v0 -= ((v1 << 4) ^ (v1 >> 5)) + v1 ^ (sum + k[sum & 3]);
    }

    // 将解密后的结果保存回原始数组中
    v[0] = v0;
    v[1] = v1;
}

解释

  1. 输入参数

    • v[2]:是一个包含两个 32 位整数的数组,表示待加密的 64 位数据块。
    • k[4]:是一个包含四个 32 位整数的数组,表示 128 位的密钥。
  2. 初始状态

    • v0v1 分别代表 64 位数据块的前 32 位和后 32 位。
    • sum 是一个累加变量,初始化为 0。
    • delta 是一个固定的常数 0x9E3779B9
  3. 加密过程

    • XTEA 的加密循环执行 32 次,每次循环包括两轮加密操作。
    • 在每轮中,v0v1 被混合,通过移位、异或和加法操作与密钥部分结合。
    • sum 在每轮中累加 delta,并用作密钥索引。
  4. 轮次操作

    • v0 更新:使用 v1 的左移、右移与当前 sum 和密钥的异或操作进行更新。
    • v1 更新:使用 v0 的左移、右移与更新后的 sum 和密钥的异或操作进行更新。
    • 这种操作重复 32 次,相当于 64 轮加密。
  5. 最终结果

    • 加密完成后,v0v1 的更新值存储回 v[0]v[1] 中,得到加密后的数据。

xxTEA

xxTEA 加密算法简介

XXTEA 是 TEA 和 XTEA 的改进版本,旨在解决 TEA 和 XTEA 中的弱点。XXTEA 是一种分组加密算法,但与 TEA 和 XTEA 不同的是,它能够加密长度为任意多个字节的数据,而不仅仅是固定长度的数据块。

XXTEA 通过将数据分割成多个 32 位的块,然后对这些块进行多轮的混淆和加密。它的核心思路是采用了一种特殊的非线性变换,防止简单的模式出现。

xxTEA 加密的 C 代码

c 复制代码
// 定义常量 DELTA,用于加密和解密操作中的累加器增量
#define DELTA 0x9E3779B9

// XXTEA 加密函数
void xxtea_encrypt(uint32_t *v, int n, const uint32_t k[4]) {
    // 如果数组大小 n 小于 2,不进行加密,直接返回
    if (n < 2) return;

    // 初始化 z 和 y,z 为数组最后一个元素,y 为第一个元素
    uint32_t z = v[n - 1], y = v[0], sum = 0;

    // 计算加密轮数,XXTEA 的轮数依赖于数据块的个数 n
    uint32_t rounds = 6 + 52 / n;

    // 外层循环执行轮数次
    for (uint32_t i = 0; i < rounds; i++) {
        // 累加器 sum 增加 DELTA,每轮都递增
        sum += DELTA;

        // 计算 e,用于密钥选择
        uint32_t e = (sum >> 2) & 3;

        // 内层循环处理 n-1 个数据块
        for (uint32_t p = 0; p < n - 1; p++) {
            y = v[p + 1];  // 下一个块的值
            // 更新当前块的值,使用 z 和 y 进行加密操作,结合移位、异或和密钥
            v[p] += ((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4)) ^ (sum ^ y) + (k[(p & 3) ^ e] ^ z);
            z = v[p];  // 更新 z 为当前块
        }

        // 最后一个数据块的加密操作
        y = v[0];  // 第一个块的值
        v[n - 1] += ((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4)) ^ (sum ^ y) + (k[((n - 1) & 3) ^ e] ^ z);
        z = v[n - 1];  // 更新 z 为最后一个块
    }
}

// XXTEA 解密函数
void xxtea_decrypt(uint32_t *v, int n, const uint32_t k[4]) {
    // 如果数组大小 n 小于 2,不进行解密,直接返回
    if (n < 2) return;

    // 初始化 z 和 y,z 为数组最后一个元素,y 为第一个元素
    uint32_t z = v[n - 1], y = v[0];

    // 初始化累加器 sum,为加密的总和,解密时从最大值开始递减
    uint32_t sum = DELTA * (6 + 52 / n);

    // 外层循环执行轮数次,与加密时的轮数相同
    for (uint32_t i = 0; i < 6 + 52 / n; i++) {
        // 计算 e,用于密钥选择
        uint32_t e = (sum >> 2) & 3;

        // 内层循环处理 n-1 个数据块,从数组末尾往前遍历
        for (uint32_t p = n - 1; p > 0; p--) {
            z = v[p - 1];  // 前一个块的值
            // 更新当前块的值,使用 z 和 y 进行解密操作,结合移位、异或和密钥
            v[p] -= ((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4)) ^ (sum ^ y) + (k[(p & 3) ^ e] ^ z);
            y = v[p];  // 更新 y 为当前块
        }

        // 第一个数据块的解密操作
        z = v[n - 1];  // 最后一个块的值
        v[0] -= ((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4)) ^ (sum ^ y) + (k[(0 & 3) ^ e] ^ z);
        y = v[0];  // 更新 y 为第一个块

        // 累加器 sum 减少 DELTA 值,与加密时相反
        sum -= DELTA;
    }
}

代码说明

  • 函数参数

    • v 是要加密/解密的数据块,类型为 uint32_t*,表示数据的多个 32 位块。
    • n 是数据块的个数,即数据中包含的 32 位块的数量。
    • k[4] 是 128 位的密钥,分成四个 32 位的无符号整数。
  • 加密过程

    • XXTEA 会对长度为 nv 数组进行多轮加密,轮数由 6 + 52 / n 决定(这确保对不同长度的数据,轮数适当调整)。
    • 在每一轮中,XXTEA 对每个数据块进行复杂的非线性混合,并结合密钥 k 来加密。
  • 解密过程

    • 解密的过程和加密的过程基本对称。唯一不同的是解密时从最大 sum 开始递减,并通过与加密时相反的操作还原数据。

特征总结

特征 TEA XTEA XXTEA
数据块大小 固定 64 位(2 x 32 位) 固定 64 位(2 x 32 位) 任意长度的数据块(n 个 32 位块)
轮数 固定 32 轮 固定 32 轮(每轮两步,64 步) 动态轮数(6 + 52 / n
变换复杂度 简单的移位和 XOR 操作 相对复杂的 XORsum 操作 更复杂的移位、XOR、索引操作
累加器 固定累加 sumdelta sum 逐步增加,两次累加 动态累加 sum,并引入动态索引 e
加密逻辑 操作两个 32 位块 双重变换操作(左右两次) 动态遍历每个数据块进行加密

练习!

BUUCTF在线评测

相关推荐
云梦姐姐7 小时前
第四届“网鼎杯”网络安全大赛 - 青龙组
ctf·wp
A5rZ1 天前
ctf-pwn: 数组越界
pwn·ctf
风飘红技术中心3 天前
2024-网鼎杯第二次模拟练习-web02
sql·web·ctf·sql注入·网鼎杯
Gnevergiveup4 天前
NewStar CTF 2024 Week1,Week2部分
web安全·网络安全·ctf·misc
A5rZ5 天前
CTF-RE 从0到N: 理解base64算法
ctf·ctf-re
孪生质数-6 天前
记录:网鼎杯2024赛前热身CRYPT02密码学
网络安全·密码学·ctf·网鼎杯
雪痕春风天音九重色7 天前
Re:从零开始的pwn学习(栈溢出篇)
pwn·ctf·栈溢出
石氏是时试9 天前
[NewStar 2024] week3
ctf
梦 & 醒9 天前
SHCTF-2024-week2-wp(web)
web安全·网络安全·ctf