@@ -11,6 +11,33 @@ import (
1111 "github.com/lestrrat-go/option"
1212)
1313
14+ // Clock provides the current time for timestamp generation.
15+ type Clock interface {
16+ Now () time.Time
17+ }
18+
19+ // SystemClock uses the system time.
20+ type SystemClock struct {}
21+
22+ func (SystemClock ) Now () time.Time {
23+ return time .Now ()
24+ }
25+
26+ // fixedClock always returns the same time, useful for testing.
27+ type fixedClock struct {
28+ time time.Time
29+ }
30+
31+ func (c fixedClock ) Now () time.Time {
32+ return c .time
33+ }
34+
35+ // FixedClock returns a Clock that always returns the same time.
36+ // This is useful for testing to ensure deterministic timestamps.
37+ func FixedClock (t time.Time ) Clock {
38+ return fixedClock {time : t }
39+ }
40+
1441// SigningTransport is an http.RoundTripper that signs HTTP requests.
1542type SigningTransport struct {
1643 // Transport is the underlying RoundTripper.
@@ -41,6 +68,9 @@ type SigningTransport struct {
4168
4269 // Tag is an application-specific tag to include in the signature.
4370 Tag string
71+
72+ // Clock provides timestamps. If nil, SystemClock is used.
73+ Clock Clock
4474}
4575
4676// NewSigningTransport creates a new SigningTransport with the given configuration.
@@ -110,7 +140,11 @@ func (t *SigningTransport) createSignatureDefinition() *input.Definition {
110140 }
111141
112142 if t .IncludeCreated {
113- builder = builder .Created (time .Now ().Unix ())
143+ clock := t .Clock
144+ if clock == nil {
145+ clock = SystemClock {}
146+ }
147+ builder = builder .Created (clock .Now ().Unix ())
114148 }
115149
116150 if t .Tag != "" {
@@ -144,10 +178,12 @@ func NewClient(key any, keyID string, options ...TransportOption) *http.Client {
144178 transport .Components = option .Value ().([]component.Identifier )
145179 case identSignatureLabel {}:
146180 transport .SignatureLabel = option .Value ().(string )
147- case identWithoutCreated {}:
148- transport .IncludeCreated = false
181+ case identCreated {}:
182+ transport .IncludeCreated = option . Value ().( bool )
149183 case identTag {}:
150184 transport .Tag = option .Value ().(string )
185+ case identClockOption {}:
186+ transport .Clock = option .Value ().(Clock )
151187 }
152188 }
153189
@@ -195,14 +231,14 @@ type identSignatureLabel struct{}
195231
196232func (identSignatureLabel ) String () string { return "WithSignatureLabel" }
197233
198- // WithoutCreated disables the created parameter.
199- func WithoutCreated ( ) TransportOption {
200- return option .New (identWithoutCreated {}, true )
234+ // WithCreated controls whether to include the created parameter.
235+ func WithCreated ( include bool ) TransportOption {
236+ return option .New (identCreated {}, include )
201237}
202238
203- type identWithoutCreated struct {}
239+ type identCreated struct {}
204240
205- func (identWithoutCreated ) String () string { return "WithoutCreated " }
241+ func (identCreated ) String () string { return "WithCreated " }
206242
207243// WithTag sets the application-specific tag.
208244func WithTag (tag string ) TransportOption {
@@ -212,3 +248,30 @@ func WithTag(tag string) TransportOption {
212248type identTag struct {}
213249
214250func (identTag ) String () string { return "WithTag" }
251+
252+ // SignVerifyOption can be used with both signing and verification operations.
253+ type SignVerifyOption interface {
254+ transportOption ()
255+ signerOption ()
256+ option.Interface
257+ }
258+
259+ // clockOption implements SignVerifyOption
260+ type clockOption struct {
261+ clock Clock
262+ }
263+
264+ func (c clockOption ) Ident () any { return identClockOption {} }
265+ func (c clockOption ) Value () any { return c .clock }
266+ func (c clockOption ) transportOption () {}
267+ func (c clockOption ) signerOption () {}
268+
269+ type identClockOption struct {}
270+
271+ func (identClockOption ) String () string { return "WithClock" }
272+
273+ // WithClock sets the clock used for timestamp generation.
274+ // This option works for both TransportOption and signerOption.
275+ func WithClock (clock Clock ) SignVerifyOption {
276+ return clockOption {clock : clock }
277+ }
0 commit comments