@ikenxuan/amagi 7.0.0-beta.7 → 7.0.0-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,128 @@
1
+ import "../endpoint-QPR2Pp-S.js";
2
+ import { a as WEBSIGN_CONST, c as isSecsdkProtected, d as av2bv, f as bv2av, i as SecsdkSignResult, l as signSecsdkWebQuery, n as SECSDK_SIG_KEY, o as canonicalQuery, r as SecsdkSignOptions, s as extractUifidFromCookie, u as signSecsdkWebUrl } from "../secsdkWebSign-DoqHj52s.js";
3
+ //#region src/platforms/kuaishou/sign/hudr.d.ts
4
+ /**
5
+ * 快手 `window.SECS` 的最小状态描述。
6
+ */
7
+ type KuaishouSecsState = {
8
+ c?: number;
9
+ s?: string;
10
+ };
11
+ /**
12
+ * 生成 `HUDR_` 段所需的上下文参数。
13
+ */
14
+ type KuaishouHudrContext = {
15
+ count: number;
16
+ scriptCount?: number;
17
+ secs?: KuaishouSecsState;
18
+ };
19
+ /**
20
+ * 快手 `HUDR_` 段的中间结果。
21
+ */
22
+ type KuaishouHudrResult = {
23
+ body: string;
24
+ full: string;
25
+ infoCache: number[];
26
+ maskedPayload: Uint8Array;
27
+ nextCount: number;
28
+ };
29
+ //#endregion
30
+ //#region src/platforms/kuaishou/sign/he.d.ts
31
+ /**
32
+ * 生成快手 `$HE_` 段所需的上下文参数。
33
+ */
34
+ type KuaishouHeContext = {
35
+ count: number;
36
+ hudrBody: string;
37
+ randomValue: number;
38
+ signInput: string;
39
+ startupRandom: number;
40
+ timestamp: number;
41
+ };
42
+ /**
43
+ * 快手完整纯算法签名所需的上下文参数。
44
+ */
45
+ type KuaishouPureSignContext = KuaishouHudrContext & {
46
+ randomValue: number;
47
+ signInput: string;
48
+ startupRandom: number;
49
+ timestamp: number;
50
+ };
51
+ /**
52
+ * 快手 `$HE_` 段的中间结果。
53
+ */
54
+ type KuaishouHeResult = {
55
+ finalHex: string;
56
+ hashFieldHex: string;
57
+ preHex: string;
58
+ };
59
+ /**
60
+ * 快手纯算法签名的完整结果。
61
+ */
62
+ type KuaishouPureSignResult = KuaishouHudrResult & {
63
+ he: KuaishouHeResult;
64
+ signResult: string;
65
+ };
66
+ /**
67
+ * 计算 `$HE_` 中的 hash field。
68
+ *
69
+ * 它由 `signInput + HUDRBody` 经 `b2sa -> cts -> 截断 -> 异或掩码`
70
+ * 这条链路导出,是 `$HE_` 中与接口输入最直接相关的一段。
71
+ *
72
+ * @param signInput - 快手 `__NS_hxfalcon` 的 sign input
73
+ * @param hudrBody - `HUDR_` 去前缀后的主体
74
+ * @returns `$HE_` 载荷中的 4 字节 hash field hex
75
+ */
76
+ export declare const deriveKuaishouHeHashFieldHex: (signInput: string, hudrBody: string) => string;
77
+ /**
78
+ * 推导快手签名中的 `$HE_` 段。
79
+ *
80
+ * @param context - 生成 `$HE_` 所需的上下文参数
81
+ * @returns `$HE_` 的最终 hex、中间 hash field 和 preHex
82
+ */
83
+ export declare const deriveKuaishouHeHex: (context: KuaishouHeContext) => KuaishouHeResult;
84
+ /**
85
+ * 一次性推导快手完整纯算法签名。
86
+ *
87
+ * 该方法会先生成 `HUDR_`,再拼出 `$HE_`,最终返回完整
88
+ * `HUDR_...$HE_...` 形式的 `__NS_hxfalcon`。
89
+ *
90
+ * @param context - 快手纯算法签名上下文
91
+ * @returns 完整签名结果及关键中间态
92
+ */
93
+ export declare const deriveKuaishouPureSignature: (context: KuaishouPureSignContext) => KuaishouPureSignResult;
94
+ /** 结构检查能发现的问题。真实签名永远一个都不该有 */
95
+ type KuaishouHeProblem = 'not hex' | 'length not 90' | 'envelope checksum' | 'tail lrc' | 'header magic' | 'version' | 'startup marker' | 'fixed body' | 'tail';
96
+ /** {@link decodeKuaishouHe} 的拆解结果 */
97
+ interface DecodedKuaishouHe {
98
+ /** 页面加载时的一次性随机数(LE 6 字节,原样读回) */
99
+ startupRandom: number;
100
+ /** 本条签名自己的 48 位随机数(LE 6 字节,原样读回) */
101
+ random: number;
102
+ /** 签名计数器(异或掩码已解掉) */
103
+ count: number;
104
+ /** 毫秒时间戳(异或掩码已解掉)—— 与 a_bogus 的毫秒时钟同源,都是 Date.now() 一路 */
105
+ timestampMs: number;
106
+ /** 4 字节 hash field(十六进制)。重算它需要 signInput 与 HUDR body,见 {@link deriveKuaishouHeHashFieldHex} */
107
+ hashFieldHex: string;
108
+ /** 发现的全部问题;空数组 = 结构良好 */
109
+ problems: KuaishouHeProblem[];
110
+ }
111
+ /**
112
+ * 拆开一段 `$HE_`。
113
+ *
114
+ * 最终输出的最后一个字节是**异或键**:它本身是前 44 字节的 LRC 校验,同时把那
115
+ * 44 字节逐个异或成密文 —— 所以解码顺序固定为「拆键 → 还原 → 逐段校验 → 读字段」。
116
+ * 能同时通过两层校验(信封 LRC + 尾段 LRC)与四个布局常量的值,必然是这套装配
117
+ * 顺序产出的;`count` 与时间戳随后原样读回,不需要任何候选输入。
118
+ *
119
+ * 它**不**校验 hash field —— 那四字节绑的是 signInput + HUDR body,候选值给齐了
120
+ * 可用 {@link deriveKuaishouHeHashFieldHex} 自行比对。
121
+ * @param hex - `$HE_` 后面的那段 hex(90 个字符)
122
+ * @returns 拆解结果;布局不符时 `problems` 非空,字段值不可信
123
+ */
124
+ export declare const decodeKuaishouHe: (hex: string) => DecodedKuaishouHe;
125
+ //#endregion
1
126
  //#region src/platforms/douyin/sign/a_bogus.d.ts
2
127
  /**
3
128
  * a_bogus —— 抖音 Web 加在每个数据接口上的签名。
@@ -694,5 +819,165 @@ export declare const DOUYIN_TTWID_PAYLOAD: {
694
819
  };
695
820
  /** 抖音访客 ttwid 注册:`POST {url}`,body 用 `data` */
696
821
  export declare const DOUYIN_TTWID: TtwidSpec;
822
+ /** 结构检查能发现的问题。真值永远一个都不该有 */
823
+ type VerifyFpProblem = 'prefix' | 'tail length' | 'separators' | 'version' | 'variant' | 'alphabet';
824
+ /** {@link decodeVerifyFp} 的拆解结果 */
825
+ interface DecodedVerifyFp {
826
+ /** 毫秒时间戳(36 进制段原样还原,无任何推断) */
827
+ timestampMs: number;
828
+ /** 发现的全部问题;空数组 = 结构良好 */
829
+ problems: VerifyFpProblem[];
830
+ }
831
+ /**
832
+ * 拆开一个 `verify_fp` / `s_v_web_id`。
833
+ *
834
+ * 这类值的唯一真实载荷就是**生成时刻**(`verify_<36 进制毫秒>_<36 位 UUID v4 骨架>`),
835
+ * 其余 31 个字符是纯随机。骨架的四个位置常量(分隔符、版本位、变体位)加上字母表
836
+ * 约束构成指纹;时钟能原样读回,所以「这条 verify_fp 是什么时候生成的」是可判定的。
837
+ *
838
+ * 它**不能**辨别真假:假值的形状目标就是与真值一致(见 {@link genVerifyFp})。
839
+ * @param value - 待检查的值
840
+ * @returns 拆解结果;骨架不符时 `problems` 非空
841
+ */
842
+ export declare const decodeVerifyFp: (value: string) => DecodedVerifyFp;
843
+ //#endregion
844
+ //#region src/platforms/douyin/sign/x_bogus.d.ts
845
+ /** 站点混在时间戳旁边的固定常量 */
846
+ export declare const CANVAS_CONSTANT = 536919696;
847
+ /** X-Bogus 签名算法的返回结果 */
848
+ interface XBogusResult {
849
+ /** 已拼上 `X-Bogus=` 的完整 URL */
850
+ fullUrl: string;
851
+ /** 签名值本身,28 个字符 */
852
+ xbogus: string;
853
+ /** 实际参与签名的 User-Agent */
854
+ userAgent: string;
855
+ }
856
+ /** {@link XBogus.getXBogus} 的注入点 */
857
+ interface XBogusOptions {
858
+ /**
859
+ * 秒级 Unix 时间戳,默认 `Math.floor(Date.now() / 1000)`。
860
+ *
861
+ * 签名里封着它(4 个字节),所以同一秒内两次调用结果相同,钉死它才能复现一份签名
862
+ * —— 这既是对拍浏览器输出的前提,也是快照测试能成立的原因。
863
+ */
864
+ timestamp?: number;
865
+ }
866
+ declare class XBogus {
867
+ /** V4 兼容字段:V4 会把结果同步写进 `params` / `xb`,本实现不写 */
868
+ params?: string;
869
+ xb?: string;
870
+ /**
871
+ * 生成 X-Bogus 签名。
872
+ *
873
+ * @param url - 完整的 URL 地址(签的是它的 pathname + search)
874
+ * @param ua - 可选的 User-Agent,不提供则使用默认值
875
+ * @param options - `timestamp` 注入点(秒级),省略时取当前时间
876
+ * @returns 完整 URL(已带 `X-Bogus=`)、签名值与实际使用的 User-Agent
877
+ */
878
+ getXBogus(url: string, ua?: string, options?: XBogusOptions): XBogusResult;
879
+ }
880
+ /**
881
+ * 对一条 path+search 签出 X-Bogus。
882
+ *
883
+ * {@link XBogus.getXBogus} 的函数式形态 —— 验证工具要用它对候选输入重签;
884
+ * 输入是已经拆好的 `pathname + search`,不重复解析 URL。
885
+ * @param urlPath - 参与 签名的 `pathname + search`
886
+ * @param userAgent - 参与签名的 User-Agent
887
+ * @param timestamp - 秒级时间戳
888
+ * @returns 28 个字符的签名值
889
+ */
890
+ export declare const signXBogus: (urlPath: string, userAgent: string, timestamp: number) => string;
891
+ /** 结构检查能发现的问题。真实签名永远一个都不该有 */
892
+ type XBogusProblem = 'alphabet' | 'length not 28' | 'envelope lead' | 'lead slots' | 'empty digest' | 'canvas constant' | 'checksum';
893
+ /**
894
+ * 只凭签名本身能做的全部检查 —— 不需要任何候选输入。
895
+ *
896
+ * X-Bogus 里封着三个**常量**(载荷前四格、empty 摘要链字节、canvas 常量),
897
+ * 它们与校验位一起构成指纹:一份能通过全部检查的值,必然出自这套算法的装配顺序。
898
+ * @param value - 待检查的值(28 个字符)
899
+ * @returns 第一个发现的问题;`null` 表示全部通过
900
+ */
901
+ export declare const xBogusStructureError: (value: string) => XBogusProblem | null;
902
+ /** {@link decodeXBogus} 的候选输入。给了哪个就校验哪条链 */
903
+ interface XBogusCandidates {
904
+ /** 签名所覆盖的 `pathname + search`(不含 `X-Bogus` 自身) */
905
+ query?: string;
906
+ userAgent?: string;
907
+ }
908
+ /**
909
+ * 拆开一份 X-Bogus,并就调用方给出的候选值做校验。
910
+ *
911
+ * 能原样读回的只有一个值:秒级时间戳。三条摘要链各留两个字节(16 位),输入无法
912
+ * 从中倒推,做的是校验 —— 给候选值,回答是不是它封的那一个。证据量比 a_bogus
913
+ * 的 24 位小,但足以区分「对着的 URL」与「差一个参数的 URL」。
914
+ * @param value - X-Bogus 的值(28 个字符)
915
+ * @param candidates - 候选的 path+search 与 User-Agent,给哪个校验哪个
916
+ * @returns 拆解结果;格式不合法时 `recovered` 为 `false` 并给出 `reason`
917
+ */
918
+ export declare const decodeXBogus: (value: string, candidates?: XBogusCandidates) => Decoded;
919
+ //#endregion
920
+ //#region src/platforms/bilibili/sign/wbi.d.ts
921
+ /** 从 URL 末尾取文件名部分(去扩展名),得到 img_key / sub_key */
922
+ declare const extractKey: (url: string) => string;
923
+ /** 签名参数值类型 */
924
+ type SignParamValue = string | number | boolean;
925
+ /**
926
+ * 一次 wbi 签名的全部产物。
927
+ */
928
+ interface WbiSignature {
929
+ /** 参与签名的秒级时间戳,同时是要发送的 `wts` */
930
+ wts: number;
931
+ /** 32 位小写十六进制的 `w_rid` */
932
+ w_rid: string;
933
+ /** 实际参与哈希的规范化 query(已含 `wts`,按 key 排序、值滤掉 `!'()*`) */
934
+ canonicalQuery: string;
935
+ /** 由 img_key + sub_key 打乱出的 32 位混合密钥 */
936
+ mixinKey: string;
937
+ }
938
+ /**
939
+ * 按给定时间戳计算 wbi 签名 —— **验证工具与 {@link encWbi} 共用的唯一实现**。
940
+ *
941
+ * 不修改传入的 `params`;时钟由调用方注入,所以对一份已签名的 URL 重算
942
+ * `w_rid` 时可以钉死它自己的 `wts`,逐字符复现。
943
+ * @param params - 请求参数(不含 wts / w_rid)
944
+ * @param img_key - 图片密钥
945
+ * @param sub_key - 子密钥
946
+ * @param wts - 秒级时间戳
947
+ * @returns 签名产物
948
+ */
949
+ export declare const computeWbiSignature: (params: Record<string, SignParamValue>, img_key: string, sub_key: string, wts: number) => WbiSignature;
950
+ //#endregion
951
+ //#region src/platforms/xiaohongshu/sign/shape.d.ts
952
+ /**
953
+ * 小红书反爬头部的**形状检查** —— 验证工具在小红书这边能做的全部事情。
954
+ *
955
+ * 真正的签名算法在 `@ikenxuan/xhshow-ts` 里,那条依赖链用了 `node:crypto` 与
956
+ * `node:zlib`,进不了浏览器;所以与 a_bogus / X-Bogus 那种「拆开验」不同,
957
+ * 小红书在这里只能验形状:前缀、长度、字符集、时钟的合理范围。这不是偷工减料
958
+ * ——XYS_/XYW_ 前缀区分两套协议(数据接口 2026-03 起拒收 XYS_),x-t 的时钟
959
+ * 范围能暴露「拿秒当毫秒」这类错,形状本身就有鉴别力。
960
+ *
961
+ * 本文件**不得** import `./index`(它会拉进 `@ikenxuan/xhshow-ts`,整条
962
+ * `@ikenxuan/amagi/signing` 的浏览器可用性就毁了)。它只认传入的字符串。
963
+ *
964
+ * @module platforms/xiaohongshu/sign/shape
965
+ */
966
+ /** 一个头部被检查后的结果 */
967
+ interface XhsHeaderInspection {
968
+ /** 头名(原样返回,方便调用方渲染) */
969
+ name: string;
970
+ /** x-s 独有:识别出的协议格式 */
971
+ format?: 'XYS' | 'XYW';
972
+ /** 发现的全部问题;空数组 = 形状良好 */
973
+ problems: string[];
974
+ }
975
+ /**
976
+ * 检查一个签名头部的形状。
977
+ * @param name - 头名(`x-s` / `x-s-common` / `x-t` / `x-xray-traceid` / `x-b3-traceid`)
978
+ * @param value - 头部的值
979
+ * @returns 检查结果;不认识的头名按「非空」处理
980
+ */
981
+ export declare const inspectXhsHeader: (name: string, value: string) => XhsHeaderInspection;
697
982
  //#endregion
698
- export type { ABogusCandidates, ABogusOptions, ABogusSignOptions, Check, Decoded, DecodedABogus, DigestChain, Field, MsTokenSpec, SaltDiagnosis, SignedQueryRecovery, TtwidSpec, VerifyFpOptions };
983
+ export { type ABogusCandidates, type ABogusOptions, type ABogusSignOptions, type Check, type Decoded, type DecodedABogus, type DecodedKuaishouHe, type DecodedVerifyFp, type DigestChain, type Field, type KuaishouHeProblem, type KuaishouPureSignContext, type MsTokenSpec, SECSDK_SIG_KEY, type SaltDiagnosis, type SecsdkSignOptions, type SecsdkSignResult, type SignedQueryRecovery, type TtwidSpec, type VerifyFpOptions, type VerifyFpProblem, WEBSIGN_CONST, type WbiSignature, XBogus, type XBogusCandidates, type XBogusOptions, type XBogusProblem, type XBogusResult, type XhsHeaderInspection, av2bv, bv2av, extractUifidFromCookie, extractKey as extractWbiKey, isSecsdkProtected, canonicalQuery as secsdkCanonicalQuery, signSecsdkWebQuery, signSecsdkWebUrl };