From ec775ada1f7c8aeeea549d61d3da5d4bdf9bde03 Mon Sep 17 00:00:00 2001 From: Patrick Zheng Date: Fri, 28 Jun 2024 09:05:01 +0800 Subject: [PATCH 1/8] added TimestampLimit Signed-off-by: Patrick Zheng --- conformance_test.go | 14 +++++++------- http_test.go | 14 +++++++------- internal/oid/oid.go | 9 +++++++++ token.go | 42 ++++++++++++++++++++++++++++++++++++------ token_test.go | 15 ++++++++------- 5 files changed, 67 insertions(+), 27 deletions(-) diff --git a/conformance_test.go b/conformance_test.go index 8697dd1..fd18477 100644 --- a/conformance_test.go +++ b/conformance_test.go @@ -113,17 +113,17 @@ func TestTSATimestampGranted(t *testing.T) { if err != nil { t.Fatal("SignedToken.Info() error =", err) } - ts, accuracy, err := info.Validate(message) + timestampLimit, err := info.Validate(message) if err != nil { t.Errorf("TSTInfo.Timestamp() error = %v", err) } - wantTimestamp := now - if ts != wantTimestamp { - t.Errorf("TSTInfo.Timestamp() Timestamp = %v, want %v", ts, wantTimestamp) + wantTimestampLowerLimit := time.Date(2021, 9, 18, 11, 54, 33, 0, time.UTC) + wantTimestampUpperLimit := time.Date(2021, 9, 18, 11, 54, 35, 0, time.UTC) + if timestampLimit.LowerLimit != wantTimestampLowerLimit { + t.Errorf("TSTInfo.Timestamp() Timestamp = %v, want %v", timestampLimit.LowerLimit, wantTimestampLowerLimit) } - wantAccuracy := time.Second - if accuracy != wantAccuracy { - t.Errorf("TSTInfo.Timestamp() Accuracy = %v, want %v", accuracy, wantAccuracy) + if timestampLimit.UpperLimit != wantTimestampUpperLimit { + t.Errorf("TSTInfo.Timestamp() Timestamp = %v, want %v", timestampLimit.UpperLimit, wantTimestampUpperLimit) } } diff --git a/http_test.go b/http_test.go index 9714298..94aaeff 100644 --- a/http_test.go +++ b/http_test.go @@ -122,17 +122,17 @@ func TestHTTPTimestampGranted(t *testing.T) { if err != nil { t.Fatal("SignedToken.Info() error =", err) } - timestamp, accuracy, err := info.Validate(message) + timestampLimit, err := info.Validate(message) if err != nil { t.Errorf("TSTInfo.Timestamp() error = %v", err) } - wantTimestamp := time.Date(2021, 9, 18, 11, 54, 34, 0, time.UTC) - if timestamp != wantTimestamp { - t.Errorf("TSTInfo.Timestamp() Timestamp = %v, want %v", timestamp, wantTimestamp) + wantTimestampLowerLimit := time.Date(2021, 9, 18, 11, 54, 33, 0, time.UTC) + wantTimestampUpperLimit := time.Date(2021, 9, 18, 11, 54, 35, 0, time.UTC) + if timestampLimit.LowerLimit != wantTimestampLowerLimit { + t.Errorf("TSTInfo.Timestamp() Timestamp = %v, want %v", timestampLimit.LowerLimit, wantTimestampLowerLimit) } - wantAccuracy := time.Second - if accuracy != wantAccuracy { - t.Errorf("TSTInfo.Timestamp() Accuracy = %v, want %v", accuracy, wantAccuracy) + if timestampLimit.UpperLimit != wantTimestampUpperLimit { + t.Errorf("TSTInfo.Timestamp() Timestamp = %v, want %v", timestampLimit.UpperLimit, wantTimestampUpperLimit) } } diff --git a/internal/oid/oid.go b/internal/oid/oid.go index d93ba6b..abdddce 100644 --- a/internal/oid/oid.go +++ b/internal/oid/oid.go @@ -98,3 +98,12 @@ var ( // Reference: https://datatracker.ietf.org/doc/html/rfc3161#section-2.3 TimeStamping = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8} ) + +// OIDs for RFC 3628 Policy Requirements for Time-Stamping Authorities (TSAs) +var ( + // BaselineTimeStampPolicy (baseline time-stamp policy) is defined in + // RFC 3628 + // + // Referene: https://datatracker.ietf.org/doc/html/rfc3628#section-5.2 + BaselineTimeStampPolicy = asn1.ObjectIdentifier{0, 4, 0, 2023, 1, 1} +) diff --git a/token.go b/token.go index 216b5c4..4edfe25 100644 --- a/token.go +++ b/token.go @@ -214,16 +214,46 @@ type TSTInfo struct { Extensions []pkix.Extension `asn1:"optional,tag:1"` } +// TimestampLimit contains the lower and upper limits of the time at which the +// timestamp token has been created by the TSA +// +// Reference: RFC 3161 2.4.2 +type TimestampLimit struct { + // LowerLimit denotes the lower limit of the time at which the + // timestamp token has been created by the TSA + LowerLimit time.Time + + // UpperLimit denotes the upper limit of the time at which the + // timestamp token has been created by the TSA + UpperLimit time.Time +} + // Validate validates tst and returns the GenTime and Accuracy. // tst MUST be valid and the time stamped datum MUST match message. -func (tst *TSTInfo) Validate(message []byte) (time.Time, time.Duration, error) { +func (tst *TSTInfo) Validate(message []byte) (*TimestampLimit, error) { if err := tst.validate(message); err != nil { - return time.Time{}, 0, err + return nil, err } - accuracy := time.Duration(tst.Accuracy.Seconds)*time.Second + - time.Duration(tst.Accuracy.Milliseconds)*time.Millisecond + - time.Duration(tst.Accuracy.Microseconds)*time.Microsecond - return tst.GenTime, accuracy, nil + + var accuracy time.Duration + // References: + // https://datatracker.ietf.org/doc/html/rfc3628#section-5.1 + // https://github.com/notaryproject/specifications/blob/main/specs/trust-store-trust-policy.md#steps + if tst.Accuracy.Seconds == 0 && + tst.Accuracy.Microseconds == 0 && + tst.Accuracy.Milliseconds == 0 && + oid.BaselineTimeStampPolicy.Equal(tst.Policy) { + accuracy = 1 * time.Second + } else { + accuracy = time.Duration(tst.Accuracy.Seconds)*time.Second + + time.Duration(tst.Accuracy.Milliseconds)*time.Millisecond + + time.Duration(tst.Accuracy.Microseconds)*time.Microsecond + } + + return &TimestampLimit{ + LowerLimit: tst.GenTime.Add(-accuracy), + UpperLimit: tst.GenTime.Add(accuracy), + }, nil } // validate checks tst against RFC 3161. diff --git a/token_test.go b/token_test.go index 4ef212c..5f51cfa 100644 --- a/token_test.go +++ b/token_test.go @@ -202,7 +202,7 @@ func TestTimestamp(t *testing.T) { t.Fatal(err) } expectedErrMsg := "invalid TSTInfo: mismatched message" - if _, _, err := tstInfo.Validate([]byte("invalid")); err == nil || err.Error() != expectedErrMsg { + if _, err := tstInfo.Validate([]byte("invalid")); err == nil || err.Error() != expectedErrMsg { t.Fatalf("expected error %s, but got %v", expectedErrMsg, err) } @@ -214,16 +214,17 @@ func TestTimestamp(t *testing.T) { if err != nil { t.Fatal(err) } - timestamp, accuracy, err := tstInfo.Validate([]byte("notation")) + timestampLimit, err := tstInfo.Validate([]byte("notation")) if err != nil { t.Fatalf("expected nil error, but got %v", err) } - expectedTimestamp := time.Date(2021, time.September, 17, 14, 9, 10, 0, time.UTC) - if timestamp != expectedTimestamp { - t.Fatalf("expected timestamp %s, but got %s", expectedTimestamp, timestamp) + expectedLowerLimit := time.Date(2021, time.September, 17, 14, 9, 9, 0, time.UTC) + expectedUpperLimit := time.Date(2021, time.September, 17, 14, 9, 11, 0, time.UTC) + if timestampLimit.LowerLimit != expectedLowerLimit { + t.Fatalf("expected timestamp %s, but got %s", expectedLowerLimit, timestampLimit.LowerLimit) } - if accuracy.Seconds() != 1 { - t.Fatalf("expected 1s accuracy, but got %s", accuracy) + if timestampLimit.UpperLimit != expectedUpperLimit { + t.Fatalf("expected timestamp %s, but got %s", expectedUpperLimit, timestampLimit.UpperLimit) } } From 458ec160a79c29927d0c4140e6e23e29476dda7e Mon Sep 17 00:00:00 2001 From: Patrick Zheng Date: Fri, 28 Jun 2024 09:26:08 +0800 Subject: [PATCH 2/8] add more tests Signed-off-by: Patrick Zheng --- token_test.go | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/token_test.go b/token_test.go index 5f51cfa..9a19ed6 100644 --- a/token_test.go +++ b/token_test.go @@ -192,7 +192,7 @@ func TestGetSigningCertificate(t *testing.T) { } } -func TestTimestamp(t *testing.T) { +func TestValidate(t *testing.T) { timestampToken, err := getTimestampTokenFromPath("testdata/TimeStampToken.p7s") if err != nil { t.Fatal(err) @@ -226,6 +226,29 @@ func TestTimestamp(t *testing.T) { if timestampLimit.UpperLimit != expectedUpperLimit { t.Fatalf("expected timestamp %s, but got %s", expectedUpperLimit, timestampLimit.UpperLimit) } + + timestampToken, err = getTimestampTokenFromPath("testdata/TimeStampToken.p7s") + if err != nil { + t.Fatal(err) + } + tstInfo, err = timestampToken.Info() + if err != nil { + t.Fatal(err) + } + tstInfo.Accuracy = Accuracy{} + tstInfo.Policy = oid.BaselineTimeStampPolicy + timestampLimit, err = tstInfo.Validate([]byte("notation")) + if err != nil { + t.Fatalf("expected nil error, but got %v", err) + } + expectedLowerLimit = time.Date(2021, time.September, 17, 14, 9, 9, 0, time.UTC) + expectedUpperLimit = time.Date(2021, time.September, 17, 14, 9, 11, 0, time.UTC) + if timestampLimit.LowerLimit != expectedLowerLimit { + t.Fatalf("expected timestamp %s, but got %s", expectedLowerLimit, timestampLimit.LowerLimit) + } + if timestampLimit.UpperLimit != expectedUpperLimit { + t.Fatalf("expected timestamp %s, but got %s", expectedUpperLimit, timestampLimit.UpperLimit) + } } func TestValidateInfo(t *testing.T) { From cc399dbe7bc31300cb68a5fe659cbb2a2dbc44d4 Mon Sep 17 00:00:00 2001 From: Patrick Zheng Date: Fri, 28 Jun 2024 10:36:47 +0800 Subject: [PATCH 3/8] naming Signed-off-by: Patrick Zheng --- conformance_test.go | 4 ++-- http_test.go | 24 ++++++++++++------------ internal/oid/oid.go | 8 ++++---- response.go | 4 ++-- response_test.go | 18 +++++++++--------- token.go | 2 +- token_test.go | 2 +- 7 files changed, 31 insertions(+), 31 deletions(-) diff --git a/conformance_test.go b/conformance_test.go index fd18477..da6545e 100644 --- a/conformance_test.go +++ b/conformance_test.go @@ -328,7 +328,7 @@ func newTestTSA(malformedExtKeyUsage, criticalTimestampingExtKeyUsage bool) (*te BasicConstraintsValid: true, } if criticalTimestampingExtKeyUsage { - extValue, err := asn1.Marshal([]asn1.ObjectIdentifier{oid.TimeStamping}) + extValue, err := asn1.Marshal([]asn1.ObjectIdentifier{oid.Timestamping}) if err != nil { return nil, err } @@ -414,7 +414,7 @@ func (tsa *testTSA) Timestamp(_ context.Context, req *Request) (*Response, error Status: pki.StatusInfo{ Status: pki.StatusGranted, }, - TimeStampToken: token, + TimestampToken: token, }, nil } diff --git a/http_test.go b/http_test.go index 94aaeff..e06553c 100644 --- a/http_test.go +++ b/http_test.go @@ -40,10 +40,10 @@ func TestHTTPTimestampGranted(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { const wantContentType = MediaTypeTimestampQuery if got := r.Header.Get("Content-Type"); got != wantContentType { - t.Fatalf("TimeStampRequest.ContentType = %v, want %v", err, wantContentType) + t.Fatalf("TimestampRequest.ContentType = %v, want %v", err, wantContentType) } if _, err := io.ReadAll(r.Body); err != nil { - t.Fatalf("TimeStampRequest.Body read error = %v", err) + t.Fatalf("TimestampRequest.Body read error = %v", err) } // write reply @@ -145,10 +145,10 @@ func TestHTTPTimestampRejection(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { const wantContentType = MediaTypeTimestampQuery if got := r.Header.Get("Content-Type"); got != wantContentType { - t.Fatalf("TimeStampRequest.ContentType = %v, want %v", err, wantContentType) + t.Fatalf("TimestampRequest.ContentType = %v, want %v", err, wantContentType) } if _, err := io.ReadAll(r.Body); err != nil { - t.Fatalf("TimeStampRequest.Body read error = %v", err) + t.Fatalf("TimestampRequest.Body read error = %v", err) } // write reply @@ -267,10 +267,10 @@ func TestHttpTimestamperTimestamp(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { const wantContentType = MediaTypeTimestampQuery if got := r.Header.Get("Content-Type"); got != wantContentType { - t.Fatalf("TimeStampRequest.ContentType = %v, want %v", err, wantContentType) + t.Fatalf("TimestampRequest.ContentType = %v, want %v", err, wantContentType) } if _, err := io.ReadAll(r.Body); err != nil { - t.Fatalf("TimeStampRequest.Body read error = %v", err) + t.Fatalf("TimestampRequest.Body read error = %v", err) } // write reply @@ -308,10 +308,10 @@ func TestHttpTimestamperTimestamp(t *testing.T) { ts2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { const wantContentType = MediaTypeTimestampQuery if got := r.Header.Get("Content-Type"); got != wantContentType { - t.Fatalf("TimeStampRequest.ContentType = %v, want %v", err, wantContentType) + t.Fatalf("TimestampRequest.ContentType = %v, want %v", err, wantContentType) } if _, err := io.ReadAll(r.Body); err != nil { - t.Fatalf("TimeStampRequest.Body read error = %v", err) + t.Fatalf("TimestampRequest.Body read error = %v", err) } // write reply @@ -334,10 +334,10 @@ func TestHttpTimestamperTimestamp(t *testing.T) { ts3 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { const wantContentType = MediaTypeTimestampQuery if got := r.Header.Get("Content-Type"); got != wantContentType { - t.Fatalf("TimeStampRequest.ContentType = %v, want %v", err, wantContentType) + t.Fatalf("TimestampRequest.ContentType = %v, want %v", err, wantContentType) } if _, err := io.ReadAll(r.Body); err != nil { - t.Fatalf("TimeStampRequest.Body read error = %v", err) + t.Fatalf("TimestampRequest.Body read error = %v", err) } // write reply @@ -363,10 +363,10 @@ func TestHttpTimestamperTimestamp(t *testing.T) { ts4 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { const wantContentType = MediaTypeTimestampQuery if got := r.Header.Get("Content-Type"); got != wantContentType { - t.Fatalf("TimeStampRequest.ContentType = %v, want %v", err, wantContentType) + t.Fatalf("TimestampRequest.ContentType = %v, want %v", err, wantContentType) } if _, err := io.ReadAll(r.Body); err != nil { - t.Fatalf("TimeStampRequest.Body read error = %v", err) + t.Fatalf("TimestampRequest.Body read error = %v", err) } // write reply diff --git a/internal/oid/oid.go b/internal/oid/oid.go index abdddce..7ea542f 100644 --- a/internal/oid/oid.go +++ b/internal/oid/oid.go @@ -93,17 +93,17 @@ var ( // Reference: https://www.rfc-editor.org/rfc/rfc5280.html#section-4.2.1.12 ExtKeyUsage = asn1.ObjectIdentifier{2, 5, 29, 37} - // TimeStamping (id-kp-timeStamping) is defined in RFC 3161 2.3 + // Timestamping (id-kp-timeStamping) is defined in RFC 3161 2.3 // // Reference: https://datatracker.ietf.org/doc/html/rfc3161#section-2.3 - TimeStamping = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8} + Timestamping = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8} ) // OIDs for RFC 3628 Policy Requirements for Time-Stamping Authorities (TSAs) var ( - // BaselineTimeStampPolicy (baseline time-stamp policy) is defined in + // BaselineTimestampPolicy (baseline time-stamp policy) is defined in // RFC 3628 // // Referene: https://datatracker.ietf.org/doc/html/rfc3628#section-5.2 - BaselineTimeStampPolicy = asn1.ObjectIdentifier{0, 4, 0, 2023, 1, 1} + BaselineTimestampPolicy = asn1.ObjectIdentifier{0, 4, 0, 2023, 1, 1} ) diff --git a/response.go b/response.go index ba428d6..5d6492b 100644 --- a/response.go +++ b/response.go @@ -107,7 +107,7 @@ type generalNames struct { // timeStampToken TimeStampToken OPTIONAL } type Response struct { Status pki.StatusInfo - TimeStampToken asn1.RawValue `asn1:"optional"` + TimestampToken asn1.RawValue `asn1:"optional"` } // MarshalBinary encodes the response to binary form. @@ -138,7 +138,7 @@ func (r *Response) SignedToken() (*SignedToken, error) { if err := r.validateStatus(); err != nil { return nil, err } - return ParseSignedToken(r.TimeStampToken.FullBytes) + return ParseSignedToken(r.TimestampToken.FullBytes) } // Validate checks if resp is a successful timestamp response against diff --git a/response_test.go b/response_test.go index 1f06cbc..64f1fe7 100644 --- a/response_test.go +++ b/response_test.go @@ -168,7 +168,7 @@ func TestValidateResponse(t *testing.T) { Status: pki.StatusInfo{ Status: pki.StatusGranted, }, - TimeStampToken: asn1.RawValue{ + TimestampToken: asn1.RawValue{ FullBytes: token, }, } @@ -187,7 +187,7 @@ func TestValidateResponse(t *testing.T) { Status: pki.StatusInfo{ Status: pki.StatusGranted, }, - TimeStampToken: asn1.RawValue{ + TimestampToken: asn1.RawValue{ FullBytes: token, }, } @@ -208,7 +208,7 @@ func TestValidateResponse(t *testing.T) { Status: pki.StatusInfo{ Status: pki.StatusGranted, }, - TimeStampToken: asn1.RawValue{ + TimestampToken: asn1.RawValue{ FullBytes: token, }, } @@ -227,7 +227,7 @@ func TestValidateResponse(t *testing.T) { Status: pki.StatusInfo{ Status: pki.StatusGranted, }, - TimeStampToken: asn1.RawValue{ + TimestampToken: asn1.RawValue{ FullBytes: token, }, } @@ -264,7 +264,7 @@ func TestValidateResponse(t *testing.T) { Status: pki.StatusInfo{ Status: pki.StatusGranted, }, - TimeStampToken: asn1.RawValue{ + TimestampToken: asn1.RawValue{ FullBytes: token, }, } @@ -286,7 +286,7 @@ func TestValidateResponse(t *testing.T) { Status: pki.StatusInfo{ Status: pki.StatusGranted, }, - TimeStampToken: asn1.RawValue{ + TimestampToken: asn1.RawValue{ FullBytes: token, }, } @@ -308,7 +308,7 @@ func TestValidateResponse(t *testing.T) { Status: pki.StatusInfo{ Status: pki.StatusGranted, }, - TimeStampToken: asn1.RawValue{ + TimestampToken: asn1.RawValue{ FullBytes: token, }, } @@ -332,7 +332,7 @@ func TestValidateResponse(t *testing.T) { Status: pki.StatusInfo{ Status: pki.StatusGranted, }, - TimeStampToken: asn1.RawValue{ + TimestampToken: asn1.RawValue{ FullBytes: token, }, } @@ -355,7 +355,7 @@ func TestValidateResponse(t *testing.T) { Status: pki.StatusInfo{ Status: pki.StatusGranted, }, - TimeStampToken: asn1.RawValue{ + TimestampToken: asn1.RawValue{ FullBytes: token, }, } diff --git a/token.go b/token.go index 4edfe25..8bdf38d 100644 --- a/token.go +++ b/token.go @@ -242,7 +242,7 @@ func (tst *TSTInfo) Validate(message []byte) (*TimestampLimit, error) { if tst.Accuracy.Seconds == 0 && tst.Accuracy.Microseconds == 0 && tst.Accuracy.Milliseconds == 0 && - oid.BaselineTimeStampPolicy.Equal(tst.Policy) { + oid.BaselineTimestampPolicy.Equal(tst.Policy) { accuracy = 1 * time.Second } else { accuracy = time.Duration(tst.Accuracy.Seconds)*time.Second + diff --git a/token_test.go b/token_test.go index 9a19ed6..64d7a59 100644 --- a/token_test.go +++ b/token_test.go @@ -236,7 +236,7 @@ func TestValidate(t *testing.T) { t.Fatal(err) } tstInfo.Accuracy = Accuracy{} - tstInfo.Policy = oid.BaselineTimeStampPolicy + tstInfo.Policy = oid.BaselineTimestampPolicy timestampLimit, err = tstInfo.Validate([]byte("notation")) if err != nil { t.Fatalf("expected nil error, but got %v", err) From 7c324548090508018ad41ef9eb4ea30835275061 Mon Sep 17 00:00:00 2001 From: Patrick Zheng Date: Fri, 28 Jun 2024 12:35:40 +0800 Subject: [PATCH 4/8] updated to Timestamp Signed-off-by: Patrick Zheng --- conformance_test.go | 14 +++++++------- http_test.go | 14 +++++++------- token.go | 41 ++++++++++++++++++++++++++++------------- token_test.go | 41 +++++++++++++++++++++++++++-------------- 4 files changed, 69 insertions(+), 41 deletions(-) diff --git a/conformance_test.go b/conformance_test.go index da6545e..c14aa59 100644 --- a/conformance_test.go +++ b/conformance_test.go @@ -113,17 +113,17 @@ func TestTSATimestampGranted(t *testing.T) { if err != nil { t.Fatal("SignedToken.Info() error =", err) } - timestampLimit, err := info.Validate(message) + timestamp, err := info.Validate(message) if err != nil { t.Errorf("TSTInfo.Timestamp() error = %v", err) } - wantTimestampLowerLimit := time.Date(2021, 9, 18, 11, 54, 33, 0, time.UTC) - wantTimestampUpperLimit := time.Date(2021, 9, 18, 11, 54, 35, 0, time.UTC) - if timestampLimit.LowerLimit != wantTimestampLowerLimit { - t.Errorf("TSTInfo.Timestamp() Timestamp = %v, want %v", timestampLimit.LowerLimit, wantTimestampLowerLimit) + wantTimestampValue := time.Date(2021, 9, 18, 11, 54, 34, 0, time.UTC) + wantTimestampAccuracy := time.Second + if timestamp.Value != wantTimestampValue { + t.Fatalf("TSTInfo.Timestamp() Timestamp = %v, want %v", wantTimestampValue, timestamp.Value) } - if timestampLimit.UpperLimit != wantTimestampUpperLimit { - t.Errorf("TSTInfo.Timestamp() Timestamp = %v, want %v", timestampLimit.UpperLimit, wantTimestampUpperLimit) + if timestamp.Accuracy != wantTimestampAccuracy { + t.Fatalf("TSTInfo.Timestamp() Timestamp Accuracy = %v, want %v", wantTimestampAccuracy, timestamp.Accuracy) } } diff --git a/http_test.go b/http_test.go index e06553c..25554bc 100644 --- a/http_test.go +++ b/http_test.go @@ -122,17 +122,17 @@ func TestHTTPTimestampGranted(t *testing.T) { if err != nil { t.Fatal("SignedToken.Info() error =", err) } - timestampLimit, err := info.Validate(message) + timestamp, err := info.Validate(message) if err != nil { t.Errorf("TSTInfo.Timestamp() error = %v", err) } - wantTimestampLowerLimit := time.Date(2021, 9, 18, 11, 54, 33, 0, time.UTC) - wantTimestampUpperLimit := time.Date(2021, 9, 18, 11, 54, 35, 0, time.UTC) - if timestampLimit.LowerLimit != wantTimestampLowerLimit { - t.Errorf("TSTInfo.Timestamp() Timestamp = %v, want %v", timestampLimit.LowerLimit, wantTimestampLowerLimit) + wantTimestampValue := time.Date(2021, 9, 18, 11, 54, 34, 0, time.UTC) + wantTimestampAccuracy := time.Second + if timestamp.Value != wantTimestampValue { + t.Fatalf("TSTInfo.Timestamp() Timestamp = %v, want %v", wantTimestampValue, timestamp.Value) } - if timestampLimit.UpperLimit != wantTimestampUpperLimit { - t.Errorf("TSTInfo.Timestamp() Timestamp = %v, want %v", timestampLimit.UpperLimit, wantTimestampUpperLimit) + if timestamp.Accuracy != wantTimestampAccuracy { + t.Fatalf("TSTInfo.Timestamp() Timestamp Accuracy = %v, want %v", wantTimestampAccuracy, timestamp.Accuracy) } } diff --git a/token.go b/token.go index 8bdf38d..79a29da 100644 --- a/token.go +++ b/token.go @@ -214,23 +214,38 @@ type TSTInfo struct { Extensions []pkix.Extension `asn1:"optional,tag:1"` } -// TimestampLimit contains the lower and upper limits of the time at which the -// timestamp token has been created by the TSA +// Timestamp denots the time at which the timestamp token was created by the TSA // // Reference: RFC 3161 2.4.2 -type TimestampLimit struct { - // LowerLimit denotes the lower limit of the time at which the - // timestamp token has been created by the TSA - LowerLimit time.Time +type Timestamp struct { + // Value is the GenTime of TSTInfo + Value time.Time - // UpperLimit denotes the upper limit of the time at which the - // timestamp token has been created by the TSA - UpperLimit time.Time + // Accuracy is the Accuracy of TSTInfo + Accuracy time.Duration +} + +// Before returns true if the lower limit of the time at which the timestamp +// token was created is before u. +// +// Reference: RFC 3161 2.4.2 +func (t *Timestamp) Before(u time.Time) bool { + timestampLowerLimit := t.Value.Add(-t.Accuracy) + return timestampLowerLimit.Before(u) +} + +// After returns true if the upper limit of the time at which the timestamp +// token was created is after u. +// +// Reference: RFC 3161 2.4.2 +func (t *Timestamp) After(u time.Time) bool { + timestampUpperLimit := t.Value.Add(t.Accuracy) + return timestampUpperLimit.After(u) } // Validate validates tst and returns the GenTime and Accuracy. // tst MUST be valid and the time stamped datum MUST match message. -func (tst *TSTInfo) Validate(message []byte) (*TimestampLimit, error) { +func (tst *TSTInfo) Validate(message []byte) (*Timestamp, error) { if err := tst.validate(message); err != nil { return nil, err } @@ -250,9 +265,9 @@ func (tst *TSTInfo) Validate(message []byte) (*TimestampLimit, error) { time.Duration(tst.Accuracy.Microseconds)*time.Microsecond } - return &TimestampLimit{ - LowerLimit: tst.GenTime.Add(-accuracy), - UpperLimit: tst.GenTime.Add(accuracy), + return &Timestamp{ + Value: tst.GenTime, + Accuracy: accuracy, }, nil } diff --git a/token_test.go b/token_test.go index 64d7a59..be014f2 100644 --- a/token_test.go +++ b/token_test.go @@ -192,6 +192,21 @@ func TestGetSigningCertificate(t *testing.T) { } } +func TestTimestamp(t *testing.T) { + timestamp := Timestamp{ + Value: time.Date(2021, time.September, 17, 14, 9, 10, 0, time.UTC), + Accuracy: 5 * time.Second, + } + + if !timestamp.Before(time.Date(2021, time.September, 17, 14, 9, 9, 0, time.UTC)) { + t.Fatal("timestamp.Before expected true, but got false") + } + + if !timestamp.After(time.Date(2021, time.September, 17, 14, 9, 11, 0, time.UTC)) { + t.Fatal("timestamp.After expected true, but got false") + } +} + func TestValidate(t *testing.T) { timestampToken, err := getTimestampTokenFromPath("testdata/TimeStampToken.p7s") if err != nil { @@ -214,17 +229,17 @@ func TestValidate(t *testing.T) { if err != nil { t.Fatal(err) } - timestampLimit, err := tstInfo.Validate([]byte("notation")) + timestamp, err := tstInfo.Validate([]byte("notation")) if err != nil { t.Fatalf("expected nil error, but got %v", err) } - expectedLowerLimit := time.Date(2021, time.September, 17, 14, 9, 9, 0, time.UTC) - expectedUpperLimit := time.Date(2021, time.September, 17, 14, 9, 11, 0, time.UTC) - if timestampLimit.LowerLimit != expectedLowerLimit { - t.Fatalf("expected timestamp %s, but got %s", expectedLowerLimit, timestampLimit.LowerLimit) + expectedTimestampValue := time.Date(2021, time.September, 17, 14, 9, 10, 0, time.UTC) + expectedTimestampAccuracy := time.Second + if timestamp.Value != expectedTimestampValue { + t.Fatalf("expected timestamp value %s, but got %s", expectedTimestampValue, timestamp.Value) } - if timestampLimit.UpperLimit != expectedUpperLimit { - t.Fatalf("expected timestamp %s, but got %s", expectedUpperLimit, timestampLimit.UpperLimit) + if timestamp.Accuracy != expectedTimestampAccuracy { + t.Fatalf("expected timestamp accuracy %s, but got %s", expectedTimestampAccuracy, timestamp.Accuracy) } timestampToken, err = getTimestampTokenFromPath("testdata/TimeStampToken.p7s") @@ -237,17 +252,15 @@ func TestValidate(t *testing.T) { } tstInfo.Accuracy = Accuracy{} tstInfo.Policy = oid.BaselineTimestampPolicy - timestampLimit, err = tstInfo.Validate([]byte("notation")) + timestamp, err = tstInfo.Validate([]byte("notation")) if err != nil { t.Fatalf("expected nil error, but got %v", err) } - expectedLowerLimit = time.Date(2021, time.September, 17, 14, 9, 9, 0, time.UTC) - expectedUpperLimit = time.Date(2021, time.September, 17, 14, 9, 11, 0, time.UTC) - if timestampLimit.LowerLimit != expectedLowerLimit { - t.Fatalf("expected timestamp %s, but got %s", expectedLowerLimit, timestampLimit.LowerLimit) + if timestamp.Value != expectedTimestampValue { + t.Fatalf("expected timestamp value %s, but got %s", expectedTimestampValue, timestamp.Value) } - if timestampLimit.UpperLimit != expectedUpperLimit { - t.Fatalf("expected timestamp %s, but got %s", expectedUpperLimit, timestampLimit.UpperLimit) + if timestamp.Accuracy != expectedTimestampAccuracy { + t.Fatalf("expected timestamp accuracy %s, but got %s", expectedTimestampAccuracy, timestamp.Accuracy) } } From 149239f825a8159b3baaf6c55b905e3798ba99e0 Mon Sep 17 00:00:00 2001 From: Patrick Zheng Date: Fri, 28 Jun 2024 16:51:13 +0800 Subject: [PATCH 5/8] updated per code review Signed-off-by: Patrick Zheng --- conformance_test.go | 4 +-- http_test.go | 4 +-- token.go | 30 +++++++++---------- token_test.go | 71 ++++++++++++++++++++++++++++++++++++++------- 4 files changed, 80 insertions(+), 29 deletions(-) diff --git a/conformance_test.go b/conformance_test.go index c14aa59..d531fe5 100644 --- a/conformance_test.go +++ b/conformance_test.go @@ -119,8 +119,8 @@ func TestTSATimestampGranted(t *testing.T) { } wantTimestampValue := time.Date(2021, 9, 18, 11, 54, 34, 0, time.UTC) wantTimestampAccuracy := time.Second - if timestamp.Value != wantTimestampValue { - t.Fatalf("TSTInfo.Timestamp() Timestamp = %v, want %v", wantTimestampValue, timestamp.Value) + if timestamp.GeneralizedTime != wantTimestampValue { + t.Fatalf("TSTInfo.Timestamp() Timestamp = %v, want %v", wantTimestampValue, timestamp.GeneralizedTime) } if timestamp.Accuracy != wantTimestampAccuracy { t.Fatalf("TSTInfo.Timestamp() Timestamp Accuracy = %v, want %v", wantTimestampAccuracy, timestamp.Accuracy) diff --git a/http_test.go b/http_test.go index 25554bc..3de0f50 100644 --- a/http_test.go +++ b/http_test.go @@ -128,8 +128,8 @@ func TestHTTPTimestampGranted(t *testing.T) { } wantTimestampValue := time.Date(2021, 9, 18, 11, 54, 34, 0, time.UTC) wantTimestampAccuracy := time.Second - if timestamp.Value != wantTimestampValue { - t.Fatalf("TSTInfo.Timestamp() Timestamp = %v, want %v", wantTimestampValue, timestamp.Value) + if timestamp.GeneralizedTime != wantTimestampValue { + t.Fatalf("TSTInfo.Timestamp() Timestamp = %v, want %v", wantTimestampValue, timestamp.GeneralizedTime) } if timestamp.Accuracy != wantTimestampAccuracy { t.Fatalf("TSTInfo.Timestamp() Timestamp Accuracy = %v, want %v", wantTimestampAccuracy, timestamp.Accuracy) diff --git a/token.go b/token.go index 79a29da..82ec086 100644 --- a/token.go +++ b/token.go @@ -214,33 +214,33 @@ type TSTInfo struct { Extensions []pkix.Extension `asn1:"optional,tag:1"` } -// Timestamp denots the time at which the timestamp token was created by the TSA +// Timestamp denotes the time at which the timestamp token was created by the TSA // // Reference: RFC 3161 2.4.2 type Timestamp struct { - // Value is the GenTime of TSTInfo - Value time.Time + // GeneralizedTime is the GenTime of TSTInfo + GeneralizedTime time.Time // Accuracy is the Accuracy of TSTInfo Accuracy time.Duration } -// Before returns true if the lower limit of the time at which the timestamp -// token was created is before u. +// BoundedBefore returns true if the upper limit of the time at which the +// timestamp token was created is before or equal to u. // // Reference: RFC 3161 2.4.2 -func (t *Timestamp) Before(u time.Time) bool { - timestampLowerLimit := t.Value.Add(-t.Accuracy) - return timestampLowerLimit.Before(u) +func (t *Timestamp) BoundedBefore(u time.Time) bool { + timestampUpperLimit := t.GeneralizedTime.Add(t.Accuracy) + return timestampUpperLimit.Before(u) || timestampUpperLimit.Equal(u) } -// After returns true if the upper limit of the time at which the timestamp -// token was created is after u. +// BoundedAfter returns true if the lower limit of the time at which the +// timestamp token was created is after or equal to u. // // Reference: RFC 3161 2.4.2 -func (t *Timestamp) After(u time.Time) bool { - timestampUpperLimit := t.Value.Add(t.Accuracy) - return timestampUpperLimit.After(u) +func (t *Timestamp) BoundedAfter(u time.Time) bool { + timestampLowerLimit := t.GeneralizedTime.Add(-t.Accuracy) + return timestampLowerLimit.After(u) || timestampLowerLimit.Equal(u) } // Validate validates tst and returns the GenTime and Accuracy. @@ -266,8 +266,8 @@ func (tst *TSTInfo) Validate(message []byte) (*Timestamp, error) { } return &Timestamp{ - Value: tst.GenTime, - Accuracy: accuracy, + GeneralizedTime: tst.GenTime, + Accuracy: accuracy, }, nil } diff --git a/token_test.go b/token_test.go index be014f2..8c708d6 100644 --- a/token_test.go +++ b/token_test.go @@ -193,17 +193,68 @@ func TestGetSigningCertificate(t *testing.T) { } func TestTimestamp(t *testing.T) { + // timestamp range: + // [time.Date(2021, time.September, 17, 14, 9, 8, 0, time.UTC), + // time.Date(2021, time.September, 17, 14, 9, 12, 0, time.UTC)] timestamp := Timestamp{ - Value: time.Date(2021, time.September, 17, 14, 9, 10, 0, time.UTC), - Accuracy: 5 * time.Second, + GeneralizedTime: time.Date(2021, time.September, 17, 14, 9, 10, 0, time.UTC), + Accuracy: 2 * time.Second, } + u1 := time.Date(2021, time.September, 17, 14, 9, 7, 0, time.UTC) + u2 := time.Date(2021, time.September, 17, 14, 9, 8, 0, time.UTC) + u3 := time.Date(2021, time.September, 17, 14, 9, 9, 0, time.UTC) + u4 := time.Date(2021, time.September, 17, 14, 9, 10, 0, time.UTC) + u5 := time.Date(2021, time.September, 17, 14, 9, 11, 0, time.UTC) + u6 := time.Date(2021, time.September, 17, 14, 9, 12, 0, time.UTC) + u7 := time.Date(2021, time.September, 17, 14, 9, 13, 0, time.UTC) - if !timestamp.Before(time.Date(2021, time.September, 17, 14, 9, 9, 0, time.UTC)) { - t.Fatal("timestamp.Before expected true, but got false") + if timestamp.BoundedBefore(u1) { + t.Fatal("timestamp.BoundedBefore expected false, but got true") + } + if !timestamp.BoundedAfter(u1) { + t.Fatal("timestamp.BoundedAfter expected true, but got false") } - if !timestamp.After(time.Date(2021, time.September, 17, 14, 9, 11, 0, time.UTC)) { - t.Fatal("timestamp.After expected true, but got false") + if timestamp.BoundedBefore(u2) { + t.Fatal("timestamp.BoundedBefore expected false, but got true") + } + if !timestamp.BoundedAfter(u2) { + t.Fatal("timestamp.BoundedAfter expected true, but got false") + } + + if timestamp.BoundedBefore(u3) { + t.Fatal("timestamp.BoundedBefore expected false, but got true") + } + if timestamp.BoundedAfter(u3) { + t.Fatal("timestamp.BoundedAfter expected false, but got true") + } + + if timestamp.BoundedBefore(u4) { + t.Fatal("timestamp.BoundedBefore expected false, but got true") + } + if timestamp.BoundedAfter(u4) { + t.Fatal("timestamp.BoundedAfter expected false, but got true") + } + + if timestamp.BoundedBefore(u5) { + t.Fatal("timestamp.BoundedBefore expected false, but got true") + } + if timestamp.BoundedAfter(u5) { + t.Fatal("timestamp.BoundedAfter expected false, but got true") + } + + if !timestamp.BoundedBefore(u6) { + t.Fatal("timestamp.BoundedBefore expected true, but got false") + } + if timestamp.BoundedAfter(u6) { + t.Fatal("timestamp.BoundedAfter expected false, but got true") + } + + if !timestamp.BoundedBefore(u7) { + t.Fatal("timestamp.BoundedBefore expected true, but got false") + } + if timestamp.BoundedAfter(u7) { + t.Fatal("timestamp.BoundedAfter expected false, but got true") } } @@ -235,8 +286,8 @@ func TestValidate(t *testing.T) { } expectedTimestampValue := time.Date(2021, time.September, 17, 14, 9, 10, 0, time.UTC) expectedTimestampAccuracy := time.Second - if timestamp.Value != expectedTimestampValue { - t.Fatalf("expected timestamp value %s, but got %s", expectedTimestampValue, timestamp.Value) + if timestamp.GeneralizedTime != expectedTimestampValue { + t.Fatalf("expected timestamp value %s, but got %s", expectedTimestampValue, timestamp.GeneralizedTime) } if timestamp.Accuracy != expectedTimestampAccuracy { t.Fatalf("expected timestamp accuracy %s, but got %s", expectedTimestampAccuracy, timestamp.Accuracy) @@ -256,8 +307,8 @@ func TestValidate(t *testing.T) { if err != nil { t.Fatalf("expected nil error, but got %v", err) } - if timestamp.Value != expectedTimestampValue { - t.Fatalf("expected timestamp value %s, but got %s", expectedTimestampValue, timestamp.Value) + if timestamp.GeneralizedTime != expectedTimestampValue { + t.Fatalf("expected timestamp value %s, but got %s", expectedTimestampValue, timestamp.GeneralizedTime) } if timestamp.Accuracy != expectedTimestampAccuracy { t.Fatalf("expected timestamp accuracy %s, but got %s", expectedTimestampAccuracy, timestamp.Accuracy) From 4aa58001caddab93f160bc1577c1db82fd0e1ade Mon Sep 17 00:00:00 2001 From: Patrick Zheng Date: Fri, 28 Jun 2024 16:54:12 +0800 Subject: [PATCH 6/8] update Signed-off-by: Patrick Zheng --- conformance_test.go | 4 ++-- http_test.go | 4 ++-- token.go | 12 ++++++------ token_test.go | 12 ++++++------ 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/conformance_test.go b/conformance_test.go index d531fe5..c14aa59 100644 --- a/conformance_test.go +++ b/conformance_test.go @@ -119,8 +119,8 @@ func TestTSATimestampGranted(t *testing.T) { } wantTimestampValue := time.Date(2021, 9, 18, 11, 54, 34, 0, time.UTC) wantTimestampAccuracy := time.Second - if timestamp.GeneralizedTime != wantTimestampValue { - t.Fatalf("TSTInfo.Timestamp() Timestamp = %v, want %v", wantTimestampValue, timestamp.GeneralizedTime) + if timestamp.Value != wantTimestampValue { + t.Fatalf("TSTInfo.Timestamp() Timestamp = %v, want %v", wantTimestampValue, timestamp.Value) } if timestamp.Accuracy != wantTimestampAccuracy { t.Fatalf("TSTInfo.Timestamp() Timestamp Accuracy = %v, want %v", wantTimestampAccuracy, timestamp.Accuracy) diff --git a/http_test.go b/http_test.go index 3de0f50..25554bc 100644 --- a/http_test.go +++ b/http_test.go @@ -128,8 +128,8 @@ func TestHTTPTimestampGranted(t *testing.T) { } wantTimestampValue := time.Date(2021, 9, 18, 11, 54, 34, 0, time.UTC) wantTimestampAccuracy := time.Second - if timestamp.GeneralizedTime != wantTimestampValue { - t.Fatalf("TSTInfo.Timestamp() Timestamp = %v, want %v", wantTimestampValue, timestamp.GeneralizedTime) + if timestamp.Value != wantTimestampValue { + t.Fatalf("TSTInfo.Timestamp() Timestamp = %v, want %v", wantTimestampValue, timestamp.Value) } if timestamp.Accuracy != wantTimestampAccuracy { t.Fatalf("TSTInfo.Timestamp() Timestamp Accuracy = %v, want %v", wantTimestampAccuracy, timestamp.Accuracy) diff --git a/token.go b/token.go index 82ec086..d401deb 100644 --- a/token.go +++ b/token.go @@ -218,8 +218,8 @@ type TSTInfo struct { // // Reference: RFC 3161 2.4.2 type Timestamp struct { - // GeneralizedTime is the GenTime of TSTInfo - GeneralizedTime time.Time + // Value is the GenTime of TSTInfo + Value time.Time // Accuracy is the Accuracy of TSTInfo Accuracy time.Duration @@ -230,7 +230,7 @@ type Timestamp struct { // // Reference: RFC 3161 2.4.2 func (t *Timestamp) BoundedBefore(u time.Time) bool { - timestampUpperLimit := t.GeneralizedTime.Add(t.Accuracy) + timestampUpperLimit := t.Value.Add(t.Accuracy) return timestampUpperLimit.Before(u) || timestampUpperLimit.Equal(u) } @@ -239,7 +239,7 @@ func (t *Timestamp) BoundedBefore(u time.Time) bool { // // Reference: RFC 3161 2.4.2 func (t *Timestamp) BoundedAfter(u time.Time) bool { - timestampLowerLimit := t.GeneralizedTime.Add(-t.Accuracy) + timestampLowerLimit := t.Value.Add(-t.Accuracy) return timestampLowerLimit.After(u) || timestampLowerLimit.Equal(u) } @@ -266,8 +266,8 @@ func (tst *TSTInfo) Validate(message []byte) (*Timestamp, error) { } return &Timestamp{ - GeneralizedTime: tst.GenTime, - Accuracy: accuracy, + Value: tst.GenTime, + Accuracy: accuracy, }, nil } diff --git a/token_test.go b/token_test.go index 8c708d6..3c57194 100644 --- a/token_test.go +++ b/token_test.go @@ -197,8 +197,8 @@ func TestTimestamp(t *testing.T) { // [time.Date(2021, time.September, 17, 14, 9, 8, 0, time.UTC), // time.Date(2021, time.September, 17, 14, 9, 12, 0, time.UTC)] timestamp := Timestamp{ - GeneralizedTime: time.Date(2021, time.September, 17, 14, 9, 10, 0, time.UTC), - Accuracy: 2 * time.Second, + Value: time.Date(2021, time.September, 17, 14, 9, 10, 0, time.UTC), + Accuracy: 2 * time.Second, } u1 := time.Date(2021, time.September, 17, 14, 9, 7, 0, time.UTC) u2 := time.Date(2021, time.September, 17, 14, 9, 8, 0, time.UTC) @@ -286,8 +286,8 @@ func TestValidate(t *testing.T) { } expectedTimestampValue := time.Date(2021, time.September, 17, 14, 9, 10, 0, time.UTC) expectedTimestampAccuracy := time.Second - if timestamp.GeneralizedTime != expectedTimestampValue { - t.Fatalf("expected timestamp value %s, but got %s", expectedTimestampValue, timestamp.GeneralizedTime) + if timestamp.Value != expectedTimestampValue { + t.Fatalf("expected timestamp value %s, but got %s", expectedTimestampValue, timestamp.Value) } if timestamp.Accuracy != expectedTimestampAccuracy { t.Fatalf("expected timestamp accuracy %s, but got %s", expectedTimestampAccuracy, timestamp.Accuracy) @@ -307,8 +307,8 @@ func TestValidate(t *testing.T) { if err != nil { t.Fatalf("expected nil error, but got %v", err) } - if timestamp.GeneralizedTime != expectedTimestampValue { - t.Fatalf("expected timestamp value %s, but got %s", expectedTimestampValue, timestamp.GeneralizedTime) + if timestamp.Value != expectedTimestampValue { + t.Fatalf("expected timestamp value %s, but got %s", expectedTimestampValue, timestamp.Value) } if timestamp.Accuracy != expectedTimestampAccuracy { t.Fatalf("expected timestamp accuracy %s, but got %s", expectedTimestampAccuracy, timestamp.Accuracy) From 98b1c64c4172d453943e6d871d77bb71be341cd2 Mon Sep 17 00:00:00 2001 From: Patrick Zheng Date: Fri, 28 Jun 2024 16:58:16 +0800 Subject: [PATCH 7/8] updated per code review Signed-off-by: Patrick Zheng --- timestamp.go | 45 +++++++++++++++++++++++++ timestamp_test.go | 85 +++++++++++++++++++++++++++++++++++++++++++++++ token.go | 31 +---------------- token_test.go | 66 ------------------------------------ 4 files changed, 131 insertions(+), 96 deletions(-) create mode 100644 timestamp.go create mode 100644 timestamp_test.go diff --git a/timestamp.go b/timestamp.go new file mode 100644 index 0000000..0f6c2c7 --- /dev/null +++ b/timestamp.go @@ -0,0 +1,45 @@ +// Copyright The Notary Project Authors. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tspclient + +import "time" + +// Timestamp denotes the time at which the timestamp token was created by the TSA +// +// Reference: RFC 3161 2.4.2 +type Timestamp struct { + // Value is the GenTime of TSTInfo + Value time.Time + + // Accuracy is the Accuracy of TSTInfo + Accuracy time.Duration +} + +// BoundedBefore returns true if the upper limit of the time at which the +// timestamp token was created is before or equal to u. +// +// Reference: RFC 3161 2.4.2 +func (t *Timestamp) BoundedBefore(u time.Time) bool { + timestampUpperLimit := t.Value.Add(t.Accuracy) + return timestampUpperLimit.Before(u) || timestampUpperLimit.Equal(u) +} + +// BoundedAfter returns true if the lower limit of the time at which the +// timestamp token was created is after or equal to u. +// +// Reference: RFC 3161 2.4.2 +func (t *Timestamp) BoundedAfter(u time.Time) bool { + timestampLowerLimit := t.Value.Add(-t.Accuracy) + return timestampLowerLimit.After(u) || timestampLowerLimit.Equal(u) +} diff --git a/timestamp_test.go b/timestamp_test.go new file mode 100644 index 0000000..57a9756 --- /dev/null +++ b/timestamp_test.go @@ -0,0 +1,85 @@ +// Copyright The Notary Project Authors. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tspclient + +import ( + "testing" + "time" +) + +func TestTimestamp(t *testing.T) { + // timestamp range: + // [time.Date(2021, time.September, 17, 14, 9, 8, 0, time.UTC), + // time.Date(2021, time.September, 17, 14, 9, 12, 0, time.UTC)] + timestamp := Timestamp{ + Value: time.Date(2021, time.September, 17, 14, 9, 10, 0, time.UTC), + Accuracy: 2 * time.Second, + } + u1 := time.Date(2021, time.September, 17, 14, 9, 7, 0, time.UTC) + u2 := time.Date(2021, time.September, 17, 14, 9, 8, 0, time.UTC) + u3 := time.Date(2021, time.September, 17, 14, 9, 9, 0, time.UTC) + u4 := time.Date(2021, time.September, 17, 14, 9, 10, 0, time.UTC) + u5 := time.Date(2021, time.September, 17, 14, 9, 11, 0, time.UTC) + u6 := time.Date(2021, time.September, 17, 14, 9, 12, 0, time.UTC) + u7 := time.Date(2021, time.September, 17, 14, 9, 13, 0, time.UTC) + + if timestamp.BoundedBefore(u1) { + t.Fatal("timestamp.BoundedBefore expected false, but got true") + } + if !timestamp.BoundedAfter(u1) { + t.Fatal("timestamp.BoundedAfter expected true, but got false") + } + + if timestamp.BoundedBefore(u2) { + t.Fatal("timestamp.BoundedBefore expected false, but got true") + } + if !timestamp.BoundedAfter(u2) { + t.Fatal("timestamp.BoundedAfter expected true, but got false") + } + + if timestamp.BoundedBefore(u3) { + t.Fatal("timestamp.BoundedBefore expected false, but got true") + } + if timestamp.BoundedAfter(u3) { + t.Fatal("timestamp.BoundedAfter expected false, but got true") + } + + if timestamp.BoundedBefore(u4) { + t.Fatal("timestamp.BoundedBefore expected false, but got true") + } + if timestamp.BoundedAfter(u4) { + t.Fatal("timestamp.BoundedAfter expected false, but got true") + } + + if timestamp.BoundedBefore(u5) { + t.Fatal("timestamp.BoundedBefore expected false, but got true") + } + if timestamp.BoundedAfter(u5) { + t.Fatal("timestamp.BoundedAfter expected false, but got true") + } + + if !timestamp.BoundedBefore(u6) { + t.Fatal("timestamp.BoundedBefore expected true, but got false") + } + if timestamp.BoundedAfter(u6) { + t.Fatal("timestamp.BoundedAfter expected false, but got true") + } + + if !timestamp.BoundedBefore(u7) { + t.Fatal("timestamp.BoundedBefore expected true, but got false") + } + if timestamp.BoundedAfter(u7) { + t.Fatal("timestamp.BoundedAfter expected false, but got true") + } +} diff --git a/token.go b/token.go index d401deb..bf65870 100644 --- a/token.go +++ b/token.go @@ -214,36 +214,7 @@ type TSTInfo struct { Extensions []pkix.Extension `asn1:"optional,tag:1"` } -// Timestamp denotes the time at which the timestamp token was created by the TSA -// -// Reference: RFC 3161 2.4.2 -type Timestamp struct { - // Value is the GenTime of TSTInfo - Value time.Time - - // Accuracy is the Accuracy of TSTInfo - Accuracy time.Duration -} - -// BoundedBefore returns true if the upper limit of the time at which the -// timestamp token was created is before or equal to u. -// -// Reference: RFC 3161 2.4.2 -func (t *Timestamp) BoundedBefore(u time.Time) bool { - timestampUpperLimit := t.Value.Add(t.Accuracy) - return timestampUpperLimit.Before(u) || timestampUpperLimit.Equal(u) -} - -// BoundedAfter returns true if the lower limit of the time at which the -// timestamp token was created is after or equal to u. -// -// Reference: RFC 3161 2.4.2 -func (t *Timestamp) BoundedAfter(u time.Time) bool { - timestampLowerLimit := t.Value.Add(-t.Accuracy) - return timestampLowerLimit.After(u) || timestampLowerLimit.Equal(u) -} - -// Validate validates tst and returns the GenTime and Accuracy. +// Validate validates tst and returns the Timestamp on success. // tst MUST be valid and the time stamped datum MUST match message. func (tst *TSTInfo) Validate(message []byte) (*Timestamp, error) { if err := tst.validate(message); err != nil { diff --git a/token_test.go b/token_test.go index 3c57194..5a4ef78 100644 --- a/token_test.go +++ b/token_test.go @@ -192,72 +192,6 @@ func TestGetSigningCertificate(t *testing.T) { } } -func TestTimestamp(t *testing.T) { - // timestamp range: - // [time.Date(2021, time.September, 17, 14, 9, 8, 0, time.UTC), - // time.Date(2021, time.September, 17, 14, 9, 12, 0, time.UTC)] - timestamp := Timestamp{ - Value: time.Date(2021, time.September, 17, 14, 9, 10, 0, time.UTC), - Accuracy: 2 * time.Second, - } - u1 := time.Date(2021, time.September, 17, 14, 9, 7, 0, time.UTC) - u2 := time.Date(2021, time.September, 17, 14, 9, 8, 0, time.UTC) - u3 := time.Date(2021, time.September, 17, 14, 9, 9, 0, time.UTC) - u4 := time.Date(2021, time.September, 17, 14, 9, 10, 0, time.UTC) - u5 := time.Date(2021, time.September, 17, 14, 9, 11, 0, time.UTC) - u6 := time.Date(2021, time.September, 17, 14, 9, 12, 0, time.UTC) - u7 := time.Date(2021, time.September, 17, 14, 9, 13, 0, time.UTC) - - if timestamp.BoundedBefore(u1) { - t.Fatal("timestamp.BoundedBefore expected false, but got true") - } - if !timestamp.BoundedAfter(u1) { - t.Fatal("timestamp.BoundedAfter expected true, but got false") - } - - if timestamp.BoundedBefore(u2) { - t.Fatal("timestamp.BoundedBefore expected false, but got true") - } - if !timestamp.BoundedAfter(u2) { - t.Fatal("timestamp.BoundedAfter expected true, but got false") - } - - if timestamp.BoundedBefore(u3) { - t.Fatal("timestamp.BoundedBefore expected false, but got true") - } - if timestamp.BoundedAfter(u3) { - t.Fatal("timestamp.BoundedAfter expected false, but got true") - } - - if timestamp.BoundedBefore(u4) { - t.Fatal("timestamp.BoundedBefore expected false, but got true") - } - if timestamp.BoundedAfter(u4) { - t.Fatal("timestamp.BoundedAfter expected false, but got true") - } - - if timestamp.BoundedBefore(u5) { - t.Fatal("timestamp.BoundedBefore expected false, but got true") - } - if timestamp.BoundedAfter(u5) { - t.Fatal("timestamp.BoundedAfter expected false, but got true") - } - - if !timestamp.BoundedBefore(u6) { - t.Fatal("timestamp.BoundedBefore expected true, but got false") - } - if timestamp.BoundedAfter(u6) { - t.Fatal("timestamp.BoundedAfter expected false, but got true") - } - - if !timestamp.BoundedBefore(u7) { - t.Fatal("timestamp.BoundedBefore expected true, but got false") - } - if timestamp.BoundedAfter(u7) { - t.Fatal("timestamp.BoundedAfter expected false, but got true") - } -} - func TestValidate(t *testing.T) { timestampToken, err := getTimestampTokenFromPath("testdata/TimeStampToken.p7s") if err != nil { From 2d38353808808c8f438e073af4313f452b912432 Mon Sep 17 00:00:00 2001 From: Patrick Zheng Date: Tue, 2 Jul 2024 09:06:35 +0800 Subject: [PATCH 8/8] update Signed-off-by: Patrick Zheng --- token.go | 1 - 1 file changed, 1 deletion(-) diff --git a/token.go b/token.go index bf65870..f63dccb 100644 --- a/token.go +++ b/token.go @@ -223,7 +223,6 @@ func (tst *TSTInfo) Validate(message []byte) (*Timestamp, error) { var accuracy time.Duration // References: - // https://datatracker.ietf.org/doc/html/rfc3628#section-5.1 // https://github.com/notaryproject/specifications/blob/main/specs/trust-store-trust-policy.md#steps if tst.Accuracy.Seconds == 0 && tst.Accuracy.Microseconds == 0 &&