Python爬蟲進階必備 | 一個典型的 AES 加密在爬蟲中的應用案例
- 2019 年 10 月 31 日
- 筆記

一個典型的AES案例
AES 的案例之前有推薦大家關於 AES 加密的案例文章,不少朋友問我加密解決了有什麼用?
最大的用途當然就是不用模擬請求,大大提高了爬取效率。
可能之前舉例都是使用的 AES 加密的密碼,所以不少朋友只關注了加密沒注意實現後的用途,所以這次再寫一個其他的 AES 加密作為示例。
這個例子來自 JS 逆向課程的預售群,偶然看到有群友提問,這裡簡單分析一下。
分析加密
抓包可以看到這裡 data 部分是加密的。【圖1-1】

直接搜索 data 這個加密參數可以看到有很多的相關項【圖1-2】

那麼如何快速定位這個加密內容解密的地方呢?
我們把請求返回的內容先美化一下,看看有沒有什麼點可以追蹤一下。
可以看到在返回內容里和加密相關的欄位有一個 isEncrypt 通過參數的名字我們可以猜測這個欄位是用來標識內容是否加密。【圖1-3】

我們檢索這個欄位看看有什麼樣的結果。【圖1-4】

可以看到只有兩個相關的內容,我們在第一個找到了解密相關的內容。【圖1-5】

接下來就可以參考我前面的文章套路直接把關鍵的解密程式碼套進去就可以解密了。
可以直接套用 JS 的解密程式碼,也可以參考我們文章舉例的 Python 程式碼
Python 複寫加密
我們先把上次的 Python 程式碼 CV 過來。
import base64from Crypto.Cipher import AESimport random def pkcs7padding(text): """ 明文使用PKCS7填充 最終調用AES加密方法時,傳入的是一個byte數組,要求是16的整數倍,因此需要對明文進行處理 :param text: 待加密內容(明文) :return: """ bs = AES.block_size # 16 length = len(text) bytes_length = len(bytes(text, encoding='utf-8')) # tips:utf-8編碼時,英文佔1個byte,而中文佔3個byte padding_size = length if(bytes_length == length) else bytes_length padding = bs - padding_size % bs # tips:chr(padding)看與其它語言的約定,有的會使用'' padding_text = chr(padding) * padding return text + padding_text def pkcs7unpadding(text): """ 處理使用PKCS7填充過的數據 :param text: 解密後的字元串 :return: """ length = len(text) unpadding = ord(text[length-1]) return text[0:length-unpadding] def encrypt(key, content): """ AES加密 key,iv使用同一個 模式cbc 填充pkcs7 :param key: 密鑰 :param content: 加密內容 :return: """ key_bytes = bytes(key, encoding='utf-8') iv = key_bytes cipher = AES.new(key_bytes, AES.MODE_CBC, iv) # 處理明文 content_padding = pkcs7padding(content) # 加密 encrypt_bytes = cipher.encrypt(bytes(content_padding, encoding='utf-8')) # 重新編碼 result = str(base64.b64encode(encrypt_bytes), encoding='utf-8') return result def decrypt(key, content): """ AES解密 key,iv使用同一個 模式cbc 去填充pkcs7 :param key: :param content: :return: """ key_bytes = bytes(key, encoding='utf-8') iv = key_bytes cipher = AES.new(key_bytes, AES.MODE_CBC, iv) # base64解碼 encrypt_bytes = base64.b64decode(content) # 解密 decrypt_bytes = cipher.decrypt(encrypt_bytes) # 重新編碼 result = str(decrypt_bytes, encoding='utf-8') # 去除填充內容 result = pkcs7unpadding(result) return result def get_key(n): """ 獲取密鑰 n 密鑰長度 :return: """ c_length = int(n) source = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678' length = len(source) - 1 result = '' for i in range(c_length): result += source[random.randint(0, length)] return result
按照程式碼上的注釋,我們找找這裡我們 key 和 iv 是怎麼生成的。【圖2-1】

參考【圖1-3】這個 lastFetchTime 就是請求返回的值。
所以我們按照 JS 邏輯直接把加密內容和 key 傳入即可。
data = 'WPZVRdF+hMHReWs0rgM+SR+uV3TjVPhsVKOCrW+cOF8jfhT/JL/faU3tYyBVPkyJsV+P6ReJ46/Pi0...' encrypt_en = decrypt('1572353144793000',data) print(encrypt_en)解密的結果如下:【圖2-2】

以上就是 AES 加密的另一種在爬蟲中的運用了。
