Commit 955aa14d authored by Sietse Ringers's avatar Sietse Ringers
Browse files

chore: comment and document

parent bb0d9f90
...@@ -23,18 +23,21 @@ const ( ...@@ -23,18 +23,21 @@ const (
LDContextRevocationRequest = "https://irma.app/ld/request/revocation/v1" LDContextRevocationRequest = "https://irma.app/ld/request/revocation/v1"
) )
// BaseRequest contains the context and nonce for an IRMA session. // BaseRequest contains information used by all IRMA session types, such the context and nonce,
// and revocation information.
type BaseRequest struct { type BaseRequest struct {
LDContext string `json:"@context,omitempty"` LDContext string `json:"@context,omitempty"`
// Revocation instructs the client to include nonrevocation zero-knowledge proofs for the // 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"`
// Revocation is set by the requestor to indicate that it requires nonrevocation proofs for the
// specified credential types. // specified credential types.
Revocation []CredentialTypeIdentifier `json:"revocation,omitempty"` Revocation []CredentialTypeIdentifier `json:"revocation,omitempty"`
// RevocationUpdates contains revocation update messages for the client to update its
// Set by the IRMA server during the session // revocation state.
Context *big.Int `json:"context,omitempty"`
Nonce *big.Int `json:"nonce,omitempty"`
ProtocolVersion *ProtocolVersion `json:"protocolVersion,omitempty"`
RevocationUpdates map[CredentialTypeIdentifier][]*RevocationRecord `json:"revocationUpdates,omitempty"` RevocationUpdates map[CredentialTypeIdentifier][]*RevocationRecord `json:"revocationUpdates,omitempty"`
ids *IrmaIdentifierSet // cache for Identifiers() method ids *IrmaIdentifierSet // cache for Identifiers() method
...@@ -229,14 +232,12 @@ func (b *BaseRequest) GetNonce(*atum.Timestamp) *big.Int { ...@@ -229,14 +232,12 @@ func (b *BaseRequest) GetNonce(*atum.Timestamp) *big.Int {
return b.Nonce return b.Nonce
} }
// RequestsRevocation indicates whether or not the requestor requires a nonrevocation proof for
// the given credential type; that is, whether or not it included revocation update messages.
func (b *BaseRequest) RequestsRevocation(id CredentialTypeIdentifier) bool { func (b *BaseRequest) RequestsRevocation(id CredentialTypeIdentifier) bool {
// If the requestor wants us to include a nonrevocation proof,
// it will have sent us the latest revocation update messages
return len(b.RevocationUpdates) > 0 && len(b.RevocationUpdates[id]) > 0 return len(b.RevocationUpdates) > 0 && len(b.RevocationUpdates[id]) > 0
} }
const revocationUpdateCount = 5
// CredentialTypes returns an array of all credential types occuring in this conjunction. // CredentialTypes returns an array of all credential types occuring in this conjunction.
func (c AttributeCon) CredentialTypes() []CredentialTypeIdentifier { func (c AttributeCon) CredentialTypes() []CredentialTypeIdentifier {
var result []CredentialTypeIdentifier var result []CredentialTypeIdentifier
......
...@@ -13,6 +13,9 @@ import ( ...@@ -13,6 +13,9 @@ import (
) )
type ( type (
// RevocationStorage stores and retrieves revocation-related data from and to a SQL database,
// and offers a revocation API for all other irmago code, including a Revoke() method that
// revokes an earlier issued credential.
RevocationStorage struct { RevocationStorage struct {
conf *Configuration conf *Configuration
db revStorage db revStorage
...@@ -24,22 +27,31 @@ type ( ...@@ -24,22 +27,31 @@ type (
client RevocationClient client RevocationClient
} }
// RevocationClient offers an HTTP client to the revocation server endpoints.
RevocationClient struct { RevocationClient struct {
Conf *Configuration Conf *Configuration
} }
// RevocationKeys contains helper functions for retrieving revocation private and public keys
// from an irma.Configuration instance.
RevocationKeys struct { RevocationKeys struct {
Conf *Configuration Conf *Configuration
} }
// RevocationSetting contains revocation settings for a given credential type.
RevocationSetting struct { RevocationSetting struct {
Mode RevocationMode `json:"mode"` Mode RevocationMode `json:"mode"`
PostURLs []string `json:"post_urls" mapstructure:"post_urls"` PostURLs []string `json:"post_urls" mapstructure:"post_urls"`
updated time.Time updated time.Time
} }
// RevocationMode specifies for a given credential type what revocation operations are
// supported, and how the associated data is stored (SQL or memory).
RevocationMode string RevocationMode string
// RevocationRecord contains a signed AccumulatorUpdate and associated information and is used
// by clients, issuers and verifiers to update their revocation state, so that they can create
// and verify nonrevocation proofs and witnesses.
RevocationRecord struct { RevocationRecord struct {
revocation.Record `gorm:"embedded"` revocation.Record `gorm:"embedded"`
PublicKeyIndex uint PublicKeyIndex uint
...@@ -63,13 +75,35 @@ type ( ...@@ -63,13 +75,35 @@ type (
) )
const ( const (
// RevocationModeRequestor is the default revocation mode in which only RevocationRecord instances
// are consumed for issuance or verification. Uses an in-memory store.
RevocationModeRequestor RevocationMode = "" RevocationModeRequestor RevocationMode = ""
RevocationModeProxy RevocationMode = "proxy"
RevocationModeServer RevocationMode = "server" // RevocationModeProxy indicates that this server
// (1) allows fetching of RevocationRecord instances from its database,
// (2) relays all RevocationRecord instances it receives to the URLs configured in the containing
// RevocationSetting struct.
// Requires a SQL server to store and retrieve RevocationRecord instances from.
RevocationModeProxy RevocationMode = "proxy"
// RevocationModeServer indicates that this is the revocation server for a credential type,
// to which the credential type's RevocationServer URL should point.
// IssuanceRecord instances are sent to this server, as well as revocation commands, through
// revocation sessions or through the RevocationStorage.Revoke() method.
// Requires a SQL server to store and retrieve all records from and requires the issuer's
// private key to be accessible, in order to revoke and to sign new revocation records.
RevocationModeServer RevocationMode = "server"
// revocationUpdateCount specifies how many revocation records are attached to session requests
// for the client to update its revocation state.
revocationUpdateCount = 5
) )
// Revocation record methods // Revocation record methods
// EnableRevocation creates an initial accumulator for a given credential type. This function is the
// only way to create such an initial accumulator and it must be called before anyone can use
// revocation for this credential type. Requires the issuer private key.
func (rs *RevocationStorage) EnableRevocation(typ CredentialTypeIdentifier) error { func (rs *RevocationStorage) EnableRevocation(typ CredentialTypeIdentifier) error {
hasRecords, err := rs.db.HasRecords(typ, (*RevocationRecord)(nil)) hasRecords, err := rs.db.HasRecords(typ, (*RevocationRecord)(nil))
if err != nil { if err != nil {
...@@ -103,7 +137,17 @@ func (rs *RevocationStorage) EnableRevocation(typ CredentialTypeIdentifier) erro ...@@ -103,7 +137,17 @@ func (rs *RevocationStorage) EnableRevocation(typ CredentialTypeIdentifier) erro
return nil return nil
} }
// Get returns all records that a client requires to update its revocation state if it is currently // RevocationEnabled returns whether or not revocation is enabled for the given credential type,
// by checking if any revocation record exists in the database.
func (rs *RevocationStorage) RevocationEnabled(typ CredentialTypeIdentifier) (bool, error) {
if rs.sqlMode {
return rs.db.HasRecords(typ, (*RevocationRecord)(nil))
} else {
return rs.memdb.HasRecords(typ), nil
}
}
// RevocationRecords 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 // at the specified index, that is, all records whose end index is greater than or equal to
// the specified index. // the specified index.
func (rs *RevocationStorage) RevocationRecords(typ CredentialTypeIdentifier, index uint64) ([]*RevocationRecord, error) { func (rs *RevocationStorage) RevocationRecords(typ CredentialTypeIdentifier, index uint64) ([]*RevocationRecord, error) {
...@@ -176,16 +220,6 @@ func (rs *RevocationStorage) addRevocationRecord(tx revStorage, record *Revocati ...@@ -176,16 +220,6 @@ func (rs *RevocationStorage) addRevocationRecord(tx revStorage, record *Revocati
return nil return nil
} }
// RevocationEnabled returns whether or not revocation is enabled for the given credential type,
// by checking if any revocation record exists in the database.
func (rs *RevocationStorage) RevocationEnabled(typ CredentialTypeIdentifier) (bool, error) {
if rs.sqlMode {
return rs.db.HasRecords(typ, (*RevocationRecord)(nil))
} else {
return rs.memdb.HasRecords(typ), nil
}
}
// Issuance records // Issuance records
func (rs *RevocationStorage) IssuanceRecordExists(typ CredentialTypeIdentifier, key []byte) (bool, error) { func (rs *RevocationStorage) IssuanceRecordExists(typ CredentialTypeIdentifier, key []byte) (bool, error) {
...@@ -207,18 +241,14 @@ func (rs *RevocationStorage) IssuanceRecord(typ CredentialTypeIdentifier, key [] ...@@ -207,18 +241,14 @@ func (rs *RevocationStorage) IssuanceRecord(typ CredentialTypeIdentifier, key []
// Revocation methods // Revocation methods
// Revoke revokes the credential specified specified by key if found within the current database, // Revoke revokes the credential specified by key if found within the current database,
// by updating its revocation time to now, adding its revocation attribute to the current accumulator, // by updating its revocation time to now, removing its revocation attribute from the current accumulator,
// and updating the revocation database on disk. // and updating the revocation database on disk.
func (rs *RevocationStorage) Revoke(typ CredentialTypeIdentifier, key string) error { func (rs *RevocationStorage) Revoke(typ CredentialTypeIdentifier, key string) error {
sk, err := rs.conf.PrivateKey(typ.IssuerIdentifier()) if rs.getSettings(typ).Mode != RevocationModeServer {
if err != nil { return errors.Errorf("cannot revoke %s", typ)
return err
}
if sk == nil {
return errors.New("private key not found")
} }
rsk, err := sk.RevocationKey() rsk, err := rs.Keys.PrivateKey(typ.IssuerIdentifier())
if err != nil { if err != nil {
return err return err
} }
...@@ -321,7 +351,7 @@ func (rs *RevocationStorage) UpdateDB(typ CredentialTypeIdentifier) error { ...@@ -321,7 +351,7 @@ func (rs *RevocationStorage) UpdateDB(typ CredentialTypeIdentifier) error {
return rs.AddRevocationRecords(records) return rs.AddRevocationRecords(records)
} }
func (rs *RevocationStorage) updateIfOld(typ CredentialTypeIdentifier) error { func (rs *RevocationStorage) UpdateIfOld(typ CredentialTypeIdentifier) error {
if rs.getSettings(typ).updated.Before(time.Now().Add(-5 * time.Minute)) { if rs.getSettings(typ).updated.Before(time.Now().Add(-5 * time.Minute)) {
if err := rs.UpdateDB(typ); err != nil { if err := rs.UpdateDB(typ); err != nil {
return err return err
...@@ -417,7 +447,7 @@ func (rs *RevocationStorage) SetRevocationRecords(b *BaseRequest) error { ...@@ -417,7 +447,7 @@ func (rs *RevocationStorage) SetRevocationRecords(b *BaseRequest) error {
var err error var err error
b.RevocationUpdates = make(map[CredentialTypeIdentifier][]*RevocationRecord, len(b.Revocation)) b.RevocationUpdates = make(map[CredentialTypeIdentifier][]*RevocationRecord, len(b.Revocation))
for _, credid := range b.Revocation { for _, credid := range b.Revocation {
if err = rs.updateIfOld(credid); err != nil { if err = rs.UpdateIfOld(credid); err != nil {
return err return err
} }
b.RevocationUpdates[credid], err = rs.LatestRevocationRecords(credid, revocationUpdateCount) b.RevocationUpdates[credid], err = rs.LatestRevocationRecords(credid, revocationUpdateCount)
......
...@@ -96,6 +96,9 @@ func (s *Server) CancelSession(token string) error { ...@@ -96,6 +96,9 @@ func (s *Server) CancelSession(token string) error {
return s.Server.CancelSession(token) return s.Server.CancelSession(token)
} }
// Revoke revokes the earlier issued credential specified by key. (Can only be used if this server
// is the revocation server for the specified credential type and if the corresponding
// issuer private key is present in the server configuration.)
func Revoke(credid irma.CredentialTypeIdentifier, key string) error { func Revoke(credid irma.CredentialTypeIdentifier, key string) error {
return s.Revoke(credid, key) return s.Revoke(credid, key)
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment