credential.go 3.08 KB
Newer Older
1
2
package irmago

Sietse Ringers's avatar
Sietse Ringers committed
3
4
5
import (
	"strings"

6
7
	"math/big"

Sietse Ringers's avatar
Sietse Ringers committed
8
9
	"github.com/mhe/gabi"
)
10

Sietse Ringers's avatar
Sietse Ringers committed
11
// credential represents an IRMA credential, whose zeroth attribute
12
// is always the secret key and the first attribute the metadata attribute.
Sietse Ringers's avatar
Sietse Ringers committed
13
type credential struct {
14
15
	*gabi.Credential
	*MetadataAttribute
16
	attrs *AttributeList
Sietse Ringers's avatar
Sietse Ringers committed
17
18
}

19
20
// CredentialInfo contains all information of an IRMA credential.
type CredentialInfo struct {
Sietse Ringers's avatar
Sietse Ringers committed
21
	ID            string             // e.g., "irma-demo.RU.studentCard"
22
	Index         int                // This is the Index-th credential instance of this type
Sietse Ringers's avatar
Sietse Ringers committed
23
24
	SignedOn      Timestamp          // Unix timestamp
	Expires       Timestamp          // Unix timestamp
25
26
27
	Type          *CredentialType    // Credential information from ConfigurationStore
	Issuer        *Issuer            // Issuer information from ConfigurationStore
	SchemeManager *SchemeManager     // Scheme manager information from ConfigurationStore
Sietse Ringers's avatar
Sietse Ringers committed
28
29
	Attributes    []TranslatedString // Human-readable rendered attributes
	Logo          string             // Path to logo on storage
Sietse Ringers's avatar
Sietse Ringers committed
30
	Hash          string             // SHA256 hash over the attributes
31
32
}

33
34
// A CredentialInfoList is a list of credentials (implements sort.Interface).
type CredentialInfoList []*CredentialInfo
Sietse Ringers's avatar
Sietse Ringers committed
35

36
37
func NewCredentialInfo(ints []*big.Int, store *ConfigurationStore) *CredentialInfo {
	meta := MetadataFromInt(ints[0], store)
38
39
40
41
42
43
44
45
46
	credtype := meta.CredentialType()
	issid := credtype.IssuerIdentifier()

	attrs := make([]TranslatedString, len(credtype.Attributes))
	for i := range credtype.Attributes {
		val := string(ints[i+1].Bytes())
		attrs[i] = TranslatedString(map[string]string{"en": val, "nl": val})
	}

47
	return &CredentialInfo{
48
49
50
51
		ID:            credtype.Identifier().String(),
		SignedOn:      Timestamp(meta.SigningDate()),
		Expires:       Timestamp(meta.Expiry()),
		Type:          credtype,
52
53
		Issuer:        store.Issuers[issid],
		SchemeManager: store.SchemeManagers[issid.SchemeManagerIdentifier()],
54
55
		Attributes:    attrs,
		Logo:          "", // TODO
Sietse Ringers's avatar
Sietse Ringers committed
56
		Hash:          NewAttributeListFromInts(ints, store).hash(),
57
58
59
	}
}

60
func newCredential(gabicred *gabi.Credential, store *ConfigurationStore) (*credential, error) {
61
	meta := MetadataFromInt(gabicred.Attributes[1], store)
62
	cred := &credential{
Sietse Ringers's avatar
Sietse Ringers committed
63
64
65
		Credential:        gabicred,
		MetadataAttribute: meta,
	}
66
67
68
69
70
71
	var err error
	cred.Pk, err = store.PublicKey(meta.CredentialType().IssuerIdentifier(), cred.KeyCounter())
	if err != nil {
		return nil, err
	}
	return cred, nil
72
}
Sietse Ringers's avatar
Sietse Ringers committed
73

74
75
76
77
78
79
80
func (cred *credential) AttributeList() *AttributeList {
	if cred.attrs == nil {
		cred.attrs = NewAttributeListFromInts(cred.Credential.Attributes[1:], cred.MetadataAttribute.store)
	}
	return cred.attrs
}

Sietse Ringers's avatar
Sietse Ringers committed
81
// Len implements sort.Interface.
82
func (cl CredentialInfoList) Len() int {
Sietse Ringers's avatar
Sietse Ringers committed
83
84
85
86
	return len(cl)
}

// Swap implements sort.Interface.
87
func (cl CredentialInfoList) Swap(i, j int) {
Sietse Ringers's avatar
Sietse Ringers committed
88
89
90
91
	cl[i], cl[j] = cl[j], cl[i]
}

// Less implements sort.Interface.
92
func (cl CredentialInfoList) Less(i, j int) bool {
Sietse Ringers's avatar
Sietse Ringers committed
93
94
95
	// TODO Decide on sorting, and if it depends on a TranslatedString, allow language choosing
	return strings.Compare(cl[i].Type.Name["en"], cl[j].Type.Name["en"]) > 0
}