PYTHON实现JS里面ECB加密

659 阅读2分钟

最近研究js逆向,找到了js里的解密代码

//DES加密
function encryptByDES(message, key) {
    var key = 'PassB01Il71';
    var keyHex = CryptoJS.enc.Utf8.parse(key);
    var encrypted = CryptoJS.DES.encrypt(message, keyHex, {
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
    });
    return encrypted.toString();
}
 
//DES  ECB模式解密
function decryptByDESModeEBC(ciphertext) {
    var key = 'PassB01Il71';
 
    //把私钥转换成16进制的字符串
    var keyHex = CryptoJS.enc.Utf8.parse(key);
    //把需要解密的数据从16进制字符串转换成字符byte数组
    var decrypted = CryptoJS.DES.decrypt({
//        ciphertext: CryptoJS.enc.Hex.parse(ciphertext)
        ciphertext: CryptoJS.enc.Base64.parse(ciphertext)
    }, keyHex, {
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
    });
    //以utf-8的形式输出解密过后内容
    var result_value = decrypted.toString(CryptoJS.enc.Utf8);
    return result_value;
}

查了一晚上百度, " CryptoJS.enc.Utf8.parse",除了这句不知道是啥意思.其余的倒是能找到一部分python转写的方案,还有查到的代码里面偏移量什么的不清楚,苦心提问后得到如下结果

from Crypto.Cipher import AES, DES
from base64 import b64decode, b64encode
 
def pad(data, block_size=8):
    length = block_size - (len(data) % block_size)
    return data.encode(encoding='utf-8') + (chr(length)*length).encode(encoding='utf-8')
 
def unpad(data):
    """去除解密后的填充数据
 
    Args:
        data (bytes): 字节序列
 
    Returns:
        bytes: 解密后的字节序列
    """
    return data[:-(data[-1] if type(data[-1]) == int else ord(data[-1]))]
 
key = 'PassB01Il71'
# 测试用的密文
r1 = 'wd+j1cVdbss='
 
# 先把密钥转换成bytes, 由于密钥长度是8, CryptoJS会自动取前面8个, 这里也直接取前面8个
key1 = key.encode('utf-8')[:8]
 
# 加密模式是ECB
# 填充模式是pkcs7, 解密的时候python库默认的好像就是pkcs7,这里就不手动填充了, 手动填充的函数我也写了, 看完下面的那个博客就知道这个函数是什么意思了
# 填充模式的具体细节可以看这个https://blog.csdn.net/boweiqiang/article/details/109860950
# ECB模式是没有iv的, 所有不用指定
cipher = DES.new(key=key1, mode=DES.MODE_ECB)
result = cipher.decrypt(base64.b64decode(r1))
 
# 如果你现在把result转换成utf-8打印出来会发现后面有很多的填充, 现在要把填充的东西去掉
result_unpad = unpad(result)
 
# 转换成utf-8编码
result_unpad = result_unpad.decode('utf-8')
print("解密后: ", result_unpad)
 
 
# 再加密回去看看, 注意这里填充的是块大小是8
encrypted_text = cipher.encrypt(pad(result_unpad, block_size=8))
# based64编码
encrypted_text = b64encode(encrypted_text)
print("正确的加密结果: ", r1)
print("实际的加密结果: ", encrypted_text.decode('utf-8'))