爬虫逆向必备:一文吃透常见加密(MD5/URL/Base64/AES/DES/RSA)

一、MD5 摘要算法 —— 不可逆的“指纹”

from hashlib import md5, sha1, sha224, sha256, sha384, sha512

"""
md5叫摘要算法
md5是一个大的hash算法
md5加密不可逆
md5加密的值是确定的
sha1, sha224, sha256, sha384, sha512 也差不多
"""


def calculate_md5(text: str) -> tuple[str, str]:
    """计算给定文本的MD5哈希值

    Args:
        text: 要计算哈希值的字符串

    Returns:
        包含32位和16位MD5哈希值的元组
    """
    # 将输入转换为字节
    text_bytes = text.encode('utf-8')

    # 创建MD5哈希对象并更新数据
    # md5_hash = sha1() 可以换成别的
    md5_hash = md5()
    md5_hash.update(text_bytes)

    # 获取32位MD5哈希值
    full_md5 = md5_hash.hexdigest()

    # 获取16位MD5哈希值(取中间16个字符)
    short_md5 = full_md5[8:24]

    return full_md5, short_md5


if __name__ == "__main__":
    input_text = "123456"
    full, short = calculate_md5(input_text)

    print(f'md5({input_text},32) = {full}')
    print(f'md5({input_text},16) = {short}')
    # 背前几位e10 49b 看到了就是md5
    # md5(123456,32) = e10adc3949ba59abbe56e057f20f883e
    # md5(123456,16) = 49ba59abbe56e057


经验

  • 32 位/16 位、字符范围 0-9a-f,大概率 MD5。

  • 只能做签名/校验,不能解密,但数据库撞库可反查。

二、URL 编码 —— 浏览器帮你做的“百分号”

from urllib.parse import urlencode, unquote

"""
我们在访问一个ur的时候.浏览器会自动的进行urlencode操作.
会对我们请求的url进行编码,这种编码规则被称为百分号编码.
是专门为url(统一资源定位符)准备的一套编码规则
其实里面的规则非常简单.就是把url中的参数部分转化成字节.
每字节的再转化成1个16进制的数字.前面补%.
"""
# url 编码
base_url = 'https://www.baidu.***/s?'
params = {
    'wd': '我饿了'
}
url = base_url + urlencode(params)
print("url 编码:::", url)

# url 解码
url = 'https://www.baidu.***/s?wd=%E6%88%91%E9%A5%BF%E4%BA%86'
print("url 解码:::", unquote(url))

经验

  • % + 两位十六进制 → URL Encode,不是加密,只是传输友好

三、Base64 —— 二进制数据变“字符串”

import base64
# Base64字符集,逆向时可以搜
# ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
"""
Base64是什么?
Base64编码,是由64个字符组成编码集:26个大写字母A~Z,26个小写字母a~z,10个数字0~9,符号“+”与
符号“/”。Base64编码的基本思路是将原始数据的三个字节拆分转化为四个字节,然后根据Base64的对应表,
得到对应的编码数据。
当原始数据凑不够三个字节时,编码结果中会使用额外的符号“="来表示这种情况。

Base64原理:https://www.jyshare.***/front-end/693/
('A',0)……('a',26)……('0',52)……('/',63)
ps:如果这张Base64的表在网页上被改了,那就是不是原来的版本,我们也要对应修改,虽然大概率是原版
ASCII 表:https://www.runoob.***/w3***ote/ascii.html
('0',48)……('A',65)……('a',97)
"""
# 编码
ret = base64.b64encode(b'123456')  # b'MTIzNDU2'
print(ret.decode())  # MTIzNDU2
# 实际上网页上的base64是去处理字节的
bs = "我爱吃饭".encode()  # b'\xe6\x88\x91\xe7\x88\xb1\xe5\x90\x83\xe9\xa5\xad'
print(base64.b64encode(bs).decode())  # 5oiR54ix5ZCD6aWt
"""
如果那一串字符不超过那64各字符集,则可以怀疑它是base64
"""

# 解码
data = base64.b64decode(b'MTIzNDU2')
print(data.decode())  # 123456
data = base64.b64decode(b'5oiR54ix5ZCD6aWt')
print(data.decode())  # 我爱吃饭

# 场景1,网页把等于号去掉了,导致无法解码
S = "eW91IGFyZSBnb29kISE"
S += "=" * (4 - len(S) % 4)
print(base64.b64decode(S).decode())

# 场景2.网页中为了SQL便于储存,把+换成-,把/换成_

"""
Base64的意义:
有些网络传输协议是为了传输ASCII文本设计的,当你使用其传输二进制流时(比如视频/图片),二进制流
中的数据可能会被协议错误的识别为控制字符等等,因而出现错误。那这时就要将二进制流传输编码,因为有
些8Bit字节码并没有对应的ASCI字符。

比如十进制ASCll码8对应的是后退符号(backspace),如果被编码的数据中包含这个数值,那么编码出来的结果
在很多编程语言里会导致前一个字符被删掉。又比如ASCI码O对应的是空字符,在一些编程语言里代表字符串
结束,后续的数据就不会被处理了。

用Base64编码因为限定了用于编码的字符集,确保编码的结果可打印且无歧义。

爬虫中,因为加密数据后,数据非常乱,用base64就能确保其在网络中传输
"""

img_url = 'iVBORw0KGgoAAAANSUhEUgAAAAcAAAAFCAYAAACJmvbYAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3***ulE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAABYlAAAWJQFJUiTwAAAAJklEQVQI12NgwAEsuv/8xy9h3vX7P6oEKp/BHCqA0yhzdB0MDAwAFXkTK5la4mAAAAAASUVORK5CYII='
data = base64.b64decode(img_url)
with open('img.png', 'wb') as f:
    f.write(data)

坑点

  • 末尾缺少 = 时先补 = 再解码。

  • 变体:-_ 替换 +/,需手动替换回来。

四、AES 对称加密

对称加密:AES与DES
所谓对称加密就是加密和解密用的是同一个秘钥,就好比.我要给你邮寄一个箱子.上面上锁.提前我把钥匙给了你一把,我一把.
那么我在邮寄之前就可以把箱子锁上.然后快递到你那里.你用相同的钥匙就可以打开这个箱子
条件:加密和解密用的是同一个秘钥.那么两边就必须同时拥有钥匙才可以,

AES>>>>>>>>>>>>>>>>>>>>>>
key长度 必须是16、24、32
iv长度  必须是16

MODE加密模式
    ECB:只需要key,不需要iv偏移量
    CBC:都要

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64
from urllib.parse import quote_plus
from datetime import datetime
import requests
import json


# AES加密
def aes_encrypt(plaintext, key, iv):
    """
    :param plaintext:   明文
    :param key:         密钥
    :param iv:          偏移量
    :return:            密文
    """
    if len(key) not in [16, 24, 32]:
        raise ValueError("密钥长度必须为16、24或32字节")
    if len(iv) != 16:
        raise ValueError("偏移量长度必须为16字节")
    key1 = key.encode()
    iv1 = iv.encode()
    # 创建AES加密器
    cipher = AES.new(key=key1, mode=AES.MODE_CBC, iv=iv1)
    # 对明文进行填充
    padded_plaintext = pad(plaintext.encode(), AES.block_size)
    # 对明文加密
    ciphertext = cipher.encrypt(padded_plaintext)
    # 将IV和密文拼接后进行Base64编码
    encrypt_data = base64.b64encode(ciphertext)
    # 返回密文
    return encrypt_data.decode()


# AES解密
def aes_decrypt(encrypted_data, key, iv):
    """
    :param encrypted_data:  密文
    :param key:             密钥
    :param iv:              偏移量
    :return:                明文
    """
    if len(key) not in [16, 24, 32]:
        raise ValueError("密钥长度必须为16、24或32字节")
    if len(iv) != 16:
        raise ValueError("偏移量长度必须为16字节")
    key1 = key.encode()
    iv1 = iv.encode()
    # 对Base64编码的数据进行解码
    ciphertext = base64.b64decode(encrypted_data)
    # 创建AES解密器
    cipher = AES.new(key=key1, mode=AES.MODE_CBC, iv=iv1)
    # 解密
    padded_plaintext = cipher.decrypt(ciphertext)
    # 去除填充
    plaintext_data = unpad(padded_plaintext, AES.block_size)
    # 返回明文
    return plaintext_data.decode()


if __name__ == "__main__":
    # start_urls = 'http://www.pingdu.gov.***/xxgkx_15/fdzdgknr_15/zdjcygk_15/yjzj_15/'
    # 密钥(必须是16、24或32字节)
    key = "yaweisoftoa@2018"
    # 偏移量
    iv = "2018@oayaweisoft"
    # 获取当前时间
    current_time = datetime.now()
    # 格式化时间
    formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
    plaintext = {"webStartTime": formatted_time, "guid": "2544884718402278968"}
    encrypt_data = quote_plus(aes_encrypt(str(plaintext), key, iv))
    url = f"http://120.221.72.129:9088/questionFormApi/queFormGui/loadAdd?encrypt={encrypt_data}"
    headers = {
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
    }
    res = requests.get(url, headers=headers)
    mi_wen = res.json()["data"]
    decrypted_data = aes_decrypt(mi_wen, key, iv)
    # print(f"解密后的数据::: {decrypted_data}")
    html_dict = json.loads(decrypted_data)
    content = json.loads(html_dict['data']["queFormGui"]["content"])
    print(content["fields"][6]["editHtml"])

五、DES 对称加密

DES>>>>>>>>>>>>>>>>>>>>>>
    key密钥长度固定为8字节
    iv长度与DES块大小相同,即8字节

import json
from Crypto.Cipher import DES
from Crypto.Util.Padding import pad, unpad
import base64
# https://ctbpsp.***/#/
"""
看到async关键词,说明是异步加载,可以直接搜索interceptors关键词来定位
"""


# DES加密
def des_encrypt(plaintext, key, iv):
    """
    :param plaintext:   明文
    :param key:         密钥
    :param iv:          偏移量
    :return:            密文
    """
    # 确保密钥和偏移量长度符合DES要求
    if len(key) != 8:
        raise ValueError("DES密钥长度必须为8字节")
    if len(iv) != 8:
        raise ValueError("DES偏移量长度必须为8字节")
    key1 = key.encode()
    iv1 = iv.encode()
    # 创建DES加密器
    cipher = DES.new(key1, DES.MODE_CBC, iv1)
    # 对明文进行填充
    padded_plaintext = pad(plaintext.encode('utf-8'), DES.block_size)
    # 对明文加密
    ciphertext = cipher.encrypt(padded_plaintext)
    # 将密文进行Base64编码
    encrypt_data = base64.b64encode(ciphertext)
    # 返回密文
    return encrypt_data.decode()

# DES解密
def des_decrypt(encrypted_data, key):
    """
    :param encrypted_data:  密文
    :param key:             密钥
    :param iv:              偏移量
    :return:                明文
    """
    # 确保密钥和偏移量长度符合DES要求
    if len(key) != 8:
        raise ValueError("DES密钥长度必须为8字节")
    key1 = key.encode()
    # 对Base64编码的数据进行解码
    ciphertext = base64.b64decode(encrypted_data)
    # 创建DES解密器
    cipher = DES.new(key1, DES.MODE_ECB)
    # 解密
    padded_plaintext = cipher.decrypt(ciphertext)
    # 去除填充
    plaintext_data = unpad(padded_plaintext, DES.block_size)
    # 返回明文
    return plaintext_data.decode()


# 测试代码
if __name__ == "__main__":
    # 密钥(必须是8字节)
    key = "1qaz@wsx3e"[:8]

    # 明文
    encrypted_data = 'JwdsCjMM05e4niaZd3zOKXjfJCSKzfLUd1joO6+H0TGjmj0y4AzXIiFlVNgGu02jLvo9yNvP3xP7X/7aPZ70J8szgU0bskEDXoSv7+Aix8lCe***j5HHMUP5G/ea+css5EDpX5nE5rlfWIiaJ6P0x3p41b5qHIvaj0aPQwnSpTsqAmmLiQOYem6aEz51HFMNJ9EVrgR8pM3JoGtYjS0eAtS/gGs02ttYqg7eEjJNOHDQe744uDKOgu/MB3uZgYh/KFX***Fm3f5WVVt6Aa5vEEv16B1LnFPknvHIsIk+TqI9ShDh3gDOzMdSeYbPaSLRgz8o***4WqHfyvqakNNhJ1/Q8eqqdvYbjAjT/XkhO0Vd4mifL79/f***mokcplJSfK2JAuUsj6RBE1w6VWvJUB0FNDibMuaqpFzCXPor6IgQqAi/LYzyyBkxP89/W6Ie7Mkieeetu9CaxrdnDWnkfCSUBUSFeqUra94DsfoxkxRg02b6VYCPdtk90Hd7tsbiTn/Gk8t9hv70rQm7naeCp9PcZFwb1+cljC94DSgfCOU2nxf3klP7ZAoDMJ8kh3ImMiuAVbegGubxBL94qqnUlW1xsF0KxNFCm13Rqlm3IVJ7nZS47hcAGkWxAbLGdpbp3d+q4U4jMnfzkaWWI+X4XJ32S0EsOhy/Yi/UuYfMBl8lfDoHKZEMAj8BO51JZLdgmNHartoH/4mzk2YoNJiOVI8T8JvumZ1A40D9gbXk3V1N07eb7pmdQONA/bLt***LxR+2RZtn0BpIDuJwM86Y4jDn2lndGa0Ek73ewg3Z0iyFn1URk+dXr5ssprEUwePL/Hh1ea3GAEQkDdW6GEMnpDEZx2cHzv7JgQNIJ3BL/YqJcJKCVEd+nIYTvewABWZXGhdg/ZHPi0kTXfaMeouMZC2rwOqDC07G6QgVLionDtw4qzVHfHyJPwcmyxrPD6+lFa0vodou2qNiDfY0NCpmily/4epbvfh4nhdUgvu2+9kn+p9BJVOXnxf40JO+6CBQjjF6NDQAiW9hsgGbqvLrU+Zwr9RvLoHK5XtRJJIC5O3ln0QKhim9H/3pUpRrpHN6uK4TVXrLYSLNAwFz7fVTOlF06+nC/a6YUHiFebPwEGTE8dgS/S5H45R9XR+kFpOl+nZtXg9jiV6Ooo+RGqHbTw4IiEETFyQHpKyjNffOwIWwT/RumrqPv2z3Ehv3IE4eboNjrZ7QuyicLAw/QlHysk6zdt4okn1/oy/X14C60C5ZAkg***W18TIwlLC5EEC5ZiiJ28QiTtmhfiiJ9+MwmqXn35av5bxqWO/WcHykqhK6pwDRx6nW5TJGBD0mff+YbFY***CiuTpHXe2IcgMxLJcIkIyPEFtT+F2AR5/aARMcIUkbYdqJJEGGnChOaS8lAjeaHUe2Rsy/NuZb8VXbqOQ4OM207nWv5g6OofSrak2BVyqJaMPOkIQPaVmd+b8DQpZSxd01sIYAdOkGuiaxBh6PflUtgS/SenpnNk9N+LgsC28RrziSKVPCzt431uSDzVWfOcdG9gOaX/XVGRyLtTnPvHo9/Y92AScagFo1GjdugAjkO***uBqZ+K4Fm/lj+YFskS+vco63zHw1k92eWTp7rSy4vfx6O1kXon4DmgBBZsbEs5Dq2jszhQG2HFyYR7mNos88Ht4ycXFsriyYJ181qGe68JMllSDhggeMRY7Zpzp+DhNnZDm1yS4b+DuC/Hw56iug5WfQ5k5ahfaeKhwlL4zA4poAQWbGxLOQIdtfCl0NjU6tOWrXcJr4g1jVg24zxPKzcBVw9chWQFuxCYVmqVwK+zQC+UXpdxRFpHr2os8hvoxWi63D754DRpB1dDTMmFXyRIV6pStr3gPy17Otzc3ou3HW0MPFNs56l/Fjsu3XJJ9UrSRzUkafOtB3wCk78PZ9zsK1W3zqG/FPHLIbkUDcoUmrV3CDW3GzxxV6FF3GDwIHNIKusilv4wqzwibrr3ajueCeZgi0qNJ1t7gjjjYkNTKJvnmD3QPkLKpp/ZFkWb9nyKb2KCMMXFnyqe1sjNYN10KxU4X6RO/XiW23hklsOu/4ch3/s6u63pWIAfXXhXWRBAuWYoidvIskbNxcflycorSFbsNmjKRMFOOwnlK82xvER5Do8ZF0iO836ifiWNIez7PnFdYFtxV3JxZt3+VlVbegGubxBL9egdS5xT5J7xyLCJPk6iPURTB48v8eHV6kRdFgWMLqmKjhGkl/iK2Of+hDZrAuIqOrRp6A5rMgDhkl8ouWpxEfSBvMTTDMYFx+kyoLUMbCKZ3+S2K6sFlcwRQzE64dHnFt08Y2u7IyKpzV9wuVYi4evHu2JW***In3vd/SUPUakjGsUwyEMKA/A6fQgipT/iUtgoSp++HQDYjlnsEWrVlbK/M1E2UOuEBoOEgF3Zac+aXKpgKD4Hk+pmgBBZsbEs5CqpepygPh17J9ORKdtLbY3OeqtPjPyD7KcEdZ5/O0yt4gBq/dOUN2UMnVi39Wbb2Gdp7ZncraWYmopjQxIidD5st9InNBgGZU5haSi6uKJVKaD6EQnG2BDkL3WLNvKgY8NdDHzFMxkMi51DcR/bsAXm+6ZnUDjQP3XgkvX826ZPx3t6Ou0d5lP6LGFxe0T4dEd7ejrtHeZT1RR4neUvJ5yUvkggbxa/ip8lFIX3yMdFqY8YVRe8tnnS6lfm5J61RWxF5knUqZ+wBvYDml/11RkxGX+1esk8zy7V1pbCpz/W4MzYgOpJVmiwI4q4PaSzVVEhXqlK2veA0pjT***yMSQ9uYfMBl8lfDp96mJOF4vPh2x8WCHUgz6G8rA/BL+eynj4Sj7fLKiRkNE9yaivdqJW7owNwFz4KpTbtypCl+jxaeh6+SK5goU18ZNkFWjxLYVzIKYIzaehrNVpVoBkoWrBZGd3OuiU1cU2DVGmpuLOAmmEnQDPCjVomsf+JbuxrpIGrRS67Lk0bC9NMHtsSB2prY04D0OOuvuKG97ZJlKvcqNIwOGyqWep26aeaIP9lEGgnfMHCsgy114s6viS47He0t9ivjQNFramNAqp/VySUOzhYz6CtaRHYSKvdz9zdZmIuO+***U2/AiM2b5lpDMhzw6c/RRQG/D0ryxoy3hkYLYmrdZHPQqZb0heA30uEVUjyiQrJ52DazNNLpzpkL5akadXqQzYbqRIoGgTXPpX6dnhpxb9f/tImPT/wkOqjXmf9bSKvRJqjQTy8Q9Yos6/cegHBBLC6Ki8PnjJMsuhzFcyex/Iit1cvdmGWlYqmHRiElDMGBxY9MdbWVnmA1mib/roKWbVNcwSzdivGJ7AGec27G7YK/ZIluda/mDo6h9KJj9vffECv2I1Og2sL7RMrxKra4iMoGAv52JTAWzbjYqSAPi4N2EJTbJ+63go8LeZPs4ypf02m/86Im9/nHqqB0p9LG7nwqBWpiel9ZurXLLdCeBlT5YsP9ds22D4LVMKI0ZkqYA4YmFwntgeH+HXHrne+UoddqgTumjHIe/VH4T9W7GnJGlKwhJQzBgcWPTENcOLrMqWzQUisWQL/H9u2VO1wkWkMSKa7gM+DePT6N0uNC5QL09picE83Qlux3XZtVcR7mK4R1l6dfGHi/U2MhwYJRb+20hhWgptoF1kie4SUMwYHFj0xLNclRSC2cefPRPmoxh3iZFMAvMg33zu2ZQOV3leozlcXedFmYBGXRRoyTCIMW+HY5BY2dTiJsBnDK0zFd1aqcFuSDzVWfOcdaxTDIQwoD8DaojoU8XupqlvGa5IKPdYNPjPvCibYSeftyPn0m3Yh4cgBmJlHtJYkRY7Zpzp+DhM+5/sBfPW78qqIQ1zDAi0HHbt4oHfZSDrOwrVbfOob8XvLDWfeq3Q/WHM/DN/Vfja+I65oEZ7/qajKHaO+oBLQ5eSuHAFJn6J8awt1nQ0P3apPJeFg+mCARoNvEcRSfxHlUYXDJSL4iUVxWLLQqksMWW5JbRiieuXTS6c6ZC+WpBtNAdY8OGMfWvhEn3Vmzw6maph7PbCjA1G2omL002E8VFWX/LByHz34mTytEs6CX931cMgoHk7opaMAAhvshxKjg0aaJTKiENelYAaVRIO6vhPpTZEJJMwg0Jv+O8Cpw1Gv4THhk42R4g5Yt4yHELvbOR+Ijq028LQkFVgfpkOsOG1BtJf10pjaUrVrmgVuDlnfQ4Tgx/crgJpi4kDmHpumhM+dRxTDSUWQq+m60+2ViXAGznio0Lko70o/j+gVqQyOJNhbdNIDa3GAEQkDdW5xfeqA3t3***d81lxrAkxzdSCdk47acYYoGBSrZnRHhDY***8Mi2Zi9OFyE2Z8qeempdkPoHZ8v95YcZHGFPGAWz/5cx/A5BkoV15x3nfIsamSQxlUJJNMW2LQIDzelFcLqElDMGBxY9MZzvQH+wcSdq7UPs47Kyi0ZVnMCA2ob4A8a0Q5+EVSTXBFvLW8NLyNMTz+nwWeNomlEbV18i/J3U9En+ItkSDe1kc+LSRNd9o2cu1/Z87PGFsraazsooKV+aAEFmxsSzkNIRbayHfgrBrtoH/4mzk2bqHE/iKdqV167aB/+Js5NmCa5v0kJoNt0JAQslsL3wVKRMimFKxs8htwoWnAlnCm2QvdYs28qBj6H+WvahsDD+diD/OxML+iNegdS5xT5J78Non9irXC5a4yCKbVBoOn0jMMQxKINT7pzJaQMtYR8Wnd8kaGToqoZkV8coeX4WKBc4y9jFi5E3IPyPoDUWNRXTM67v5s4m2e939JQ9RqSMa3GAEQkDdW5fe+28aQhotpLCmtzzH3EdE3gzb2LQV8tdtyA9qxgx2PjPAaVFioxlfsQrorX93bj8XeyVRgTkdL7ebGHlnZzq/I9YicgBOW0Mkyjg8t2NU8W9zQEyqK59xKnJ5i1aQ/K7vCa/9R1QUdA4BEo2WVeHgOi8Nb3CQ3KrkGjIcufIfAdhRRpjp7vyQ/qVZrZKifR4ujhv4DBtp7obpWpEZdAmEa7qzGB8c+OkBdRpiwPRBWDK1yWLc6AgNheYkS4XoKJu/qinugAd7ZhfjkOURzlVamY5IebBpbArZDfsi3/blHGwsNOvCMBa4g5Yt4yHELvRW3wTJk69Qwu1zwjdZjiwARguykpkVZnJg3v5iBA9MYrk6R13tiHIDMSyXCJCMjxBbU/hdgEef2gETHCFJG2HaiSRBhpwoTmkvJQI3mh1HtkbMvzbmW/FV26jkODjNtO51r+YOjqH0q2pNgVcqiWjDzpCED2lZnfm/A0KWUsXdNbCGAHTpBromsQYej35VLYEv0np6ZzZPTfi4LAtvEa84kilTws7eN9bkg81VnznHRvYDml/11RkUWMko18fbalxGDeLHijTiOdUlh3YHJGItOXMs1bd3o2JGrYKKsddzNGfSTqjzloAbrTRKLo+dmNOcOWiJZrGLp3fJGhk6KqGw63yeKjaH6JlttF7GuR19bzGU4E/h2MZfuj91+q2JrpKrYlUB1XCzJJfpRhoTlpYmgBBZsbEs5BnZDm1yS4b+EVimNeJahE0JdWRd/vvUujp2Jbkus1QvNgI9KF7OdklJwUDkt/whE8sUZFYE3E592Xno87GlBhZxaehdc7MHgO8FRwLa2uWqhmgqLucOJobXtzQXXAkgblgoGyVbLZWzm0uj33CAhNxuVn4J95LSC+TEiRqw4mymhRjjzUQvRlfCut/DVn+UH/jyHD9Lxo0R3sSaS/65DgFs+OTr+MCYvkIZpKwS5bsakT9D8UoLKNcUVqm+014zQTZnsuLduXxHpzJaQMtYR8WI9GMi2zTVnNsHA9dL3jsbC18hVwbXv+4UNNM4mLMIPB6O0jBojX/ftxQe+oKLQYSUClL/SvWCtoaTvfCeZ642hDJaektx***GBaNLE9Gtg5nOyNFe3gPHOpW/CyYsuasGYdMzSf4msibJvurBQQaZLxrScXp4P+mH8Hu6VIckXhBeLOr4kuOx3juC/Hw56iug7XrTZ71LoBGxYc40w3WDs6D+eFisu6TmjTTFSEaN61iqACU93bEDIiiCPsx/YoFel/0wQrfABrTHhH0rdfW9fDd7x5MAwtfKFqoPSgWu1oYJ2QguI8wSuTa4+kgJffzFhAJvFmwxTo1BU7A1kusa+db53mT/JfogMQroiDxKeHoYV3YxEzWgDcJfCvWfmkqbE3eMUjXr/6rGjJpjQCbWS06qx6tT6mwjW3qwRwUm2HtEhXqlK2veA7H6MZMUYNNm+lWAj3bZPdAkd5egDOeOs47zrwqm7qdNSq/VsbVP1mifv56jQufGvFW3oBrm8QS/3rdzJn9cKZej3ebAOLVieoYf1537ADnp9BvnJdPb5LUctxohtsBCI9XECPvMb1kLXX1m5QYGjYHt480LkAyqpdg5nz+MR4U9SWB+JeWEU+5eIhqaZ9XYt/esNQ+iD+xCynIQ3cuK9EEd7ejrtHeZT6kJUkO/MFZ3lSxqFOU4E0hOcOWiJZrGLpUsahTlOBNIUROPGhGcHK0QZwYTndJG3Ko9u12krwmSsu0I0vFH7ZFB69vmMHt61V6B1LnFPknvw2if2KtcLlrjIIptUGg6fSMwxDEog1PunMlpAy1hHxad3yRoZOiqhmRXxyh5fhYoFzjL2MWLkTcg/I+gNRY1FdMzru/mzibZ73f0lD1GpIxrcYARCQN1bl977bxpCGi2Z9Z/n4wEzLtzhBkXAmtwxlwWp0MtKYb08oPx9dcDw3uXqY3v1q6ejgiZftT3az/hDNqeKYxZN7l8mq46El08NeAijuvZKvuG3HM8XCQ9tZEyMpBjKkieddmi33o2EDcDsbf7I851H/2Www2QYKGObFcaCGvW/KUVqjZHgJH2k9n0rhCbRN6x1rFsEhJQ1NcKRAoUcV6sOlZJR5yXNpNe2bsdvJsyD1geKO9KP4/oFakMjiTYW3TSAwNVplpITFyuTnjONR37UoEciwiT5Ooj1NNNukFfAouGNaMR8XT0Y0PwWgWn6PoO9zv4QrPwlINYAnTl3dGcq4n9bSKvRJqjQTy8Q9Yos6/cegHBBLC6Ki8PnjJMsuhzFcyex/Iit1cvdmGWlYqmHRiElDMGBxY9MdbWVnmA1mib/roKWbVNcwSzdivGJ7AGec27G7YK/ZIluda/mDo6h9KJj9vffECv2I1Og2sL7RMrxKra4iMoGAv52JTAWzbjYqSAPi4N2EJTbJ+63go8LeZkc+LSRNd9o0e4eu3YuMkOhjsfdvqCOzANwWZyI0FMkAg7olqk3SvBE2meB5NKmSiEXNUaqddNsdQy2Xx2YSrxkArRj***8uDCQFsMx/6fqbU6DdaDRIYAM5OBDJWDBN+UBKb8+J7Ws9jOfPXpWpEJ2NYBaq160UToYt2qyeGSWuQtArYSQmGKgTUTwEaQEtnigmS3PmWg05TJbFE9RPLPVkBbDMf+n6m23ZURU38Y+l85akZibMqgT09FTOXLOjID6vPvdk1WI1zuKlvMgsrnld2ksWA0PzhLv5ZwspnTBbD4efvVD2nI1kxIkasOJspqTWPO3YyjtsCadhkjpkoB8mgBBZsbEs5CVXT3fbpjceeVvKURZmWmeHXGunxbArjBwTzdCW7HddtkKEOrYYAROHELqrM/Uo4nINthiVCuuY0WO2ac6fg4T/bacraI6ZhAadHK47jjawnZmK9l6Y3ANIWVU2Aa7TaOnOwoV2IYkGJdM7PkixjG+w8f1xervKESljvEi46nxLRt5xBqt0+/O/kb95r5yyzkQOlfmcTmuV/79omgMeRDP1toUlgMlzvwrP0fL0q2aPfVKcWWOpecS65TGVFOtE+FG+4f272bLOLMVhvv0PjRq2fAG2+y56T6Q3k6OnCrHGktOkaL8u3P+LFJxDxJMgnclA/y962vr8lJgYIcPb50QgVB9EUxv0xqNfGNaWc+vtfOoGhQdZz7KwFZ4/HIABTO0VuFYE7punjFVvq8lOGApVcry7R1GDmiAVtcWQIXNUqkWAqjwkQeFZxPt8jENNK2Y0qlnt6B7JKsdej7InigQN3PkD1VOzCkrqEJnuimRN57KwsDGIa1KDXtHWj+wZl6d/ktiurBZXAd38iosCSEalRHfpyGE73vrA00sp52/mtbnHlaCO/mwOIC5lGsXv5WLzI5L4QReIiKUPwt2XTzR6InHQ7gBdhWElDMGBxY9Mb71FYDcm5lox3dd6IEEyk37iqq20rbTTAOHCVgXuZv5K7bNfnFmtp/IQ5UKWk36sFjW0+IpUFumSIbrdkHfBnPJ+XCvvs86UMF98LozLJ5vIFh1pqMsWEYgSVFn1xzCRS51DcR/bsAXm+6ZnUDjQP3XgkvX826ZPx3t6Ou0d5lP6LGFxe0T4dEd7ejrtHeZT1RR4neUvJ5yUvkggbxa/irvsUHGztE4H6Y8YVRe8tnnoafw2ZnQ7wR8p0daaeLnkBQEJHqh/X2G5JEGQYHhYULPZMo+C1rEUiCVjpMsbm6OK8lY3yxGX4+TwwcDPXjHIGUJ/lW/xSgT7zyW2Et794fMbc+vTALE+m***aeR8JJQFXoHUucU+Se+tE5XQWgok0A2QqBFoM1v5DqebyX1kNVQOWEPT3WYGkYayPyWlUDxZ2IqLcUrJNhd93FPLnqVTYcHuzd1buQ+7xVltnenmawzfej+dshfUQLzi2cSRS18V4S13uwhlMHIxNHgFP3GaA79KehbxbiI4ngU+DesEptYJYzfTkQXWP5FYqeoGwPU/HjLiV5/N99GQZEqVjdVXAX4zCapefflqZHJndi91OJwl6PSwZselE0VQCHvJ8JH7teYteTyf800jDWDVhMBDZaoU4SnEbJGsS6lfm5J61RW2KWG5/tMRLlqM+lNhfPnFsEQoeY4lCpTM4Tx6YwATsQhnGnGURt7LFQk564e/grSphNeC3K5/b7bQvzfr8V4xRWKY14lqETRv0Jd6vg7fp0TGguKGJGRMmgBBZsbEs5Aotf9iAbsP2jfi4LAtvEa81c5eD3udN9SQjk1V+z9pZDg/nNBI8aVOrbyyk598O0ag8aOelk++bbicuhukdQ76/roKWbVNcwT+Rv3mvnLLOZMSJGrDibKag+TD3lJuvPQCw0vVrbq+B/TtXaSC8m1R7tHHJfVU/UaI0ZkqYA4YmFwntgeH+HXHrne+UoddqgTumjHIe/VH4T9W7GnJGlKwhJQzBgcWPTENcOLrMqWzQUisWQL/H9u2VO1wkWkMSKa7gM+DePT6N0uNC5QL09picE83Qlux3XZtVcR7mK4R1l6dfGHi/U2MhwYJRb+20hhWgptoF1kie4SUMwYHFj0xLNclRSC2cefPRPmoxh3iZFMAvMg33zu2ZQOV3leozlcXedFmYBGXRRoyTCIMW+HY5BY2dTiJsBnDK0zFd1aqcFuSDzVWfOcdaxTDIQwoD8DaojoU8XupqlvGa5IKPdYNPjPvCibYSeftyPn0m3Yh4cgBmJlHtJYkRY7Zpzp+DhM+5/sBfPW78qqIQ1zDAi0HHbt4oHfZSDrOwrVbfOob8XvLDWfeq3Q/WHM/DN/Vfja+I65oEZ7/qajKHaO+oBLQuD8PjgQx+TZyd/8SqOf3JfARMHzOcHX6AnHwmM4eUzeVkknl7dVV70VxWLLQqksMWW5JbRiieuXKr28Z5nrqZyESH9HRTP9s34rHvbcrdH5oOtfVUV4SfsdbInt3VBXD5pL7RowXKKxPEt3HGDDbEBY2WMo2lMQlR92wlP7hATzOLjP2k2ykzNIOZ3+3TW5A+nIKu6ws1gMb8SYA9nztou8gHInKj0uxWjsxpVmQvQ1ax9DhY08a0p8Zg+jx+1C2mgBBZsbEs5B+iIYttEwLXvnRYLdzZsUJEyUgOU5c+2b6X4/gsmPr3DfomqfaXSIRzCSCKMuyISecVld86z5vcSr9BR7eFEk+o8EvBEZ3zb62uQgQyD/o8n4zCapefflqZHJndi91OJwl6PSwZselE0VQCHvJ8JH7teYteTyf801egdS5xT5J7+yOVH+YeIGB4jsuH5qja+B6lvdDI3IyAEYqfYlcd6J2Kv0FHt4UST6jwS8ERnfNvoHYsIUhbMwZ3OY+bsfDMNWGH9ed+wA56fQb5yXT2+S16bPEQTlliSrpC8fNt1Vt4ZoAQWbGxLOQc5yAGekBornjifyHs+PTJrT5pSKMaPEfNg7FqbRO2+oaTvfCeZ642v//OC1TpqpPHSM6CgaaheG08/v7IrGSK2RXxyh5fhYoBcU7JoFKhLDYCF6Y6R548yUWOKdKd6ZVsgmFn4VpCiaaAEFmxsSzkFQzAwPTPtZVmgBBZsbEs5D9uD3uDpQu/pEYaSEjXvM8FllR/5vuAKrkKwMThgFyCLmHzAZfJXw68gpH8E2IuZBTnue2eiX/***ynR1pp4ueQFAQkeqH9fYbkkQZBgeFhQs9kyj4LWsRSIJWOkyxubo4ryVjfLEZfj5PDBwM9eMcgZQn+Vb/FKBPvPJbYS3v3h8xtz69MAsT6Zw1p5HwklAVegdS5xT5J760TldBaCiTQV1GjxzIiv84Ybsr32c852+mH23ThK1DGoHsiMnHjQqHYiotxSsk2Fzek1y3qcahvxj4Fs+oSR+634XaaicffI1ekOY22AGU75kHSVUHIt1wsVnDeqqNlVNJcuISzcDsn5zk9WHhQxgV/r8G/QsxtyxWC2VGFDSKO4B4vl9mYjRojDWDVhMBDZaoU4SnEbJGsVPBH5x13A9oiMoJSpPDtMlqM+lNhfPnFsEQoeY4lCpTM4Tx6YwATsQhnGnGURt7LFQk564e/grSphNeC3K5/b7bQvzfr8V4xRWKY14lqETRv0Jd6vg7fp0TGguKGJGRMmgBBZsbEs5Aotf9iAbsP2jfi4LAtvEa81c5eD3udN9SQjk1V+z9pZDg/nNBI8aVOrbyyk598O0ag8aOelk++bbicuhukdQ76/roKWbVNcwT+Rv3mvnLLOZMSJGrDibKa3qnSbxHlFx075+jdarhSsjv4j2tpTJOcR54W091U9BeI0ZkqYA4YmFwntgeH+HXHrne+UoddqgTumjHIe/VH4T9W7GnJGlKwhJQzBgcWPTENcOLrMqWzQUisWQL/H9u2VO1wkWkMSKa7gM+DePT6N0uNC5QL09picE83Qlux3XZtVcR7mK4R1l6dfGHi/U2MhwYJRb+20hhWgptoF1kie4SUMwYHFj0xLNclRSC2cefPRPmoxh3iZFMAvMg33zu2ZQOV3leozlcXedFmYBGXRRoyTCIMW+HY5BY2dTiJsBnDK0zFd1aqcFuSDzVWfOcdaxTDIQwoD8DaojoU8XupqlvGa5IKPdYNPjPvCibYSeftyPn0m3Yh4cgBmJlHtJYkRY7Zpzp+DhM+5/sBfPW78qqIQ1zDAi0HHbt4oHfZSDrOwrVbfOob8XvLDWfeq3Q/WHM/DN/Vfja+I65oEZ7/qajKHaO+oBLQzKRrLpPYxNMde/HFNlWHtIklrsE4vXAB8dKIMR1sCiEBpocsV2GmOkVxWLLQqksMWW5JbRiieuX6VYCPdtk90MBFMRgmEnuR1IZqOD0xgQMdTiIlCBbo4/Buznky85LXq0aegOazIA4fi//e2SDK6boF***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***In3vd/SUPUakjGsUwyEMKA/A6fQgipT/iUtgoSp++HQDYjlnsEWrVlbK/M1E2UOuEBoOEgF3Zac+aXKpgKD4Hk+pmgBBZsbEs5CqpepygPh17J9ORKdtLbY3OeqtPjPyD7KcEdZ5/O0yt4gBq/dOUN2UMnVi39Wbb2Gdp7ZncraWYmopjQxIidD5st9InNBgGZU5haSi6uKJVKaD6EQnG2BDkL3WLNvKgY8NdDHzFMxkMi51DcR/bsAXm+6ZnUDjQP3XgkvX826ZPx3t6Ou0d5lP6LGFxe0T4dEd7ejrtHeZT1RR4neUvJ5yUvkggbxa/ipODBzAh9TvRaY8YVRe8tnnS6lfm5J61RWxF5knUqZ+wDjfbPnU4e+fKs3MuM8YAaO7V1pbCpz/W4MzYgOpJVmiwI4q4PaSzVVEhXqlK2veA0pjT***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***nGDu4rJBQvUB5FQcFtiZ1pc5oqt+FOKM5qQVUnpi5J5/sMrVcwWPQ+y01vHg+ybRbk1HYuRHzR+EuT6K2Q37It/25RxsLDTrwjAWvQLZmUSVXf6/W0ir0Sao0HQDRKfCqRMI9jYUUiwoZ2uFuac***RUHgq3P/aaxu2sYyTruNmKzk60VbegGubxBL9VYZMAIc0wTCydYFVrzj1vRtFxPPNKzGCxgFwMc68y5Tfi4LAtvEa8ONZhuWYf3HoK2NMIdaRdFIwonRNLyws6v76l86pJd9bgeoS11Yb1/o/v6jjQHl1D341umfXf6zUb1QqKHJ9B5zGMKHPUwg0Hn6L8aGMv6kzalwx5EJqbzayGPwBprd8wnB8/zJwRFHBzr7YhhaOTksmt+5xps3WObRVr6w+YHqcRkmvniNmhqRddvduJg4F4bUhCMvVB8y4kONdn/nW2F2gajaXu4ZVBpNZQLqrUWcIfmlQmajL2C6ST7OoB7OpV2fueisOZ+TJnxkoPGxb+syCVjpMsbm6O1EnMbsMJ7AL2Xxr3KWN+zIrHR79ziGCmv9YhuF2f+hUWQVAK5/MExpUR36chhO97VL5zclaFdp3LbKuqpcpZukVyPQnmkUf7FvQEJWfJLDSX35oNNx6uQCu787Kv7GuH60***AIdklVZywlEI4Fyesz4Ti1NEa***3WYADc4L2exK4nLobpHUO+lnOlo10ve6/XnRrXQic08cd0Aw0H/Vj/SZjXVhzc0zGO2TB8KjZHbDtEWUBelV93nLdt1O6oIyR9YX6jF7dQUTkse838vgSiXRxLGOHBHAuFy7lacL+ElMlS19HXIVP8hIcoZocjzuV9gAj0PIWYp3e7WYuDlhZ0KRBILRYw5Q703fmvH94F/x8BSr0shxiXyY+8acXLXvXnym/cQntjlIkONdn/nW2F/ACSFvUtZhYRip9iVx3onYJKLOvpEVh2NurMsK0d/cKqw0QzgNLKXF6nW5TJGBD0kUSF+mcQj0xVYD9sVVkW8GvyZA4ruoYTkAaPaDvx49Oz***LO/V9YAKgOjh0DLarnJ3+S2K6sFlcZxsrTYne6k31yX4TOt7dHeDae+TwqunnX1d3U8LcjhzwRQI***MjkoGFhRfQTudnLlTWMxjsI0oh2JoGtZ7z6+sKyjNU8RjvzYa0NOH8XW3HKpeMnOZv8DEfZ00Pf1gNpNIuOUqIE1soqAg1tNQTrKIcZHGFPGAWz/5cx/A5BkoV15x3nfIsamSQxlUJJNMW2LQIDzelFcLqElDMGBxY9MZzvQH+wcSdqW0a/03s2Ao9/CRu6EBexsH6dDoR5ry8JeDVQnurI3NBY1tPiKVBbpkiG63ZB3wZzyflwr77POlDBffC6MyyebyBYdaajLFhGpcagAbwb/***ALxej6***Fm8pyEN3LivRBHe3o67R3mU+pCVJDvzBWd5UsahTlOBNITnDloiWaxi6VLGoU5TgTSFETjxoRnBytEGcGE53SRtwWwZe9BhrjE+QrAxOGAXIIuYfMBl8lfDrU0amXcwvSo5YtpSHhI4Rfpj+beBnaiR0u6dTlcriF6f8b1hQ2g6EM1SraP5dO2D7iFBaL1OVyNWsUwyEMKA/A64UCPyXk4nKQvdYs28qBj9GRcUN5q6nO4Np75PCq6eemKd3ZvMlmW8cSrd2Y85Hmy2CJhkEPkKq3kAxE0qXFENwkAI1FuF13QAi+grCu5lhwe4sCU5BNvS6/dAb5hDgqdLlnHnCQLd2j0TehCl7k41M7qjGfkTwLlE8FKCyI7TUz/8X3oLZ/v9t1gnM/1HDwdtzAVbs6ziA5D7R***C3mXJDeTo6cKscaG/63S9CE4szbzFqFM1osrh7T+8q+Cql+I4IvdXuAPl59dgIqEGGSjfo1lL4mq/QEtUWiD3oRK02Gaw607YOpZSm2uyLcD59ZIw1g1YTAQ2WqFOEpxGyRrPuLPLA9K1A5/ypOVWYgOUxVilbDiedJlZUNJNri/qaQcb1xXPiDyxru1NIX4ukkT3KKjMZOfeihROkRXF5aV+GNrelflfm4oUFtT+F2AR5/aARMcIUkbYdqJJEGGnChOaS8lAjeaHUe2Rsy/NuZb8VXbqOQ4OM207nWv5g6OofSrak2BVyqJaMPOkIQPaVmd+b8DQpZSxd01sIYAdOkGuiaxBh6PflUtgS/SenpnNk9N+LgsC28RrziSKVPCzt431uSDzVWfOcdr7v3BZ/KHCEmFQtb7hFZ/Yi26tpxk8OQCUnQ5ZjsspITaZ4Hk0qZKIRc1Rqp102x1DLZfHZhKvGQCtGNwLy4MJAWwzH/p+ptToN1oNEhgAzk4EMlYME35QEpvz4ntaz2M589elakQnY1gFqrXrRROhi3arJ4ZJa5C0CthJCYYqBNRPARpAS2eKCZLc+ZaDTlMlsUT1E8s9WQFsMx/6fqbbdlRFTfxj6XzlqRmJsyqBPT0VM5cs6MgPq8+92TVYjXO4qW8yCyueV3aSxYDQ/OEu/lnCymdMFsPh5+9UPacjWTEiRqw4mympNY87djKO2wJp2GSOmSgHyaAEFmxsSzkJVdPd9umNx55W8pRFmZaZ4dca6fFsCuMHBPN0Jbsd122QoQ6thgBE4cQuqsz9Sjicg22GJUK65jRY7Zpzp+DhP9tpytojpmEBp0crjuONrC69DO5w4e76iof6e7x3h73Yx5zGVEPVYQ16bIyzLIz8MGuYWVgF7S3rB+PXiN9bQme6Xmyt+cULq1EW3f+nVRqKxF5GTNMtHQTDZASLRn038hZp/p0E7PEy5dnabxrz3RXzzd90t8lB8='

    # # 加密
    # encrypted_data = des_encrypt(plaintext, key, iv)
    # print(f"加密后的数据::: {encrypted_data}")

    # 解密
    decrypted_data = des_decrypt(encrypted_data, key)
    print("解密后的数据:::")
    data = json.loads(decrypted_data)
    for d in data['data']['dataList']:
        print(d['noticeName'])
        print(d['noticeUrl'])
        print()

六、RSA 非对称加密

它有两把钥匙 ——一把 “公钥”(可以随便给别人) 和 一把 “私钥”(只有我自己留着)。
这两把钥匙有个神奇的特点:用公钥锁上的箱子,只有私钥能打开;反过来,用私钥锁上的箱子,也只有公钥能打开。

比如你想给我寄一个秘密箱子:
    1、我先把 “公钥” 扔给你(就像把钥匙放在你家门口,谁都能拿);
    2、你用我的公钥把箱子锁好,然后快递给我 —— 这时候就算别人拿到箱子,没有我的私钥也打不开;
    3、我收到箱子后,用自己藏好的 “私钥” 就能轻松打开。

反过来,如果我想给你发一个 “证明是我发的” 箱子:
    1、我用自己的私钥把箱子锁上,然后快递给你;
    2、你收到后,用我之前给你的公钥一试 —— 如果能打开,就说明这箱子肯定是我锁的(因为只有我的私钥能配得上这把公钥)。

这里的关键是:公钥可以公开给任何人,私钥必须自己藏好。两边不需要提前交换同一个钥匙,只要各自持有一对钥匙中的一把,就能完成加密和验证啦。

import base64
from Crypto.PublicKey import RSA  # 管理密钥的


# 1、生成私钥和公钥
rsa_key = RSA.generate(1024)  # 1024、2048、3072 复杂度
print(rsa_key)
private_key = rsa_key.export_key()
# print(private_key)
public_key = rsa_key.publickey().export_key()
print(public_key)

"""
导出
with open('private_key.txt', 'wb') as f:
    f.write(private_key)


with open('public_key.txt', 'wb') as f:
    f.write(public_key)
"""
from Crypto.Cipher import PKCS1_v1_5, AES, DES  # PKCS1_v1_5就是RSA加密

# 2、加密
f = open('public_key.txt', mode='r', encoding='utf-8')  # 读取公钥
rsa_key = RSA.import_key(f.read())  # 导入公钥

text = '我想早睡'
cipher = PKCS1_v1_5.new(rsa_key)  # 创建一个RSA对象
cipher_text = cipher.encrypt(text.encode('utf-8'))  # 进行加密
cipher_text = base64.b64encode(cipher_text)  # 进行Base64编码
print(cipher_text)

# 3、解密
f = open('private_key.txt', mode='r', encoding='utf-8')
rsa_key = RSA.import_key(f.read())  # 导入私钥
cipher = PKCS1_v1_5.new(rsa_key)  # 创建一个RSA对象
cipher_text = base64.b64decode(cipher_text)  # 进行Base64解码
plain_text = cipher.decrypt(cipher_text, None)  # 进行解密
print(plain_text.decode())

七、结尾

如何快速定位加密算法
字符串特征 可能类型
32 位十六进制 MD5 / SHA 系列
出现 % URL Encode
字符集 A-Za-z0-9+/ 且长度≈4 的倍数,结尾 = Base64
16/24/32 字节 key + 16 字节 IV AES
8 字节 key + 8 字节 IV DES
长串乱码,公钥出现 RSA

转载请说明出处内容投诉
CSS教程网 » 爬虫逆向必备:一文吃透常见加密(MD5/URL/Base64/AES/DES/RSA)

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买