纯Python代码实现XXTEA解密核心算法

 更新时间:2026年06月12日 09:20:56   作者:笑虾  
XXTEA,全称是“eXtended eXtended Tiny Encryption Algorithm”,顾名思义,它是TEA (微型加密算法)家族的第三代成员,下面我们就来看看如何使用Python代码实现XXTEA解密核心算法吧

简介

XXTEA,全称是“eXtended eXtended Tiny Encryption Algorithm”,顾名思义,它是TEA (微型加密算法)家族的第三代成员。它的诞生就是为了解决一个核心矛盾:在资源极其受限的环境下,如何实现一个足够安全、代码量极小、运算速度又快的加密功能。它的设计者,剑桥大学的David Wheeler和Roger Needham,在1998年提出了这个算法,可以看作是TEA和XTEA的“完全体”。它最大的魅力就在于,你用短短一百行左右的C代码,就能实现完整的加密和解密功能,而且这个代码几乎可以不加修改地移植到任何平台上,从8位单片机到最新的服务器CPU,都能流畅运行。

纯 Python 实现的 XXTEA 解密核心算法

import os
import sys
import struct
# 配置游戏对应的密钥和签名
KEY  = b"你的秘钥"
SIGN = b"4meJnPyl"
SIGN_LEN = len(SIGN)
def _long2str(v, w):
    n = (len(v) - 1) << 2
    if w:
        m = v[-1]
        if (m < n - 3) or (m > n): return None
        n = m
    s = struct.pack('<%dL' % len(v), *v)
    return s[0:n] if w else s
def _str2long(s, w):
    n = len(s)
    m = (4 - (n & 3)) & 3
    s += b'\0' * m
    v = list(struct.unpack('<%dL' % (len(s) >> 2), s))
    if w: v.append(n)
    return v
def xxtea_decrypt(data, key):
    """纯 Python 实现的 XXTEA 解密核心算法"""
    if not data: return data
    v = _str2long(data, False)
    k = _str2long(key.ljust(16, b'\0')[:16], False)
    n = len(v) - 1
    z = v[n]
    y = v[0]
    delta = 0x9E3779B9
    q = 6 + 52 // (n + 1)
    sum_val = (q * delta) & 0xFFFFFFFF
    while sum_val != 0:
        e = (sum_val >> 2) & 3
        for p in range(n, 0, -1):
            z = v[p - 1]
            v[p] = (v[p] - (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum_val ^ y) + (k[p & 3 ^ e] ^ z)))) & 0xFFFFFFFF
            y = v[p]
        z = v[n]
        v[0] = (v[0] - (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum_val ^ y) + (k[0 & 3 ^ e] ^ z)))) & 0xFFFFFFFF
        y = v[0]
        sum_val = (sum_val - delta) & 0xFFFFFFFF
    return _long2str(v, True)
def decrypt_file(file_path):
    if not os.path.exists(file_path):
        print(f"[错误] 文件不存在: {file_path}")
        return
    print(f"[处理] 正在读取文件: {file_path}")
    try:
        with open(file_path, 'rb') as f:
            encrypted_data = f.read()
        # 检测并自动剔除文件头的签名
        if encrypted_data.startswith(SIGN):
            print(f"[检测] 发现文件头签名 '{SIGN.decode()}',已自动裁剪前 {SIGN_LEN} 字节。")
            encrypted_data = encrypted_data[SIGN_LEN:]
        else:
            print("[提示] 未发现已知文件头签名,尝试直接整包解密。")
        # 执行纯 Python 版 XXTEA 解密
        decrypted_data = xxtea_decrypt(encrypted_data, KEY)
        if not decrypted_data:
            print("[失败] 解密结果为空(可能 Key 错误,或该文件并非 XXTEA 加密)。")
            return
        # 生成输出文件(保持原后缀方便直接预览)
        dir_name, file_name = os.path.split(file_path)
        base_name, ext = os.path.splitext(file_name)
        output_name = f"{base_name}_decrypted{ext}" if ext else f"{base_name}_decrypted"
        output_path = os.path.join(dir_name, output_name)
        with open(output_path, 'wb') as f:
            f.write(decrypted_data)
        print(f"[成功] 解密完成!已生成文件: {output_path}")
    except Exception as e:
        print(f"[报错] 解密过程中出现异常: {e}")
if __name__ == "__main__":
    if len(sys.argv) > 1:
        for path in sys.argv[1:]:
            decrypt_file(path)
    else:
        print("提示: 你可以直接把文件拖到此工具上运行。")
        path = input("或者请输入要解密的文件路径: ").strip('"')
        if path:
            decrypt_file(path)
    input("\n处理完毕,按下回车键退出...")

知识扩展

XXTEA(eXtended eXtended TEA)是 TEA 分组密码家族的一个成员,由 David Wheeler 和 Roger Needham 于 1998 年提出。它修正了之前 XTEA 算法的缺陷,支持任意长度的数据块(不限于 64 位),并保持了简单的 Feistel 结构。

算法核心特点

  • 分组长度:不固定,可以是任意 32 位字(32-bit word)的整数倍(即 4 字节的倍数)。
  • 密钥长度:128 位(16 字节),固定转换为 4 个 32 位整数。
  • 轮数:取决于数据长度,计算公式为 6 + 52 / n,其中 n 是 32 位字的个数。
  • 运算:仅使用加法、减法、异或、移位等基本整数运算,非常适合嵌入式环境。
  • 填充:当原始数据不是 4 字节倍数时,需要进行填充(通常使用 PKCS#7)。

方法一:

以下是纯 Python 实现的 XXTEA 解密核心算法,包含必要的辅助函数,不依赖任何第三方库。

import struct
def _bytes_to_uint32(data: bytes) -> list:
    """将字节串转换为 32 位无符号整数列表(小端序)"""
    n = len(data)
    # 补齐到 4 的倍数
    if n % 4 != 0:
        data += b'\x00' * (4 - n % 4)
    return list(struct.unpack('<{}I'.format(len(data)//4), data))
def _uint32_to_bytes(arr: list) -> bytes:
    """将 32 位无符号整数列表转换为字节串(小端序)"""
    return struct.pack('<{}I'.format(len(arr)), *arr)
def _mx(z, y, sum_val, p, e, k):
    """XXTEA 轮函数中的辅助计算"""
    return (((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((sum_val ^ y) + (k[(p & 3) ^ e] ^ z))
def xxtea_decrypt(data: bytes, key: bytes) -> bytes:
    """
    XXTEA 解密核心算法
    :param data: 密文字节串(长度应为 4 的倍数)
    :param key: 密钥字节串(长度任意,内部将扩展/截断为 16 字节)
    :return: 解密后的明文字节串(自动去除填充)
    """
    if len(data) < 8:
        raise ValueError("密文长度过短(至少需要 8 字节)")
    # 将密钥转换为 4 个 32 位整数(小端序)
    key_bytes = key.ljust(16, b'\x00')[:16]   # 补齐或截断到 16 字节
    k = _bytes_to_uint32(key_bytes)           # k[0..3]
    # 将密文转换为 32 位整数数组
    v = _bytes_to_uint32(data)
    n = len(v)
    if n < 2:
        raise ValueError("密文至少需要 2 个 32 位字")
    # 解密常数
    DELTA = 0x9E3779B9
    rounds = 6 + 52 // n   # 轮数(标准实现)
    sum_val = (rounds * DELTA) & 0xFFFFFFFF
    y = v[0]
    # 主解密循环
    while rounds > 0:
        e = (sum_val >> 2) & 3
        for p in range(n-1, -1, -1):
            z = v[p-1] if p > 0 else v[-1]
            mx_val = _mx(z, y, sum_val, p, e, k)
            v[p] = (v[p] - mx_val) & 0xFFFFFFFF
            y = v[p]
        sum_val = (sum_val - DELTA) & 0xFFFFFFFF
        rounds -= 1
    # 将整数数组转换回字节
    plain_bytes = _uint32_to_bytes(v)
    # 去除 PKCS#7 风格填充(解密后末尾的填充字节)
    pad_len = plain_bytes[-1]
    if pad_len <= len(plain_bytes):
        return plain_bytes[:-pad_len]
    else:
        # 填充格式不正确时返回原始解密结果
        return plain_bytes
# ========== 使用示例 ==========
if __name__ == "__main__":
    # 测试数据(可以用已知的加密结果验证)
    key = b'my_secret_key_16'   # 密钥(16字节,不足会自动补零)
    plaintext = b"Hello, XXTEA!"
    print("原始明文:", plaintext)
    # 这里假设你已经有了加密函数,或者使用一个已知的密文进行解密测试
    # 为演示,我们手动构造一个简单的加密后再解密的例子(需先实现加密)
    # 实际使用中,你只需要调用 xxtea_decrypt 即可。
    # 为了完整性,提供一个简单的加密函数(纯Python,便于测试)
    def xxtea_encrypt(plain: bytes, key: bytes) -> bytes:
        if len(plain) == 0:
            return b''
        # PKCS#7 填充
        pad_len = 4 - (len(plain) % 4)
        if pad_len == 4:
            pad_len = 0
        if pad_len:
            plain += bytes([pad_len]) * pad_len
        v = _bytes_to_uint32(plain)
        n = len(v)
        k = _bytes_to_uint32(key.ljust(16, b'\x00')[:16])
        DELTA = 0x9E3779B9
        rounds = 6 + 52 // n
        sum_val = 0
        y = v[0]
        for _ in range(rounds):
            e = (sum_val >> 2) & 3
            for p in range(n):
                z = v[p-1] if p > 0 else v[-1]
                mx_val = _mx(z, y, sum_val, p, e, k)
                v[p] = (v[p] + mx_val) & 0xFFFFFFFF
                y = v[p]
            sum_val = (sum_val + DELTA) & 0xFFFFFFFF
        return _uint32_to_bytes(v)
    # 加密 -> 解密测试
    cipher = xxtea_encrypt(plaintext, key)
    print("加密后密文:", cipher)
    decrypted = xxtea_decrypt(cipher, key)
    print("解密后明文:", decrypted)
    assert decrypted == plaintext, "加解密不匹配"

核心要点说明

数据格式:XXTEA 操作的基本单元是 32 位无符号整数(4 字节)。本实现使用小端序字节与整数之间的转换。

密钥处理:密钥被转换为 4 个 32 位整数,不足 16 字节时补 0x00,超过则截断。

轮数计算:轮数 rounds = 6 + 52 / n,其中 n 是整数数组的长度(即 32 位字的个数)。

解密过程

  • 初始化 sum_val = rounds * DELTA
  • 逆向循环,每次减少 DELTA,内部按 n-1 到 0 的顺序更新每个整数。
  • 使用 _mx 辅助函数计算差值并减去。

填充处理:解密后末尾的字节表示填充长度(PKCS#7 风格),据此去除填充字节。

该实现完全自包含,可独立运行,适用于任何支持 Python 3 的环境。

方法二:

下面的实现完全基于纯 Python,不依赖任何第三方库,包含:

  • 字节与 32 位整数数组的相互转换(小端序)
  • 加密函数(带 PKCS#7 填充)
  • 解密函数(自动去填充)
  • 核心轮函数 _mx
import struct
# ---------- 辅助函数:字节 ↔ 32位整数数组 ----------
def _bytes_to_uint32(data: bytes) -> list:
    """字节串 -> 小端序 32 位无符号整数列表,长度自动补齐到 4 的倍数"""
    n = len(data)
    if n % 4 != 0:
        data += b'\x00' * (4 - n % 4)
    return list(struct.unpack(f'<{len(data)//4}I', data))
def _uint32_to_bytes(arr: list) -> bytes:
    """小端序 32 位整数列表 -> 字节串"""
    return struct.pack(f'<{len(arr)}I', *arr)
# ---------- XXTEA 加密 ----------
def xxtea_encrypt(plain: bytes, key: bytes) -> bytes:
    """
    加密任意字节串,返回密文字节串(自动添加 PKCS#7 填充)
    key: 任意长度的密钥,内部将截断或补零至 16 字节
    """
    if len(plain) == 0:
        return b''
    # PKCS#7 填充:补足到 4 字节整数倍
    pad_len = 4 - (len(plain) % 4)
    if pad_len == 4:
        pad_len = 0
    if pad_len:
        plain += bytes([pad_len]) * pad_len
    # 将密钥转换为 4 个 32 位整数
    key_bytes = key.ljust(16, b'\x00')[:16]
    k = _bytes_to_uint32(key_bytes)
    # 将明文转换为 32 位整数数组
    v = _bytes_to_uint32(plain)
    n = len(v)
    if n < 2:
        # 长度至少为 2 个字(8 字节)
        v += [0] * (2 - n)
        n = 2
    DELTA = 0x9E3779B9
    rounds = 6 + 52 // n
    sum_val = 0
    y = v[0]
    for _ in range(rounds):
        e = (sum_val >> 2) & 3
        for p in range(n):
            z = v[p-1] if p > 0 else v[-1]
            # 轮函数
            mx = (((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((sum_val ^ y) + (k[(p & 3) ^ e] ^ z))
            v[p] = (v[p] + mx) & 0xFFFFFFFF
            y = v[p]
        sum_val = (sum_val + DELTA) & 0xFFFFFFFF
    return _uint32_to_bytes(v)
# ---------- XXTEA 解密 ----------
def xxtea_decrypt(cipher: bytes, key: bytes) -> bytes:
    """
    解密密文字节串,自动去除 PKCS#7 填充
    """
    if len(cipher) == 0:
        return b''
    if len(cipher) % 4 != 0:
        raise ValueError("密文长度必须是 4 的倍数")
    # 密钥转换
    key_bytes = key.ljust(16, b'\x00')[:16]
    k = _bytes_to_uint32(key_bytes)
    # 将密文转换为 32 位整数数组
    v = _bytes_to_uint32(cipher)
    n = len(v)
    if n < 2:
        raise ValueError("密文至少需要 8 字节")
    DELTA = 0x9E3779B9
    rounds = 6 + 52 // n
    sum_val = (rounds * DELTA) & 0xFFFFFFFF
    y = v[0]
    # 解密主循环
    for _ in range(rounds):
        e = (sum_val >> 2) & 3
        for p in range(n-1, -1, -1):
            z = v[p-1] if p > 0 else v[-1]
            mx = (((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((sum_val ^ y) + (k[(p & 3) ^ e] ^ z))
            v[p] = (v[p] - mx) & 0xFFFFFFFF
            y = v[p]
        sum_val = (sum_val - DELTA) & 0xFFFFFFFF
    # 转换回字节并去除 PKCS#7 填充
    plain_bytes = _uint32_to_bytes(v)
    pad_len = plain_bytes[-1]
    if pad_len <= len(plain_bytes):
        return plain_bytes[:-pad_len]
    else:
        # 填充格式错误,返回原始解密结果
        return plain_bytes
# ---------- 测试示例 ----------
if __name__ == "__main__":
    key = b'my_secret_key_16'      # 16 字节密钥
    plain = b"Hello, XXTEA! This is a test."
    print("原  文:", plain)
    cipher = xxtea_encrypt(plain, key)
    print("密  文:", cipher)
    decrypted = xxtea_decrypt(cipher, key)
    print("解密后:", decrypted)
    assert decrypted == plain, "加解密不一致"

使用注意事项

  • 密钥长度:建议使用 16 字节(128 位),安全性最高。
  • 数据长度:XXTEA 算法本身可以处理任意长度的数据,但内部要求加密前数据长度为 4 的倍数(通过填充实现)。
  • 端序:上述实现采用小端序,与大多数 XXTEA 标准实现一致(如 QQ、微信等常用的小端序版本)。如果需要与特定系统对接,请确认端序是否匹配。
  • 安全性:XXTEA 在 2010 年后被认为存在一些理论的攻击,但对于非极敏感数据仍然足够。现代应用更推荐使用 AES。

到此这篇关于纯Python代码实现XXTEA解密核心算法的文章就介绍到这了,更多相关Python XXTEA解密算法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于Python打造一个高效开发辅助全能工具箱

    基于Python打造一个高效开发辅助全能工具箱

    在日常开发过程中,我们经常需要进行各种琐碎但又必不可少的操作,本文介绍一款基于 Python 编写的 全能工具箱,它涵盖了开发过程中常用的功能,希望对大家有所帮助
    2025-03-03
  • 基于python爬取梨视频实现过程解析

    基于python爬取梨视频实现过程解析

    这篇文章主要介绍了基于python爬取梨视频实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • Django零基础入门之调用漂亮的HTML前端页面

    Django零基础入门之调用漂亮的HTML前端页面

    这篇文章主要介绍了Django零基础入门之调用漂亮的HTML前端页面的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • Pycharm使用Gitee解读

    Pycharm使用Gitee解读

    这篇文章主要介绍了Pycharm使用Gitee解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • python中文编码与json中文输出问题详解

    python中文编码与json中文输出问题详解

    Python的编码问题还是很让人头疼的,做下笔记帮助别人,也帮助自己,下面这篇文章主要给大家介绍了关于python中文编码与json中文输出问题的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2018-08-08
  • 如何Tkinter模块编写Python图形界面

    如何Tkinter模块编写Python图形界面

    本文讲解为何使用Tkinter而非PyQt,创建一个基本的Tkinter程序,模块化Tkinter程序,希望对大家有帮助。
    2020-10-10
  • 利用Python内置库实现创建命令行应用程序

    利用Python内置库实现创建命令行应用程序

    Python 有一个叫做argparse的内置库,可以用它来创建一个命令行界面。本文将详解如何利用argparse实现创建一个命令行应用程序,需要的可以参考一下
    2022-06-06
  • python高阶函数使用教程示例

    python高阶函数使用教程示例

    这篇文章主要为大家介绍了python高阶函数使用教程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • Python3.5 win10环境下导入kera/tensorflow报错的解决方法

    Python3.5 win10环境下导入kera/tensorflow报错的解决方法

    这篇文章主要介绍了Python3.5 win10环境下导入keras/tensorflow报错的解决方法,较为详细的分析了Python3.5在win10环境下导入keras/tensorflow提示错误的原因与相关解决方法,需要的朋友可以参考下
    2019-12-12
  • 解决win10 vscode 无法激活python 虚拟环境的问题

    解决win10 vscode 无法激活python 虚拟环境的问题

    这篇文章主要介绍了win10 vscode 无法激活python 虚拟环境的解决办法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-10-10

最新评论