From b72310849b626907fa6a5a58f702d331492fe866 Mon Sep 17 00:00:00 2001 From: Philippe Boneff Date: Fri, 4 Apr 2025 14:27:17 +0000 Subject: [PATCH 1/3] move extension parsing into staticctapi --- internal/hammer/loadtest/client.go | 39 ++--------------------- internal/types/staticct/staticctapi.go | 43 ++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 36 deletions(-) diff --git a/internal/hammer/loadtest/client.go b/internal/hammer/loadtest/client.go index 30321a03..dcefd417 100644 --- a/internal/hammer/loadtest/client.go +++ b/internal/hammer/loadtest/client.go @@ -17,7 +17,6 @@ package loadtest import ( "bytes" "context" - "encoding/base64" "encoding/json" "errors" "fmt" @@ -31,7 +30,7 @@ import ( "github.com/transparency-dev/static-ct/internal/client" "github.com/transparency-dev/static-ct/internal/types/rfc6962" - "golang.org/x/crypto/cryptobyte" + "github.com/transparency-dev/static-ct/internal/types/staticct" "k8s.io/klog/v2" ) @@ -240,41 +239,9 @@ func parseAddChainResponse(body []byte) (uint64, uint64, error) { return 0, 0, fmt.Errorf("can't parse add-chain response: %v", err) } - extensionBytes, err := base64.StdEncoding.DecodeString(resp.Extensions) + leafIdx, err := staticct.ParseCTExtensions(resp.Extensions) if err != nil { - return 0, 0, fmt.Errorf("can't decode extensions: %v", err) - } - extensions := cryptobyte.String(extensionBytes) - var extensionType uint8 - var extensionData cryptobyte.String - var leafIdx int64 - if !extensions.ReadUint8(&extensionType) { - return 0, 0, fmt.Errorf("can't read extension type") - } - if extensionType != 0 { - return 0, 0, fmt.Errorf("wrong extension type %d, want 0", extensionType) - } - if !extensions.ReadUint16LengthPrefixed(&extensionData) { - return 0, 0, fmt.Errorf("can't read extension data") - } - if !readUint40(&extensionData, &leafIdx) { - return 0, 0, fmt.Errorf("can't read leaf index from extension") - } - if !extensionData.Empty() || - !extensions.Empty() { - return 0, 0, fmt.Errorf("invalid data tile extensions: %v", resp.Extensions) + return 0, 0, fmt.Errorf("can't parse extensions: %v", err) } return uint64(leafIdx), resp.Timestamp, nil } - -// readUint40 decodes a big-endian, 40-bit value into out and advances over it. -// It reports whether the read was successful. -// Code is copied from https://github.com/FiloSottile/sunlight/blob/main/extensions.go. -func readUint40(s *cryptobyte.String, out *int64) bool { - var v []byte - if !s.ReadBytes(&v, 5) { - return false - } - *out = int64(v[0])<<32 | int64(v[1])<<24 | int64(v[2])<<16 | int64(v[3])<<8 | int64(v[4]) - return true -} diff --git a/internal/types/staticct/staticctapi.go b/internal/types/staticct/staticctapi.go index a15a136c..5c86dae4 100644 --- a/internal/types/staticct/staticctapi.go +++ b/internal/types/staticct/staticctapi.go @@ -15,6 +15,7 @@ package staticct import ( + "encoding/base64" "fmt" "math" @@ -102,3 +103,45 @@ func (t *EntryBundle) UnmarshalText(raw []byte) error { t.Entries = entries return nil } + +// parseCTExtensions parses CTEXtensions into an index. +// Code is inspired by https://github.com/FiloSottile/sunlight/blob/main/tile.go. +func ParseCTExtensions(ext string) (uint64, error) { + extensionBytes, err := base64.StdEncoding.DecodeString(ext) + if err != nil { + return 0, fmt.Errorf("can't decode extensions: %v", err) + } + extensions := cryptobyte.String(extensionBytes) + var extensionType uint8 + var extensionData cryptobyte.String + var leafIdx int64 + if !extensions.ReadUint8(&extensionType) { + return 0, fmt.Errorf("can't read extension type") + } + if extensionType != 0 { + return 0, fmt.Errorf("wrong extension type %d, want 0", extensionType) + } + if !extensions.ReadUint16LengthPrefixed(&extensionData) { + return 0, fmt.Errorf("can't read extension data") + } + if !readUint40(&extensionData, &leafIdx) { + return 0, fmt.Errorf("can't read leaf index from extension") + } + if !extensionData.Empty() || + !extensions.Empty() { + return 0, fmt.Errorf("invalid data tile extensions: %v", ext) + } + return uint64(leafIdx), nil +} + +// readUint40 decodes a big-endian, 40-bit value into out and advances over it. +// It reports whether the read was successful. +// Code is copied from https://github.com/FiloSottile/sunlight/blob/main/extensions.go. +func readUint40(s *cryptobyte.String, out *int64) bool { + var v []byte + if !s.ReadBytes(&v, 5) { + return false + } + *out = int64(v[0])<<32 | int64(v[1])<<24 | int64(v[2])<<16 | int64(v[3])<<8 | int64(v[4]) + return true +} From 0218fe725d9d58e0b92189c5f4c28109ec1b27b4 Mon Sep 17 00:00:00 2001 From: Philippe Boneff Date: Mon, 7 Apr 2025 16:29:34 +0000 Subject: [PATCH 2/3] move staticctapi.go to staticct.go --- internal/types/staticct/{staticctapi.go => staticct.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename internal/types/staticct/{staticctapi.go => staticct.go} (100%) diff --git a/internal/types/staticct/staticctapi.go b/internal/types/staticct/staticct.go similarity index 100% rename from internal/types/staticct/staticctapi.go rename to internal/types/staticct/staticct.go From b0219e699eb15b88e06163951151f5740c48a10f Mon Sep 17 00:00:00 2001 From: Philippe Boneff Date: Mon, 7 Apr 2025 17:03:50 +0000 Subject: [PATCH 3/3] Address comments --- internal/types/staticct/staticct.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/types/staticct/staticct.go b/internal/types/staticct/staticct.go index 5c86dae4..44ca2c88 100644 --- a/internal/types/staticct/staticct.go +++ b/internal/types/staticct/staticct.go @@ -104,7 +104,7 @@ func (t *EntryBundle) UnmarshalText(raw []byte) error { return nil } -// parseCTExtensions parses CTEXtensions into an index. +// parseCTExtensions parses CTExtensions into an index. // Code is inspired by https://github.com/FiloSottile/sunlight/blob/main/tile.go. func ParseCTExtensions(ext string) (uint64, error) { extensionBytes, err := base64.StdEncoding.DecodeString(ext) @@ -114,7 +114,7 @@ func ParseCTExtensions(ext string) (uint64, error) { extensions := cryptobyte.String(extensionBytes) var extensionType uint8 var extensionData cryptobyte.String - var leafIdx int64 + var leafIdx uint64 if !extensions.ReadUint8(&extensionType) { return 0, fmt.Errorf("can't read extension type") } @@ -129,19 +129,19 @@ func ParseCTExtensions(ext string) (uint64, error) { } if !extensionData.Empty() || !extensions.Empty() { - return 0, fmt.Errorf("invalid data tile extensions: %v", ext) + return 0, fmt.Errorf("invalid SCT extension data: %v", ext) } - return uint64(leafIdx), nil + return leafIdx, nil } // readUint40 decodes a big-endian, 40-bit value into out and advances over it. // It reports whether the read was successful. // Code is copied from https://github.com/FiloSottile/sunlight/blob/main/extensions.go. -func readUint40(s *cryptobyte.String, out *int64) bool { +func readUint40(s *cryptobyte.String, out *uint64) bool { var v []byte if !s.ReadBytes(&v, 5) { return false } - *out = int64(v[0])<<32 | int64(v[1])<<24 | int64(v[2])<<16 | int64(v[3])<<8 | int64(v[4]) + *out = uint64(v[0])<<32 | uint64(v[1])<<24 | uint64(v[2])<<16 | uint64(v[3])<<8 | uint64(v[4]) return true }