credential.go 3.06 KB
Newer Older
1
2
package irmago

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

6
7
	"math/big"

8
9
	"fmt"

Sietse Ringers's avatar
Sietse Ringers committed
10
11
	"github.com/mhe/gabi"
)
12

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

21
22
// CredentialInfo contains all information of an IRMA credential.
type CredentialInfo struct {
23
24
25
26
27
28
29
30
31
32
	CredentialTypeID string             // e.g., "irma-demo.RU.studentCard"
	Name             string             // e.g., "studentCard"
	IssuerID         string             // e.g., "RU"
	SchemeManagerID  string             // e.g., "irma-demo"
	Index            int                // This is the Index-th credential instance of this type
	SignedOn         Timestamp          // Unix timestamp
	Expires          Timestamp          // Unix timestamp
	Attributes       []TranslatedString // Human-readable rendered attributes
	Logo             string             // Path to logo on storage
	Hash            string              // SHA256 hash over the attributes
33
34
}

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

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

	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})
	}

48
49
50
51
52
53
54
55
56
	path := fmt.Sprintf("%s/%s/%s/Issues/%s/logo.png", store.path, credtype.SchemeManagerID, credtype.IssuerID, credtype.ID)
	exists, err := PathExists(path)
	if err != nil {
		return nil
	}
	if !exists {
		path = ""
	}

57
	return &CredentialInfo{
58
59
60
61
62
63
		CredentialTypeID: credtype.Identifier().String(),
		SignedOn:         Timestamp(meta.SigningDate()),
		Expires:          Timestamp(meta.Expiry()),
		Attributes:       attrs,
		Logo:             path,
		Hash:             NewAttributeListFromInts(ints, store).hash(),
64
65
66
	}
}

67
func newCredential(gabicred *gabi.Credential, store *ConfigurationStore) (*credential, error) {
68
	meta := MetadataFromInt(gabicred.Attributes[1], store)
69
	cred := &credential{
Sietse Ringers's avatar
Sietse Ringers committed
70
71
72
		Credential:        gabicred,
		MetadataAttribute: meta,
	}
73
74
75
76
77
78
	var err error
	cred.Pk, err = store.PublicKey(meta.CredentialType().IssuerIdentifier(), cred.KeyCounter())
	if err != nil {
		return nil, err
	}
	return cred, nil
79
}
Sietse Ringers's avatar
Sietse Ringers committed
80

81
82
83
84
85
86
87
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
88
// Len implements sort.Interface.
89
func (cl CredentialInfoList) Len() int {
Sietse Ringers's avatar
Sietse Ringers committed
90
91
92
93
	return len(cl)
}

// Swap implements sort.Interface.
94
func (cl CredentialInfoList) Swap(i, j int) {
Sietse Ringers's avatar
Sietse Ringers committed
95
96
97
98
	cl[i], cl[j] = cl[j], cl[i]
}

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