App请求签名与加密码逆向实战:从抓包到Python复现
简介这份资源面向移动应用、小程序与网站开发者聚焦数字签名与加密这一安全核心环节整理了自如、小红书、蛋壳公寓、瑞幸咖啡等生活服务类App的签名或加密实现素材适合需要研究真实项目签名逻辑、排查加密流程的中高级开发者参考。压缩包共15个文件以11个Python脚本为主辅以2个JavaScript文件、1份README说明和1份LICENSE授权文件整体约26KB按自如、蛋壳、瑞幸、小红书等模块分目录组织结构清晰便于对照检索。目前已有435人学习下载。读者可从中获取各平台签名算法的代码实现、加密参数构造思路与模块化目录组织方式用于理解App请求签名、数据加密传输等实际场景也可作为自己项目安全方案设计的参考素材快速定位关键逻辑并迁移到类似业务中。1. 从自如、小红书到瑞幸App 请求签名与加密码到底在防什么抓过自如房源接口、扒过小红书笔记详情、逆过瑞幸咖啡小程序下单请求的人大概率都撞过同一堵墙请求参数里躺着一个sign、signature或X-Sign改一个字符服务端就返回「签名校验失败」。这不是普通的参数校验而是 App、小程序、网站三层客户端里普遍存在的请求签名与加密码机制。它的核心目标只有一个确认这个请求确实由官方客户端发出、内容没被中途篡改、且没有过期重放。对做数据采集、接口联调、安全测试的工程师来说不理解这套机制抓包抓到的就只是一堆看不懂的密文和哈希。这篇内容面向需要对接或分析这类接口的开发者把签名与加密码的构成、复现路径、参数设置和常见翻车点讲清楚让你拿到一个新目标时知道从哪下手、怎么验证、边界在哪。2. 请求签名与加密码的构成从参数拼接到密钥派生2.1 签名和加密码不是一回事很多人把「签名」和「加密码」混着叫实际落地时它们是两个独立环节职责不同。签名sign/signature解决的是完整性和来源认证通常是对请求参数按规则排序拼接后做哈希或 HMAC服务端用同样规则重算一遍比对。加密码encrypt/secret解决的是机密性把敏感字段或整个 body 用对称密钥加密服务端再解密。自如、蛋壳这类租房平台的接口常见「参数明文 sign 字段」小红书、瑞幸的部分接口则是「body 整体加密 头部带 sign」两层叠加。理解这个区分决定了你逆向时的切入顺序先定位签名算法再处理加密体反过来会浪费大量时间。从工程视角看签名机制的设计目标有三个防篡改改参数必失效、防重放带时间戳和随机数、防伪造密钥不出现在客户端明文里。但客户端代码终究在用户设备上密钥无论怎么藏都能被提取所以这类机制的实际强度取决于密钥派生和混淆的复杂度而不是算法本身。这也是为什么同一个平台会频繁换签名版本——不是算法被破了而是密钥泄露后必须轮换。2.2 参数拼接与排序规则绝大多数签名算法的第一步是把参与签名的参数按规则拼成一个字符串。常见规则有按参数名 ASCII 升序排列、过滤空值和 sign 自身、用或|连接、末尾追加密钥。下面是一段典型的 Python 复现逻辑用于还原「参数排序 拼接」这一步import hashlib import hmac def build_sign_string(params: dict, secret: str, algo: str md5) - str: # 1. 过滤掉 sign 字段本身和空值 filtered {k: v for k, v in params.items() if k ! sign and v not in (None, )} # 2. 按参数名 ASCII 升序排列 sorted_items sorted(filtered.items(), keylambda x: x[0]) # 3. 拼成 keyvaluekeyvalue 形式 raw .join(f{k}{v} for k, v in sorted_items) # 4. 末尾追加密钥部分平台是前置或双向拼接 raw_with_secret raw secret if algo md5: return hashlib.md5(raw_with_secret.encode(utf-8)).hexdigest() elif algo hmac-sha256: return hmac.new(secret.encode(), raw.encode(), hashlib.sha256).hexdigest() raise ValueError(unsupported algo)这段代码的关键参数有三个secret是平台下发的密钥通常藏在 so 库、JS 混淆代码或 native 层algo决定用裸哈希还是 HMAC两者结果完全不同选错必然校验失败排序规则里最容易翻车的是大小写和嵌套对象的处理很多平台对嵌套 JSON 会先序列化再参与拼接。实际调试时建议先用已知能通过的请求反推拿一个真实请求把参数按你的规则拼一遍看算出的 sign 是否和抓包一致不一致就逐项调整排序、连接符、密钥位置直到对上为止。2.3 加密码的常见形态与密钥来源加密码在客户端侧常见三种形态AES-CBC 对 body 整体加密、RSA 对 AES 密钥做非对称加密后随请求下发、以及自定义异或/位移混淆。AES 是最普遍的模式多为 CBC填充 PKCS7密钥和 IV 往往由服务端在登录或初始化接口下发或者硬编码在客户端。瑞幸、小红书这类 App 的加密体抓包看到的是一个 Base64 长串解开后是二进制密文。复现时需要拿到 key 和 iv这两个值通常来自客户端静态分析反编译 APK 或解混淆 JS、动态 HookFrida 挂加解密函数打印入参、或从初始化接口响应里提取。下面是一段 AES-CBC 解密的复现示例用于验证你拿到的 key/iv 是否正确from Crypto.Cipher import AES from Crypto.Util.Padding import unpad import base64 def decrypt_body(cipher_b64: str, key: bytes, iv: bytes) - str: # 抓包拿到的密文一般是 Base64 编码 cipher_bytes base64.b64decode(cipher_b64) cipher AES.new(key, AES.MODE_CBC, iv) plain cipher.decrypt(cipher_bytes) # PKCS7 去填充填充错误说明 key 或 iv 不对 return unpad(plain, AES.block_size).decode(utf-8)参数说明key长度必须是 16/24/32 字节对应 AES-128/192/256长度不对直接抛异常iv在 CBC 模式下必须 16 字节且每次请求可能随机生成并随密文一起传输如果固定不变说明平台安全性较弱。解密时如果unpad报错九成是 key 或 iv 错了而不是密文损坏。这一步验证通过才说明你的密钥提取是对的可以进入下一步构造请求。3. 复现一套签名请求从抓包到本地跑通3.1 抓包定位签名字段和加密体第一步永远是抓包但抓包本身有门槛。App 侧常见做法是配置系统代理后抓 HTTPS遇到证书固定SSL Pinning就需要用 Frida 或 Xposed 绕过小程序侧相对简单微信开发者工具或抓包工具能看到明文请求但部分小程序会把逻辑放在 WASM 或加密 JS 里网站侧直接看 Network 面板即可。抓包的目标是回答三个问题签名参数叫什么名字、加密体在哪个字段、有没有时间戳和随机数参与。定位到字段后不要急着逆算法。先做对照实验同一个接口连续发两次请求观察哪些字段变了。如果只有sign和timestamp变说明签名只依赖参数和时间如果nonce、encryptData也变说明有随机数和加密。这个对照能帮你快速缩小范围。我一般会把两三次请求的参数并排贴出来逐字段标注「固定/变化」变化的就是签名输入的一部分。3.2 用 Python 还原签名并验证拿到规则后用 Python 写一个最小验证脚本拿真实请求的参数复算 sign和抓包值比对。这一步是整个流程的分水岭对上了后面就是工程化对不上说明规则还有遗漏。下面是一个完整的验证脚本框架import requests import time import hashlib SECRET 从客户端提取的密钥 BASE_URL https://example.com/api/list def make_request(page: int): params { page: page, size: 20, timestamp: int(time.time() * 1000), nonce: abc123, } # 按平台规则拼签名 raw .join(f{k}{v} for k, v in sorted(params.items())) params[sign] hashlib.md5((raw SECRET).encode()).hexdigest() resp requests.get(BASE_URL, paramsparams, headers{ User-Agent: 平台官方UA, Referer: https://example.com/, }) return resp.json() if __name__ __main__: print(make_request(1))逻辑说明timestamp用毫秒级很多平台校验时间差超过 5 分钟就拒绝所以本地时间要准nonce是随机串部分平台要求每次不同且服务端会缓存已用过的值防重放sign计算必须在参数最终确定后、发请求前完成。参数上最容易忽略的是User-Agent和Referer有些平台把它们也纳入签名输入漏掉就永远对不上。验证时先用固定 timestamp 和 nonce 复算确认算法无误后再改成动态生成。3.3 处理加密 body 的请求如果接口是 POST 且 body 加密流程变成构造明文 JSON → AES 加密 → Base64 编码 → 作为某个字段发送同时对该字段或整体做签名。下面是对应的构造逻辑import json import base64 from Crypto.Cipher import AES from Crypto.Util.Padding import pad def encrypt_body(payload: dict, key: bytes, iv: bytes) - str: plain json.dumps(payload, separators(,, :)).encode(utf-8) cipher AES.new(key, AES.MODE_CBC, iv) encrypted cipher.encrypt(pad(plain, AES.block_size)) return base64.b64encode(encrypted).decode() def build_encrypted_request(payload: dict, key: bytes, iv: bytes, secret: str): enc encrypt_body(payload, key, iv) ts str(int(time.time() * 1000)) # 签名输入可能是 enc ts具体看平台 sign hashlib.sha256((enc ts secret).encode()).hexdigest() return {data: enc, timestamp: ts, sign: sign}参数说明separators去掉 JSON 里的空格因为服务端解密后可能按紧凑格式校验多一个空格就签名不一致iv如果每次随机需要把 iv 也随请求传过去通常放在头部或单独字段签名输入里enc和ts的顺序、是否加分隔符必须严格按平台规则差一个字符就失败。调试时建议先把加密结果解密回明文自检确认加解密闭环无误再去对签名。4. 签名与加密码落地时的避坑清单4.1 时间戳和随机数导致的偶发失败现象脚本跑几十次成功突然连续失败过一会又恢复。原因服务端对timestamp有窗口校验常见 ±5 分钟本地机器时间漂移或请求排队超时就会越界nonce被服务端缓存重复使用直接拒绝。解决每次请求前用 NTP 校准时间nonce用 UUID 或足够随机的字符串且不要复用。我一般会在请求前打印一次本地时间和服务器时间差超过 60 秒就先同步。4.2 参数编码不一致现象本地算出的 sign 和抓包差几位怎么调排序都不对。原因URL 编码、空格处理、中文编码方式不一致。比如抓包工具显示的是已解码的值但实际参与签名的是编码后的值或者平台用表示空格你用了%20。解决以原始请求字节为准用抓包工具的「原始请求」视图逐字节比对参与签名的字符串重点看中文、特殊符号、空格的编码形式。4.3 密钥提取错误或版本过期现象昨天还能用的 key今天全部失败。原因平台轮换了密钥或升级了签名版本客户端发版后旧 key 失效。解决建立密钥版本管理把 key、算法、版本号一起记录监控失败率突增时优先怀疑密钥轮换。逆向时不要只提取一个 key把客户端里所有疑似密钥的字符串都记下来逐个试。4.4 证书固定和代码混淆现象抓包工具一开App 直接断网或请求全部失败。原因客户端做了 SSL Pinning检测到代理证书就拒绝连接。解决用 Frida 挂载绕过 Pinning 的脚本或对 APK 做重打包去掉校验。注意重打包会改变签名部分平台会校验 APK 签名需要一并处理。小程序侧则可能是 JS 混淆用开发者工具格式化后逐段分析。4.5 频率限制和风控现象签名全对但请求几十次后被封 IP 或返回验证码。原因平台有频率风控签名只解决「请求合法」不解决「请求合理」。解决控制请求间隔模拟真实用户行为必要时加代理池。但要注意绕过风控涉及合规边界做之前先确认用途是否在授权范围内。5. 进阶把签名逻辑做成可维护的模块真正在生产里用这套东西不能每次换平台都重写一遍。我的习惯是把签名和加密抽象成配置驱动的模块算法、密钥、排序规则、连接符、时间戳字段名全部写成配置代码只负责按配置执行。这样换一个平台只需要改配置不用动逻辑。下面是一个配置结构示例SIGN_CONFIG { default: { algo: md5, secret: xxx, sort: True, join: , secret_position: suffix, exclude: [sign], timestamp_field: timestamp, timestamp_unit: ms, }, platform_xiaohongshu: { algo: hmac-sha256, secret: yyy, sort: True, join: , secret_position: prefix, exclude: [sign, signature], timestamp_field: ts, timestamp_unit: s, }, }验证模块是否正确的办法是拿一批历史成功请求做回归把参数喂进去看算出的 sign 是否和当时抓包的一致一致率 100% 才算通过。这个回归集要持续积累每次平台升级后先跑一遍能快速定位是算法变了还是密钥变了。最后一个习惯所有密钥和算法规则单独存一份加密笔记标注提取时间和对应客户端版本平台一发新版就先比对别等线上全挂了才回头找。这套流程我踩过的最大坑就是密钥轮换没监控半夜报警才发现希望帮到你。本文还有配套的精品资源点击获取

相关新闻

用XPipe统一管理SSH连接:服务器访问层的效率提升实践

用XPipe统一管理SSH连接:服务器访问层的效率提升实践

我刚开始接手团队里一批线上服务器的时候,最大的感受不是系统复杂,而是“连上去”这件事本身太消耗精力。每台机器的IP、端口、用户名、密钥、跳板路径都散落在不同的文档和Shell脚本里,换个电脑就找不着北,更别提还要在多个终端窗…

2026/9/26 21:08:46 阅读更多 →
Qt QPalette实战:从调色板机制到全局亮暗主题切换

Qt QPalette实战:从调色板机制到全局亮暗主题切换

做Qt开发这些年,我一直觉得QPalette是被很多人低估的一个类。一提到界面美化,大家第一反应就是上QSS(Qt样式表),写一堆border-radius、background-color、color,看着挺爽,等到了全局换肤、动态主…

2026/9/26 21:08:46 阅读更多 →
notepad++ 7.9.5 安装与JSON Viewer配置避坑指南

notepad++ 7.9.5 安装与JSON Viewer配置避坑指南

简介:Notepad 7.9.5是一款轻量级开源文本与源代码编辑器,面向Windows环境下的开发者、运维人员及文档编辑者,凭借语法高亮、代码折叠和插件扩展机制,显著提升代码阅读与编写效率。该资源包共含189个文件,以xml配置类文…

2026/9/26 21:08:46 阅读更多 →

最新新闻

微信开发者工具实战:从项目创建到真机排错的完整指南

微信开发者工具实战:从项目创建到真机排错的完整指南

简介:微信Web开发者工具是面向微信小程序与公众号开发的集成开发环境,适合前端开发者、产品经理及运营人员入门或进阶使用,用于代码编辑、调试预览、项目上传和版本管理。资源以zip压缩包形式提供,整体大小约68.08MB,压…

2026/9/26 21:52:13 阅读更多 →
SCA连续凸近似:从非凸问题到凸优化的工程实战指南

SCA连续凸近似:从非凸问题到凸优化的工程实战指南

简介:序贯凸近似优化实现代码包面向非凸问题研究者和MATLAB用户,聚焦序贯凸近似算法的工程落地。它针对工程设计、经济建模等领域常见的非凸难点,通过迭代构建凸近似子问题逼近全局最优解,适合需要快速获得可用优化脚本的读者。包…

2026/9/26 21:52:13 阅读更多 →
DeepSeek工程化脚本生成:从自然语言到生产就绪的闭环实践

DeepSeek工程化脚本生成:从自然语言到生产就绪的闭环实践

简介:本资源是一份面向中高级开发者与AI工程实践者的深度技术指南,聚焦DeepSeek在自动化代码生成与单元测试领域的落地应用,解决传统开发中脚本编写低效、测试覆盖率不足、重复劳动繁重等核心痛点。文档以PDF格式呈现,共1个文件&a…

2026/9/26 21:52:13 阅读更多 →
基于图谱的 RAG(GraphRAG):工业级落地的挑战与优化

基于图谱的 RAG(GraphRAG):工业级落地的挑战与优化

基于图谱的 RAG(GraphRAG):工业级落地的挑战与优化在知识图谱与检索增强生成(GraphRAG)从前沿学术原型(如微软 GraphRAG)走向企业级工业化生产落地的过程中,算法与工程团队往往会遭遇…

2026/9/26 21:52:13 阅读更多 →
开放式代码评审:从形式关卡到质量杠杆的实战指南

开放式代码评审:从形式关卡到质量杠杆的实战指南

有一次线上事故让我印象特别深:一个看似简单的分页查询改动,因为没人在 code review 时较真“索引失效”的问题,结果数据量一上来,接口直接把数据库打挂了。事后复盘,问题不在某个人身上,而在整个评审机制太…

2026/9/26 21:52:13 阅读更多 →
Atlas 300V 24G推理卡YOLO部署实战:昇腾NPU环境搭建与调优

Atlas 300V 24G推理卡YOLO部署实战:昇腾NPU环境搭建与调优

我手里这块卡,就是很多人问是不是“运算加速卡”的 Atlas 300V 24G。直接说结论:它是一张纯正的 AI 推理加速卡,干的是把训练好的模型“跑起来”的活,跟 GPU 那种既能训练又能渲染的通用加速卡不是一个路数。最近不少搞视觉检测的…

2026/9/26 21:51:12 阅读更多 →

日新闻

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、…

2026/9/26 0:00:25 阅读更多 →
学校官网模拟全流程实践:从页面布局到后端接口与部署

学校官网模拟全流程实践:从页面布局到后端接口与部署

如果你正在找一门 Web 大作业的题目,或者刚开始接触 Web 前端开发想做点能拿来展示的东西,“学校官网模拟”几乎是最稳的选择。题目看着简单,但要把导航、新闻列表、轮播 Banner、二级页面、后台数据都串起来,其实已经把前端布局、…

2026/9/26 0:00:25 阅读更多 →
超级玛丽游戏源码C++:从零搭建横版跳跃游戏工程

超级玛丽游戏源码C++:从零搭建横版跳跃游戏工程

简介:这是一份面向游戏开发初学者与C进阶学习者的超级玛丽(超级马里奥)游戏源码,基于C面向对象编程实现,适合想通过经典项目理解游戏主循环、角色类设计、地图关卡加载与物理碰撞检测的读者参考。压缩包共49个文件&…

2026/9/26 0:00:25 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/25 19:27:14 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/26 20:27:29 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/25 20:29:09 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/25 20:29:43 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/25 20:29:31 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/25 19:27:26 阅读更多 →