Commit fcac30c3 authored by Sietse Ringers's avatar Sietse Ringers

refactor: revocation attribute bookkeeping in credentials

parent 27162f74
......@@ -48,7 +48,6 @@ type AttributeList struct {
attrMap map[AttributeTypeIdentifier]TranslatedString
info *CredentialInfo
h string
RevocationIndex int `json:"-"`
}
// NewAttributeListFromInts initializes a new AttributeList from a list of bigints.
......@@ -57,9 +56,6 @@ func NewAttributeListFromInts(ints []*big.Int, conf *Configuration) *AttributeLi
Ints: ints,
MetadataAttribute: MetadataFromInt(ints[0], conf),
}
if al.CredentialType().RevocationSupported() {
al.RevocationIndex = al.CredentialType().RevocationIndex
}
return al
}
......
......@@ -196,19 +196,14 @@ func (session *session) handlePostCommitments(commitments *irma.IssueCommitmentM
if !ok {
return nil, session.fail(server.ErrorMalformedInput, "Received invalid issuance commitment")
}
attributes, err := cred.AttributeList(session.conf.IrmaConfiguration, 0x03)
attrs, witness, err := session.computeAttributes(sk, cred)
if err != nil {
return nil, session.fail(server.ErrorIssuanceFailed, err.Error())
}
witness, err := session.issuanceHandleRevocation(cred, attributes, sk)
if err != nil {
return nil, session.fail(server.ErrorRevocation, err.Error())
}
sig, err := issuer.IssueSignature(proof.U, attributes.Ints, witness, commitments.Nonce2)
sig, err := issuer.IssueSignature(proof.U, attrs, witness, commitments.Nonce2)
if err != nil {
return nil, session.fail(server.ErrorIssuanceFailed, err.Error())
}
sig.NonRevocationWitness = witness
sigs = append(sigs, sig)
}
......
......@@ -11,6 +11,7 @@ import (
"github.com/dgrijalva/jwt-go"
"github.com/go-errors/errors"
"github.com/privacybydesign/gabi"
"github.com/privacybydesign/gabi/big"
"github.com/privacybydesign/gabi/revocation"
"github.com/privacybydesign/irmago"
"github.com/privacybydesign/irmago/server"
......@@ -77,9 +78,7 @@ func (session *session) checkCache(message []byte, expectedStatus server.Status)
// Issuance helpers
func (session *session) issuanceHandleRevocation(
cred *irma.CredentialRequest, attributes *irma.AttributeList, sk *gabi.PrivateKey,
) (*revocation.Witness, error) {
func (session *session) computeWitness(sk *gabi.PrivateKey, cred *irma.CredentialRequest) (*revocation.Witness, error) {
id := cred.CredentialTypeID
credtyp := session.conf.IrmaConfiguration.CredentialTypes[id]
if !credtyp.RevocationSupported() || !session.request.Base().RevocationSupported() {
......@@ -87,12 +86,11 @@ func (session *session) issuanceHandleRevocation(
}
// ensure the client always gets an up to date nonrevocation witness
if err := session.conf.IrmaConfiguration.Revocation.SyncDB(id); err != nil {
rs := session.conf.IrmaConfiguration.Revocation
if err := rs.SyncDB(id); err != nil {
return nil, err
}
rs := session.conf.IrmaConfiguration.Revocation
// Fetch latest revocation record, and then extract the current value of the accumulator
// from it to generate the witness from
updates, err := rs.UpdateLatest(id, 0, &cred.KeyCounter)
......@@ -117,19 +115,45 @@ func (session *session) issuanceHandleRevocation(
if err != nil {
return nil, err
}
witness.SignedAccumulator = sig // attach previously selected reocation record to the witness for the client
attributes.Ints[credtyp.RevocationIndex+1] = witness.E
return witness, nil
}
func (session *session) computeAttributes(
sk *gabi.PrivateKey, cred *irma.CredentialRequest,
) ([]*big.Int, *revocation.Witness, error) {
id := cred.CredentialTypeID
witness, err := session.computeWitness(sk, cred)
if err != nil {
return nil, nil, err
}
var nonrevAttr *big.Int
if witness != nil {
nonrevAttr = witness.E
}
attributes, err := cred.AttributeList(session.conf.IrmaConfiguration, 0x03, nonrevAttr)
if err != nil {
return nil, nil, err
}
issrecord := &irma.IssuanceRecord{
CredType: id,
PKCounter: &sk.Counter,
Key: cred.RevocationKey,
Attr: (*irma.RevocationAttribute)(witness.E),
Attr: (*irma.RevocationAttribute)(nonrevAttr),
Issued: time.Now().UnixNano(), // or (floored) cred issuance time?
ValidUntil: attributes.Expiry().UnixNano(),
}
return witness, session.conf.IrmaConfiguration.Revocation.SaveIssuanceRecord(id, issrecord, sk)
if witness != nil {
err = session.conf.IrmaConfiguration.Revocation.SaveIssuanceRecord(id, issrecord, sk)
if err != nil {
return nil, nil, err
}
}
return attributes.Ints, witness, nil
}
func (s *Server) validateIssuanceRequest(request *irma.IssuanceRequest) error {
......
......@@ -556,9 +556,12 @@ func TestRevocationAll(t *testing.T) {
// by editing its irma.Configuration instance
StartIrmaServer(t, false)
defer StopIrmaServer()
credtyp := irmaServerConfiguration.IrmaConfiguration.CredentialTypes[revocationTestCred]
conf := irmaServerConfiguration.IrmaConfiguration
credtyp := conf.CredentialTypes[revocationTestCred]
servers := credtyp.RevocationServers // save it for re-enabling revocation below
credtyp.RevocationServers = nil
revAttr := credtyp.AttributeTypes[len(credtyp.AttributeTypes)-1]
credtyp.AttributeTypes = credtyp.AttributeTypes[:len(credtyp.AttributeTypes)-1]
// Issue non-revocation-aware credential instance
result := requestorSessionHelper(t, irma.NewIssuanceRequest([]*irma.CredentialRequest{{
......@@ -571,6 +574,7 @@ func TestRevocationAll(t *testing.T) {
// Restore revocation setup
credtyp.RevocationServers = servers
credtyp.AttributeTypes = append(credtyp.AttributeTypes, revAttr)
startRevocationServer(t, true)
defer stopRevocationServer()
......
......@@ -911,11 +911,20 @@ func (client *Client) ConstructCredentials(msg []*gabi.IssueSignatureMessage, re
continue
}
sig := msg[i-offset]
attrs, err := request.Credentials[i-offset].AttributeList(client.Configuration, irma.GetMetadataVersion(request.Base().ProtocolVersion))
var nonrevAttr *big.Int
if sig.NonRevocationWitness != nil {
nonrevAttr = sig.NonRevocationWitness.E
}
attrs, err := request.Credentials[i-offset].AttributeList(
client.Configuration,
irma.GetMetadataVersion(request.Base().ProtocolVersion),
nonrevAttr,
)
if err != nil {
return err
}
cred, err := credbuilder.ConstructCredential(sig, attrs.Ints, attrs.RevocationIndex+2)
cred, err := credbuilder.ConstructCredential(sig, attrs.Ints)
if err != nil {
return err
}
......
......@@ -537,7 +537,7 @@ func (dr *DisclosureRequest) Validate() error {
}
func (cr *CredentialRequest) Info(conf *Configuration, metadataVersion byte) (*CredentialInfo, error) {
list, err := cr.AttributeList(conf, metadataVersion)
list, err := cr.AttributeList(conf, metadataVersion, nil)
if err != nil {
return nil, err
}
......@@ -582,11 +582,20 @@ func (cr *CredentialRequest) Validate(conf *Configuration) error {
}
// AttributeList returns the list of attributes from this credential request.
func (cr *CredentialRequest) AttributeList(conf *Configuration, metadataVersion byte) (*AttributeList, error) {
func (cr *CredentialRequest) AttributeList(
conf *Configuration,
metadataVersion byte,
revocationAttr *big.Int,
) (*AttributeList, error) {
if err := cr.Validate(conf); err != nil {
return nil, err
}
credtype := conf.CredentialTypes[cr.CredentialTypeID]
if !credtype.RevocationSupported() && revocationAttr != nil {
return nil, errors.Errorf("cannot specify revocationAttr: credtype %s does not support revocation", cr.CredentialTypeID.String())
}
// Compute metadata attribute
meta := NewMetadataAttribute(metadataVersion)
meta.setKeyCounter(cr.KeyCounter)
......@@ -597,10 +606,19 @@ func (cr *CredentialRequest) AttributeList(conf *Configuration, metadataVersion
}
// Compute other attributes
credtype := conf.CredentialTypes[cr.CredentialTypeID]
attrs := make([]*big.Int, len(credtype.AttributeTypes)+1)
attrs[0] = meta.Int
if credtype.RevocationSupported() {
if revocationAttr != nil {
attrs[credtype.RevocationIndex+1] = revocationAttr
} else {
attrs[credtype.RevocationIndex+1] = bigZero
}
}
for i, attrtype := range credtype.AttributeTypes {
if attrtype.RevocationAttribute {
continue
}
attrs[i+1] = new(big.Int)
if str, present := cr.Attributes[attrtype.ID]; present {
// Set attribute to str << 1 + 1
......
Markdown is supported
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