From 46b482b01c218a8ef9c243d6a5038de4c4eda167 Mon Sep 17 00:00:00 2001 From: Sietse Ringers Date: Mon, 16 Sep 2019 19:36:43 +0200 Subject: [PATCH] refactor: change revocation database method names --- internal/servercore/api.go | 4 +- internal/servercore/handle.go | 12 +-- internal/servercore/helpers.go | 8 +- internal/sessiontest/server_test.go | 2 +- irmaclient/credential.go | 2 +- requests.go | 8 +- revocation.go | 129 ++++++++++++---------------- server/conf.go | 6 +- verify.go | 6 +- 9 files changed, 79 insertions(+), 98 deletions(-) diff --git a/internal/servercore/api.go b/internal/servercore/api.go index 1a71790..312e1d6 100644 --- a/internal/servercore/api.go +++ b/internal/servercore/api.go @@ -53,7 +53,7 @@ func New(conf *server.Configuration) (*Server, error) { // TODO rethink this condition continue } - if err := s.conf.IrmaConfiguration.RevocationStorage.RevocationUpdateDB(credid); err != nil { + if err := s.conf.IrmaConfiguration.RevocationStorage.UpdateDB(credid); err != nil { s.conf.Logger.Error("failed to update revocation database for %s:", credid.String()) _ = server.LogError(err) } @@ -386,7 +386,7 @@ func (s *Server) handleRevocationMessage( return server.JsonResponse(nil, server.RemoteError(server.ErrorInvalidRequest, "POST records expects 1 url arguments")) } cred := irma.NewCredentialTypeIdentifier(args[0]) - var records []*irma.Record + var records []*irma.RevocationRecord if err := json.Unmarshal(message, &records); err != nil { return server.JsonResponse(nil, server.RemoteError(server.ErrorMalformedInput, err.Error())) } diff --git a/internal/servercore/handle.go b/internal/servercore/handle.go index 67d5634..ddcfb5b 100644 --- a/internal/servercore/handle.go +++ b/internal/servercore/handle.go @@ -36,7 +36,7 @@ func (session *session) handleGetRequest(min, max *irma.ProtocolVersion) (irma.S // we include the latest revocation records for the client here, as opposed to when the session // was started, so that the client always gets the very latest revocation records var err error - if err = session.conf.IrmaConfiguration.RevocationStorage.RevocationSetRecords(session.request.Base()); err != nil { + if err = session.conf.IrmaConfiguration.RevocationStorage.SetRecords(session.request.Base()); err != nil { return nil, session.fail(server.ErrorUnknown, err.Error()) // TODO error type } @@ -215,9 +215,9 @@ func (session *session) handlePostCommitments(commitments *irma.IssueCommitmentM } func (s *Server) handlePostRevocationRecords( - cred irma.CredentialTypeIdentifier, records []*irma.Record, + cred irma.CredentialTypeIdentifier, records []*irma.RevocationRecord, ) (interface{}, *irma.RemoteError) { - db, err := s.conf.IrmaConfiguration.RevocationStorage.RevocationDB(cred) + db, err := s.conf.IrmaConfiguration.RevocationStorage.DB(cred) if err != nil { return nil, server.RemoteError(server.ErrorUnknown, err.Error()) // TODO error type } @@ -229,11 +229,11 @@ func (s *Server) handlePostRevocationRecords( func (s *Server) handleGetRevocationRecords( cred irma.CredentialTypeIdentifier, index int, -) ([]*irma.Record, *irma.RemoteError) { +) ([]*irma.RevocationRecord, *irma.RemoteError) { if _, ok := s.conf.RevocationServers[cred]; !ok { return nil, server.RemoteError(server.ErrorInvalidRequest, "not supported by this server") } - db, err := s.conf.IrmaConfiguration.RevocationStorage.RevocationDB(cred) + db, err := s.conf.IrmaConfiguration.RevocationStorage.DB(cred) if err != nil { return nil, server.RemoteError(server.ErrorUnknown, err.Error()) // TODO error type } @@ -270,7 +270,7 @@ func (s *Server) handlePostIssuanceRecord( } // Insert the record into the database - db, err := s.conf.IrmaConfiguration.RevocationStorage.RevocationDB(cred) + db, err := s.conf.IrmaConfiguration.RevocationStorage.DB(cred) if err != nil { return "", server.RemoteError(server.ErrorUnknown, err.Error()) } diff --git a/internal/servercore/helpers.go b/internal/servercore/helpers.go index 9cbfd90..5aebacb 100644 --- a/internal/servercore/helpers.go +++ b/internal/servercore/helpers.go @@ -85,12 +85,12 @@ func (session *session) issuanceHandleRevocation( // ensure the client always gets an up to date nonrevocation witness if _, ours := session.conf.RevocationServers[cred.CredentialTypeID]; !ours { - if err = session.conf.IrmaConfiguration.RevocationStorage.RevocationUpdateDB(cred.CredentialTypeID); err != nil { + if err = session.conf.IrmaConfiguration.RevocationStorage.UpdateDB(cred.CredentialTypeID); err != nil { return } } - db, err := session.conf.IrmaConfiguration.RevocationStorage.RevocationDB(cred.CredentialTypeID) + db, err := session.conf.IrmaConfiguration.RevocationStorage.DB(cred.CredentialTypeID) if err != nil { return } @@ -108,7 +108,7 @@ func (session *session) issuanceHandleRevocation( Issued: time.Now().UnixNano(), // or (floored) cred issuance time? ValidUntil: attributes.Expiry().UnixNano(), } - err = session.conf.IrmaConfiguration.RevocationStorage.SendRevocationIssuanceRecord(cred.CredentialTypeID, issrecord) + err = session.conf.IrmaConfiguration.RevocationStorage.SendIssuanceRecord(cred.CredentialTypeID, issrecord) if err != nil { _ = server.LogWarning(errors.WrapPrefix(err, "Failed to send issuance record to revocation server", 0)) session.conf.Logger.Warn("Storing issuance record locally") @@ -144,7 +144,7 @@ func (s *Server) validateIssuanceRequest(request *irma.IssuanceRequest) error { return err } if s.conf.IrmaConfiguration.CredentialTypes[cred.CredentialTypeID].SupportsRevocation() { - db, err := s.conf.IrmaConfiguration.RevocationStorage.RevocationDB(cred.CredentialTypeID) + db, err := s.conf.IrmaConfiguration.RevocationStorage.DB(cred.CredentialTypeID) if err != nil { return err } diff --git a/internal/sessiontest/server_test.go b/internal/sessiontest/server_test.go index f364607..004ae1a 100644 --- a/internal/sessiontest/server_test.go +++ b/internal/sessiontest/server_test.go @@ -66,7 +66,7 @@ func StartRevocationServer(t *testing.T) { sk, err := conf.IrmaConfiguration.RevocationStorage.PrivateKey(cred.IssuerIdentifier()) require.NoError(t, err) - db, err := conf.IrmaConfiguration.RevocationStorage.RevocationDB(cred) + db, err := conf.IrmaConfiguration.RevocationStorage.DB(cred) require.NoError(t, err) err = db.EnableRevocation(sk) require.NoError(t, err) diff --git a/irmaclient/credential.go b/irmaclient/credential.go index 23741b5..e0baf49 100644 --- a/irmaclient/credential.go +++ b/irmaclient/credential.go @@ -64,7 +64,7 @@ func (cred *credential) PrepareNonrevocation(conf *irma.Configuration, request i // nonrevocation witness is still out of date after applying the updates from the request, // i.e. we were too far behind. Update from revocation server. - revupdates, err := conf.RevocationStorage.RevocationGetUpdates(credtype, cred.NonRevocationWitness.Index+1) + revupdates, err := conf.RevocationStorage.GetUpdates(credtype, cred.NonRevocationWitness.Index+1) if err != nil { return nonrev, err } diff --git a/requests.go b/requests.go index dca1687..84eccff 100644 --- a/requests.go +++ b/requests.go @@ -32,10 +32,10 @@ type BaseRequest struct { Revocation []CredentialTypeIdentifier `json:"revocation,omitempty"` // Set by the IRMA server during the session - Context *big.Int `json:"context,omitempty"` - Nonce *big.Int `json:"nonce,omitempty"` - ProtocolVersion *ProtocolVersion `json:"protocolVersion,omitempty"` - RevocationUpdates map[CredentialTypeIdentifier][]*Record `json:"revocationUpdates,omitempty"` + Context *big.Int `json:"context,omitempty"` + Nonce *big.Int `json:"nonce,omitempty"` + ProtocolVersion *ProtocolVersion `json:"protocolVersion,omitempty"` + RevocationUpdates map[CredentialTypeIdentifier][]*RevocationRecord `json:"revocationUpdates,omitempty"` ids *IrmaIdentifierSet // cache for Identifiers() method diff --git a/revocation.go b/revocation.go index 0f884d4..5d35937 100644 --- a/revocation.go +++ b/revocation.go @@ -15,20 +15,14 @@ import ( ) type ( - // Keystore provides support for revocation public key rollover. - Keystore interface { - // PublicKey either returns the specified, non-nil public key or an error - PublicKey(counter uint) (*revocation.PublicKey, error) - } - // DB is a bolthold database storing revocation state for a particular accumulator - // (Record instances, and IssuanceRecord instances if used by an issuer). + // (RevocationRecord instances, and IssuanceRecord instances if used by an issuer). DB struct { Current revocation.Accumulator Updated time.Time - onChange []func(*Record) + onChange []func(*RevocationRecord) bolt *bolthold.Store - keystore Keystore + keystore keystore } RevocationStorage struct { @@ -36,8 +30,10 @@ type ( conf *Configuration } - // Record contains a signed AccumulatorUpdate and associated information. - Record struct { + // RevocationRecord contains a signed AccumulatorUpdate and associated information and is ued + // by clients, issuers and verifiers to update their revocation state, so that they can create + // and verify nonrevocation proofs and witnesses. + RevocationRecord struct { StartIndex uint64 EndIndex uint64 PublicKeyIndex uint @@ -61,40 +57,13 @@ type ( currentRecord struct { Index uint64 } + + // keystore provides support for revocation public key rollover. + keystore func(counter uint) (*revocation.PublicKey, error) ) const boltCurrentIndexKey = "currentIndex" -func (conf *Configuration) RevocationKeystore(issuerid IssuerIdentifier) Keystore { - return &issuerKeystore{issid: issuerid, conf: conf} -} - -// issuerKeystore implements Keystore. -type issuerKeystore struct { - issid IssuerIdentifier - conf *Configuration -} - -var _ Keystore = (*issuerKeystore)(nil) - -func (ks *issuerKeystore) PublicKey(counter uint) (*revocation.PublicKey, error) { - pk, err := ks.conf.PublicKey(ks.issid, int(counter)) - if err != nil { - return nil, err - } - if pk == nil { - return nil, errors.Errorf("public key %d of issuer %s not found", counter, ks.issid) - } - if !pk.RevocationSupported() { - return nil, errors.Errorf("public key %d of issuer %s does not support revocation", counter, ks.issid) - } - rpk, err := pk.RevocationKey() - if err != nil { - return nil, err - } - return rpk, nil -} - func (rdb *DB) EnableRevocation(sk *revocation.PrivateKey) error { msg, acc, err := revocation.NewAccumulator(sk) if err != nil { @@ -128,15 +97,15 @@ func (rdb *DB) Revoke(sk *revocation.PrivateKey, key []byte) error { // Get returns all records that a client requires to update its revocation state if it is currently // at the specified index, that is, all records whose end index is greater than or equal to // the specified index. -func (rdb *DB) RevocationRecords(index int) ([]*Record, error) { - var records []*Record +func (rdb *DB) RevocationRecords(index int) ([]*RevocationRecord, error) { + var records []*RevocationRecord if err := rdb.bolt.Find(&records, bolthold.Where(bolthold.Key).Ge(uint64(index))); err != nil { return nil, err } return records, nil } -func (rdb *DB) LatestRecords(count int) ([]*Record, error) { +func (rdb *DB) LatestRecords(count int) ([]*RevocationRecord, error) { c := int(rdb.Current.Index) - count + 1 if c < 0 { c = 0 @@ -168,7 +137,7 @@ func (rdb *DB) IssuanceRecord(key []byte) (*IssuanceRecord, error) { return r, nil } -func (rdb *DB) AddRecords(records []*Record) error { +func (rdb *DB) AddRecords(records []*RevocationRecord) error { var err error for _, r := range records { if err = rdb.Add(r.Message, r.PublicKeyIndex); err != nil { @@ -183,7 +152,7 @@ func (rdb *DB) Add(updateMsg signed.Message, counter uint) error { var err error var update revocation.AccumulatorUpdate - pk, err := rdb.keystore.PublicKey(counter) + pk, err := rdb.keystore(counter) if err != nil { return err } @@ -199,7 +168,7 @@ func (rdb *DB) Add(updateMsg signed.Message, counter uint) error { func (rdb *DB) add(update revocation.AccumulatorUpdate, updateMsg signed.Message, pkCounter uint, tx *bolt.Tx) error { var err error - record := &Record{ + record := &RevocationRecord{ StartIndex: update.StartIndex, EndIndex: update.Accumulator.Index, PublicKeyIndex: pkCounter, @@ -251,11 +220,11 @@ func (rdb *DB) loadCurrent() error { return err } - var record Record + var record RevocationRecord if err := rdb.bolt.Get(currentIndex.Index, &record); err != nil { return err } - pk, err := rdb.keystore.PublicKey(record.PublicKeyIndex) + pk, err := rdb.keystore(record.PublicKeyIndex) if err != nil { return err } @@ -304,12 +273,12 @@ func (rdb *DB) Close() error { return nil } -func (rdb *DB) OnChange(handler func(*Record)) { +func (rdb *DB) OnChange(handler func(*RevocationRecord)) { rdb.onChange = append(rdb.onChange, handler) } -func (r *Record) UnmarshalVerify(keystore Keystore) (*revocation.AccumulatorUpdate, error) { - pk, err := keystore.PublicKey(r.PublicKeyIndex) +func (r *RevocationRecord) UnmarshalVerify(keystore keystore) (*revocation.AccumulatorUpdate, error) { + pk, err := keystore(r.PublicKeyIndex) if err != nil { return nil, err } @@ -324,9 +293,9 @@ func (r *Record) UnmarshalVerify(keystore Keystore) (*revocation.AccumulatorUpda return msg, nil } -func (rs *RevocationStorage) LoadDB(credid CredentialTypeIdentifier) (*DB, error) { +func (rs *RevocationStorage) loadDB(credid CredentialTypeIdentifier) (*DB, error) { path := filepath.Join(rs.conf.RevocationPath, credid.String()) - keystore := rs.conf.RevocationKeystore(credid.IssuerIdentifier()) + keystore := rs.keystore(credid.IssuerIdentifier()) b, err := bolthold.Open(path, 0600, &bolthold.Options{Options: &bolt.Options{Timeout: 1 * time.Second}}) if err != nil { @@ -375,7 +344,7 @@ func (rs *RevocationStorage) PublicKey(issid IssuerIdentifier, counter uint) (*r return revpk, nil } -func (rs *RevocationStorage) UpdateWitness(w *revocation.Witness, msgs []*Record, issid IssuerIdentifier) (bool, error) { +func (rs *RevocationStorage) UpdateWitness(w *revocation.Witness, msgs []*RevocationRecord, issid IssuerIdentifier) (bool, error) { var err error var pk *revocation.PublicKey oldindex := w.Index @@ -390,8 +359,8 @@ func (rs *RevocationStorage) UpdateWitness(w *revocation.Witness, msgs []*Record return w.Index == oldindex, nil } -func (rs *RevocationStorage) RevocationGetUpdates(credid CredentialTypeIdentifier, index uint64) ([]*Record, error) { - var records []*Record +func (rs *RevocationStorage) GetUpdates(credid CredentialTypeIdentifier, index uint64) ([]*RevocationRecord, error) { + var records []*RevocationRecord err := NewHTTPTransport(rs.conf.CredentialTypes[credid].RevocationServer). Get(fmt.Sprintf("-/revocation/records/%s/%d", credid, index), &records) if err != nil { @@ -400,27 +369,27 @@ func (rs *RevocationStorage) RevocationGetUpdates(credid CredentialTypeIdentifie return records, nil } -func (rs *RevocationStorage) RevocationUpdateAll() error { +func (rs *RevocationStorage) UpdateAll() error { var err error for credid := range rs.dbs { - if err = rs.RevocationUpdateDB(credid); err != nil { + if err = rs.UpdateDB(credid); err != nil { return err } } return nil } -func (rs *RevocationStorage) RevocationSetRecords(b *BaseRequest) error { +func (rs *RevocationStorage) SetRecords(b *BaseRequest) error { if len(b.Revocation) == 0 { return nil } - b.RevocationUpdates = make(map[CredentialTypeIdentifier][]*Record, len(b.Revocation)) + b.RevocationUpdates = make(map[CredentialTypeIdentifier][]*RevocationRecord, len(b.Revocation)) for _, credid := range b.Revocation { - db, err := rs.RevocationDB(credid) + db, err := rs.DB(credid) if err != nil { return err } - if err = rs.revocationUpdateDelayed(credid, db); err != nil { + if err = rs.updateDelayed(credid, db); err != nil { return err } b.RevocationUpdates[credid], err = db.LatestRecords(revocationUpdateCount) @@ -431,8 +400,8 @@ func (rs *RevocationStorage) RevocationSetRecords(b *BaseRequest) error { return nil } -func (rs *RevocationStorage) RevocationUpdateDB(credid CredentialTypeIdentifier) error { - db, err := rs.RevocationDB(credid) +func (rs *RevocationStorage) UpdateDB(credid CredentialTypeIdentifier) error { + db, err := rs.DB(credid) if err != nil { return err } @@ -440,14 +409,14 @@ func (rs *RevocationStorage) RevocationUpdateDB(credid CredentialTypeIdentifier) if db.Enabled() { index = db.Current.Index + 1 } - records, err := rs.RevocationGetUpdates(credid, index) + records, err := rs.GetUpdates(credid, index) if err != nil { return err } return db.AddRecords(records) } -func (rs *RevocationStorage) RevocationDB(credid CredentialTypeIdentifier) (*DB, error) { +func (rs *RevocationStorage) DB(credid CredentialTypeIdentifier) (*DB, error) { if _, known := rs.conf.CredentialTypes[credid]; !known { return nil, errors.New("unknown credential type") } @@ -456,7 +425,7 @@ func (rs *RevocationStorage) RevocationDB(credid CredentialTypeIdentifier) (*DB, } if rs.dbs[credid] == nil { var err error - db, err := rs.LoadDB(credid) + db, err := rs.loadDB(credid) if err != nil { return nil, err } @@ -465,18 +434,16 @@ func (rs *RevocationStorage) RevocationDB(credid CredentialTypeIdentifier) (*DB, return rs.dbs[credid], nil } -func (rs *RevocationStorage) revocationUpdateDelayed(credid CredentialTypeIdentifier, db *DB) error { +func (rs *RevocationStorage) updateDelayed(credid CredentialTypeIdentifier, db *DB) error { if db.Updated.Before(time.Now().Add(-5 * time.Minute)) { - if err := rs.RevocationUpdateDB(credid); err != nil { + if err := rs.UpdateDB(credid); err != nil { return err } } return nil } -func (rs *RevocationStorage) SendRevocationIssuanceRecord( - cred CredentialTypeIdentifier, rec *IssuanceRecord, -) error { +func (rs *RevocationStorage) SendIssuanceRecord(cred CredentialTypeIdentifier, rec *IssuanceRecord) error { credtype := rs.conf.CredentialTypes[cred] if credtype == nil { return errors.New("unknown credential type") @@ -518,7 +485,7 @@ func (rs *RevocationStorage) Revoke(credid CredentialTypeIdentifier, key string) return err } - db, err := rs.RevocationDB(credid) + db, err := rs.DB(credid) if err != nil { return err } @@ -536,3 +503,17 @@ func (rs *RevocationStorage) Close() error { rs.dbs = nil return merr.ErrorOrNil() } + +func (rs *RevocationStorage) keystore(issuerid IssuerIdentifier) keystore { + return func(counter uint) (*revocation.PublicKey, error) { + key, err := rs.conf.PublicKey(issuerid, int(counter)) + if err != nil { + return nil, err + } + revkey, err := key.RevocationKey() + if err != nil { + return nil, err + } + return revkey, nil + } +} diff --git a/server/conf.go b/server/conf.go index ef50d6f..d11f4b8 100644 --- a/server/conf.go +++ b/server/conf.go @@ -213,16 +213,16 @@ func (conf *Configuration) verifyRevocation() error { return LogError(errors.Errorf("unknown credential type %s in revocation settings", credid)) } - db, err := conf.IrmaConfiguration.RevocationStorage.RevocationDB(credid) + db, err := conf.IrmaConfiguration.RevocationStorage.DB(credid) if err != nil { return LogError(err) } - db.OnChange(func(record *irma.Record) { + db.OnChange(func(record *irma.RevocationRecord) { transport := irma.NewHTTPTransport("") o := struct{}{} for _, url := range settings.PostURLs { - if err := transport.Post(url+"/-/revocation/records", &o, &[]*irma.Record{record}); err != nil { + if err := transport.Post(url+"/-/revocation/records", &o, &[]*irma.RevocationRecord{record}); err != nil { conf.Logger.Warn("error sending revocation update", err) } } diff --git a/verify.go b/verify.go index 2f8ecef..6e66093 100644 --- a/verify.go +++ b/verify.go @@ -74,7 +74,7 @@ func (pl ProofList) VerifyProofs( configuration *Configuration, context *big.Int, nonce *big.Int, publickeys []*gabi.PublicKey, - revRecords map[CredentialTypeIdentifier][]*Record, + revRecords map[CredentialTypeIdentifier][]*RevocationRecord, isSig bool, ) (bool, error) { // Empty proof lists are allowed (if consistent with the session request, which is checked elsewhere) @@ -145,7 +145,7 @@ func (pl ProofList) VerifyProofs( } // grab last message from accumulator update message set in request - keystore := configuration.RevocationKeystore(typ.Identifier().IssuerIdentifier()) + keystore := configuration.RevocationStorage.keystore(typ.Identifier().IssuerIdentifier()) msg, err := r[len(r)-1].UnmarshalVerify(keystore) if err != nil { return false, err @@ -293,7 +293,7 @@ func (d *Disclosure) VerifyAgainstRequest( issig bool, ) ([][]*DisclosedAttribute, ProofStatus, error) { var required AttributeConDisCon - var revRecords map[CredentialTypeIdentifier][]*Record + var revRecords map[CredentialTypeIdentifier][]*RevocationRecord if request != nil { revRecords = request.Base().RevocationUpdates required = request.Disclosure().Disclose -- GitLab