From cf5cfd7243dac64a23745c6e07b35c6c85564e8b Mon Sep 17 00:00:00 2001 From: Mike Wittie Date: Mon, 19 Aug 2024 15:19:54 -0600 Subject: [PATCH 1/9] Add Timestamp() to extract attestation timestamp --- go.mod | 5 +++- go.sum | 20 ++++++++++++- nitrite.go | 33 +++++++++++++++++++-- nitrite_test.go | 79 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 nitrite_test.go diff --git a/go.mod b/go.mod index 8d226c3..f8c4330 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,7 @@ module github.com/hf/nitrite go 1.15 -require github.com/fxamacker/cbor/v2 v2.2.0 +require ( + github.com/fxamacker/cbor/v2 v2.2.0 + github.com/stretchr/testify v1.9.0 +) diff --git a/go.sum b/go.sum index f7afbec..251a62c 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,23 @@ -github.com/fxamacker/cbor v1.5.1 h1:XjQWBgdmQyqimslUh5r4tUGmoqzHmBFQOImkWGi2awg= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fxamacker/cbor/v2 v2.2.0 h1:6eXqdDDe588rSYAi1HfZKbx6YYQO4mxQ9eC6xYpU/JQ= github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/nitrite.go b/nitrite.go index c5a9983..77c9607 100644 --- a/nitrite.go +++ b/nitrite.go @@ -8,9 +8,10 @@ import ( "crypto/x509" "errors" "fmt" - "github.com/fxamacker/cbor/v2" "math/big" "time" + + "github.com/fxamacker/cbor/v2" ) // Document represents the AWS Nitro Enclave Attestation Document. @@ -84,7 +85,7 @@ func (h *coseHeader) AlgorithmInt() (int64, bool) { return 0, false } -type cosePayload struct { +type CosePayload struct { _ struct{} `cbor:",toarray"` Protected []byte @@ -180,7 +181,7 @@ func reverse(enc []byte) []byte { // set! You can use the SignatureOK field from the result to distinguish // errors. func Verify(data []byte, options VerifyOptions) (*Result, error) { - cose := cosePayload{} + cose := CosePayload{} err := cbor.Unmarshal(data, &cose) if nil != err { @@ -398,3 +399,29 @@ func checkECDSASignature(publicKey *ecdsa.PublicKey, sigStruct, signature []byte return ecdsa.Verify(publicKey, hashSigStruct, r, s) } + +// Timestamp extracts attestation timestamp from `data` without verifying +// the attestation. +func Timestamp(data []byte) (time.Time, error) { + cose := CosePayload{} + err := cbor.Unmarshal(data, &cose) + if nil != err { + return time.Time{}, errors.Join(ErrBadCOSESign1Structure, err) + } + + doc := Document{} + err = cbor.Unmarshal(cose.Payload, &doc) + if nil != err { + return time.Time{}, errors.Join(ErrBadAttestationDocument, err) + } + + if doc.Timestamp == 0 { + return time.Time{}, + errors.Join(ErrMandatoryFieldsMissing, fmt.Errorf("no timestamp")) + } + + // https://docs.aws.amazon.com/pdfs/enclaves/latest/user/enclaves-user.pdf + // (p. 64) describes Timestamp as "UTC time when document was created, + // in milliseconds" + return time.UnixMilli(int64(doc.Timestamp)), nil +} diff --git a/nitrite_test.go b/nitrite_test.go new file mode 100644 index 0000000..aa042c2 --- /dev/null +++ b/nitrite_test.go @@ -0,0 +1,79 @@ +package nitrite_test + +import ( + "testing" + "time" + + "github.com/fxamacker/cbor/v2" + "github.com/hf/nitrite" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestAttestationCreatedAt(t *testing.T) { + t.Run("happy path", func(t *testing.T) { + // given + wantTime := time.Now() + doc := nitrite.Document{ + Timestamp: uint64(wantTime.UnixMilli()), + } + docBytes, err := cbor.Marshal(doc) + require.NoError(t, err) + cosePayload := nitrite.CosePayload{ + Payload: docBytes, + } + cosePayloadBytes, err := cbor.Marshal(cosePayload) + require.NoError(t, err) + + // when + gotTime, err := nitrite.Timestamp(cosePayloadBytes) + + // then + require.NoError(t, err) + assert.Equal(t, wantTime.UnixMilli(), gotTime.UnixMilli()) + }) + + t.Run("cannot unmarshal COSE payload", func(t *testing.T) { + // when + _, err := nitrite.Timestamp([]byte("invalid")) + + // then + assert.ErrorIs(t, err, nitrite.ErrBadCOSESign1Structure) + }) + + t.Run("cannot unmarshal Document", func(t *testing.T) { + // given + cosePayload := nitrite.CosePayload{ + Payload: []byte("invalid"), + } + cosePayloadBytes, err := cbor.Marshal(cosePayload) + require.NoError(t, err) + + // when + _, err = nitrite.Timestamp(cosePayloadBytes) + + // then + assert.ErrorIs(t, err, nitrite.ErrBadAttestationDocument) + }) + + t.Run("attestation document has no timestamp", func(t *testing.T) { + // given + doc := nitrite.Document{ + Timestamp: 0, + } + docBytes, err := cbor.Marshal(doc) + require.NoError(t, err) + cosePayload := nitrite.CosePayload{ + Payload: docBytes, + } + cosePayloadBytes, err := cbor.Marshal(cosePayload) + require.NoError(t, err) + + // when + _, err = nitrite.Timestamp(cosePayloadBytes) + + // then + assert.ErrorIs(t, err, nitrite.ErrMandatoryFieldsMissing) + assert.ErrorContains(t, err, "no timestamp") + }) +} From cad9d05730b3adb8de4c42c013bff9c193aa5ed6 Mon Sep 17 00:00:00 2001 From: Mike Wittie Date: Mon, 19 Aug 2024 15:20:15 -0600 Subject: [PATCH 2/9] Remove unused reverse() --- nitrite.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/nitrite.go b/nitrite.go index 77c9607..4a55089 100644 --- a/nitrite.go +++ b/nitrite.go @@ -156,16 +156,6 @@ func createAWSNitroRoot() *x509.CertPool { return pool } -func reverse(enc []byte) []byte { - rev := make([]byte, len(enc)) - - for i, b := range enc { - rev[len(enc)-i-1] = b - } - - return rev -} - // Verify verifies the attestation payload from `data` with the provided // verification options. If the options specify `Roots` as `nil`, the // `DefaultCARoot` will be used. If you do not specify `CurrentTime`, From 5f3ea6280a65c40fa30a6a0ce28c175bcc407a89 Mon Sep 17 00:00:00 2001 From: Mike Wittie Date: Mon, 19 Aug 2024 15:22:02 -0600 Subject: [PATCH 3/9] Update cbor dependency version --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f8c4330..a6321eb 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,6 @@ module github.com/hf/nitrite go 1.15 require ( - github.com/fxamacker/cbor/v2 v2.2.0 + github.com/fxamacker/cbor/v2 v2.7.0 github.com/stretchr/testify v1.9.0 ) diff --git a/go.sum b/go.sum index 251a62c..42406e2 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fxamacker/cbor/v2 v2.2.0 h1:6eXqdDDe588rSYAi1HfZKbx6YYQO4mxQ9eC6xYpU/JQ= -github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From c16b811e423a1faafc6a4d92cb5203e4bfe92197 Mon Sep 17 00:00:00 2001 From: Mike Wittie Date: Wed, 21 Aug 2024 17:42:52 -0600 Subject: [PATCH 4/9] Remove testify as a dependency --- nitrite_test.go | 50 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/nitrite_test.go b/nitrite_test.go index aa042c2..2d9c588 100644 --- a/nitrite_test.go +++ b/nitrite_test.go @@ -1,15 +1,39 @@ package nitrite_test import ( + "errors" + "strings" "testing" "time" "github.com/fxamacker/cbor/v2" "github.com/hf/nitrite" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) +func requireNoError(t *testing.T, err error) { + if err != nil { + t.Fatalf("unexpected error: %v", err) + } +} + +func requireEqual(t *testing.T, want, got interface{}) { + if want != got { + t.Fatalf("want %v, got %v", want, got) + } +} + +func requireErrorIs(t *testing.T, got, want error) { + if !errors.Is(got, want) { + t.Fatalf("want error %v, got %v", want, got) + } +} + +func requireErrorContains(t *testing.T, err error, substr string) { + if !strings.Contains(err.Error(), substr) { + t.Fatalf("error %q does not contain %q", err, substr) + } +} + func TestAttestationCreatedAt(t *testing.T) { t.Run("happy path", func(t *testing.T) { // given @@ -18,19 +42,19 @@ func TestAttestationCreatedAt(t *testing.T) { Timestamp: uint64(wantTime.UnixMilli()), } docBytes, err := cbor.Marshal(doc) - require.NoError(t, err) + requireNoError(t, err) cosePayload := nitrite.CosePayload{ Payload: docBytes, } cosePayloadBytes, err := cbor.Marshal(cosePayload) - require.NoError(t, err) + requireNoError(t, err) // when gotTime, err := nitrite.Timestamp(cosePayloadBytes) // then - require.NoError(t, err) - assert.Equal(t, wantTime.UnixMilli(), gotTime.UnixMilli()) + requireNoError(t, err) + requireEqual(t, wantTime.UnixMilli(), gotTime.UnixMilli()) }) t.Run("cannot unmarshal COSE payload", func(t *testing.T) { @@ -38,7 +62,7 @@ func TestAttestationCreatedAt(t *testing.T) { _, err := nitrite.Timestamp([]byte("invalid")) // then - assert.ErrorIs(t, err, nitrite.ErrBadCOSESign1Structure) + requireErrorIs(t, err, nitrite.ErrBadCOSESign1Structure) }) t.Run("cannot unmarshal Document", func(t *testing.T) { @@ -47,13 +71,13 @@ func TestAttestationCreatedAt(t *testing.T) { Payload: []byte("invalid"), } cosePayloadBytes, err := cbor.Marshal(cosePayload) - require.NoError(t, err) + requireNoError(t, err) // when _, err = nitrite.Timestamp(cosePayloadBytes) // then - assert.ErrorIs(t, err, nitrite.ErrBadAttestationDocument) + requireErrorIs(t, err, nitrite.ErrBadAttestationDocument) }) t.Run("attestation document has no timestamp", func(t *testing.T) { @@ -62,18 +86,18 @@ func TestAttestationCreatedAt(t *testing.T) { Timestamp: 0, } docBytes, err := cbor.Marshal(doc) - require.NoError(t, err) + requireNoError(t, err) cosePayload := nitrite.CosePayload{ Payload: docBytes, } cosePayloadBytes, err := cbor.Marshal(cosePayload) - require.NoError(t, err) + requireNoError(t, err) // when _, err = nitrite.Timestamp(cosePayloadBytes) // then - assert.ErrorIs(t, err, nitrite.ErrMandatoryFieldsMissing) - assert.ErrorContains(t, err, "no timestamp") + requireErrorIs(t, err, nitrite.ErrMandatoryFieldsMissing) + requireErrorContains(t, err, "no timestamp") }) } From 56d779185f47a4f07a28f61520ad145ed0281489 Mon Sep 17 00:00:00 2001 From: Mike Wittie Date: Wed, 21 Aug 2024 17:45:16 -0600 Subject: [PATCH 5/9] Roll back the cbor dependency version update --- go.mod | 5 +---- go.sum | 23 ++--------------------- 2 files changed, 3 insertions(+), 25 deletions(-) diff --git a/go.mod b/go.mod index a6321eb..8d226c3 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,4 @@ module github.com/hf/nitrite go 1.15 -require ( - github.com/fxamacker/cbor/v2 v2.7.0 - github.com/stretchr/testify v1.9.0 -) +require github.com/fxamacker/cbor/v2 v2.2.0 diff --git a/go.sum b/go.sum index 42406e2..c7a2ead 100644 --- a/go.sum +++ b/go.sum @@ -1,23 +1,4 @@ -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= -github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/fxamacker/cbor/v2 v2.2.0 h1:6eXqdDDe588rSYAi1HfZKbx6YYQO4mxQ9eC6xYpU/JQ= +github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From d36576498da7119b50163014fa52c1f22cba9b98 Mon Sep 17 00:00:00 2001 From: Mike Wittie Date: Wed, 21 Aug 2024 17:46:57 -0600 Subject: [PATCH 6/9] Roll back the removal of reverse to simplify the PR --- nitrite.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/nitrite.go b/nitrite.go index 4a55089..77c9607 100644 --- a/nitrite.go +++ b/nitrite.go @@ -156,6 +156,16 @@ func createAWSNitroRoot() *x509.CertPool { return pool } +func reverse(enc []byte) []byte { + rev := make([]byte, len(enc)) + + for i, b := range enc { + rev[len(enc)-i-1] = b + } + + return rev +} + // Verify verifies the attestation payload from `data` with the provided // verification options. If the options specify `Roots` as `nil`, the // `DefaultCARoot` will be used. If you do not specify `CurrentTime`, From 0c03eff624d2a3a989f978740d81ab0928b48e16 Mon Sep 17 00:00:00 2001 From: Mike Wittie Date: Thu, 22 Aug 2024 13:08:33 -0600 Subject: [PATCH 7/9] Unify error checking parameter order --- nitrite_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/nitrite_test.go b/nitrite_test.go index 2d9c588..acb98c3 100644 --- a/nitrite_test.go +++ b/nitrite_test.go @@ -10,21 +10,21 @@ import ( "github.com/hf/nitrite" ) -func requireNoError(t *testing.T, err error) { - if err != nil { - t.Fatalf("unexpected error: %v", err) +func requireNoError(t *testing.T, got error) { + if got != nil { + t.Fatalf("unexpected error: %v", got) } } -func requireEqual(t *testing.T, want, got interface{}) { - if want != got { - t.Fatalf("want %v, got %v", want, got) +func requireEqual(t *testing.T, got, want interface{}) { + if got != want { + t.Fatalf("not equal: want %v, got %v", want, got) } } func requireErrorIs(t *testing.T, got, want error) { if !errors.Is(got, want) { - t.Fatalf("want error %v, got %v", want, got) + t.Fatalf("unexpected error type: want %T, got %T", want, got) } } @@ -54,7 +54,7 @@ func TestAttestationCreatedAt(t *testing.T) { // then requireNoError(t, err) - requireEqual(t, wantTime.UnixMilli(), gotTime.UnixMilli()) + requireEqual(t, gotTime.UnixMilli(), wantTime.UnixMilli()) }) t.Run("cannot unmarshal COSE payload", func(t *testing.T) { From eb0832f5f2ee1568127ec4ba388e2482f7098049 Mon Sep 17 00:00:00 2001 From: Mike Wittie Date: Thu, 22 Aug 2024 13:46:19 -0600 Subject: [PATCH 8/9] Build and test in go1.15.15 --- nitrite.go | 10 +++++----- nitrite_test.go | 18 +++++++----------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/nitrite.go b/nitrite.go index 77c9607..00e6588 100644 --- a/nitrite.go +++ b/nitrite.go @@ -406,22 +406,22 @@ func Timestamp(data []byte) (time.Time, error) { cose := CosePayload{} err := cbor.Unmarshal(data, &cose) if nil != err { - return time.Time{}, errors.Join(ErrBadCOSESign1Structure, err) + return time.Time{}, ErrBadCOSESign1Structure } doc := Document{} err = cbor.Unmarshal(cose.Payload, &doc) if nil != err { - return time.Time{}, errors.Join(ErrBadAttestationDocument, err) + return time.Time{}, ErrBadAttestationDocument } if doc.Timestamp == 0 { - return time.Time{}, - errors.Join(ErrMandatoryFieldsMissing, fmt.Errorf("no timestamp")) + return time.Time{}, ErrMandatoryFieldsMissing } // https://docs.aws.amazon.com/pdfs/enclaves/latest/user/enclaves-user.pdf // (p. 64) describes Timestamp as "UTC time when document was created, // in milliseconds" - return time.UnixMilli(int64(doc.Timestamp)), nil + msec := int64(doc.Timestamp) + return time.Unix(msec/1e3, (msec%1e3)*1e6), nil } diff --git a/nitrite_test.go b/nitrite_test.go index acb98c3..558907c 100644 --- a/nitrite_test.go +++ b/nitrite_test.go @@ -2,7 +2,6 @@ package nitrite_test import ( "errors" - "strings" "testing" "time" @@ -18,28 +17,26 @@ func requireNoError(t *testing.T, got error) { func requireEqual(t *testing.T, got, want interface{}) { if got != want { - t.Fatalf("not equal: want %v, got %v", want, got) + t.Fatalf("not equal: got %v, want %v", got, want) } } func requireErrorIs(t *testing.T, got, want error) { if !errors.Is(got, want) { - t.Fatalf("unexpected error type: want %T, got %T", want, got) + t.Fatalf("unexpected error type: got %T, want %T", got, want) } } -func requireErrorContains(t *testing.T, err error, substr string) { - if !strings.Contains(err.Error(), substr) { - t.Fatalf("error %q does not contain %q", err, substr) +func TestAttestationCreatedAt(t *testing.T) { + timeToMillis := func(t time.Time) uint64 { + return uint64(t.UnixNano() / 1e6) } -} -func TestAttestationCreatedAt(t *testing.T) { t.Run("happy path", func(t *testing.T) { // given wantTime := time.Now() doc := nitrite.Document{ - Timestamp: uint64(wantTime.UnixMilli()), + Timestamp: timeToMillis(wantTime), } docBytes, err := cbor.Marshal(doc) requireNoError(t, err) @@ -54,7 +51,7 @@ func TestAttestationCreatedAt(t *testing.T) { // then requireNoError(t, err) - requireEqual(t, gotTime.UnixMilli(), wantTime.UnixMilli()) + requireEqual(t, timeToMillis(gotTime), timeToMillis(wantTime)) }) t.Run("cannot unmarshal COSE payload", func(t *testing.T) { @@ -98,6 +95,5 @@ func TestAttestationCreatedAt(t *testing.T) { // then requireErrorIs(t, err, nitrite.ErrMandatoryFieldsMissing) - requireErrorContains(t, err, "no timestamp") }) } From 5b379e4a703f213870c9f0932fc495dfc77f2f50 Mon Sep 17 00:00:00 2001 From: Mike Wittie Date: Thu, 22 Aug 2024 14:01:31 -0600 Subject: [PATCH 9/9] Avoid exporting nitrite.CosePayload --- nitrite.go | 6 +++--- nitrite_test.go | 15 ++++++++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/nitrite.go b/nitrite.go index 00e6588..2f78bed 100644 --- a/nitrite.go +++ b/nitrite.go @@ -85,7 +85,7 @@ func (h *coseHeader) AlgorithmInt() (int64, bool) { return 0, false } -type CosePayload struct { +type cosePayload struct { _ struct{} `cbor:",toarray"` Protected []byte @@ -181,7 +181,7 @@ func reverse(enc []byte) []byte { // set! You can use the SignatureOK field from the result to distinguish // errors. func Verify(data []byte, options VerifyOptions) (*Result, error) { - cose := CosePayload{} + cose := cosePayload{} err := cbor.Unmarshal(data, &cose) if nil != err { @@ -403,7 +403,7 @@ func checkECDSASignature(publicKey *ecdsa.PublicKey, sigStruct, signature []byte // Timestamp extracts attestation timestamp from `data` without verifying // the attestation. func Timestamp(data []byte) (time.Time, error) { - cose := CosePayload{} + cose := cosePayload{} err := cbor.Unmarshal(data, &cose) if nil != err { return time.Time{}, ErrBadCOSESign1Structure diff --git a/nitrite_test.go b/nitrite_test.go index 558907c..121af87 100644 --- a/nitrite_test.go +++ b/nitrite_test.go @@ -27,6 +27,15 @@ func requireErrorIs(t *testing.T, got, want error) { } } +type testingCOSEPayload struct { + _ struct{} `cbor:",toarray"` + + Protected []byte + Unprotected cbor.RawMessage + Payload []byte + Signature []byte +} + func TestAttestationCreatedAt(t *testing.T) { timeToMillis := func(t time.Time) uint64 { return uint64(t.UnixNano() / 1e6) @@ -40,7 +49,7 @@ func TestAttestationCreatedAt(t *testing.T) { } docBytes, err := cbor.Marshal(doc) requireNoError(t, err) - cosePayload := nitrite.CosePayload{ + cosePayload := testingCOSEPayload{ Payload: docBytes, } cosePayloadBytes, err := cbor.Marshal(cosePayload) @@ -64,7 +73,7 @@ func TestAttestationCreatedAt(t *testing.T) { t.Run("cannot unmarshal Document", func(t *testing.T) { // given - cosePayload := nitrite.CosePayload{ + cosePayload := testingCOSEPayload{ Payload: []byte("invalid"), } cosePayloadBytes, err := cbor.Marshal(cosePayload) @@ -84,7 +93,7 @@ func TestAttestationCreatedAt(t *testing.T) { } docBytes, err := cbor.Marshal(doc) requireNoError(t, err) - cosePayload := nitrite.CosePayload{ + cosePayload := testingCOSEPayload{ Payload: docBytes, } cosePayloadBytes, err := cbor.Marshal(cosePayload)