forked from privacybydesign/irmago
-
Notifications
You must be signed in to change notification settings - Fork 0
/
descriptions.go
230 lines (194 loc) · 7.32 KB
/
descriptions.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
package irma
import (
"encoding/xml"
"fmt"
"path/filepath"
"github.com/go-errors/errors"
"github.com/privacybydesign/irmago/internal/common"
)
// This file contains data types for scheme managers, issuers, credential types
// matching the XML files in irma_configuration.
// SchemeManager describes a scheme manager.
type SchemeManager struct {
ID string `xml:"Id"`
Name TranslatedString `xml:"Name"`
URL string `xml:"Url"`
Contact string `xml:"contact"`
Demo bool `xml:"Demo"` // Decides whether to download private keys
Description TranslatedString
MinimumAppVersion SchemeAppVersion
KeyshareServer string
KeyshareWebsite string
KeyshareAttribute string
TimestampServer string
XMLVersion int `xml:"version,attr"`
XMLName xml.Name `xml:"SchemeManager"`
Status SchemeManagerStatus `xml:"-"`
Valid bool `xml:"-"` // true iff Status == SchemeManagerStatusValid
Timestamp Timestamp
index SchemeManagerIndex
}
type SchemeAppVersion struct {
Android int `xml:"Android"`
IOS int `xml:"iOS"`
}
// Issuer describes an issuer.
type Issuer struct {
ID string `xml:"ID"`
Name TranslatedString `xml:"Name"`
ShortName TranslatedString `xml:"ShortName"`
SchemeManagerID string `xml:"SchemeManager"`
ContactAddress string
ContactEMail string
DeprecatedSince Timestamp
XMLVersion int `xml:"version,attr"`
Valid bool `xml:"-"`
}
// CredentialType is a description of a credential type, specifying (a.o.) its name, issuer, and attributes.
type CredentialType struct {
ID string `xml:"CredentialID"`
Name TranslatedString `xml:"Name"`
ShortName TranslatedString `xml:"ShortName"`
IssuerID string `xml:"IssuerID"`
SchemeManagerID string `xml:"SchemeManager"`
IsSingleton bool `xml:"ShouldBeSingleton"`
DisallowDelete bool `xml:"DisallowDelete"`
Description TranslatedString
AttributeTypes []*AttributeType `xml:"Attributes>Attribute" json:"-"`
RevocationServers []string `xml:"RevocationServers>RevocationServer"`
RevocationUpdateCount uint64
RevocationUpdateSpeed uint64
RevocationIndex int `xml:"-"`
XMLVersion int `xml:"version,attr"`
XMLName xml.Name `xml:"IssueSpecification"`
IssueURL TranslatedString `xml:"IssueURL"`
Valid bool `xml:"-"`
}
// AttributeType is a description of an attribute within a credential type.
type AttributeType struct {
ID string `xml:"id,attr"`
Optional string `xml:"optional,attr" json:",omitempty"`
Name TranslatedString
Description TranslatedString
Index int `xml:"-"`
DisplayIndex *int `xml:"displayIndex,attr" json:",omitempty"`
RevocationAttribute bool `xml:"revocation,attr" json:",omitempty"`
// Taken from containing CredentialType
CredentialTypeID string `xml:"-"`
IssuerID string `xml:"-"`
SchemeManagerID string `xml:"-"`
}
func (ad AttributeType) GetAttributeTypeIdentifier() AttributeTypeIdentifier {
return NewAttributeTypeIdentifier(fmt.Sprintf("%s.%s.%s.%s", ad.SchemeManagerID, ad.IssuerID, ad.CredentialTypeID, ad.ID))
}
func (ad AttributeType) IsOptional() bool {
return ad.Optional == "true"
}
func (ct *CredentialType) RevocationSupported() bool {
return len(ct.RevocationServers) > 0
}
// ContainsAttribute tests whether the specified attribute is contained in this
// credentialtype.
func (ct *CredentialType) ContainsAttribute(ai AttributeTypeIdentifier) bool {
if ai.CredentialTypeIdentifier().String() != ct.Identifier().String() {
return false
}
for _, desc := range ct.AttributeTypes {
if desc.ID == ai.Name() {
return true
}
}
return false
}
// IndexOf returns the index of the specified attribute if present,
// or an error (and -1) if not present.
func (ct CredentialType) IndexOf(ai AttributeTypeIdentifier) (int, error) {
if ai.CredentialTypeIdentifier() != ct.Identifier() {
return -1, errors.New("Wrong credential type")
}
for i, description := range ct.AttributeTypes {
if description.ID == ai.Name() {
return i, nil
}
}
return -1, errors.New("Attribute identifier not found")
}
func (ct CredentialType) AttributeType(ai AttributeTypeIdentifier) *AttributeType {
i, _ := ct.IndexOf(ai)
if i == -1 {
return nil
}
return ct.AttributeTypes[i]
}
// TranslatedString is a map of translated strings.
type TranslatedString map[string]string
type xmlTranslation struct {
XMLName xml.Name
Text string `xml:",chardata"`
}
type xmlTranslatedString struct {
Translations []xmlTranslation `xml:",any"`
}
// MarshalXML implements xml.Marshaler.
func (ts *TranslatedString) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
temp := &xmlTranslatedString{}
for lang, text := range *ts {
temp.Translations = append(temp.Translations,
xmlTranslation{XMLName: xml.Name{Local: lang}, Text: text},
)
}
return e.EncodeElement(temp, start)
}
// UnmarshalXML unmarshals an XML tag containing a string translated to multiple languages,
// for example: <Foo><en>Hello world</en><nl>Hallo wereld</nl></Foo>
// into a TranslatedString: { "en": "Hello world" , "nl": "Hallo wereld" }
func (ts *TranslatedString) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
if map[string]string(*ts) == nil {
*ts = TranslatedString(make(map[string]string))
}
temp := &xmlTranslatedString{}
if err := d.DecodeElement(temp, &start); err != nil {
return err
}
for _, translation := range temp.Translations {
(*ts)[translation.XMLName.Local] = translation.Text
}
return nil
}
// Identifier returns the identifier of the specified credential type.
func (ct *CredentialType) Identifier() CredentialTypeIdentifier {
return NewCredentialTypeIdentifier(ct.SchemeManagerID + "." + ct.IssuerID + "." + ct.ID)
}
// IssuerIdentifier returns the issuer identifier of the specified credential type.
func (ct *CredentialType) IssuerIdentifier() IssuerIdentifier {
return NewIssuerIdentifier(ct.SchemeManagerID + "." + ct.IssuerID)
}
func (ct *CredentialType) SchemeManagerIdentifier() SchemeManagerIdentifier {
return NewSchemeManagerIdentifier(ct.SchemeManagerID)
}
func (ct *CredentialType) Logo(conf *Configuration) string {
path := filepath.Join(conf.Path, ct.SchemeManagerID, ct.IssuerID, "Issues", ct.ID, "logo.png")
exists, err := common.PathExists(path)
if err != nil || !exists {
return ""
}
return path
}
// Identifier returns the identifier of the specified issuer description.
func (id *Issuer) Identifier() IssuerIdentifier {
return NewIssuerIdentifier(id.SchemeManagerID + "." + id.ID)
}
func (id *Issuer) SchemeManagerIdentifier() SchemeManagerIdentifier {
return NewSchemeManagerIdentifier(id.SchemeManagerID)
}
func NewSchemeManager(name string) *SchemeManager {
return &SchemeManager{ID: name, Status: SchemeManagerStatusUnprocessed, Valid: false}
}
// Identifier returns the identifier of the specified scheme manager.
func (sm *SchemeManager) Identifier() SchemeManagerIdentifier {
return NewSchemeManagerIdentifier(sm.ID)
}
// Distributed indicates if this scheme manager uses a keyshare server.
func (sm *SchemeManager) Distributed() bool {
return len(sm.KeyshareServer) > 0
}