当前浏览的是 v7 预览版文档(v7 尚未正式发布,API 可能随版本调整)。本页是 v7 新增内容,去 v6 正式版文档首页
@ikenxuan/amagi

为什么签名需要被验证

平台对签名是抽样校验的,「请求成功」证明不了任何事;四个平台的验证器与它们各自的验证强度

为什么签名需要被验证

抖音对签名是抽样校验的:签名用错了常量,请求大部分时候照样成功,只是被判定为高风险的概率上升。它不报错、不返回空、不给你任何可分辨的信封 —— 表现为「偶尔不稳」,而不是「坏了」。所以把「接口能通」当作签名正确的证据,是无效推理。

麻烦在于,签名算法里藏着若干个常量(抖音的盐值、page_id、SDK 版本块;快手的布局魔数;小红书的模板版本……)。它们随平台改自己的前端代码而变,而变的时候没有任何通知。

自证模型的三个空转

在这套约束下,常见的测试写法一个都发现不了常量过期:

写法为什么无效
自生成快照首次运行时由被测代码自己写入。常量改了,快照跟着改,测试永远绿
与被测对象比自身expect(v7).toBe(v6) —— 但两个符号 import 的是同一个模块,等于把函数和自己比
「输出长度 > 100」这类形状断言错的常量产出的签名与对的形状完全一致,只是字节不同

一句话:没有任何自证型断言能证伪一个常量。 这不是写得不够好,是模型的问题 —— 缺少一个不随被测代码变化的外部锚点。amagi 的数据接口就带着一个 2024 年的旧盐值活了两年(故事在抖音那页)。

四个平台,各能验到什么程度

唯一能证伪一个常量的办法,是拿平台自己的输出拆开看。每个平台的验证器都在自己那页的页顶,跑的就是 @ikenxuan/amagi/signing 本身 —— 与 oracle 测试、与线上签名同一份代码。但各平台的可验证面不一样宽,这是诚实而不是缺口:

平台可验证的签名能验到什么验证强度
抖音a_bogus结构指纹、盐值判定、query / UA 摘要链(24 位/条)、可还原时钟与五十个标量●●● 整段可拆,有真实捕获做 oracle
抖音X-Bogus常量指纹、可还原时钟、16 位摘要链●●○ 可拆;暂无浏览器捕获
抖音x-secsdk-web-signature确定性 MD5,重算逐字符比对●●● 完全可验
抖音verify_fp / msToken / ttwid骨架与时钟;msToken / ttwid 底下没有明文●○○ 部分是「说了就是答案」
B站w_rid(wbi)同一组 keys、同一个 wts 重算,逐字符比对●●● 完全可验
B站av ↔ bv双向互转,往返自洽●●● 完全可验
快手$HE_ 段布局常量、双层 LRC、可还原时钟与计数器●●○ 可拆;暂无浏览器捕获
小红书x-s 等头部前缀、长度、字符集(XYW 信封可拆一层 JSON)●○○ 算法本体在 Node 侧,进不了浏览器

「验证强度」低一档的都不藏:快手那页解释了 HUDR 段为什么拆不开,小红书那页解释了算法本体为什么进不了浏览器。

「解码」诚实地指三件事

把这三件事混为一谈,是这类工具开始撒谎的方式:

  1. 可还原 —— 值就在载荷里,能原样取回:时钟、aid、计数器。没有任何推断。
  2. 被绑定但不可还原 —— 载荷里带着某个输入的摘要。输入无法从摘要倒推,工具从不假装能;它做的是校验:给候选值,回答是不是签名封住的那一个,并标注证据位数。
  3. 根本没被计算 —— msToken、ttwid、HUDR 密文由平台签发或整体加密,底下没有明文可找。说出这一点就是答案,而不是「没能给出答案」。

下一步

最后更新于 2026-10-02

On this page