Python的TEA加密代码

最近我在逆向某个JavaScript,我的目的是将其中的加密函数还原成Python代码。

JavaScript源代码:

    function i(n) {
            return 4294967295 & n
        }
    
    function o(n, e, t, r, i, o) {
            return (t >>> 5 ^ e << 2) + (e >>> 3 ^ t << 4) ^ (n ^ e) + (o[3 & r ^ i] ^ t)
        }

    function(n, e) {
            var t, r, a, s, c, l, d = n.length, u = d - 1;
            for (r = n[u],
            a = 0,
            l = 0 | Math.floor(6 + 52 / d); l > 0; --l) {
                for (s = (a = i(a + 2654435769)) >>> 2 & 3,
                c = 0; c < u; ++c)
                    t = n[c + 1],
                    r = n[c] = i(n[c] + o(a, t, r, c, s, e));
                t = n[0],
                r = n[u] = i(n[u] + o(a, t, r, u, s, e))
            }
            return n
        }
    

经过一段时间的分析,这段JS代码的加密方式是TEA。

十分感谢lifanxin的博文:python实现tea/xtea/xxtea加密算法___lifanxin的博客-CSDN博客_python xxtea

该博文在Python环境下借助ctype库的c_uint32()函数实现了TEA加密解密算法。由于Python对整数型没有限制,而JavaScript对32位整数的处理是有符号型(signed 32bit int),超出范围的数会变成负数,而Python运算后都是正数。为了使Python运行结果与JavaScript一样有正数也有负数,需要对Python运算后的结果稍微处理一下:

for i in range(len(v)):
    v[i]=c_int32(v[i]).value

测试TEA加密的完整Python代码如下:

主程序中的data是将加密前的字符串经过某个加密算法转换成一组整数列表。

key是将密钥字符串经过同样的算法而成的整数列表。

data和key的数是怎么来的,这里不作赘述,因为它们都可以在JavaScript里找得到,而且加密比较简单,本文讲解的是TEA加密算法,需要将这两个列表代入参数进行加密运算。

## TEA加密算法原文:https://blog.csdn.net/A951860555/article/details/120120400
## 下面是我在上述博主原文基础上稍加修改的代码

from ctypes import c_uint32, c_int32

def MX(z, y, total, key, p, e):
    temp1 = (z.value>>5 ^ y.value<<2) + (y.value>>3 ^ z.value<<4)
    temp2 = (total.value ^ y.value) + (key[(p&3) ^ e.value] ^ z.value)
    
    return c_uint32(temp1 ^ temp2)

def encrypt(n, v, key):
    # delta是TEA加密算法的重要参数
    delta = 2654435769
    rounds = 6 + 52//n

    total = c_uint32(0)
    z = c_uint32(v[n-1])
    e = c_uint32(0)
    
    while rounds > 0:
        total.value += delta  
        e.value = (total.value >> 2) & 3
        for p in range(n-1):
            y = c_uint32(v[p+1])
            v[p] = c_uint32(v[p] + MX(z,y,total,key,p,e).value).value
            z.value = v[p]
        y = c_uint32(v[0])
        v[n-1] = c_uint32(v[n-1] + MX(z,y,total,key,n-1,e).value).value
        z.value = v[n-1]
        rounds -= 1 
    
    # 这是我改进的地方:把unsigned int处理成signed int,超出32bit范围的正整数会变成负数。
    for i in range(len(v)):
        v[i]=c_int32(v[i]).value
    return v
     
if __name__ == "__main__":
    # 加密前的源字符串
    ss='appid=201807308440|ctxid=9d23cc620e0dfb601f27711dcec30c64|r=0.48592600736230795'
    # data是将加密前的字符串经过下面简单的加密算法转换成一组整数列表。
    # 这加密算法比较简单,可以在JavaScript里扒出来。
    data = []
    ss_len = len(ss)
    data = [0]*((ss_len>>2)+2)
    data[-1] = ss_len
    for i in range(ss_len):
        data[i >> 2] |= ord(ss[i]) << ((3 & i) << 3)
    '''
    data = [1768976481, 808598884, 925906993, 876097587, 1669083188, 1684633716, 845429053, 912483123, 811937842, 912418404, 845558064, 825308983, 1667588964, 912470067, 1030913076, 942943792, 909261109, 859254832, 808661558, 3488055, 79]
    '''

    # key是密钥经过加密算法后而成的四个整数
    key = [1631074661, 926431333, 909271864, 1698128180]

    # key的数是怎么来的,这里不作赘述,因为它们都可以在JavaScript里找得到。
    # 本文讲解的是TEA加密算法,需要将这两个列表代入encrypt参数进行加密运算。

    length = len(data)
    # TEA加密
    res=encrypt(length, data, key)
    print(res)
    '''
    输出结果:
    [716085371, -477396898, 91038733, -105793381, -1817301194, -535430222, 1390850599, 140015488, -1430794631, 1855466254, -24428639, 1179447845, -1111913346, 586757153, -37658271, 1089200005, 848481124, 1301543136, -1437420864, -183487679, 1196366267]
    '''

Guess you like

Origin blog.csdn.net/Scott0902/article/details/129039726