You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XXTEA解密故障:Python实现无法解密12字节数据包求助

Python XXTEA解密失效的排查方案

XXTEA跨语言实现最容易栽在字节序、数据填充、密钥处理这几个细节上,结合你的场景(12字节数据包、解密后格式000\12345678),按以下步骤排查:

1. 字节序必须和Java对齐

Java默认使用**大端(Big-Endian)**处理32位整数,而很多Python XXTEA库或自定义实现默认用小端(Little-Endian),这是头号坑:

  • 检查Python代码中字节与32位整数互转的逻辑:用struct.unpack('!I', ...)和struct.pack('!I', ...)指定大端,对应Java的ByteBuffer默认行为。
  • 比如Java中ByteBuffer.wrap(cipherBytes).getInt()是大端读取,Python要完全匹配这个逻辑。

2. 数据块与填充规则匹配

你的数据包是12字节(3个32位整数块),解密后有效内容是000\12345678(长度10字节左右):

  • 确认Java加密时是否对原始明文做了填充(比如补\x00到12字节),Python解密后需要手动移除填充字节,比如用plain_bytes.rstrip(b'\x00')截断到有效长度。
  • 如果Java用了自定义填充(比如补特定字符),Python必须执行完全相同的反向操作。

3. 密钥处理完全一致

XXTEA标准密钥是16字节(4个32位整数),两边处理逻辑要丝毫不差:

  • 检查Java是否将密钥字符串按UTF-8转字节数组,再转成4个大端32位整数;Python要做同样的编码转换,不足16字节的话补\x00对齐。
  • 比如Java代码:byte[] keyBytes = "your-key".getBytes(StandardCharsets.UTF_8);,Python对应key_bytes = b"your-key".ljust(16, b'\x00')。

4. 核心算法逻辑对比

把Java和Python的XXTEA核心循环逐行对比,重点看:

  • 轮数是否为32轮,delta值是否为0x9E3779B9;
  • 解密时的循环顺序是否和Java反向(加密是正向轮,解密是逆向轮);
  • 异或、加法的操作顺序是否一致,避免出现运算优先级或变量顺序错误。

快速验证方法

用同一明文(比如b"000\\12345678")和密钥,先跑Java加密得到密文,再用Python解密这个密文:

  • 如果能解密成功,说明你的Python代码处理现有数据包时可能存在数据读取问题(比如12字节数据包截取错误);
  • 如果解密失败,直接对比两边的中间值(比如密文转成的整数数组、每轮解密后的数组),定位差异点。

对齐Java的Python XXTEA解密示例

import struct

DELTA = 0x9E3779B9

def xxtea_decrypt(cipher_bytes, key_bytes):
    # 密钥处理:转4个大端32位整数,不足16字节补0
    key = struct.unpack('!4I', key_bytes.ljust(16, b'\x00'))
    # 12字节密文转3个大端32位整数
    if len(cipher_bytes) != 12:
        raise ValueError("Invalid packet length (must be 12 bytes)")
    cipher = list(struct.unpack('!3I', cipher_bytes))
    
    n = len(cipher)
    sum_val = DELTA * n
    y = cipher[0]
    z = cipher[-1]
    q = 6 + 52 // n
    
    while q > 0:
        sum_val -= DELTA
        y_idx = (n - 1) & (0xFF & (z >> 2))
        y = cipher[y_idx] ^ (sum_val + z)
        z_idx = (n - 1) & (0xFF & (y >> 2))
        z = cipher[z_idx] ^ (sum_val + y)
        q -= 1
    
    # 转大端字节串,移除填充
    plain_bytes = struct.pack('!3I', *cipher)
    # 按已知格式截断到有效长度(假设明文是10字节)
    return plain_bytes[:10].decode('utf-8')

内容的提问来源于stack exchange,提问作者Christophe Marteil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 02:12:01