1. 项目背景与需求分析
最近在分析某短视频平台的视频解析接口时,发现其采用了RSA+AES双重加密方案。这种组合加密方式在当今Web安全领域非常典型——RSA用于密钥交换,AES用于内容加密。作为爬虫开发者,我们需要逆向这套加密逻辑才能获取目标数据。
这个案例的难度评级为"一般",主要因为:
- 没有使用冷门加密算法或自定义混淆
- JS代码没有做深度混淆(如WebAssembly)
- 参数生成逻辑相对清晰
- 关键加密函数可以直接在浏览器调试工具中定位
2. 技术方案设计
2.1 整体逆向思路
典型的加密接口逆向流程:
- 抓包分析请求参数
- 定位关键加密函数
- 还原加密逻辑
- 移植到Python实现
2.2 工具准备
- Chrome开发者工具(Network面板+Sources面板)
- PyExecJS/PyV8(执行JS代码)
- Python加密库(pycryptodome)
- 请求库(requests)
3. 实操步骤详解
3.1 请求参数分析
首先用Chrome抓包发现关键请求特征:
{ "encKey": "RSA加密的字符串", "params": "AES加密的JSON数据" }3.2 JS逆向过程
在Sources面板搜索关键词encKey,定位到加密函数:
function getEncKey() { const rsa = new JSEncrypt(); rsa.setPublicKey(publicKey); return rsa.encrypt(aesKey); }3.3 Python实现方案
安装依赖:
pip install pycryptodome requests核心加密代码:
from Crypto.Cipher import PKCS1_v1_5, AES from Crypto.PublicKey import RSA from Crypto.Util.Padding import pad import base64 def rsa_encrypt(public_key, data): rsa_key = RSA.import_key(public_key) cipher = PKCS1_v1_5.new(rsa_key) return base64.b64encode(cipher.encrypt(data.encode())) def aes_encrypt(key, iv, data): cipher = AES.new(key.encode(), AES.MODE_CBC, iv.encode()) return base64.b64encode(cipher.encrypt(pad(data.encode(), AES.block_size)))4. 关键问题解决
4.1 常见报错处理
Padding错误:
- 确保AES加密时使用PKCS7填充
- 检查IV长度是否为16字节
RSA密钥格式:
- 需要将PEM格式的公钥转换为Python可识别的格式
- 注意包含
-----BEGIN PUBLIC KEY-----头尾标记
4.2 性能优化
- 缓存RSA公钥对象避免重复解析
- 使用session保持连接
- 对AES密钥做内存缓存
5. 完整代码示例
import requests from Crypto.Cipher import PKCS1_v1_5, AES from Crypto.PublicKey import RSA from Crypto.Util.Padding import pad import base64 import json class VideoSpider: def __init__(self): self.public_key = """-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDEIx... -----END PUBLIC KEY-----""" self.session = requests.Session() self.aes_key = '随机生成的16位字符串' self.aes_iv = '与key相同的16位字符串' def _encrypt_params(self, params): # RSA加密AES密钥 enc_key = rsa_encrypt(self.public_key, self.aes_key) # AES加密请求参数 enc_params = aes_encrypt( self.aes_key, self.aes_iv, json.dumps(params) ) return { 'encKey': enc_key.decode(), 'params': enc_params.decode() } def get_video_info(self, video_id): params = {'videoId': video_id} encrypted = self._encrypt_params(params) response = self.session.post( 'https://api.example.com/video/detail', data=encrypted ) return response.json()6. 安全与反爬策略
6.1 应对反爬措施
- 随机化请求头中的User-Agent
- 控制请求频率(建议3-5秒/次)
- 使用代理IP池
6.2 法律风险提示
- 仅用于学习交流
- 不要绕过付费内容
- 遵守robots.txt协议
7. 扩展应用
这套方法可以复用于:
- 其他使用RSA+AES的网站
- 微信小程序接口分析
- 移动端APP接口逆向
实际开发中我发现,90%的网站加密方案都可以用这种组合加密思路破解。关键在于耐心分析JS代码和正确移植加密算法。