From e5b9e13f4c7847af8944dbf8129dc23ce1e3b1fb Mon Sep 17 00:00:00 2001 From: Pritesh Bandi Date: Sun, 19 Jun 2022 11:06:21 -0700 Subject: [PATCH 1/4] Fix errors in cert validation Signed-off-by: Pritesh Bandi --- x509/cert.go | 4 ++-- x509/cert_test.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/x509/cert.go b/x509/cert.go index a32e01fc..a6105953 100644 --- a/x509/cert.go +++ b/x509/cert.go @@ -48,7 +48,7 @@ func parseCertificates(data []byte) ([]*x509.Certificate, error) { // ValidateCertChain takes an ordered certificate chain and validates issuance from leaf to root func ValidateCertChain(certChain []*x509.Certificate) error { if len(certChain) < 2 { - return errors.New("certificate chain must contain at least two certificates") + return errors.New("certificate chain must contain at least two certificates: a root and a leaf certificate") } for i, cert := range certChain { @@ -60,7 +60,7 @@ func ValidateCertChain(certChain []*x509.Certificate) error { if isSelfSigned(cert) { return errors.New("certificate chain must not contain self-signed intermediate certificates") } else if nextCert := certChain[i+1]; !isIssuedBy(cert, nextCert) { - return fmt.Errorf("signature on certificate %q is not issued by %q", cert.Subject.String(), nextCert.Subject.String()) + return fmt.Errorf("certificate with subject %q is not issued by %q", cert.Subject, nextCert.Subject) } } } diff --git a/x509/cert_test.go b/x509/cert_test.go index b7aae2ec..1b639046 100644 --- a/x509/cert_test.go +++ b/x509/cert_test.go @@ -141,7 +141,7 @@ func TestFailEmptyChain(t *testing.T) { certChain := []*x509.Certificate{signingCert} err := ValidateCertChain(certChain) - assertErrorEqual("certificate chain must contain at least two certificates", err, t) + assertErrorEqual("certificate chain must contain at least two certificates: a root and a leaf certificate", err, t) } func TestFailChainNotEndingInRoot(t *testing.T) { @@ -155,14 +155,14 @@ func TestFailChainNotOrdered(t *testing.T) { certChain := []*x509.Certificate{signingCert, intermediateCert2, intermediateCert1, rootCert} err := ValidateCertChain(certChain) - assertErrorEqual("signature on certificate \"CN=Wallaby,OU=Signer,O=Amazon.com Services LLC,L=Seattle,ST=Washington,C=US,1.2.840.113549.1.9.1=#0c126a64646f6e617340616d617a6f6e2e636f6d\" is not issued by \"CN=jddonas-intermediate,OU=Wallaby,O=Marsupial Ventures\"", err, t) + assertErrorEqual("certificate with subject \"CN=Wallaby,OU=Signer,O=Amazon.com Services LLC,L=Seattle,ST=Washington,C=US,1.2.840.113549.1.9.1=#0c126a64646f6e617340616d617a6f6e2e636f6d\" is not issued by \"CN=jddonas-intermediate,OU=Wallaby,O=Marsupial Ventures\"", err, t) } func TestFailChainWithUnrelatedCert(t *testing.T) { certChain := []*x509.Certificate{signingCert, unrelatedCert, intermediateCert2, rootCert} err := ValidateCertChain(certChain) - assertErrorEqual("signature on certificate \"CN=Wallaby,OU=Signer,O=Amazon.com Services LLC,L=Seattle,ST=Washington,C=US,1.2.840.113549.1.9.1=#0c126a64646f6e617340616d617a6f6e2e636f6d\" is not issued by \"CN=imburger-dev-root,OU=AWS Cryptography,O=Marsupial Ventures,L=Seattle,ST=Washington,C=US\"", err, t) + assertErrorEqual("certificate with subject \"CN=Wallaby,OU=Signer,O=Amazon.com Services LLC,L=Seattle,ST=Washington,C=US,1.2.840.113549.1.9.1=#0c126a64646f6e617340616d617a6f6e2e636f6d\" is not issued by \"CN=imburger-dev-root,OU=AWS Cryptography,O=Marsupial Ventures,L=Seattle,ST=Washington,C=US\"", err, t) } func TestFailChainWithDuplicateRepeatedRoots(t *testing.T) { From 2beff36c7fad737e20625eae78194c78394a1455 Mon Sep 17 00:00:00 2001 From: Pritesh Bandi Date: Mon, 20 Jun 2022 16:06:33 -0700 Subject: [PATCH 2/4] Remove opencontainer dependency on timestamping code Signed-off-by: Pritesh Bandi --- go.mod | 2 - go.sum | 2 - timestamp/errors.go | 10 +++++ timestamp/http_test.go | 12 +++--- timestamp/request.go | 64 +++++++++++++++++++---------- timestamp/timestamptest/tsa_test.go | 13 +++--- timestamp/token.go | 32 +++++++++------ 7 files changed, 86 insertions(+), 49 deletions(-) create mode 100644 timestamp/errors.go diff --git a/go.mod b/go.mod index 92ca754f..9bbb7b4f 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,3 @@ module github.com/notaryproject/notation-core-go go 1.17 - -require github.com/opencontainers/go-digest v1.0.0 diff --git a/go.sum b/go.sum index 30f45e97..e69de29b 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +0,0 @@ -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= diff --git a/timestamp/errors.go b/timestamp/errors.go new file mode 100644 index 00000000..1ccdd4b2 --- /dev/null +++ b/timestamp/errors.go @@ -0,0 +1,10 @@ +package timestamp + +// MalformedRequestError is used when timestamping request is malformed. +type MalformedRequestError struct { + msg string +} + +func (e MalformedRequestError) Error() string { + return e.msg +} diff --git a/timestamp/http_test.go b/timestamp/http_test.go index 57e619d2..6b697c3a 100644 --- a/timestamp/http_test.go +++ b/timestamp/http_test.go @@ -75,7 +75,7 @@ func TestHTTPTimestampGranted(t *testing.T) { t.Fatalf("NewHTTPTimestamper() error = %v", err) } message := []byte("notation") - req, err := NewRequestFromBytes(message) + req, err := NewRequestWithData(message, crypto.SHA256) if err != nil { t.Fatalf("NewRequestFromString() error = %v", err) } @@ -128,7 +128,7 @@ func TestHTTPTimestampGranted(t *testing.T) { if err != nil { t.Fatal("SignedToken.Info() error =", err) } - if err := info.Verify(message); err != nil { + if err := info.VerifyWithData(message); err != nil { t.Errorf("TSTInfo.Verify() error = %v", err) } timestamp, accuracy := info.Timestamp() @@ -173,7 +173,7 @@ func TestHTTPTimestampRejection(t *testing.T) { t.Fatalf("NewHTTPTimestamper() error = %v", err) } message := []byte("notation") - req, err := NewRequestFromBytes(message) + req, err := NewRequestWithData(message, crypto.SHA256) if err != nil { t.Fatalf("NewRequestFromString() error = %v", err) } @@ -215,7 +215,8 @@ func TestHTTPTimestampBadEndpoint(t *testing.T) { if err != nil { t.Fatalf("NewHTTPTimestamper() error = %v", err) } - req, err := NewRequestFromString("notation") + message := []byte("notation") + req, err := NewRequestWithData(message, crypto.SHA256) if err != nil { t.Fatalf("NewRequestFromString() error = %v", err) } @@ -238,7 +239,8 @@ func TestHTTPTimestampEndpointNotFound(t *testing.T) { if err != nil { t.Fatalf("NewHTTPTimestamper() error = %v", err) } - req, err := NewRequestFromString("notation") + message := []byte("notation") + req, err := NewRequestWithData(message, crypto.SHA256) if err != nil { t.Fatalf("NewRequestFromString() error = %v", err) } diff --git a/timestamp/request.go b/timestamp/request.go index 3e589ce3..88b98950 100644 --- a/timestamp/request.go +++ b/timestamp/request.go @@ -1,14 +1,15 @@ package timestamp import ( + "crypto" "crypto/x509/pkix" "encoding/asn1" - "encoding/hex" "errors" + "fmt" + "github.com/notaryproject/notation-core-go/internal/crypto/hashutil" "math/big" "github.com/notaryproject/notation-core-go/internal/crypto/oid" - digest "github.com/opencontainers/go-digest" ) // MessageImprint contains the hash of the datum to be time-stamped. @@ -37,36 +38,38 @@ type Request struct { Extensions []pkix.Extension `asn1:"optional,tag:0"` } -// NewRequest creates a request based on the given digest. -func NewRequest(contentDigest digest.Digest) (*Request, error) { - hashAlgorithm, err := getOIDFromDigestAlgorithm(contentDigest.Algorithm()) +// NewRequest creates a request based on the given digest and hash algorithm. +func NewRequest(digest []byte, alg crypto.Hash) (*Request, error) { + err := validate(digest, alg) if err != nil { return nil, err } - hashedMessage, err := hex.DecodeString(contentDigest.Encoded()) + + hashAlg, err := getOID(alg) if err != nil { return nil, err } + return &Request{ Version: 1, MessageImprint: MessageImprint{ HashAlgorithm: pkix.AlgorithmIdentifier{ - Algorithm: hashAlgorithm, + Algorithm: hashAlg, }, - HashedMessage: hashedMessage, + HashedMessage: digest, }, CertReq: true, }, nil } -// NewRequestFromBytes creates a request based on the given byte slice. -func NewRequestFromBytes(content []byte) (*Request, error) { - return NewRequest(digest.FromBytes(content)) -} +// NewRequestWithData creates a request based on the given data and hash algorithm. +func NewRequestWithData(content []byte, alg crypto.Hash) (*Request, error) { + digest, err := hashutil.ComputeHash(alg, content) + if err != nil { + return nil, err + } -// NewRequestFromString creates a request based on the given string. -func NewRequestFromString(content string) (*Request, error) { - return NewRequest(digest.FromString(content)) + return NewRequest(digest, alg) } // MarshalBinary encodes the request to binary form. @@ -85,15 +88,34 @@ func (r *Request) UnmarshalBinary(data []byte) error { return err } -// getOIDFromDigestAlgorithm returns corresponding ASN.1 OID for the given digest algorithm. -func getOIDFromDigestAlgorithm(alg digest.Algorithm) (asn1.ObjectIdentifier, error) { +// getOID returns corresponding ASN.1 OID for the given Hash algorithm. +func getOID(alg crypto.Hash) (asn1.ObjectIdentifier, error) { switch alg { - case digest.SHA256: + case crypto.SHA256: return oid.SHA256, nil - case digest.SHA384: + case crypto.SHA384: return oid.SHA384, nil - case digest.SHA512: + case crypto.SHA512: return oid.SHA512, nil } - return nil, digest.ErrDigestUnsupported + return nil, MalformedRequestError{msg: fmt.Sprintf("unsupported hashing algorithm: %s", alg)} } + +func validate(digest []byte, alg crypto.Hash) error { + l := len(digest) + var validContent bool + switch alg { + case crypto.SHA256: + validContent = l == 256/8 + case crypto.SHA384: + validContent = l == 384/8 + case crypto.SHA512: + validContent = l == 384/8 + default: + return MalformedRequestError{msg: fmt.Sprintf("unsupported hashing algorithm: %s", alg)} + } + if !validContent { + return MalformedRequestError{msg: fmt.Sprintf("digest is of incorrect size: %d", l)} + } + return nil +} \ No newline at end of file diff --git a/timestamp/timestamptest/tsa_test.go b/timestamp/timestamptest/tsa_test.go index 1ff9110d..c2487975 100644 --- a/timestamp/timestamptest/tsa_test.go +++ b/timestamp/timestamptest/tsa_test.go @@ -2,6 +2,7 @@ package timestamptest import ( "context" + "crypto" "crypto/x509" "testing" "time" @@ -24,7 +25,7 @@ func TestTSATimestampGranted(t *testing.T) { // do timestamp message := []byte("notation") - req, err := timestamp.NewRequestFromBytes(message) + req, err := timestamp.NewRequestWithData(message, crypto.SHA256) if err != nil { t.Fatalf("NewRequestFromString() error = %v", err) } @@ -55,13 +56,13 @@ func TestTSATimestampGranted(t *testing.T) { if err != nil { t.Fatal("SignedToken.Info() error =", err) } - if err := info.Verify(message); err != nil { + if err := info.VerifyWithData(message); err != nil { t.Errorf("TSTInfo.Verify() error = %v", err) } - timestamp, accuracy := info.Timestamp() + ts, accuracy := info.Timestamp() wantTimestamp := now - if timestamp != wantTimestamp { - t.Errorf("TSTInfo.Timestamp() Timestamp = %v, want %v", timestamp, wantTimestamp) + if ts != wantTimestamp { + t.Errorf("TSTInfo.Timestamp() Timestamp = %v, want %v", ts, wantTimestamp) } wantAccuracy := time.Second if accuracy != wantAccuracy { @@ -78,7 +79,7 @@ func TestTSATimestampRejection(t *testing.T) { // do timestamp message := []byte("notation") - req, err := timestamp.NewRequestFromBytes(message) + req, err := timestamp.NewRequestWithData(message, crypto.SHA256) if err != nil { t.Fatalf("NewRequestFromString() error = %v", err) } diff --git a/timestamp/token.go b/timestamp/token.go index 04e0a03f..5cea07c8 100644 --- a/timestamp/token.go +++ b/timestamp/token.go @@ -7,11 +7,11 @@ import ( "encoding/asn1" "errors" "fmt" + "github.com/notaryproject/notation-core-go/internal/crypto/hashutil" "math/big" "time" "github.com/notaryproject/notation-core-go/internal/crypto/cms" - "github.com/notaryproject/notation-core-go/internal/crypto/hashutil" "github.com/notaryproject/notation-core-go/internal/crypto/oid" asn1util "github.com/notaryproject/notation-core-go/internal/encoding/asn1" ) @@ -83,16 +83,16 @@ type Accuracy struct { } // TSTInfo ::= SEQUENCE { -// version INTEGER { v1(1) }, -// policy TSAPolicyId, -// messageImprint MessageImprint, -// serialNumber INTEGER, -// genTime GeneralizedTime, -// accuracy Accuracy OPTIONAL, -// ordering BOOLEAN DEFAULT FALSE, -// nonce INTEGER OPTIONAL, -// tsa [0] GeneralName OPTIONAL, -// extensions [1] IMPLICIT Extensions OPTIONAL } +// version INTEGER { v1(1) }, +// policy TSAPolicyId, +// messageImprint MessageImprint, +// serialNumber INTEGER, +// genTime GeneralizedTime, +// accuracy Accuracy OPTIONAL, +// ordering BOOLEAN DEFAULT FALSE, +// nonce INTEGER OPTIONAL, +// tsa [0] GeneralName OPTIONAL, +// extensions [1] IMPLICIT Extensions OPTIONAL } type TSTInfo struct { Version int // fixed to 1 as defined in RFC 3161 2.4.2 Response Format Policy asn1.ObjectIdentifier @@ -106,8 +106,8 @@ type TSTInfo struct { Extensions []pkix.Extension `asn1:"optional,tag:1"` } -// Verify verifies the message against the timestamp token information. -func (tst *TSTInfo) Verify(message []byte) error { +// VerifyWithData verifies the message against the timestamp token information. +func (tst *TSTInfo) VerifyWithData(message []byte) error { hashAlg := tst.MessageImprint.HashAlgorithm.Algorithm hash, ok := oid.ConvertToHash(hashAlg) if !ok { @@ -117,6 +117,12 @@ func (tst *TSTInfo) Verify(message []byte) error { if err != nil { return err } + + return tst.Verify(messageDigest) +} + +// Verify verifies the message digest against the timestamp token information. +func (tst *TSTInfo) Verify(messageDigest []byte) error { if !bytes.Equal(tst.MessageImprint.HashedMessage, messageDigest) { return errors.New("mismatch message digest") } From 185b9470b4b59ffd5358c7f029a7bb510ea9aaf5 Mon Sep 17 00:00:00 2001 From: Pritesh Bandi Date: Mon, 27 Jun 2022 10:30:35 -0700 Subject: [PATCH 3/4] somefixups Signed-off-by: Pritesh Bandi --- timestamp/http_test.go | 18 +++++++++--------- timestamp/request.go | 13 ++++++------- timestamp/timestamptest/tsa_test.go | 10 +++++----- timestamp/token.go | 6 +++--- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/timestamp/http_test.go b/timestamp/http_test.go index 6b697c3a..fedf8367 100644 --- a/timestamp/http_test.go +++ b/timestamp/http_test.go @@ -75,9 +75,9 @@ func TestHTTPTimestampGranted(t *testing.T) { t.Fatalf("NewHTTPTimestamper() error = %v", err) } message := []byte("notation") - req, err := NewRequestWithData(message, crypto.SHA256) + req, err := NewRequestWithContent(message, crypto.SHA256) if err != nil { - t.Fatalf("NewRequestFromString() error = %v", err) + t.Fatalf("NewRequestWithContent() error = %v", err) } ctx := context.Background() resp, err := tsa.Timestamp(ctx, req) @@ -128,7 +128,7 @@ func TestHTTPTimestampGranted(t *testing.T) { if err != nil { t.Fatal("SignedToken.Info() error =", err) } - if err := info.VerifyWithData(message); err != nil { + if err := info.VerifyWithContent(message); err != nil { t.Errorf("TSTInfo.Verify() error = %v", err) } timestamp, accuracy := info.Timestamp() @@ -173,9 +173,9 @@ func TestHTTPTimestampRejection(t *testing.T) { t.Fatalf("NewHTTPTimestamper() error = %v", err) } message := []byte("notation") - req, err := NewRequestWithData(message, crypto.SHA256) + req, err := NewRequestWithContent(message, crypto.SHA256) if err != nil { - t.Fatalf("NewRequestFromString() error = %v", err) + t.Fatalf("NewRequestWithContent() error = %v", err) } ctx := context.Background() resp, err := tsa.Timestamp(ctx, req) @@ -216,9 +216,9 @@ func TestHTTPTimestampBadEndpoint(t *testing.T) { t.Fatalf("NewHTTPTimestamper() error = %v", err) } message := []byte("notation") - req, err := NewRequestWithData(message, crypto.SHA256) + req, err := NewRequestWithContent(message, crypto.SHA256) if err != nil { - t.Fatalf("NewRequestFromString() error = %v", err) + t.Fatalf("NewRequestWithContent() error = %v", err) } ctx := context.Background() _, err = tsa.Timestamp(ctx, req) @@ -240,9 +240,9 @@ func TestHTTPTimestampEndpointNotFound(t *testing.T) { t.Fatalf("NewHTTPTimestamper() error = %v", err) } message := []byte("notation") - req, err := NewRequestWithData(message, crypto.SHA256) + req, err := NewRequestWithContent(message, crypto.SHA256) if err != nil { - t.Fatalf("NewRequestFromString() error = %v", err) + t.Fatalf("NewRequestWithContent() error = %v", err) } ctx := context.Background() _, err = tsa.Timestamp(ctx, req) diff --git a/timestamp/request.go b/timestamp/request.go index 88b98950..f9cdab39 100644 --- a/timestamp/request.go +++ b/timestamp/request.go @@ -6,9 +6,9 @@ import ( "encoding/asn1" "errors" "fmt" - "github.com/notaryproject/notation-core-go/internal/crypto/hashutil" "math/big" + "github.com/notaryproject/notation-core-go/internal/crypto/hashutil" "github.com/notaryproject/notation-core-go/internal/crypto/oid" ) @@ -49,7 +49,6 @@ func NewRequest(digest []byte, alg crypto.Hash) (*Request, error) { if err != nil { return nil, err } - return &Request{ Version: 1, MessageImprint: MessageImprint{ @@ -62,8 +61,8 @@ func NewRequest(digest []byte, alg crypto.Hash) (*Request, error) { }, nil } -// NewRequestWithData creates a request based on the given data and hash algorithm. -func NewRequestWithData(content []byte, alg crypto.Hash) (*Request, error) { +// NewRequestWithContent creates a request based on the given data and hash algorithm. +func NewRequestWithContent(content []byte, alg crypto.Hash) (*Request, error) { digest, err := hashutil.ComputeHash(alg, content) if err != nil { return nil, err @@ -106,11 +105,11 @@ func validate(digest []byte, alg crypto.Hash) error { var validContent bool switch alg { case crypto.SHA256: - validContent = l == 256/8 + validContent = l == crypto.SHA256.Size() case crypto.SHA384: - validContent = l == 384/8 + validContent = l == crypto.SHA384.Size() case crypto.SHA512: - validContent = l == 384/8 + validContent = l == crypto.SHA512.Size() default: return MalformedRequestError{msg: fmt.Sprintf("unsupported hashing algorithm: %s", alg)} } diff --git a/timestamp/timestamptest/tsa_test.go b/timestamp/timestamptest/tsa_test.go index c2487975..c6ffe24a 100644 --- a/timestamp/timestamptest/tsa_test.go +++ b/timestamp/timestamptest/tsa_test.go @@ -25,9 +25,9 @@ func TestTSATimestampGranted(t *testing.T) { // do timestamp message := []byte("notation") - req, err := timestamp.NewRequestWithData(message, crypto.SHA256) + req, err := timestamp.NewRequestWithContent(message, crypto.SHA256) if err != nil { - t.Fatalf("NewRequestFromString() error = %v", err) + t.Fatalf("NewRequestWithContent() error = %v", err) } ctx := context.Background() resp, err := tsa.Timestamp(ctx, req) @@ -56,7 +56,7 @@ func TestTSATimestampGranted(t *testing.T) { if err != nil { t.Fatal("SignedToken.Info() error =", err) } - if err := info.VerifyWithData(message); err != nil { + if err := info.VerifyWithContent(message); err != nil { t.Errorf("TSTInfo.Verify() error = %v", err) } ts, accuracy := info.Timestamp() @@ -79,9 +79,9 @@ func TestTSATimestampRejection(t *testing.T) { // do timestamp message := []byte("notation") - req, err := timestamp.NewRequestWithData(message, crypto.SHA256) + req, err := timestamp.NewRequestWithContent(message, crypto.SHA256) if err != nil { - t.Fatalf("NewRequestFromString() error = %v", err) + t.Fatalf("NewRequestWithContent() error = %v", err) } req.MessageImprint.HashAlgorithm.Algorithm = oid.SHA1WithRSA // set bad algorithm ctx := context.Background() diff --git a/timestamp/token.go b/timestamp/token.go index 5cea07c8..84eda556 100644 --- a/timestamp/token.go +++ b/timestamp/token.go @@ -7,11 +7,11 @@ import ( "encoding/asn1" "errors" "fmt" - "github.com/notaryproject/notation-core-go/internal/crypto/hashutil" "math/big" "time" "github.com/notaryproject/notation-core-go/internal/crypto/cms" + "github.com/notaryproject/notation-core-go/internal/crypto/hashutil" "github.com/notaryproject/notation-core-go/internal/crypto/oid" asn1util "github.com/notaryproject/notation-core-go/internal/encoding/asn1" ) @@ -106,8 +106,8 @@ type TSTInfo struct { Extensions []pkix.Extension `asn1:"optional,tag:1"` } -// VerifyWithData verifies the message against the timestamp token information. -func (tst *TSTInfo) VerifyWithData(message []byte) error { +// VerifyWithContent verifies the message against the timestamp token information. +func (tst *TSTInfo) VerifyWithContent(message []byte) error { hashAlg := tst.MessageImprint.HashAlgorithm.Algorithm hash, ok := oid.ConvertToHash(hashAlg) if !ok { From ff1f31f203a506c588dbeb5e50ca4ef817d90507 Mon Sep 17 00:00:00 2001 From: Pritesh Bandi Date: Wed, 29 Jun 2022 02:36:14 -0700 Subject: [PATCH 4/4] somemorefixups Signed-off-by: Pritesh Bandi --- timestamp/http_test.go | 18 +++++++++--------- timestamp/request.go | 20 ++++++-------------- timestamp/timestamptest/tsa_test.go | 10 +++++----- timestamp/token.go | 24 ++++++++++++------------ 4 files changed, 32 insertions(+), 40 deletions(-) diff --git a/timestamp/http_test.go b/timestamp/http_test.go index fedf8367..d0fcf3cc 100644 --- a/timestamp/http_test.go +++ b/timestamp/http_test.go @@ -75,9 +75,9 @@ func TestHTTPTimestampGranted(t *testing.T) { t.Fatalf("NewHTTPTimestamper() error = %v", err) } message := []byte("notation") - req, err := NewRequestWithContent(message, crypto.SHA256) + req, err := NewRequestFromContent(message, crypto.SHA256) if err != nil { - t.Fatalf("NewRequestWithContent() error = %v", err) + t.Fatalf("NewRequestFromContent() error = %v", err) } ctx := context.Background() resp, err := tsa.Timestamp(ctx, req) @@ -128,7 +128,7 @@ func TestHTTPTimestampGranted(t *testing.T) { if err != nil { t.Fatal("SignedToken.Info() error =", err) } - if err := info.VerifyWithContent(message); err != nil { + if err := info.VerifyContent(message); err != nil { t.Errorf("TSTInfo.Verify() error = %v", err) } timestamp, accuracy := info.Timestamp() @@ -173,9 +173,9 @@ func TestHTTPTimestampRejection(t *testing.T) { t.Fatalf("NewHTTPTimestamper() error = %v", err) } message := []byte("notation") - req, err := NewRequestWithContent(message, crypto.SHA256) + req, err := NewRequestFromContent(message, crypto.SHA256) if err != nil { - t.Fatalf("NewRequestWithContent() error = %v", err) + t.Fatalf("NewRequestFromContent() error = %v", err) } ctx := context.Background() resp, err := tsa.Timestamp(ctx, req) @@ -216,9 +216,9 @@ func TestHTTPTimestampBadEndpoint(t *testing.T) { t.Fatalf("NewHTTPTimestamper() error = %v", err) } message := []byte("notation") - req, err := NewRequestWithContent(message, crypto.SHA256) + req, err := NewRequestFromContent(message, crypto.SHA256) if err != nil { - t.Fatalf("NewRequestWithContent() error = %v", err) + t.Fatalf("NewRequestFromContent() error = %v", err) } ctx := context.Background() _, err = tsa.Timestamp(ctx, req) @@ -240,9 +240,9 @@ func TestHTTPTimestampEndpointNotFound(t *testing.T) { t.Fatalf("NewHTTPTimestamper() error = %v", err) } message := []byte("notation") - req, err := NewRequestWithContent(message, crypto.SHA256) + req, err := NewRequestFromContent(message, crypto.SHA256) if err != nil { - t.Fatalf("NewRequestWithContent() error = %v", err) + t.Fatalf("NewRequestFromContent() error = %v", err) } ctx := context.Background() _, err = tsa.Timestamp(ctx, req) diff --git a/timestamp/request.go b/timestamp/request.go index f9cdab39..1f4d926f 100644 --- a/timestamp/request.go +++ b/timestamp/request.go @@ -61,8 +61,8 @@ func NewRequest(digest []byte, alg crypto.Hash) (*Request, error) { }, nil } -// NewRequestWithContent creates a request based on the given data and hash algorithm. -func NewRequestWithContent(content []byte, alg crypto.Hash) (*Request, error) { +// NewRequestFromContent creates a request based on the given data and hash algorithm. +func NewRequestFromContent(content []byte, alg crypto.Hash) (*Request, error) { digest, err := hashutil.ComputeHash(alg, content) if err != nil { return nil, err @@ -101,20 +101,12 @@ func getOID(alg crypto.Hash) (asn1.ObjectIdentifier, error) { } func validate(digest []byte, alg crypto.Hash) error { - l := len(digest) - var validContent bool - switch alg { - case crypto.SHA256: - validContent = l == crypto.SHA256.Size() - case crypto.SHA384: - validContent = l == crypto.SHA384.Size() - case crypto.SHA512: - validContent = l == crypto.SHA512.Size() - default: + if !(alg == crypto.SHA256 || alg == crypto.SHA384 || alg == crypto.SHA512) { return MalformedRequestError{msg: fmt.Sprintf("unsupported hashing algorithm: %s", alg)} } - if !validContent { - return MalformedRequestError{msg: fmt.Sprintf("digest is of incorrect size: %d", l)} + + if len(digest) != alg.Size() { + return MalformedRequestError{msg: fmt.Sprintf("digest is of incorrect size: %d", len(digest))} } return nil } \ No newline at end of file diff --git a/timestamp/timestamptest/tsa_test.go b/timestamp/timestamptest/tsa_test.go index c6ffe24a..07d4fea1 100644 --- a/timestamp/timestamptest/tsa_test.go +++ b/timestamp/timestamptest/tsa_test.go @@ -25,9 +25,9 @@ func TestTSATimestampGranted(t *testing.T) { // do timestamp message := []byte("notation") - req, err := timestamp.NewRequestWithContent(message, crypto.SHA256) + req, err := timestamp.NewRequestFromContent(message, crypto.SHA256) if err != nil { - t.Fatalf("NewRequestWithContent() error = %v", err) + t.Fatalf("NewRequestFromContent() error = %v", err) } ctx := context.Background() resp, err := tsa.Timestamp(ctx, req) @@ -56,7 +56,7 @@ func TestTSATimestampGranted(t *testing.T) { if err != nil { t.Fatal("SignedToken.Info() error =", err) } - if err := info.VerifyWithContent(message); err != nil { + if err := info.VerifyContent(message); err != nil { t.Errorf("TSTInfo.Verify() error = %v", err) } ts, accuracy := info.Timestamp() @@ -79,9 +79,9 @@ func TestTSATimestampRejection(t *testing.T) { // do timestamp message := []byte("notation") - req, err := timestamp.NewRequestWithContent(message, crypto.SHA256) + req, err := timestamp.NewRequestFromContent(message, crypto.SHA256) if err != nil { - t.Fatalf("NewRequestWithContent() error = %v", err) + t.Fatalf("NewRequestFromContent() error = %v", err) } req.MessageImprint.HashAlgorithm.Algorithm = oid.SHA1WithRSA // set bad algorithm ctx := context.Background() diff --git a/timestamp/token.go b/timestamp/token.go index 84eda556..5e4ec19d 100644 --- a/timestamp/token.go +++ b/timestamp/token.go @@ -83,16 +83,16 @@ type Accuracy struct { } // TSTInfo ::= SEQUENCE { -// version INTEGER { v1(1) }, -// policy TSAPolicyId, -// messageImprint MessageImprint, -// serialNumber INTEGER, -// genTime GeneralizedTime, -// accuracy Accuracy OPTIONAL, -// ordering BOOLEAN DEFAULT FALSE, -// nonce INTEGER OPTIONAL, -// tsa [0] GeneralName OPTIONAL, -// extensions [1] IMPLICIT Extensions OPTIONAL } +// version INTEGER { v1(1) }, +// policy TSAPolicyId, +// messageImprint MessageImprint, +// serialNumber INTEGER, +// genTime GeneralizedTime, +// accuracy Accuracy OPTIONAL, +// ordering BOOLEAN DEFAULT FALSE, +// nonce INTEGER OPTIONAL, +// tsa [0] GeneralName OPTIONAL, +// extensions [1] IMPLICIT Extensions OPTIONAL } type TSTInfo struct { Version int // fixed to 1 as defined in RFC 3161 2.4.2 Response Format Policy asn1.ObjectIdentifier @@ -106,8 +106,8 @@ type TSTInfo struct { Extensions []pkix.Extension `asn1:"optional,tag:1"` } -// VerifyWithContent verifies the message against the timestamp token information. -func (tst *TSTInfo) VerifyWithContent(message []byte) error { +// VerifyContent verifies the message against the timestamp token information. +func (tst *TSTInfo) VerifyContent(message []byte) error { hashAlg := tst.MessageImprint.HashAlgorithm.Algorithm hash, ok := oid.ConvertToHash(hashAlg) if !ok {