Skip to content

js逆向是一座大山

一、浏览器的问题

1.Elements

里面的东西是页面源代码 =>可以经过js进行整容(script),浏览器进行二次渲染(如table或其他标签),=>elements里面的代码

2.Console

控制台,这里可以写js代码

3.Sources

放着页面源代码和网页的所有资源,后期会作为调试js的主要工具

4.Network:

  • headers:

    • User-agent:请求的设备版本,以后所有请求至少给一个这个东西
    • Refer:防盗链,在抓包工具中,双击url,如果能跳转获取到你需要的东西,就不需要加Refer,Refer其实就是判断上一个url是什么
  • Payload:请求参数,get,post

    • get请求

      • query String parameters

        • 把参数通过url进行传递

          url = “http://www.baidu.com?name=coder&age=18”

        • 通过params传递参数

          python
          url = “http://www.baidu.com”
          dict = {
            name: "coder",
            age: 18
          }
          requests.get(url, params = dict)
          #上述参数最终也会放到url里
    • post请求

      发送请求默认Content-Typeapplication/x-www-form-urlencoded

      • Form Data

        python
        #直接给字典就行
        url = “http://www.baidu.com”
        data = {
          name: "coder",
          age: 18
        }
        requests.post(url, data = data)
        #上述参数最终也会放到url里
      • Request Payload

        请求挂载,传输的数据大多情况下是json字符串,在payload里面可以观察到是json格式的数据,或者在请求头里面看到Content-Type:application/json

        • 通过data传递数据

          python
          import json
          url = “http://www.baidu.com”
          data = {
            name: "coder",
            age: 18
          }
          headers = {
            Content-Type: "application/json;charset=utf-8"
          }
          requests.post(url, data = json.dumps(data, separators=(",", ":")), headers = headers)
        • 通过requests中的json直接处理,不过有坑!

          python
          url = “http://www.baidu.com”
          data = {
            name: "coder",
            age: 18
          }
          requests.post(url, json = data)

          坑就是:python自动进行字典转换为json的时候,会有空格,很多后台在做反爬时会判断,这种时候没法解决,只能换data方式

如果在protocol里面看到h2的时候,表示当前请求用的是http2.0的版本,大多数网页都是兼容http1.1的,有些网页会屏蔽http1.1,python的requests模块不支持http2.0,如果你能使用的所有手段都测试过了发现还是不行,可以考虑用一下http2的请求,python发送http2的请求使用httpx

bash
pip install httpx
python
import httpx
client = httpx.Client(http2=True)
#后面和requests一样
client.get()
client.post()

5.Application:cookies

在requests中详解

6.无痕模式

去除缓存的干扰,建议使用

二、requests

几个关键点

可以直接使用session来代替requests,建议使用session

  • 优点1是保存cookie信息
  • 优点2是保存headers信息
python
import requests

session = requests.session()
url = ""

resp = session.get(url)
print(resp.cookies)
print(session.cookies)#已经拿到了
#修改cookies或headers
session.cookies.set("name", "hello")
session.headers = {
  "user-agent": "xxxx"
}
#后面可以直接使用session来发送请求,不用每次都传入headers
session.get(url)

三、数据解析

  • html

bs4 xpath

  • js代码

    使用re,正则来做

jsonp:js代码+数据(jd为例)

image-20230606142527089

py
obj = re.compole(r"\((?P<data>.*)\)")

r = obj.search(res)
# print(r.group("data"))

import json
resp = json.loads(r.group('data'))
print(resp)
  • json数据

    python
    resp = session.get()
    print(resp.text) # 先看一下获取的东西是不是json
    dic = resp.json()
  • png,jpg图片,m3u8,mp4….

  • css样式文件 直接保存即可

  • 字体文件 直接保存即可

  • 其他

    一些加密数据,看js是怎么加密的我们就怎么解密

四、存储

1.存储csv

python
lst = [
    (1,"a", "aaaa"),
    (2,"b", "bbbb"),
    (3,"c", "cccc"),
]
with open("数据.csv", mode="w", encoding="utf-8") as f:
    for item in lst:
        f.write('"'+str(item[0])+'"')
        f.write(",")
        f.write(str(item[1]))
        f.write(",")
        f.write(str(item[2]))
        f.write("\n")

# 如果数据中有逗号
with open("数据.csv", mode="w", encoding="utf-8") as f:
    for item in lst:
        f.write('"'+str(item[0])+'"')
        f.write(",")
        f.write('"'+str(item[1])+'"')
        f.write(",")
        f.write('"'+str(item[2])+'"')
        f.write("\n")

# 如果有一些奇怪符号如引号,那就更换分隔符
# 要告诉客户分隔符是什么
with open("数据.csv", mode="w", encoding="utf-8") as f:
    for item in lst:
        f.write(str(item[0]))
        f.write("|")
        f.write(str(item[1]))
        f.write("|")
        f.write(str(item[2]))
        f.write("\n")

import pandas as pd

r = pd.read_csv("数据.csv", sep="|", header=None)
print(r)
#转存到excel
r.to_excel("data.xlsx")

2.mysql

sqlite好用

3.sqlite3

python
import sqlite3

conn = sqlite3.connect("data.db")
cur = conn.cursor()
try:
  sql = ""
  cur.excute(sql, (p1, p2, ...))
  cur.commit()
except Exception as e:
  print(e)

4.普通文件下载

python
import requests
url = ""
resp = requests.get(url)
with open("", mode="wb") as f:
    f.write(resp.content)

五、如何提高爬虫效率

  • 多线程

    直接上线程池,控制好并发

    相似或者相同的任务适合多线程

    python
    from concurrent.futures import ThreadPoolExecutor
    
    def work(i):
        print("爬取", i)
    
    # 10是并发量,注意控制
    if __name__ == '__main__':
        with ThreadPoolExecutor(10) as t:
            for i in range(100):
                t.submit(work, i)
        print("done")
  • 多进程

    多个任务之间关联不大的时候可用多进程

  • 协程

    电影:m3u8一般不设防,一堆URL,下载文件,一般是云服务,

六、爬虫框架

scrapy,一般不用

七、找到加密入口方案

目标:

  • 参数加密前什么样
  • 怎么加密的

1. 找浏览器的initiator

启动器,下下策,它记录着浏览器js执行的过程

request call stack

  • 断点

    • 可以查看当前这个位置所有能够使用到的标量
    • 可以查看当前位置可以执行的函数是什么?以及函数执行之后的结果是什么,甚至可以改变当前位置的函数声明
    • 可以在断电状态下,选择一个变量或函数,鼠标划上去,看一下有什么东西
    • 可以在断点状态下,在console中输入一个变量或者函数,来看该函数或变量的内容,通过call stack可以查看上一步调用位置的参数,数据,内存,函数(可能会有风险,但是问题不大),但是不要去单步调试,尽可能在当前断点位置进行调试
    image-20230607072706075
  • 加密相关

    image-20230607113601508

类似上面这种,一般是第三方库,Crypto-js

如何抠代码:

  • 找到入口,把入口拿下来,尝试一个函数一个函数的去填补,过程非常曲折

  • 找到代码的边界

    一个大闭包?两个闭包之间?肯定是具有相似性的,需要人为去判别

  • 找第三方库

2.在Search中进行搜索,这是最好的方案

  • 搜url,在url的?前面一个单词接一个单词的搜索

  • 搜参数,请求上的各种参数,主要针对加密参数

  • 拦截器,该网站使用的异步,Promise

没有100%的方案,又快又准确,没有哟!

八、加密

1.md5

当在网站上看到一些加密逻辑,发现计算结果是32位字符串长,该字符串的组成是0-9a-f(十六进制) 然后去尝试,把123456丢进去,看看结果,如果是e10开头,直接标准md5,就可以开始写python代码了

python
from hashlib import md5
# md5可以加盐,默认是放在待加密数据前面
# obj = md5(b'jdklajflauei')
obj = md5(b'jdkajflajf')

obj.update("hello".encode("utf-8"))
md5_val = obj.hexdigest()
# 0aee8e7baca0a10ea2f97c6f5c6b1f27
print(md5_val)
print(len(md5_val))

def get_md5(s):
    obj = md5()
    obj.update(s.encode("utf-8"))
    return obj.hexdigest()

# 0aee8e7baca0a10ea2f97c6f5c6b1f27
print(get_md5("jdkajflajfhello"))

sha1 sha512等等都一样,可以查网站https://1024tools.com/hash

#算法结果结果(大写)长度备注
1md5e10adc3949ba59abbe56e057f20f883eE10ADC3949BA59ABBE56E057F20F883E32前16位: 小写:e10adc3949ba59ab 大写:E10ADC3949BA59AB
2sha17c4a8d09ca3762af61e59520943dc26494f8941b7C4A8D09CA3762AF61E59520943DC26494F8941B40
3sha2568d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c928D969EEF6ECAD3C29A3A629280E686CF0C3F5D5A86AFF3CA12020C923ADC6C9264
4sha512ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413BA3253876AED6BC22D4A6FF53D8406C6AD864195ED144AB5C87621B6C233B548BAEAE6956DF346EC8C17F5EA10F35EE3CBC514797ED7DDD3145464E2A0BAB413128
5adler32042e0136042E01368
6crc3270930f2770930F278
7crc32b0972d3610972D3618
8crc32c41357186413571868
9fnv132eb008bb8EB008BB88
10fnv16410f897e26c4b947810F897E26C4B947816
11fnv1a329995b6aa9995B6AA8
12fnv1a64f6e3ed7e0e67290aF6E3ED7E0E67290A16
13gost84cdecc9c273927ff6d9cca1ae75945990a2cb1f81e5daab52a987f6d788c37284CDECC9C273927FF6D9CCA1AE75945990A2CB1F81E5DAAB52A987F6D788C37264
14gost-crypto7db20e3a7d652bde0b1a1b7486076a2e11f795e99bf7f5fe700fb83f15b19ef27DB20E3A7D652BDE0B1A1B7486076A2E11F795E99BF7F5FE700FB83F15B19EF264
15haval128,31d8071d4a59f25a2a92a9a4844ba1e051D8071D4A59F25A2A92A9A4844BA1E0532
16haval128,42019090003211f11c03adb877bf3ae202019090003211F11C03ADB877BF3AE2032
17haval128,560271b45e6d4b8eea7d9f474e69c848b60271B45E6D4B8EEA7D9F474E69C848B32
18haval160,383e612afb8ed267198b696759a49561375f70c8183E612AFB8ED267198B696759A49561375F70C8140
19haval160,43da690924ffb8d3f5bff8b608279f3c419bdb9c93DA690924FFB8D3F5BFF8B608279F3C419BDB9C940
20haval160,5ee85271e7bb4b7f2ec4c5418b47804eb1be9e91fEE85271E7BB4B7F2EC4C5418B47804EB1BE9E91F40
21haval192,3d2cfda5179fd9b6037ba35f261c576b2300717151a8db6a5D2CFDA5179FD9B6037BA35F261C576B2300717151A8DB6A548
22haval192,47e1e573209c8d7f39919bea0d1466df325f3dbdd1fd3057a7E1E573209C8D7F39919BEA0D1466DF325F3DBDD1FD3057A48
23haval192,59e8acd170a8fe1b929c0c652397b6b494abf1cd095371ad79E8ACD170A8FE1B929C0C652397B6B494ABF1CD095371AD748
24haval224,3d59e77b4c4d7aa6e02708683381c5631ee79b9e50ab9eaeb4dc38b9aD59E77B4C4D7AA6E02708683381C5631EE79B9E50AB9EAEB4DC38B9A56
25haval224,464d007c6e75ee71244bf33a876c8f380c17e64b18d3d9be67000b27764D007C6E75EE71244BF33A876C8F380C17E64B18D3D9BE67000B27756
26haval224,5dbcdd0348d0b23a89fe3e190abd8b279a5d8d4fa4e62d1e02ad0a6ffDBCDD0348D0B23A89FE3E190ABD8B279A5D8D4FA4E62D1E02AD0A6FF56
27haval256,30e3b78d8380844b0f697bb912da7f4d210382c6714194fd16039ef2acd924dcf0E3B78D8380844B0F697BB912DA7F4D210382C6714194FD16039EF2ACD924DCF64
28haval256,484095060071ad0f4f41fa629653511074720aaa94c4f0d873e317d58002f802084095060071AD0F4F41FA629653511074720AAA94C4F0D873E317D58002F802064
29haval256,52f014311e0926fa8b3d6e6de2051bf69332123baadfe522b62f4645655859e7a2F014311E0926FA8B3D6E6DE2051BF69332123BAADFE522B62F4645655859E7A64
30joaateef833c1EEF833C18
31md2d4541250b586296fcce5dea4463ae17fD4541250B586296FCCE5DEA4463AE17F32
32md4585028aa0f794af812ee3be8804eb14a585028AA0F794AF812EE3BE8804EB14A32
33ripemd128d6d56cab46e0f3af2c756289f2b447e0D6D56CAB46E0F3AF2C756289F2B447E032
34ripemd160d8913df37b24c97f28f840114d05bd110dbb2e44D8913DF37B24C97F28F840114D05BD110DBB2E4440
35ripemd25677093b1266befed58d512e67b3a8a15398c3ce5c1333d66a190becc9baa329e977093B1266BEFED58D512E67B3A8A15398C3CE5C1333D66A190BECC9BAA329E964
36ripemd320a2ee4b6b9e3144c7db61b1ffc748bf2c728b65819e3f69a021f515acb044995b90f03d60974b6b4aA2EE4B6B9E3144C7DB61B1FFC748BF2C728B65819E3F69A021F515ACB044995B90F03D60974B6B4A80
37sha224f8cdb04495ded47615258f9dc6a3f4707fd2405434fefc3cbf4ef4e6F8CDB04495DED47615258F9DC6A3F4707FD2405434FEFC3CBF4EF4E656
38sha3-2246be790258b73da9441099c4cb6aeec1f0c883152dd74e7581b70a6486BE790258B73DA9441099C4CB6AEEC1F0C883152DD74E7581B70A64856
39sha3-256d7190eb194ff9494625514b6d178c87f99c5973e28c398969d2233f2960a573eD7190EB194FF9494625514B6D178C87F99C5973E28C398969D2233F2960A573E64
40sha3-3841fb0da774034ba308fbe02f3e90dc004191df7aec3758b6be8451d09f1ff7ec18765f96e71faff637925c6be1d65f1cd1FB0DA774034BA308FBE02F3E90DC004191DF7AEC3758B6BE8451D09F1FF7EC18765F96E71FAFF637925C6BE1D65F1CD96
41sha3-51264d09d9930c8ecf79e513167a588cb75439b762ce8f9b22ea59765f32aa74ca19d2f1e97dc922a3d4954594a05062917fb24d1f8e72f2ed02a58ed7534f94d2764D09D9930C8ECF79E513167A588CB75439B762CE8F9B22EA59765F32AA74CA19D2F1E97DC922A3D4954594A05062917FB24D1F8E72F2ED02A58ED7534F94D27128
42sha3840a989ebc4a77b56a6e2bb7b19d995d185ce44090c13e2984b7ecc6d446d4b61ea9991b76a4c2f04b1b4d2448414494540A989EBC4A77B56A6E2BB7B19D995D185CE44090C13E2984B7ECC6D446D4B61EA9991B76A4C2F04B1B4D24484144945496
43sha512/224007ca663c61310fbee4c1680a5bbe70071825079b23f092713383296007CA663C61310FBEE4C1680A5BBE70071825079B23F09271338329656
44sha512/256184b5379d5b5a7ab42d3de1d0ca1fedc1f0ffb14a7673ebd026a6369745deb72184B5379D5B5A7AB42D3DE1D0CA1FEDC1F0FFB14A7673EBD026A6369745DEB7264
45snefru3321dcaf8911d3842e14a7a415be2fb1a337f4306a4fb8290fd7fe33be269df73321DCAF8911D3842E14A7A415BE2FB1A337F4306A4FB8290FD7FE33BE269DF764
46snefru2563321dcaf8911d3842e14a7a415be2fb1a337f4306a4fb8290fd7fe33be269df73321DCAF8911D3842E14A7A415BE2FB1A337F4306A4FB8290FD7FE33BE269DF764
47tiger128,35b2715f7cb7488ce2deb8544f0aa91b65B2715F7CB7488CE2DEB8544F0AA91B632
48tiger128,4effe440b596c7d1766d435a2fd16641eEFFE440B596C7D1766D435A2FD16641E32
49tiger160,35b2715f7cb7488ce2deb8544f0aa91b6f0eec76f5B2715F7CB7488CE2DEB8544F0AA91B6F0EEC76F40
50tiger160,4effe440b596c7d1766d435a2fd16641e27d32af5EFFE440B596C7D1766D435A2FD16641E27D32AF540
51tiger192,35b2715f7cb7488ce2deb8544f0aa91b6f0eec76fb3b742655B2715F7CB7488CE2DEB8544F0AA91B6F0EEC76FB3B7426548
52tiger192,4effe440b596c7d1766d435a2fd16641e27d32af54ec875c2EFFE440B596C7D1766D435A2FD16641E27D32AF54EC875C248
53whirlpoolfd9d94340dbd72c11b37ebb0d2a19b4d05e00fd78e4e2ce8923b9ea3a54e900df181cfb112a8a73228d1f3551680e2ad9701a4fcfb248fa7fa77b95180628bb2FD9D94340DBD72C11B37EBB0D2A19B4D05E00FD78E4E2CE8923B9EA3A54E900DF181CFB112A8A73228D1F3551680E2AD9701A4FCFB248FA7FA77B95180628BB2128

2.URLEncode和Base64

(1)URLEncode

quote和quote_plus可以帮我们完成字符串的处理

在逆向的过程中,有可能需要我们在处理cookie的时候,可能会用到

python
from urllib.parse import quote, quote_plus

#  %26%3Dlove/
print(quote("&=love/"))
#  %26%3Dlove%2F
print(quote_plus("&=love/"))

反向使用unquote,unquote_plus

2.base64

base64的encode作用是将字节ascII范围内的字节,3个字节变成4个字节,

26个大写字母+26个小写字母+10个数字+2个特殊字符(+和/),它是一种摘要算法,跟加密解密没有关系

python
import base64

# encode过程
s = "我爱上天".encode("utf-8") # b'\xe6\x88\x91\xe7\x88\xb1\xe4\xb8\x8a\xe5\xa4\xa9'
# 先使用base64编码,编码后bs4同样是字节,不过都是ascII范围内的
bs4 = base64.b64encode(s) # b'5oiR54ix5LiK5aSp'
# 将字节处理成base64字符串
print(bs4.decode()) # 5oiR54ix5LiK5aSp

# decode过程
s = "5oiR54ix5LiK5aSp"
bs = base64.b64decode(s) # b'\xe6\x88\x91\xe7\x88\xb1\xe4\xb8\x8a\xe5\xa4\xa9'
  • base64的末尾可能是=,是用来填充的

  • base64既然可以把字节处理成字符串,有的网站就会把一些小的图片(头像,图标)处理成base64,学会吧base64的图片转存为真实的图片

    python
    s = "data:image/png;base64, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxjfklafjdla"
    s = s.split(',')[1]
    bs = base64.b64decode(s)
    with open('xxx.png', mode='wb') as f:
      f.write(bs)
  • 有些时候,有的网站会把base64进行特殊的处理,比如把+替换成-,把/替换成_

    • 应对方案一:replace(“-”, "+").replace("_", "/")

    • 应对方案二:使用base64自动处理

      python
      sy = "Z21kD9ZK1ke6ugku2ccWu-MeDWh3z252xRTQv-wZ6jddVo3tJLe7gIXz4PyxGl73nSfLAADyElSjjvrYdCvEP4pfohVVEX1DxoI0yhm36ytQNvu-WLU94qULZQ72aml65Eb-"
      bsy = base64.b64decode(sy,altchars=b"_-")

      如果通过上述转换后,进行解密操作发现数据不对,或者根本无法解密,调换一下顺序即可。

  • 字符串可以转换为十六进制的数字,转化逻辑:字节=>8个二进制=>数字=>十六进制,可以使用一个库来操作,那就是binascii

    python
    import binascii
    # 字符串转换成十六进制
    bs = "abcd我喜欢你".encode("utf-8") #字符串变字节
    res = binascii.b2a_hex(bs)
    print(res) # b'61626364e68891e5969ce6aca2e4bda0'
    # 十六进制转换为字节
    s = "61626364e68891e5969ce6aca2e4bda0"
    print(binascii.a2b_hex(s))
    # b'abcd\xe6\x88\x91\xe5\x96\x9c\xe6\xac\xa2\xe4\xbd\xa0'

3.AES

标准库:

  • 对称加密:加密和解密时使用的是同一个密钥
  • 非对称加密:加密和解密时使用的密钥不是同一个

python的一个第三方库提供了加密逻辑,PyCrypto,一般装不上,使用pycrytodome进行平替

bash
pip install pycryptodome

安装成功后,有可能加密包无法使用(不一定能用)

 ```python
 from Crypto.Cipher import AES
 from Crypto.Util.Padding import pad
 
 # 创建一个aes加密器
 aes = AES.new(key=b'1234567890123456',IV=b'1234567890123456',mode=AES.MODE_CBC)
 
 ming = "这是一个测试用例"
 ming = ming.encode("utf-8")
 # 注意这里加密必须要填充成16字节的倍数,可以使用自带的pad来进行填充
 # Data must be padded to 16 byte boundary in CBC mode
 ming = pad(ming, 16)
 mi = aes.encrypt(ming)
 print(mi)
 
 # 解密
 aes = AES.new(key=b'1234567890123456',IV=b'1234567890123456',mode=AES.MODE_CBC)
 mi = base64.b64decode(mi)
 ming = aes.decrypt(mi)
 ming = unpad(ming, 16)
 print(ming.decode("utf-8"))
 ```

key通常是16位的字节

new创建一个密码器,AES的key有16位、24位、32位字节几种情况,我们在使用时不对了可以切换再试,一般网站上给出的key可能是16进制字符串(32)位,这种情况99%的可能是使用16字节的key,转换关系为每2个字符串对应于一个字节,使用binascii.a2b_hex(xxxx)

image-20230609142158902

mode

ECB:不需要给IV

CBC:需要给一个16位的IV

总结:

加密:明文字符串-处理成字节-填充pad至16字节倍数-加密-密文(字节)-base64处理成16进制字符串-加密字符串

解密:倒过来,先用base64将字符串转为字节,再通过aes解密为字节,unpad成可识别的utf-8编码字节后decode

4.DES

和AES基本一样,区别的是加密的字节需要是8字节的倍数,区别就在pad和unpad的参数,DES是8

python
import base64

from Crypto.Cipher import DES
from Crypto.Util.Padding import pad, unpad
# 加密
# create a DES encryptor
des = DES.new(key=b'12345678', IV=b'12345678', mode=DES.MODE_CBC)
ming = "我爱你,宝贝"
ming = ming.encode()
print(ming)
ming = pad(ming, 8)
mi = des.encrypt(ming)
print(mi)
mi = base64.b64encode(mi).decode()
print(mi)

# 解密
des = DES.new(key=b'12345678', IV=b'12345678', mode=DES.MODE_CBC)
dmi = "mv8qg9CMzRDzwxmtMQh5zjmjgPo8PTxV"
dmi = base64.b64decode(dmi)
print('===', dmi)
dmi = des.decrypt(dmi)
print(dmi, len(dmi))
dmi = unpad(dmi, 8)
print(dmi, len(dmi))
dmi = dmi.decode()
print(dmi)

实际案例:

image-20230612195257249

全国招标公告公示搜索引擎-中国招标投标公共服务平台 (ctbpsp.com)

python
import base64
import json

import requests

session = requests.session()
session.headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.43"
}
url = "https://custominfo.cebpubservice.com/cutominfoapi/recommand/type/5/pagesize/10/currentpage/1"
resp = session.get(url=url)
# print(resp.text)

mi = resp.text.strip('"')

# 解密
from Crypto.Cipher import DES
from Crypto.Util.Padding import pad, unpad

key_str = "1qaz@wsx3e"
des = DES.new(key=key_str[:8].encode("utf-8"), mode=DES.MODE_ECB)
mi = base64.b64decode(mi)
ming = des.decrypt(mi)
ming = unpad(ming, 8)
s = ming.decode()
dic = json.loads(s)
print(dic)
# print(s)

image-20230612195407375

5.非对称加密 RSA

非对称加密,加密和解密的密钥不一样,加密的是公钥,解密的是私钥,公钥和私钥是一对,在生成密钥的时候会同时生成,必须配合使用才行。rsa最为常用,可以说是一加独大,python中主要有两个库支持rsa,只需掌握一个。在前端js,rsa加密逻辑有两个:

  • No Padding:这种方案不推荐直接用python搞,推荐用js库弄
  • PKCS padding:python中只能搞这种

rsa两个特征:

  • 65537

  • 010001 (16进制,转为10进制就是65537)70%是noPading,建议使用js来做

  • JSEncrypt js的一个第三方加密库,专门用来做rsa加密, PKCs,padding

  • publicKey 一定是rsa加密,如果穿进去的是一个base64字样的东西,99%是PCKS padding

生成公钥he私钥的方式:

python
from Crypto.PublicKey import RSA # 这个RSA帮我们生成公钥和私钥
# 如何生成公钥和私钥,一定要一起生成,先生成私钥再生成公钥,默认导出的key都是pem格式
# 生成的key是私钥
key = RSA.generate(bits=1024, e=65537)
with open("private.pem", mode="wb") as f:
    f.write(key.exportKey())

# 公钥是用私钥来生成
with open("public.pem", mode="wb") as f:
    f.write(key.public_key().exportKey())

image-20230614105045140

加密处理:

python
# 加密
import base64
from Crypto.Cipher import PKCS1_v1_5
from Crypto.PublicKey import RSA # 这个RSA帮我们生成公钥和私钥
# 明文
s = "这是一个测试"
# 明文转换成字节才能加密
ming_s = s.encode()
# 读取公钥
f = open("public.pem", mode="rb")
pub_key = RSA.importKey(f.read())
# 加密器
rsa = PKCS1_v1_5.new(pub_key)
# 加密完成生成的是字节
mi_bs = rsa.encrypt(ming_s)
print(mi_bs)
# 使用base64将字节转换为字符串
mi_s = base64.b64encode(mi_bs).decode()
print(mi_s)

解密处理:

Released under the MIT License.