简介这份资源面向移动应用、小程序与网站开发者聚焦数字签名与加密这一安全核心环节整理了自如、小红书、蛋壳公寓、瑞幸咖啡等生活服务类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% 才算通过。这个回归集要持续积累每次平台升级后先跑一遍能快速定位是算法变了还是密钥变了。最后一个习惯所有密钥和算法规则单独存一份加密笔记标注提取时间和对应客户端版本平台一发新版就先比对别等线上全挂了才回头找。这套流程我踩过的最大坑就是密钥轮换没监控半夜报警才发现希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
Delphi 13 安装全攻略:从离线 ISO 到补丁配置与迁移避坑 1. 为什么 Delphi 13 的安装值得单独写一篇Delphi 13 是 Embarcadero 推出的一个较新版本,很多从 Delphi 7、Delphi 10.2、Delphi 11 一路走过来的老开发者,第一次装 Delphi 13 的时候都会有点懵——不是装不上,而是装完之后发现编译不过、组… · 2026/9/26 21:08:33
金庸全集Kindle精校实战:新修版+三联版双版本制作全流程 作为一个在Kindle上看完了金庸全集的读者,我一直觉得这件事应该有人认真做一次:把“金庸作品kindle资源精校(新修版三联版)”做成一套真正能沉下心读的版本。市面上金庸的电子书资源不能说少,但打开一看,错… · 2026/9/26 21:08:33
字幕乱码怎么修复?中文编码问题排查与转码实战指南 1. 乱码这件事,几乎每个中文用户都踩过字幕乱码这个问题,我从大学做字幕组压制那会儿就开始跟它打交道,到现在少说也处理过几百个案例了。不管是下载的日剧外挂字幕变成一堆问号,还是自己写的代码在终端里输出“锟斤拷”ÿ… · 2026/9/26 21:08:33
一体化Agent沙箱:浏览器、Shell、MCP与VSCode共处一个容器 做一个完整跑在浏览器里的开源项目,标题看着就挺吸引人——AIO Sandbox,一句话介绍就是:把浏览器、Shell、文件系统、MCP和VSCode这五样东西,全部塞进同一个容器,做成一个开箱即用的Agent沙箱。最近一段时间做AI Agent… · 2026/9/26 21:42:17
AI编程完整工作流程v2.0:从需求到交付的实战拆解 1. AI 编程完整工作流程 v2.0:从需求到交付的实战拆解过去一年我几乎把日常开发的主战场搬到了 AI 辅助环境里,从最初“让 AI 补全几行代码”的玩具心态,到现在整套需求分析、架构设计、编码、测试、文档、部署都跑通了一条相对稳定的流水线。… · 2026/9/26 21:42:10
Claude Code Skill 实战:40个Skill从安装到进阶全指南 1. 从“能跑就行”到“体系化作战”:我为什么开始折腾 Skill用了大半年 Claude Code,我一度觉得自己已经摸到了天花板。终端里敲几行指令,让它读文件、改代码、跑测试,日常开发效率确实比纯手写高出一截。但时间一长,问… · 2026/9/26 21:42:10
Higgsfield框架实战:从散装模型调用到生产级智能体任务编排 我最早注意到Higgsfield这个项目,纯粹是被名字吸引的。物理上,希格斯场赋予基本粒子质量,是标准模型里最底层的那块拼图;而放在大模型应用工程里,Higgsfield想做的事情也类似——给散装的大模型能力“赋质量”… · 2026/9/26 21:42:10
麒麟V10黑屏故障五层定位与GRUB核心诊断指南 1. 项目概述:这不是系统崩溃,是麒麟V10在向你“打哑语”“麒麟V10操作系统黑屏原因汇总”——这个标题背后,藏着成千上万政企用户、信创项目工程师、国产化替代一线运维人员的真实焦虑。我从2019年参与首批麒麟V10适配测试起,到如… · 2026/9/26 21:42:10
Claude Code Skill 实战:40个Skill的选型、编写与避坑指南 1. 从“能用”到“好用”:为什么40个Skill是分水岭我大概是在去年年底开始把 Claude Code 当作日常主力工具的。最开始那两个月,我的用法特别朴素:打开终端,敲一句需求,等它吐代码,复制粘贴,跑一… · 2026/9/26 21:42:10
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46