Commit 12492d94 authored by Sietse Ringers's avatar Sietse Ringers

Refer to instances using hash, and provide candidates in request structs

parent fb7b374f
......@@ -2,3 +2,4 @@
.idea/
testdata/storage/*
!testdata/storage/cardemu.xml
errors_*.go
\ No newline at end of file
......@@ -50,6 +50,7 @@ type AttributeList struct {
Ints []*big.Int
strings []TranslatedString
info *CredentialInfo
h string
}
// NewAttributeListFromInts initializes a new AttributeList from a list of bigints.
......@@ -68,12 +69,15 @@ func (al *AttributeList) Info() *CredentialInfo {
}
func (al *AttributeList) hash() string {
bytes := []byte{}
for _, i := range al.Ints {
bytes = append(bytes, i.Bytes()...)
if al.h == "" {
bytes := []byte{}
for _, i := range al.Ints {
bytes = append(bytes, i.Bytes()...)
}
shasum := sha256.Sum256(bytes)
al.h = hex.EncodeToString(shasum[:])
}
shasum := sha256.Sum256(bytes)
return hex.EncodeToString(shasum[:])
return al.h
}
// Strings converts the current instance to human-readable strings.
......
......@@ -26,16 +26,14 @@ type AttributeTypeIdentifier struct {
// CredentialIdentifier identifies a credential instance.
type CredentialIdentifier struct {
Type CredentialTypeIdentifier
Index int
Count int
Type CredentialTypeIdentifier
Hash string
}
// AttributeIdentifier identifies an attribute instance.
type AttributeIdentifier struct {
Type AttributeTypeIdentifier
Index int
Count int
Type AttributeTypeIdentifier
Hash string
}
// IrmaIdentifierSet contains a set (ensured by using map[...]struct{}) of all scheme managers,
......@@ -107,7 +105,7 @@ func (id AttributeTypeIdentifier) IsCredential() bool {
// CredentialIdentifier returns the credential identifier of this attribute.
func (ai *AttributeIdentifier) CredentialIdentifier() CredentialIdentifier {
return CredentialIdentifier{Type: ai.Type.CredentialTypeIdentifier(), Index: ai.Index, Count: ai.Count}
return CredentialIdentifier{Type: ai.Type.CredentialTypeIdentifier(), Hash: ai.Hash}
}
// MarshalText implements encoding.TextMarshaler.
......
......@@ -311,7 +311,8 @@ func (cm *CredentialManager) credentialByHash(hash string) (*credential, int, er
}
func (cm *CredentialManager) credentialByID(id CredentialIdentifier) (*credential, error) {
return cm.credential(id.Type, id.Index)
cred, _, err := cm.credentialByHash(id.Hash)
return cred, err
}
// credential returns the requested credential, or nil if we do not have it.
......@@ -365,17 +366,16 @@ func (cm *CredentialManager) Candidates(disjunction *AttributeDisjunction) []*At
if !cm.ConfigurationStore.Contains(credID) {
continue
}
creds := cm.credentials[credID]
creds := cm.attributes[credID]
count := len(creds)
if count == 0 {
continue
}
for i, cred := range creds {
id := &AttributeIdentifier{Type: attribute, Index: i, Count: count}
for _, attrs := range creds {
id := &AttributeIdentifier{Type: attribute, Hash: attrs.hash()}
if attribute.IsCredential() {
candidates = append(candidates, id)
} else {
attrs := cred.AttributeList()
val := attrs.untranslatedAttribute(attribute)
if val == "" { // This won't handle empty attributes correctly
continue
......@@ -393,19 +393,26 @@ func (cm *CredentialManager) Candidates(disjunction *AttributeDisjunction) []*At
// CheckSatisfiability checks if this credential manager has the required attributes
// to satisfy the specifed disjunction list. If not, the unsatisfiable disjunctions
// are returned.
func (cm *CredentialManager) CheckSatisfiability(disjunctions AttributeDisjunctionList) AttributeDisjunctionList {
missing := make(AttributeDisjunctionList, 0, 5)
for _, disjunction := range disjunctions {
if len(cm.Candidates(disjunction)) == 0 {
func (cm *CredentialManager) CheckSatisfiability(
disjunctions AttributeDisjunctionList,
) ([][]*AttributeIdentifier, AttributeDisjunctionList) {
candidates := [][]*AttributeIdentifier{}
missing := AttributeDisjunctionList{}
for i, disjunction := range disjunctions {
candidates = append(candidates, []*AttributeIdentifier{})
candidates[i] = cm.Candidates(disjunction)
if len(candidates[i]) == 0 {
missing = append(missing, disjunction)
}
}
return missing
return candidates, missing
}
func (cm *CredentialManager) groupCredentials(choice *DisclosureChoice) (map[CredentialIdentifier][]int, error) {
grouped := make(map[CredentialIdentifier][]int)
if choice == nil || choice.Attributes == nil {
return grouped, nil
}
for _, attribute := range choice.Attributes {
identifier := attribute.Type
......
......@@ -17,10 +17,15 @@ import (
type SessionRequest struct {
Context *big.Int `json:"context"`
Nonce *big.Int `json:"nonce"`
Candidates [][]*AttributeIdentifier
choice *DisclosureChoice
identifiers *IrmaIdentifierSet
}
func (sr *SessionRequest) SetCandidates(candidates [][]*AttributeIdentifier) {
sr.Candidates = candidates
}
// DisclosureChoice returns the attributes to be disclosed in this session.
func (sr *SessionRequest) DisclosureChoice() *DisclosureChoice {
return sr.choice
......@@ -113,6 +118,7 @@ type IrmaSession interface {
ToDisclose() AttributeDisjunctionList
DisclosureChoice() *DisclosureChoice
SetDisclosureChoice(choice *DisclosureChoice)
SetCandidates(candidates [][]*AttributeIdentifier)
Identifiers() *IrmaIdentifierSet
}
......
......@@ -193,12 +193,13 @@ func (session *session) start() {
}
}
missing := session.credManager.CheckSatisfiability(session.irmaSession.ToDisclose())
candidates, missing := session.credManager.CheckSatisfiability(session.irmaSession.ToDisclose())
if len(missing) > 0 {
session.Handler.UnsatisfiableRequest(session.Action, missing)
// TODO: session.transport.Delete() on dialog cancel
return
}
session.irmaSession.SetCandidates(candidates)
// Ask for permission to execute the session
callback := PermissionHandler(func(proceed bool, choice *DisclosureChoice) {
......
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