package events import ( "crypto/hmac" "crypto/sha256" "encoding/hex" "strings" "testing" ) func hmacHex(body []byte, secret string) string { mac := hmac.New(sha256.New, []byte(secret)) mac.Write(body) return hex.EncodeToString(mac.Sum(nil)) } func TestVerifyGiteaHMAC(t *testing.T) { body := []byte(`{"action":"approved","number":5}`) secret := "gitea-hook-secret" cases := []struct { name string sig string wantErr bool }{ {"valid signature", hmacHex(body, secret), false}, {"missing header value", "", true}, {"all-zero signature", strings.Repeat("00", 32), true}, {"wrong secret", hmacHex(body, "other-secret"), true}, {"not hex", "not-hex-at-all", true}, {"truncated signature", hmacHex(body, secret)[:32], true}, {"uppercase hex still valid", strings.ToUpper(hmacHex(body, secret)), false}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { err := VerifyGiteaHMAC(body, tc.sig, secret) if tc.wantErr && err == nil { t.Fatalf("expected error, got nil") } if !tc.wantErr && err != nil { t.Fatalf("unexpected error: %v", err) } if err != nil && !IsUnverified(err) { t.Errorf("error %v is not ErrUnverified", err) } }) } } func TestVerifyGiteaHMACBodySensitivity(t *testing.T) { secret := "s" sig := hmacHex([]byte(`{"a":1}`), secret) if err := VerifyGiteaHMAC([]byte(`{"a":2}`), sig, secret); err == nil { t.Fatal("signature over a different body must not verify") } } func TestVerifySharedSecret(t *testing.T) { const header = "X-Test-Secret" secret := "shared-hook-secret" cases := []struct { name string value string wantErr bool }{ {"valid", secret, false}, {"missing header value", "", true}, {"wrong secret", "wrong", true}, {"prefix of secret", secret[:10], true}, {"case differs", strings.ToUpper(secret), true}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { err := VerifySharedSecret(header, tc.value, secret) if tc.wantErr && err == nil { t.Fatalf("expected error, got nil") } if !tc.wantErr && err != nil { t.Fatalf("unexpected error: %v", err) } }) } } func TestSignGiteaMatchesVerify(t *testing.T) { body, secret := []byte(`{}`), "k" if err := VerifyGiteaHMAC(body, SignGitea(body, secret), secret); err != nil { t.Fatalf("SignGitea does not verify: %v", err) } if GiteaSignatureHeader() != "X-Gitea-Signature" { t.Errorf("unexpected header name %q", GiteaSignatureHeader()) } // sha256 import guard: helper must agree with a direct hmac. if SignGitea(body, secret) != hmacHex(body, secret) { t.Errorf("SignGitea disagrees with hmacHex") } }