# -*- coding: utf-8 -*- """用真机 collect 密文的**长度与填充**判决「四段加密」结构。 不需要密钥:段结构在 base64 的长度与 '=' 分布上留下指纹。 判决依据(docs/tdc-案例.md §5.1): chunk1/trajectory/chunk2 各 pad 到 24 字节 -> 密文长度是 24 的倍数 -> base64 无 '=' sd 不 pad,只被 XTEA 补到 8 的倍数 -> 长度%3 != 0 -> base64 带 '=' 用法: .venv/bin/python scripts/verify/verify_seglen.py """ import base64 import re import sys from pathlib import Path if len(sys.argv) < 2: print("用法: verify_seglen.py ") raise SystemExit(2) _arg = sys.argv[1] _p = Path(_arg) b64 = (_p.read_text(encoding="ascii") if _p.exists() else _arg).strip() print("真机 collect: %d 字符, 含 '=' : %s" % (len(b64), "=" in b64)) print() raw = base64.b64decode(b64) print("解码后密文: %d 字节" % len(raw)) print() # 真机明文(另一份同会话样本)给出的各段长度 segs = [("chunk1", 355, 5), ("trajectory", 62, 10), ("chunk2", 288, 24), ("sd", 33, None)] print("%-11s %8s %6s %10s %12s %10s" % ("段", "内容", "pad", "密文字节", "base64字符", "含'='")) print("-" * 66) total = 0 total_b64 = 0 for name, content, pad in segs: if pad is not None: n = content + pad # 空格 pad 到 24 assert n % 24 == 0 else: n = content + ((8 - content % 8) % 8) # sd: 只被 XTEA 补到 8 的倍数 enc = base64.b64encode(b"\x00" * n).decode() total += n total_b64 += len(enc) print("%-11s %8d %6s %10d %12d %10s" % (name, content, pad if pad is not None else "(xtea)", n, len(enc), "=" in enc)) print("-" * 66) print("%-11s %8s %6s %10d %12d" % ("合计", "", "", total, total_b64)) print() print(">>> 推算总密文字节 %d == 实际 %d : %s" % (total, len(raw), total == len(raw))) print(">>> 推算 base64 字符 %d == 实际 %d : %s" % (total_b64, len(b64), total_b64 == len(b64))) print() # 反过来看:把整串按 24 字节切,前三段应能整除 print("[反向校验] 把密文按 24 字节切分:") off = 0 for name, content, pad in segs: if pad is None: print(" %-11s 剩余 %3d 字节 (sd, 非 24 倍数)" % (name, len(raw) - off)) break n = content + pad print(" %-11s [%4d:%4d] %3d 字节 24倍数=%s" % (name, off, off + n, n, n % 24 == 0)) off += n print() # 关键指纹: '=' 只应出现在最后(来自 sd 段) idx = b64.find("=") print("'=' 首次出现位置: %d / 总长 %d -> %s" % (idx, len(b64), "在末尾区域(符合 sd 段不 pad)" if idx >= len(b64) - 4 else "⚠️ 在中间(与四段结构矛盾)")) if idx >= 0: print(" 尾部填充: %r" % b64[idx:])