diff --git a/internal/algos/golden_test.go b/internal/algos/golden_test.go new file mode 100644 index 0000000..a598575 --- /dev/null +++ b/internal/algos/golden_test.go @@ -0,0 +1,79 @@ +//go:debug randseednop=0 + +package algos + +import ( + "encoding/hex" + "math/rand" + "testing" +) + +// 固定输入 + 固定时间戳的 golden 测试:签名算法被改坏时在此最先失败。 +// 基准值取自当前实现;有意修改算法后用相同输入重新生成并更新期望值。 +// 8404 内嵌随机数且走全局 math/rand,Go 1.25 起 rand.Seed 默认是 no-op, +// 故用 //go:debug randseednop=0 恢复其钉死随机序列的旧语义。 +// x-argus 的 protobuf 编码按 map 迭代顺序输出(protobuf.go:385),天然 +// 不确定,无法全量 golden,只测其内部的确定性哈希层。 + +const ( + goldenParams = "aid=1967&app_name=fanqie_novel&device_id=1234567890123456&version_name=5.9.5" + goldenStub = "d41d8cd98f00b204e9800998ecf8427e" + goldenCookie = "install_id=728944090949322; device_id=1234567890123456" + goldenSecDev = "1234567890123456" + goldenAID = 1967 + goldenLcID = 1611921764 +) + +// var:Sign2 需要 *int64,不能对常量取址 +var goldenTS = int64(1700000000) + +func goldenArgs() (string, string, string, string, int, int, string, int, int, *int64) { + return goldenParams, goldenStub, goldenSecDev, goldenCookie, + goldenAID, goldenLcID, "v04.06.01-ml-android", 135004672, 0, &goldenTS +} + +func assertGolden(t *testing.T, name string, got map[string]string, want map[string]string) { + t.Helper() + for k, v := range want { + if got[k] != v { + t.Errorf("%s %s = %q, want %q", name, k, got[k], v) + } + } +} + +func TestGorgonSign2Golden(t *testing.T) { + GlobalAlgorithmSwitcher.SwitchAlgorithm("gorgon") + assertGolden(t, "gorgon", Sign2(goldenArgs()), map[string]string{ + "x-gorgon": "0404b0d30000bbd9e75fe1edb046d324b7853694a6177ca72d0a", + "x-khronos": "1700000000", + "x-ss-req-ticket": "1700000000000", + }) +} + +func TestAlgo8404Sign2Golden(t *testing.T) { + rand.Seed(1) + GlobalAlgorithmSwitcher.SwitchAlgorithm("8404") + defer GlobalAlgorithmSwitcher.SwitchAlgorithm("gorgon") + assertGolden(t, "8404", Sign2(goldenArgs()), map[string]string{ + "X-Gorgon": "8404210f00008eec413318e9f810571e96fca6fb4a0f497e78e5", + "X-Khronos": "1700000000", + "X-SS-REQ-Ticket": "1700000000000", + }) +} + +func TestLadonGolden(t *testing.T) { + // 固定 randomBytes,绕开 crypto/rand + got := LadonEncrypt(goldenTS, goldenLcID, goldenAID, []byte{0xde, 0xad, 0xbe, 0xef}) + if want := "3q2+7/6PK4T/ZqM1zu2AIWFdXW2D9gdHrXRfOb02lxi6GnYm"; got != want { + t.Errorf("ladon = %q, want %q", got, want) + } +} + +func TestArgusHashGolden(t *testing.T) { + if got := hex.EncodeToString(GetBodyHash(goldenStub)); got != "9c840df1aec0" { + t.Errorf("bodyHash = %s, want 9c840df1aec0", got) + } + if got := hex.EncodeToString(GetQueryHash(goldenParams)); got != "58bc068af10b" { + t.Errorf("queryHash = %s, want 58bc068af10b", got) + } +}