├── CryptEncryptor.jar ├── QQTEA.py ├── README.md └── 加解密1.ZIP /CryptEncryptor.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ColasDAD/Py3QQTEA/0ac97a5cfbb6ca5f8846e56e132845ecef70b990/CryptEncryptor.jar -------------------------------------------------------------------------------- /QQTEA.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | #-*- coding:utf-8-*- 3 | import queue, sys, os 4 | import time 5 | import struct 6 | import jpype 7 | import random 8 | 9 | #JVM_PATH = "C:/Program Files/Java/jre1.8.0_201/bin/server/jvm.dll" 10 | 11 | class QQ_TEA(): 12 | """QQ TEA 加解密, 64比特明码, 128比特密钥 13 | 这是一个确认线程安全的独立加密模块,使用时必须要有一个全局变量secret_key,要求大于等于16位 14 | """ 15 | 16 | def xor(self,a, b): 17 | op = 0xffffffff 18 | a1,a2 = struct.unpack(b'>LL', a[0:8]) 19 | b1,b2 = struct.unpack(b'>LL', b[0:8]) 20 | return struct.pack(b'>LL', ( a1 ^ b1) & op, ( a2 ^ b2) & op) 21 | 22 | def code(self,v, k): 23 | n=16 24 | op = 0xffffffff 25 | delta = 0x9e3779b9 26 | k = struct.unpack(b'>LLLL', k[0:16]) 27 | y, z = struct.unpack(b'>LL', v[0:8]) 28 | s = 0 29 | for i in range(n): 30 | s += delta 31 | y += (op &(z<<4))+ k[0] ^ z+ s ^ (op&(z>>5)) + k[1] 32 | y &= op 33 | z += (op &(y<<4))+ k[2] ^ y+ s ^ (op&(y>>5)) + k[3] 34 | z &= op 35 | r = struct.pack(b'>LL',y,z) 36 | return r 37 | 38 | def decipher(self,v, k): 39 | n = 16 40 | op = 0xffffffff 41 | y, z = struct.unpack(b'>LL', v[0:8]) 42 | a, b, c, d = struct.unpack(b'>LLLL', k[0:16]) 43 | delta = 0x9E3779B9 44 | s = (delta << 4)&op 45 | for i in range(n): 46 | z -= ((y<<4)+c) ^ (y+s) ^ ((y>>5) + d) 47 | z &= op 48 | y -= ((z<<4)+a) ^ (z+s) ^ ((z>>5) + b) 49 | y &= op 50 | s -= delta 51 | s &= op 52 | return struct.pack(b'>LL', y, z) 53 | 54 | def encrypt(self,v): 55 | END_CHAR = b'\0' 56 | FILL_N_OR = 0xF8 57 | vl = len(v) 58 | filln = (8-(vl+2))%8 + 2 59 | fills = b'' 60 | for i in range(filln): 61 | fills = fills + bytes([220]) 62 | v = ( bytes([(filln -2)|FILL_N_OR]) 63 | + fills 64 | + v 65 | + END_CHAR * 7) 66 | tr = b'\0'*8 67 | to = b'\0'*8 68 | r = b'' 69 | o = b'\0' * 8 70 | for i in range(0, len(v), 8): 71 | o = self.xor(v[i:i+8], tr) 72 | tr = self.xor( self.code(o, secret_key), to) 73 | to = o 74 | r += tr 75 | return r 76 | 77 | def decrypt(self,v): 78 | l = len(v) 79 | prePlain = self.decipher(v, secret_key) 80 | pos = (prePlain[0] & 0x07) +2 81 | r = prePlain 82 | preCrypt = v[0:8] 83 | for i in range(8, l, 8): 84 | x = self.xor(self.decipher(self.xor(v[i:i+8], prePlain),secret_key ), preCrypt) 85 | prePlain = self.xor(x, preCrypt) 86 | preCrypt = v[i:i+8] 87 | r += x 88 | if r[-7:] != b'\0'*7: 89 | return None 90 | return r[pos+1:-7] 91 | 92 | if __name__ == '__main__': 93 | global secret_key 94 | key_hex = format(247,'x')+format(106,'x')+format(238,'x')+format(189,'x')+format(105,'x')+format(138,'x')+format(110,'x')+format(222,'x')+format(104,'x')+format(171,'x')+format(240,'x')+format(233,'x')+format(211,'x')+'00'+format(106,'x')+format(76,'x') 95 | secret_key = bytearray.fromhex(key_hex) 96 | print(secret_key) 97 | 98 | QQ = QQ_TEA() 99 | 100 | #jpype.startJVM(JVM_PATH, "-ea", "-Djava.class.path=CryptEncryptor.jar") 101 | #JClass = jpype.JClass("CryptEncryptor") 102 | #CryptEncryptor = JClass() 103 | plaintext = '0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,0123456789 bou 宇宙银行,' 104 | plaintext = bytes(plaintext,encoding = "GBK") 105 | enc = QQ.encrypt(plaintext) 106 | #enc = CryptEncryptor.encrypt(plaintext,secret_key) 107 | print(enc) 108 | dec = QQ.decrypt(enc) 109 | #dec = CryptEncryptor.decrypt(enc,secret_key) 110 | print(dec) 111 | #jpype.shutdownJVM() 112 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Py3QQTEA 2 | Tencent QQ TEA encrypt and decrypt in python 3. 腾讯QQ消息加解密算法的python 3实现。 3 | 4 | 最近做项目遇到一家给烟草公司做银行接口的公司海晟信息使用了QQ消息的加解密算法,对方提供了JAVA实现,详见(加解密1.ZIP)。由于本人习惯玩python,就想上网搜一个现成的python3实现,结果要么是不行,要么就是基于python2的。故本人根据python2的改造了一个可以用于python3的,希望能帮助到大家。 5 | 6 | 加解密1.ZIP -------------- 公司提供的java实现 7 | 8 | CryptEncryptor.jar ------ 用公司提供的java打包出来的jar报,用于python3直接调用java实现测试有效性用 9 | 10 | QQTEA.py ---------------- python3的实现代码 11 | -------------------------------------------------------------------------------- /加解密1.ZIP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ColasDAD/Py3QQTEA/0ac97a5cfbb6ca5f8846e56e132845ecef70b990/加解密1.ZIP --------------------------------------------------------------------------------