From 0493e608d6b0e00e65e4e909e97504b4f6fe4565 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Wed, 28 May 2025 16:57:46 +0000 Subject: [PATCH] Fix hash generation to use new line char as delimiter also switch to using consts for header names Signed-off-by: Prabhjot Singh Sethi --- hash/const.go | 11 +++++++++++ hash/generator.go | 8 ++++---- hash/generator_test.go | 2 +- hash/validator.go | 6 +++--- 4 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 hash/const.go diff --git a/hash/const.go b/hash/const.go new file mode 100644 index 0000000..97f4ef6 --- /dev/null +++ b/hash/const.go @@ -0,0 +1,11 @@ +// Copyright © 2025 Prabhjot Singh Sethi, All Rights reserved +// Author: Prabhjot Singh Sethi + +package hash + +// Constants for HTTP authentication header keys used in HMAC-based signing and validation. +const ( + apiKeySignatureHeader = "x-signature" // Header for the HMAC-SHA256 signature + apiKeyTimestampHeader = "x-timestamp" // Header for the request timestamp (RFC3339 format) + apiKeyIdHeader = "x-api-key-id" // Header for the API key identifier +) diff --git a/hash/generator.go b/hash/generator.go index 5cad3b4..af728c9 100644 --- a/hash/generator.go +++ b/hash/generator.go @@ -77,7 +77,7 @@ Signing HTTP Requests: // Returns the HMAC as a byte slice (not hex-encoded). func generateSHA256HMAC(secret string, v ...string) []byte { // Concatenate all input strings into a single string - raw := strings.Join(v, "") + raw := strings.Join(v, "\n") // Create a new HMAC hasher using SHA-256 and the provided secret key h := hmac.New(sha256.New, []byte(secret)) @@ -135,13 +135,13 @@ func (g *generator) AddAuthHeaders(r *http.Request) *http.Request { sig := GenerateSHA256HMAC(g.secret, r.Method, r.URL.Path, timeStamp) // Add the computed signature to the request headers - r.Header.Add("x-signature", sig) + r.Header.Add(apiKeySignatureHeader, sig) // Add the API key ID to the request headers - r.Header.Add("x-api-key-id", g.id) + r.Header.Add(apiKeyIdHeader, g.id) // add timestamp to header - r.Header.Add("x-timestamp", timeStamp) + r.Header.Add(apiKeyTimestampHeader, timeStamp) return r } diff --git a/hash/generator_test.go b/hash/generator_test.go index faeaf85..a36b914 100644 --- a/hash/generator_test.go +++ b/hash/generator_test.go @@ -15,7 +15,7 @@ func Test_HashGeneration(t *testing.T) { sig := GenerateSHA256HMAC(secret, method, path, timestamp) - if sig != "2c269d572fbd6b324b5f6eb1cf06bed60811b43a82642d5f7f438b65160caa08" { + if sig != "04a41d00f2f133c8746d11c7d3d5bfc547fc514b583e3798b1df2c9c09204461" { t.Errorf("generated HMAC signature doesn't match as expected") } } diff --git a/hash/validator.go b/hash/validator.go index 39bd371..9f84e28 100644 --- a/hash/validator.go +++ b/hash/validator.go @@ -95,7 +95,7 @@ func (v *validator) Validate(r *http.Request, secret string) (bool, error) { } // Retrieve the signature from the header - sigStr := r.Header.Get("x-signature") + sigStr := r.Header.Get(apiKeySignatureHeader) if sigStr == "" { return false, fmt.Errorf("missing signature header") } @@ -107,7 +107,7 @@ func (v *validator) Validate(r *http.Request, secret string) (bool, error) { } // Retrieve the timestamp from the header - timeStr := r.Header.Get("x-timestamp") + timeStr := r.Header.Get(apiKeyTimestampHeader) if timeStr == "" { return false, fmt.Errorf("missing timestamp header") } @@ -133,7 +133,7 @@ func (v *validator) Validate(r *http.Request, secret string) (bool, error) { } func (v *validator) GetKeyId(r *http.Request) string { - return r.Header.Get("x-api-key-id") + return r.Header.Get(apiKeyIdHeader) } // NewValidator creates a new Validator instance for validating HTTP requests.