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

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

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