package ingest import ( "crypto/hmac" "crypto/sha256" "encoding/hex" "strconv" "testing" "time" ) // verify 是后台 internal/pkg/hmac.Verify 的逐字镜像,仅用于本测试验证「爬虫签名能被 // 后台同算法校验通过」这条契约——算法必须与后台保持一致。 func verify(secret, body, sig, ts, nonce string, ttl int) bool { if sig == "" || ts == "" || nonce == "" { return false } if ttl <= 0 { ttl = 300 } tsN, err := strconv.ParseInt(ts, 10, 64) if err != nil { return false } now := time.Now().Unix() if diff := now - tsN; diff > int64(ttl) || diff < -int64(ttl) { return false } mac := hmac.New(sha256.New, []byte(secret)) mac.Write([]byte(ts)) mac.Write([]byte(".")) mac.Write([]byte(nonce)) mac.Write([]byte(".")) mac.Write([]byte(body)) expected := hex.EncodeToString(mac.Sum(nil)) return hmac.Equal([]byte(expected), []byte(sig)) } func TestSignVerifyRoundtrip(t *testing.T) { secret := "test-secret" body := `{"brand_uid":"001DESke","title_en":"Fall 2024 Ready-to-Wear"}` ts := strconv.FormatInt(time.Now().Unix(), 10) nonce := "abc123nonce" sig := Sign(secret, ts, nonce, body) if !verify(secret, body, sig, ts, nonce, 300) { t.Fatal("后台应当校验通过爬虫签名,但未通过") } // 篡改 body if verify(secret, body+"x", sig, ts, nonce, 300) { t.Fatal("body 被篡改后不应通过校验") } // 错误密钥 if verify("wrong", body, sig, ts, nonce, 300) { t.Fatal("错误密钥不应通过校验") } // 过期时间戳 old := strconv.FormatInt(time.Now().Unix()-600, 10) if verify(secret, body, Sign(secret, old, nonce, body), old, nonce, 300) { t.Fatal("过期时间戳不应通过校验") } } func TestEncodeBrandNonSequential(t *testing.T) { // 相邻主键编码结果应互不相关(防顺序枚举),且同值稳定 a := EncodeBrand(108) b := EncodeBrand(109) if a == b { t.Fatal("相邻 id 编码必须不同") } if EncodeBrand(108) != a { t.Fatal("编码必须稳定(同输入同输出)") } if len(a) < 8 { t.Fatalf("编码长度不应短于 minLen=8,实际 %d", len(a)) } }