From 25d1c18a3f5c42bdaf246d4104f13ea2a2eb4929 Mon Sep 17 00:00:00 2001 From: Luis Pater Date: Thu, 2 Apr 2026 11:03:11 +0800 Subject: [PATCH] fix: scope experimental cch signing to billing header --- go.mod | 2 +- internal/runtime/executor/claude_signing.go | 25 +++++++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 9213f736..7ad363a7 100644 --- a/go.mod +++ b/go.mod @@ -81,7 +81,7 @@ require ( github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/termenv v0.16.0 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect - github.com/pierrec/xxHash v0.1.5 // indirect + github.com/pierrec/xxHash v0.1.5 github.com/pjbgf/sha1cd v0.5.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rs/xid v1.5.0 // indirect diff --git a/internal/runtime/executor/claude_signing.go b/internal/runtime/executor/claude_signing.go index c52aef49..697a6882 100644 --- a/internal/runtime/executor/claude_signing.go +++ b/internal/runtime/executor/claude_signing.go @@ -8,19 +8,36 @@ import ( xxHash64 "github.com/pierrec/xxHash/xxHash64" "github.com/router-for-me/CLIProxyAPI/v6/internal/config" cliproxyauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" + "github.com/tidwall/gjson" + "github.com/tidwall/sjson" ) const claudeCCHSeed uint64 = 0x6E52736AC806831E -var claudeBillingHeaderPlaceholderPattern = regexp.MustCompile(`(x-anthropic-billing-header:[^"]*?\bcch=)(00000)(;)`) +var claudeBillingHeaderCCHPattern = regexp.MustCompile(`\bcch=([0-9a-f]{5});`) func signAnthropicMessagesBody(body []byte) []byte { - if !claudeBillingHeaderPlaceholderPattern.Match(body) { + billingHeader := gjson.GetBytes(body, "system.0.text").String() + if !strings.HasPrefix(billingHeader, "x-anthropic-billing-header:") { + return body + } + if !claudeBillingHeaderCCHPattern.MatchString(billingHeader) { return body } - cch := fmt.Sprintf("%05x", xxHash64.Checksum(body, claudeCCHSeed)&0xFFFFF) - return claudeBillingHeaderPlaceholderPattern.ReplaceAll(body, []byte("${1}"+cch+"${3}")) + unsignedBillingHeader := claudeBillingHeaderCCHPattern.ReplaceAllString(billingHeader, "cch=00000;") + unsignedBody, err := sjson.SetBytes(body, "system.0.text", unsignedBillingHeader) + if err != nil { + return body + } + + cch := fmt.Sprintf("%05x", xxHash64.Checksum(unsignedBody, claudeCCHSeed)&0xFFFFF) + signedBillingHeader := claudeBillingHeaderCCHPattern.ReplaceAllString(unsignedBillingHeader, "cch="+cch+";") + signedBody, err := sjson.SetBytes(unsignedBody, "system.0.text", signedBillingHeader) + if err != nil { + return unsignedBody + } + return signedBody } func resolveClaudeKeyConfig(cfg *config.Config, auth *cliproxyauth.Auth) *config.ClaudeKey {