T22对称加密
一:抓包分析
下一页抓包分析,可以看到请求体有两个加密参数,aes_sign、des_sign

汲取上一题的教训,查看下请求头,可以看到有两个加密参数X-Aes-Token、X-Des-Token

二:加密参数分析
直接搜索大法

可以看到四个参数都在这里

1、X-Aes-Token
直接让AI帮我改写,发现不对后调整

第一次生成的代码出入很大,加限制条件和结果


最后代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| import base64 from Crypto.Cipher import AES
def cryptojs_aes_ctr_encrypt(plaintext: str) -> str: """ 完全模拟 CryptoJS 的 AES-128-CTR 加密 - 密钥、IV 均以 UTF-8 字符串传入 - IV 不足 16 字节右补 0x00,超出截断 - 使用 CTR 模式,计数器初始值为 IV 的 **小端整数**(与 CryptoJS 内部一致) - 输出 Base64 字符串 """ key = "1234567890123456".encode('utf-8') iv_bytes = "abcdefghijklmnop".encode('utf-8')
# IV 补齐/截断至 16 字节 if len(iv_bytes) < 16: iv_bytes += b'\x00' * (16 - len(iv_bytes)) elif len(iv_bytes) > 16: iv_bytes = iv_bytes[:16]
plain = plaintext.encode('utf-8') block_size = 16 counter = int.from_bytes(iv_bytes, 'big') # 大端整数初始计数器 cipher_ecb = AES.new(key, AES.MODE_ECB) # 用于加密计数器
ciphertext_parts = [] for i in range(0, len(plain), block_size): # 当前计数器的 16 字节大端表示 counter_bytes = counter.to_bytes(16, 'big') # 加密计数器 -> 密钥流 keystream = cipher_ecb.encrypt(counter_bytes) # 当前明文块(可能不足 16 字节) block = plain[i:i + block_size] # 异或生成密文块 encrypted_block = bytes(a ^ b for a, b in zip(keystream, block)) ciphertext_parts.append(encrypted_block) # 计数器加 1 counter += 1
ciphertext = b''.join(ciphertext_parts) return base64.b64encode(ciphertext).decode('ascii')
|


测试结果一致
2、X-Des-Token
进入函数实际上是

代码改写验证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| def l(e: str) -> str: """ 对应 JS 中的 l 函数: var n = CryptoJS.enc.Utf8.parse("6f726c64"); var t = CryptoJS.enc.Utf8.parse("01234567"); return CryptoJS.DES.encrypt(e, n, { iv: t, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }).toString() """ key = b"6f726c64" # UTF-8 字节,恰好 8 字节 iv = b"01234567" # UTF-8 字节,恰好 8 字节
# 明文转 UTF-8 字节 plaintext = e.encode('utf-8')
# PKCS7 填充(DES 块大小 8 字节) padded = pad(plaintext, DES.block_size)
# DES CBC 加密 cipher = DES.new(key, DES.MODE_CBC, iv) ciphertext = cipher.encrypt(padded)
# 返回 Base64 字符串(与 CryptoJS 的 .toString() 一致) return base64.b64encode(ciphertext).decode('ascii')
|


一致
3、aes_sign

也就是如上函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| def p(e: str) -> str: """ 对应 JS 中的: var n = CryptoJS.enc.Utf8.parse("12345678901234567890123456789012"); var t = CryptoJS.enc.Utf8.parse(u); // u = "abcdefghijklmnop" return CryptoJS.AES.encrypt(e, n, { iv: t, mode: CryptoJS.mode.OFB, padding: CryptoJS.pad.NoPadding }).toString() """ # 密钥(32 字节 → AES-256) key = b"12345678901234567890123456789012" # IV(16 字节,AES 块大小) iv = b"abcdefghijklmnop"
# 明文转 UTF-8 plaintext = e.encode('utf-8')
# 创建 OFB 模式密码器(无需填充) cipher = AES.new(key, AES.MODE_OFB, iv=iv) ciphertext = cipher.encrypt(plaintext)
# 返回 Base64 字符串(与 CryptoJS 的 .toString() 一致) return base64.b64encode(ciphertext).decode('ascii')
|


一致
4、des_sign
略,实际为l(i + "_param")
三:编码与验证

更多内容也在公众号更新:码字的秃猴
