抓包全是密文?AES+RSA混合加密接口逆向全流程实战 📅 2026/6/21 8:00:02 做工业数据采集的朋友大概率都碰过这种硬骨头接口地址一清二楚请求响应也能正常抓到可参数和返回体全是一长串无意义的字符串肉眼根本读不出结构。普通的接口采集方案直接失效想拿到结构化数据就得先过加密这道关。在所有传输层防护方案里AESRSA混合加密是普及率最高的一种保守估计占了加密接口的90%以上。看起来复杂其实套路非常固定只要摸清楚了标准流程绝大多数加密接口都能按图索骥破解掉。今天这篇文章我把混合加密的原理、逆向全流程、参数对齐技巧、常见踩坑点一次性讲透看完你就能独立搞定绝大多数AES/RSA加密接口。一、前期准备先搞懂混合加密的底层逻辑1.1 为什么一定是AESRSA混合单独用AES对称加密加解密速度快但密钥需要和数据一起传输很容易被截获单独用RSA非对称加密安全性高但加密速度极慢稍长一点的业务数据就扛不住性能开销。混合加密就是取两者的长处是工业界通用的标准方案用RSA传输AES的随机密钥密钥很短非对称加密完全扛得住用AES加密实际业务数据速度快适合大批量业务数据传输站点不会凭空发明加密算法绝大多数都是基于这套标准逻辑做的封装这也是逆向有章可循的根本原因。1.2 混合加密标准交互流程服务端客户端服务端客户端生成随机AES密钥RSA公钥加密AES密钥AES加密业务请求数据发送【加密密钥 加密数据】RSA私钥解密出AES密钥AES密钥解密业务数据AES加密响应数据返回加密响应AES密钥解密响应数据简单来说就是非对称加密管密钥对称加密管数据。一次请求生成一次随机密钥既保证了传输安全又不损失性能。1.3 快速识别一眼判断是不是混合加密不用翻代码抓包看字段就能猜个八九不离十请求体里通常有两个核心字段一个短的固定长度字段加密后的AES密钥一个长的可变长度字段加密后的业务数据字段名常见为encryptKey、secretKey、ciphertext、encryptData、data等密文格式多为Base64编码偶尔是Hex字符串2048位RSA加密后的密钥Base64编码后约344字符1024位约172字符抓包就能大致判断密钥长度符合这几个特征90%概率就是标准的AESRSA混合加密。1.4 工具准备浏览器开发者工具F12核心调试工具用来断点定位加密逻辑Python 3.x最终的代码复现环境pycryptodome库Python侧的加解密实现安装命令pip install pycryptodome可选Node.js环境用来运行扣取的JS代码做对比验证二、分步实操从抓包到Python复现完整流程2.1 第一步抓包定位锁定加密字段先不要急着翻代码第一步先把输入输出搞清楚后面调试才有参照。找一个有明确业务含义的请求比如列表页、详情页接口确保能稳定复现对比请求参数和页面展示内容确认哪些字段是加密的明文大致是什么结构记录加密字段的名称、编码格式Base64/Hex、大致长度同样确认响应体的加密字段位置和格式这一步的核心是明确目标我们要复现的是哪个函数的输入输出避免后面调试的时候漫无目的。2.2 第二步断点调试定位加密入口这是逆向最关键的一步找到JS里执行加密的具体位置。三种常用方法按效率从高到低排序1. 关键词搜索法优先用直接在Sources面板全局搜索关键词encrypt、AES、RSA、CryptoJS、cipher、encryptKey大概率能直接定位到加密函数。绝大多数站点的加密代码不会过度混淆函数名搜关键词是最快的方式。2. XHR断点回溯法如果关键词搜不到给目标接口打XHR断点刷新页面触发请求后查看调用栈从发起请求的位置往前回溯找参数组装和处理的逻辑加密函数一定在请求发出之前的调用链上。3. Hook拦截法针对JSON.stringify、btoaBase64编码这类通用方法打Hook在加密前的明文处断下来顺着调用栈往上找就能找到调用加密函数的位置。定位到加密函数后先打个断点触发一次请求看清楚入参和出参入参是明文业务数据出参是加密后的密文和密钥。2.3 第三步提取算法参数抠出核心逻辑找到加密函数后不要急着全量扣代码先确认几个核心参数——这是后续复现的关键80%的复现失败都是参数没对齐。AES部分必须确认的参数算法模式最常见的是CBC其次是ECBGCM模式也逐渐增多填充方式绝大多数是Pkcs7对应Python里的PKCS7填充IV偏移量CBC/GCM模式必须有ECB模式没有长度固定16字节密钥长度128位16字节最常见256位32字节次之RSA部分必须确认的参数填充方式PKCS1_v1_5最普遍少数站点用OAEP填充公钥内容一般是固定的PEM格式字符串或者硬编码的模数指数密钥长度1024位和2048位为主把这些参数和公钥提取出来再确认密文的输出编码格式基本就完成了80%的工作。2.4 第四步Python侧复现加解密拿到所有参数后就可以用Python的Crypto库实现加解密了。下面给出标准实现覆盖绝大多数场景。AES加解密核心实现fromCrypto.CipherimportAESfromCrypto.Util.Paddingimportpad,unpadimportbase64classAesUtil:def__init__(self,key,ivNone,modeAES.MODE_CBC):self.keykey.encode(utf-8)self.modemode self.iviv.encode(utf-8)ifivelseNonedefencrypt(self,plaintext):cipherAES.new(self.key,self.mode,self.iv)padded_datapad(plaintext.encode(utf-8),AES.block_size)returnbase64.b64encode(cipher.encrypt(padded_data)).decode(utf-8)defdecrypt(self,ciphertext):cipherAES.new(self.key,self.mode,self.iv)cipher_bytesbase64.b64decode(ciphertext)plain_bytesunpad(cipher.decrypt(cipher_bytes),AES.block_size)returnplain_bytes.decode(utf-8)RSA公钥加密核心实现fromCrypto.CipherimportPKCS1_v1_5fromCrypto.PublicKeyimportRSAimportbase64classRsaUtil:def__init__(self,public_key_str):# 自动补全PEM格式公钥头尾ifnotpublic_key_str.startswith(-----BEGIN):public_key_str(-----BEGIN PUBLIC KEY-----\npublic_key_str\n-----END PUBLIC KEY-----)self.public_keyRSA.import_key(public_key_str)defencrypt(self,plaintext):cipherPKCS1_v1_5.new(self.public_key)cipher_bytescipher.encrypt(plaintext.encode(utf-8))returnbase64.b64encode(cipher_bytes).decode(utf-8)混合加密调用逻辑importsecrets# 1. 生成16位随机AES密钥aes_keysecrets.token_hex(8)aes_iv1234567890123456# 实际值以站点逻辑为准# 2. RSA加密AES密钥rsa_utilRsaUtil(public_key_str)encrypt_keyrsa_util.encrypt(aes_key)# 3. AES加密业务数据aes_utilAesUtil(aes_key,aes_iv)encrypt_dataaes_util.encrypt({page:1,pageSize:10})# 4. 组装最终请求参数payload{encryptKey:encrypt_key,encryptData:encrypt_data}响应解密逻辑更简单用同一个AES密钥直接解密返回的加密数据字段即可。三、问题排查90%的复现失败都栽在这几个坑很多人逆向的时候算法名对上了密钥也拿到了可就是加密结果和站点不一样或者解密出来全是乱码。绝大多数问题都出在细节参数上挨个排查就行。坑1填充方式不匹配这是最高频的错误。AES的填充有Pkcs7、Pkcs5、ZeroPadding等JS端CryptoJS默认是Pkcs7Python里要显式指定很多人用了默认无填充结果密文永远对不上。RSA同理PKCS1_v1_5和OAEP是完全不同的填充方式搞混了直接解密失败。坑2IV偏移量遗漏或错误AES的CBC模式必须有IV长度固定16字节。很多站点的IV是硬编码在JS里的或者和密钥一起生成逆向的时候很容易漏掉。注意ECB模式不需要IV传了反而会出错。模式和IV一定要严格对应。坑3编码格式混乱密文输出到底是Base64还是Hex字符串必须和站点完全一致。JS里CryptoJS默认toString()输出Hex很多站点会额外转成Base64传输。另外明文的字符集也要注意绝大多数是UTF-8少数老站点可能用GBK解密乱码的时候可以优先排查。坑4RSA公钥格式不对很多站点的公钥是去掉头尾的纯Base64字符串导入的时候必须补全PEM格式的头尾标记否则RSA库会直接导入失败。还有部分站点用模数(n)和指数(e)的形式存储公钥需要自己组装成公钥对象不能直接当PEM格式导入。坑5字节处理差异JS里的字符串是UTF-16编码而Python操作的是字节串。尤其是处理中文的时候如果编码转换没做好很容易出现明文一致但密文不同的情况。最稳妥的验证方法两边都用同样的纯英文测试明文先对齐纯英文的结果再处理中文编码问题。坑6密钥长度错误AES密钥必须是16/24/32字节对应128/192/256位少一个字节都会直接报错。RSA公钥的长度要和密文长度对应拿不准的时候可以通过抓包的密文长度反推。四、进阶拓展遇到混淆代码怎么办上面讲的是明文JS的情况实际项目里很多站点的JS代码是混淆过的变量名全是无意义字符加密函数藏得很深。分享三个实用的应对方案按成本从低到高排序。1. 直接调用JS法不用费劲扣代码用PyExecJS库直接在Python里运行JS代码把明文传进去直接拿密文。优点是简单快捷不用关心内部逻辑缺点是性能一般适合小规模采集场景。2. 补环境运行法把混淆后的JS文件整体拿下来在Node.js里补全浏览器环境window、document、navigator等对象直接调用加密函数。适合混淆严重但加密入口明确的场景是平衡效率和成本的最优解。3. AST还原法用Babel等工具对混淆JS做AST解析还原变量名、拆分控制流、去除死代码把混淆代码还原成可读形式。适合高强度混淆、需要深度分析的场景门槛相对高一些。对绝大多数采集场景来说前两种方案就足够用了。能用工程方法解决的问题就不要死啃代码逆向。五、写在最后加密接口逆向看起来门槛很高其实核心难点从来不是算法本身——AES和RSA都是公开的标准算法Python有成熟的库可以直接调用。真正考验人的是定位加密入口、对齐细节参数的过程。总结下来就是三步走先抓包确认加密方案再断点调试提取核心参数最后用Python复现加解密逻辑。绝大多数混合加密接口都逃不开这个固定套路。最后还是要提醒一句接口逆向技术请仅用于合法合规的技术研究与公开数据采集遵守目标站点的服务条款与robots协议不要用于非法用途。技术是工具底线不能丢。