From 7306ad54892e9d58f6ecbdb5dc6f49944ed144c7 Mon Sep 17 00:00:00 2001 From: tim-kos Date: Mon, 27 Apr 2026 13:35:21 +0200 Subject: [PATCH 1/3] Use sha384 signatures in list requests --- transloadit.go | 5 +-- transloadit_signature_test.go | 82 +++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 transloadit_signature_test.go diff --git a/transloadit.go b/transloadit.go index 588e697..5e25700 100755 --- a/transloadit.go +++ b/transloadit.go @@ -4,7 +4,6 @@ package transloadit import ( "context" "crypto/hmac" - "crypto/sha1" "crypto/sha256" "crypto/sha512" "encoding/hex" @@ -213,11 +212,11 @@ func (client *Client) listRequest(ctx context.Context, path string, listOptions return fmt.Errorf("unable to create signature: %s", err) } - hash := hmac.New(sha1.New, []byte(client.config.AuthSecret)) + hash := hmac.New(sha512.New384, []byte(client.config.AuthSecret)) hash.Write(b) params := string(b) - signature := hex.EncodeToString(hash.Sum(nil)) + signature := "sha384:" + hex.EncodeToString(hash.Sum(nil)) v := url.Values{} v.Set("params", params) diff --git a/transloadit_signature_test.go b/transloadit_signature_test.go new file mode 100644 index 0000000..f781240 --- /dev/null +++ b/transloadit_signature_test.go @@ -0,0 +1,82 @@ +package transloadit + +import ( + "context" + "crypto/hmac" + "crypto/sha512" + "encoding/hex" + "net/http" + "net/http/httptest" + "strings" + "testing" +) + +func TestSign_UsesSha384WithAlgorithmPrefix(t *testing.T) { + client := NewClient(Config{ + AuthKey: "foo_key", + AuthSecret: "foo_secret", + Endpoint: "https://api2.transloadit.com", + }) + + params, signature, err := client.sign(map[string]interface{}{ + "foo": "bar", + }) + if err != nil { + t.Fatal(err) + } + + if !strings.HasPrefix(signature, "sha384:") { + t.Fatalf("signature prefix should be sha384:, got %q", signature) + } + + hash := hmac.New(sha512.New384, []byte(client.config.AuthSecret)) + hash.Write([]byte(params)) + expected := "sha384:" + hex.EncodeToString(hash.Sum(nil)) + + if signature != expected { + t.Fatalf("wrong signature, expected %q got %q", expected, signature) + } +} + +func TestListRequest_UsesSha384WithAlgorithmPrefix(t *testing.T) { + client := NewClient(Config{ + AuthKey: "foo_key", + AuthSecret: "foo_secret", + }) + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + params := r.URL.Query().Get("params") + signature := r.URL.Query().Get("signature") + + if params == "" { + t.Fatal("params query should be set") + } + + if !strings.HasPrefix(signature, "sha384:") { + t.Fatalf("listRequest signature prefix should be sha384:, got %q", signature) + } + + hash := hmac.New(sha512.New384, []byte(client.config.AuthSecret)) + hash.Write([]byte(params)) + expected := "sha384:" + hex.EncodeToString(hash.Sum(nil)) + + if signature != expected { + t.Fatalf("wrong listRequest signature, expected %q got %q", expected, signature) + } + + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"items":[],"count":0}`)) + })) + defer server.Close() + + client.config.Endpoint = server.URL + + list, err := client.ListTemplates(context.Background(), &ListOptions{PageSize: 1}) + if err != nil { + t.Fatal(err) + } + + if list.Count != 0 { + t.Fatalf("expected empty list count 0, got %d", list.Count) + } +} From 5ac3e929afa659e2e19a7b480b73b445839a9ee8 Mon Sep 17 00:00:00 2001 From: tim-kos Date: Mon, 27 Apr 2026 13:37:47 +0200 Subject: [PATCH 2/3] Avoid FailNow in HTTP handler goroutine --- transloadit_signature_test.go | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/transloadit_signature_test.go b/transloadit_signature_test.go index f781240..70f5eaa 100644 --- a/transloadit_signature_test.go +++ b/transloadit_signature_test.go @@ -5,6 +5,7 @@ import ( "crypto/hmac" "crypto/sha512" "encoding/hex" + "fmt" "net/http" "net/http/httptest" "strings" @@ -44,16 +45,24 @@ func TestListRequest_UsesSha384WithAlgorithmPrefix(t *testing.T) { AuthSecret: "foo_secret", }) + errCh := make(chan error, 1) + reportErr := func(err error) { + select { + case errCh <- err: + default: + } + } + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { params := r.URL.Query().Get("params") signature := r.URL.Query().Get("signature") if params == "" { - t.Fatal("params query should be set") + reportErr(fmt.Errorf("params query should be set")) } if !strings.HasPrefix(signature, "sha384:") { - t.Fatalf("listRequest signature prefix should be sha384:, got %q", signature) + reportErr(fmt.Errorf("listRequest signature prefix should be sha384:, got %q", signature)) } hash := hmac.New(sha512.New384, []byte(client.config.AuthSecret)) @@ -61,7 +70,7 @@ func TestListRequest_UsesSha384WithAlgorithmPrefix(t *testing.T) { expected := "sha384:" + hex.EncodeToString(hash.Sum(nil)) if signature != expected { - t.Fatalf("wrong listRequest signature, expected %q got %q", expected, signature) + reportErr(fmt.Errorf("wrong listRequest signature, expected %q got %q", expected, signature)) } w.Header().Set("Content-Type", "application/json") @@ -79,4 +88,10 @@ func TestListRequest_UsesSha384WithAlgorithmPrefix(t *testing.T) { if list.Count != 0 { t.Fatalf("expected empty list count 0, got %d", list.Count) } + + select { + case verifyErr := <-errCh: + t.Fatal(verifyErr) + default: + } } From 1598f076155d55873fc29cff0d71e33ab9ca2968 Mon Sep 17 00:00:00 2001 From: tim-kos Date: Tue, 19 May 2026 11:15:27 +0200 Subject: [PATCH 3/3] Fix example build and document CDN signing --- Makefile | 10 +++++++--- transloadit.go | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 184c7f7..e571c66 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,11 @@ SHELL := /usr/bin/env bash test-examples: - cd ./examples && find . -type f | xargs -i sh -c "go build {} && go clean" \; + tmp=$$(mktemp -d); \ + trap 'rm -rf "$$tmp"' EXIT; \ + while IFS= read -r -d '' file; do \ + go build -o "$$tmp/$$(basename "$$(dirname "$$file")")" "$$file"; \ + done < <(find ./examples -name '*.go' -print0) test-package: go test -v -coverprofile=coverage.out -covermode=atomic . @@ -20,5 +24,5 @@ release: .PHONY: \ release \ test \ - test-package \ - test-examples + test-package \ + test-examples diff --git a/transloadit.go b/transloadit.go index 5e25700..acdb038 100755 --- a/transloadit.go +++ b/transloadit.go @@ -293,7 +293,7 @@ func (client *Client) CreateSignedSmartCDNUrl(opts SignedSmartCDNUrlOptions) str stringToSign := fmt.Sprintf("%s/%s/%s?%s", workspaceSlug, templateSlug, inputField, queryString) - // Create signature using SHA-256 + // Smart CDN signatures intentionally remain SHA-256; API request signatures use SHA-384. hash := hmac.New(sha256.New, []byte(client.config.AuthSecret)) hash.Write([]byte(stringToSign)) signature := url.QueryEscape("sha256:" + hex.EncodeToString(hash.Sum(nil)))