diff --git a/libs/httpsignature/nitro_test.go b/libs/httpsignature/nitro_test.go index 566d5d42e..5db151bef 100644 --- a/libs/httpsignature/nitro_test.go +++ b/libs/httpsignature/nitro_test.go @@ -30,7 +30,7 @@ func TestVerifyNitroAttestation(t *testing.T) { t.Fatal("error reading sample attestation doc:", err) } - verifier := NitroVerifier{PCRs: pcrs, now: now} + verifier := NitroVerifier{PCRs: pcrs, Now: now} valid, err := verifier.Verify([]byte{}, doc, crypto.Hash(0)) if err != nil { diff --git a/libs/nitro/attestation.go b/libs/nitro/attestation.go index bbfe22fc7..7e4409ffb 100644 --- a/libs/nitro/attestation.go +++ b/libs/nitro/attestation.go @@ -113,14 +113,14 @@ func (s Signer) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (si // Verifier specifies the PCR values required for verification type Verifier struct { PCRs map[uint][]byte - now func() time.Time + Now func() time.Time } // NewVerifier returns a new verifier for nitro attestations func NewVerifier(pcrs map[uint][]byte) Verifier { return Verifier{ PCRs: pcrs, - now: time.Now, + Now: time.Now, } } @@ -136,7 +136,7 @@ func (v Verifier) verifySigOnlyNotPCRs(message, sig []byte, opts crypto.SignerOp sig, nitrite.VerifyOptions{ Roots: pool, - CurrentTime: v.now(), + CurrentTime: v.Now(), }, ) if nil != err { diff --git a/libs/payments/crypto.go b/libs/payments/crypto.go index 424f21ebe..3f0077d7c 100644 --- a/libs/payments/crypto.go +++ b/libs/payments/crypto.go @@ -4,6 +4,7 @@ import ( "context" "crypto" "io" + "time" ) // Signator is an interface for cryptographic signature creation @@ -19,6 +20,6 @@ type Verifier interface { // Keystore provides a way to lookup a public key based on the keyID a request was signed with type Keystore interface { - // LookupVerifier based on the keyID - LookupVerifier(ctx context.Context, keyID string) (context.Context, *Verifier, error) + // LookupVerifier based on the keyID and updatedAt + LookupVerifier(ctx context.Context, keyID string, updatedAt time.Time) (context.Context, *Verifier, error) } diff --git a/libs/payments/state.go b/libs/payments/state.go index 68c1c0d01..362af260a 100644 --- a/libs/payments/state.go +++ b/libs/payments/state.go @@ -6,6 +6,7 @@ import ( "crypto/rand" "encoding/json" "fmt" + "time" "github.com/google/uuid" "github.com/shopspring/decimal" @@ -50,6 +51,7 @@ type PaymentState struct { Signature []byte `ion:"signature"` PublicKey string `ion:"publicKey"` ID uuid.UUID `ion:"idempotencyKey"` + UpdatedAt time.Time `ion:"-"` } // PaymentStateHistory is a sequence of payment states. @@ -133,7 +135,7 @@ func (p PaymentStateHistory) GetAuthenticatedPaymentState(keystore Keystore, doc // 3. the transition was valid var authenticatedState AuthenticatedPaymentState for i, state := range []PaymentState(p) { - _, verifier, err := keystore.LookupVerifier(context.Background(), state.PublicKey) + _, verifier, err := keystore.LookupVerifier(context.Background(), state.PublicKey, state.UpdatedAt) if err != nil { return nil, fmt.Errorf("signature validation for state with document ID %s failed: %w", documentID, err) } diff --git a/services/payments/datastore.go b/services/payments/datastore.go index b274f8039..ae9211a6d 100644 --- a/services/payments/datastore.go +++ b/services/payments/datastore.go @@ -123,6 +123,7 @@ func (q *QLDBDatastore) GetPaymentStateHistory(ctx context.Context, documentID s if err != nil { return nil, fmt.Errorf("ion unmarshal failed: %w", err) } + latestHistoryItem.Data.UpdatedAt = latestHistoryItem.Metadata.TxTime stateHistory = append(stateHistory, latestHistoryItem.Data) } diff --git a/services/payments/state_verifier.go b/services/payments/state_verifier.go index 71a04e3d9..812d200f6 100644 --- a/services/payments/state_verifier.go +++ b/services/payments/state_verifier.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "errors" "fmt" + "time" "github.com/brave-intl/bat-go/libs/nitro" "github.com/brave-intl/bat-go/libs/payments" @@ -14,7 +15,7 @@ import ( var previousPCR2Values = []string{} type VerifierStore struct { - verifiers map[string]payments.Verifier + verifiers map[string]nitro.Verifier } func NewVerifierStore() (*VerifierStore, error) { @@ -23,7 +24,7 @@ func NewVerifierStore() (*VerifierStore, error) { return nil, errors.New("could not retrieve nitro PCRs") } - s := VerifierStore{verifiers: map[string]payments.Verifier{}} + s := VerifierStore{verifiers: map[string]nitro.Verifier{}} // always accept attestations matching our own pubKey := hex.EncodeToString(pcrs[2]) @@ -48,10 +49,12 @@ func NewVerifierStore() (*VerifierStore, error) { } -func (s *VerifierStore) LookupVerifier(ctx context.Context, keyID string) (context.Context, *payments.Verifier, error) { +func (s *VerifierStore) LookupVerifier(ctx context.Context, keyID string, updatedAt time.Time) (context.Context, *payments.Verifier, error) { for k, v := range s.verifiers { if k == keyID { - return ctx, &v, nil + v.Now = func() time.Time { return updatedAt } + vv := (payments.Verifier)(v) + return ctx, &vv, nil } } return ctx, nil, fmt.Errorf("unknown key: %s", keyID)