requests.go 28.9 KB
Newer Older
1
package irma
2
3

import (
4
	"encoding/json"
5
	"encoding/xml"
6
	"fmt"
7
	"io/ioutil"
8
9
10
	"strconv"
	"time"

11
	"github.com/bwesterb/go-atum"
12
	"github.com/dgrijalva/jwt-go"
Sietse Ringers's avatar
Sietse Ringers committed
13
	"github.com/go-errors/errors"
14
	"github.com/privacybydesign/gabi"
15
	"github.com/privacybydesign/gabi/big"
16
	"github.com/privacybydesign/gabi/revocation"
17
	"github.com/privacybydesign/irmago/internal/fs"
Sietse Ringers's avatar
Sietse Ringers committed
18
)
19

20
21
22
23
const (
	LDContextDisclosureRequest = "https://irma.app/ld/request/disclosure/v2"
	LDContextSignatureRequest  = "https://irma.app/ld/request/signature/v2"
	LDContextIssuanceRequest   = "https://irma.app/ld/request/issuance/v2"
24
	LDContextRevocationRequest = "https://irma.app/ld/request/revocation/v1"
25
26
)

27
28
// BaseRequest contains the context and nonce for an IRMA session.
type BaseRequest struct {
29
	LDContext string `json:"@context,omitempty"`
30

31
32
	// Revocation instructs the client to include nonrevocation zero-knowledge proofs for the
	// specified credential types.
33
	Revocation []CredentialTypeIdentifier `json:"revocation,omitempty"`
34
35

	// Set by the IRMA server during the session
36
37
38
39
	Context           *big.Int                                          `json:"context,omitempty"`
	Nonce             *big.Int                                          `json:"nonce,omitempty"`
	ProtocolVersion   *ProtocolVersion                                  `json:"protocolVersion,omitempty"`
	RevocationUpdates map[CredentialTypeIdentifier][]*revocation.Record `json:"revocationUpdates,omitempty"`
40

41
42
43
44
	ids *IrmaIdentifierSet // cache for Identifiers() method

	legacy bool   // Whether or not this was deserialized from a legacy (pre-condiscon) request
	Type   Action `json:"type,omitempty"` // Session type, only used in legacy code
45
46

	ClientReturnURL string `json:"clientReturnUrl,omitempty"` // URL to proceed to when IRMA session is completed
Sietse Ringers's avatar
Sietse Ringers committed
47
48
}

49
50
// An AttributeCon is only satisfied if all of its containing attribute requests are satisfied.
type AttributeCon []AttributeRequest
51

52
53
// An AttributeDisCon is satisfied if at least one of its containing AttributeCon is satisfied.
type AttributeDisCon []AttributeCon
54

55
56
// AttributeConDisCon is only satisfied if all of the containing AttributeDisCon are satisfied.
type AttributeConDisCon []AttributeDisCon
57

58
59
// A DisclosureRequest is a request to disclose certain attributes. Construct new instances using
// NewDisclosureRequest().
60
type DisclosureRequest struct {
61
	BaseRequest
62

63
64
	Disclose AttributeConDisCon       `json:"disclose,omitempty"`
	Labels   map[int]TranslatedString `json:"labels,omitempty"`
65
66
}

67
68
// A SignatureRequest is a a request to sign a message with certain attributes. Construct new
// instances using NewSignatureRequest().
69
type SignatureRequest struct {
70
	DisclosureRequest
71
	Message string `json:"message"`
72
73
}

Sietse Ringers's avatar
Sietse Ringers committed
74
// An IssuanceRequest is a request to issue certain credentials,
75
76
// optionally also asking for certain attributes to be simultaneously disclosed. Construct new
// instances using NewIssuanceRequest().
77
type IssuanceRequest struct {
78
	DisclosureRequest
79
	Credentials []*CredentialRequest `json:"credentials"`
Tomas's avatar
Tomas committed
80
81
82

	// Derived data
	CredentialInfoList        CredentialInfoList `json:",omitempty"`
83
	RemovalCredentialInfoList CredentialInfoList `json:",omitempty"`
84
85
}

Sietse Ringers's avatar
Sietse Ringers committed
86
87
// A CredentialRequest contains the attributes and metadata of a credential
// that will be issued in an IssuanceRequest.
88
type CredentialRequest struct {
89
90
	Validity         *Timestamp               `json:"validity,omitempty"`
	KeyCounter       int                      `json:"keyCounter,omitempty"`
91
92
	CredentialTypeID CredentialTypeIdentifier `json:"credential"`
	Attributes       map[string]string        `json:"attributes"`
93
	RevocationKey    string                   `json:"revocationKey,omitempty"`
Sietse Ringers's avatar
Sietse Ringers committed
94
95
}

96
97
98
99
// SessionRequest instances contain all information the irmaclient needs to perform an IRMA session.
type SessionRequest interface {
	Validator
	Base() *BaseRequest
100
	GetNonce(timestamp *atum.Timestamp) *big.Int
101
102
103
	Disclosure() *DisclosureRequest
	Identifiers() *IrmaIdentifierSet
	Action() Action
104
	Legacy() (SessionRequest, error)
105
106
107
108
109
}

// Timestamp is a time.Time that marshals to Unix timestamps.
type Timestamp time.Time

Sietse Ringers's avatar
Sietse Ringers committed
110
111
112
113
114
115
116
// ServerJwt contains standard JWT fields.
type ServerJwt struct {
	Type       string    `json:"sub"`
	ServerName string    `json:"iss"`
	IssuedAt   Timestamp `json:"iat"`
}

117
118
// RequestorBaseRequest contains fields present in all RequestorRequest types
// with which the requestor configures an IRMA session.
119
type RequestorBaseRequest struct {
Sietse Ringers's avatar
Sietse Ringers committed
120
121
	ResultJwtValidity int    `json:"validity,omitempty"`    // Validity of session result JWT in seconds
	ClientTimeout     int    `json:"timeout,omitempty"`     // Wait this many seconds for the IRMA app to connect before the session times out
122
	CallbackURL       string `json:"callbackUrl,omitempty"` // URL to post session result to
123
124
}

125
126
// RequestorRequest is the message with which requestors start an IRMA session. It contains a
// SessionRequest instance for the irmaclient along with extra fields in a RequestorBaseRequest.
127
128
129
type RequestorRequest interface {
	Validator
	SessionRequest() SessionRequest
130
	Base() RequestorBaseRequest
131
132
}

Sietse Ringers's avatar
Sietse Ringers committed
133
134
// A ServiceProviderRequest contains a disclosure request.
type ServiceProviderRequest struct {
135
	RequestorBaseRequest
Sietse Ringers's avatar
Sietse Ringers committed
136
137
138
139
140
	Request *DisclosureRequest `json:"request"`
}

// A SignatureRequestorRequest contains a signing request.
type SignatureRequestorRequest struct {
141
	RequestorBaseRequest
Sietse Ringers's avatar
Sietse Ringers committed
142
143
144
145
146
	Request *SignatureRequest `json:"request"`
}

// An IdentityProviderRequest contains an issuance request.
type IdentityProviderRequest struct {
147
	RequestorBaseRequest
Sietse Ringers's avatar
Sietse Ringers committed
148
149
150
151
152
153
	Request *IssuanceRequest `json:"request"`
}

// ServiceProviderJwt is a requestor JWT for a disclosure session.
type ServiceProviderJwt struct {
	ServerJwt
154
	Request *ServiceProviderRequest `json:"sprequest"`
Sietse Ringers's avatar
Sietse Ringers committed
155
156
157
158
159
}

// SignatureRequestorJwt is a requestor JWT for a signing session.
type SignatureRequestorJwt struct {
	ServerJwt
160
	Request *SignatureRequestorRequest `json:"absrequest"`
Sietse Ringers's avatar
Sietse Ringers committed
161
162
163
164
165
}

// IdentityProviderJwt is a requestor JWT for issuance session.
type IdentityProviderJwt struct {
	ServerJwt
166
167
168
	Request *IdentityProviderRequest `json:"iprequest"`
}

169
170
171
172
173
type RevocationJwt struct {
	ServerJwt
	Request *RevocationRequest `json:"revrequest"`
}

174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
// A RequestorJwt contains an IRMA session object.
type RequestorJwt interface {
	Action() Action
	RequestorRequest() RequestorRequest
	SessionRequest() SessionRequest
	Requestor() string
	Valid() error
	Sign(jwt.SigningMethod, interface{}) (string, error)
}

// A DisclosureChoice contains the attributes chosen to be disclosed.
type DisclosureChoice struct {
	Attributes [][]*AttributeIdentifier
}

// An AttributeRequest asks for an instance of an attribute type, possibly requiring it to have
// a specified value, in a session request.
type AttributeRequest struct {
192
193
194
	Type    AttributeTypeIdentifier `json:"type"`
	Value   *string                 `json:"value,omitempty"`
	NotNull bool                    `json:"notNull,omitempty"`
195
196
}

197
198
199
200
201
202
203
204
205
206
207
208
209
type RevocationRequest struct {
	LDContext      string                   `json:"@context,omitempty"`
	CredentialType CredentialTypeIdentifier `json:"type"`
	Key            string                   `json:"key"`
}

func (r *RevocationRequest) Validate() error {
	if r.LDContext == LDContextRevocationRequest {
		return errors.New("not a revocation request")
	}
	return nil
}

210
211
212
213
214
var (
	bigZero = big.NewInt(0)
	bigOne  = big.NewInt(1)
)

215
216
217
218
func (b *BaseRequest) Legacy() bool {
	return b.legacy
}

219
220
221
func (b *BaseRequest) GetContext() *big.Int {
	if b.Context == nil {
		return bigOne
222
	}
223
	return b.Context
224
225
}

226
func (b *BaseRequest) GetNonce(*atum.Timestamp) *big.Int {
227
228
	if b.Nonce == nil {
		return bigZero
229
	}
230
	return b.Nonce
231
232
}

233
234
235
236
237
238
func (b *BaseRequest) RequestsRevocation(id CredentialTypeIdentifier) bool {
	// If the requestor wants us to include a nonrevocation proof,
	// it will have sent us the latest revocation update messages
	return len(b.RevocationUpdates) > 0 && len(b.RevocationUpdates[id]) > 0
}

239
240
const revocationUpdateCount = 5

241
242
243
// CredentialTypes returns an array of all credential types occuring in this conjunction.
func (c AttributeCon) CredentialTypes() []CredentialTypeIdentifier {
	var result []CredentialTypeIdentifier
244

245
	for _, attr := range c {
246
247
248
249
		typ := attr.Type.CredentialTypeIdentifier()
		if len(result) == 0 || result[len(result)-1] != typ {
			result = append(result, typ)
		}
250
	}
251

252
	return result
253
254
}

255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
func (c AttributeCon) Validate() error {
	// Unlike AttributeDisCon, we don't have to check here that the current instance is of length 0,
	// as that is actually a valid conjunction: one that specifies that the containing disjunction
	// is optional.

	credtypes := map[CredentialTypeIdentifier]struct{}{}
	var last CredentialTypeIdentifier
	for _, attr := range c {
		typ := attr.Type.CredentialTypeIdentifier()
		if _, contains := credtypes[typ]; contains && last != typ {
			return errors.New("Within inner conjunctions, attributes from the same credential type must be adjacent")
		}
		last = typ
		credtypes[typ] = struct{}{}
	}
	return nil
}

273
274
// AttributeRequest synonym with default JSON (un)marshaler
type jsonAttributeRequest AttributeRequest
275

276
277
func (ar *AttributeRequest) UnmarshalJSON(bts []byte) error {
	var s AttributeTypeIdentifier
278

279
280
281
	// first try to parse as JSON string into s
	if err := json.Unmarshal(bts, &s); err == nil {
		*ar = AttributeRequest{Type: s}
282
283
284
		return nil
	}

285
286
	return json.Unmarshal(bts, (*jsonAttributeRequest)(ar))
}
287

288
func (ar *AttributeRequest) MarshalJSON() ([]byte, error) {
289
	if !ar.NotNull && ar.Value == nil {
290
		return json.Marshal(ar.Type)
291
	}
292
	return json.Marshal((*jsonAttributeRequest)(ar))
293
294
}

295
// Satisfy indicates whether the given attribute type and value satisfies this AttributeRequest.
296
func (ar *AttributeRequest) Satisfy(attr AttributeTypeIdentifier, val *string) bool {
297
	return ar.Type == attr &&
298
		(!ar.NotNull || val != nil) &&
299
		(ar.Value == nil || (val != nil && *ar.Value == *val))
Sietse Ringers's avatar
Sietse Ringers committed
300
301
}

302
303
// Satisfy returns if each of the attributes specified by proofs and indices satisfies each of
// the contained AttributeRequests's. If so it also returns a list of the disclosed attribute values.
304
func (c AttributeCon) Satisfy(proofs gabi.ProofList, indices []*DisclosedAttributeIndex, conf *Configuration) (bool, []*DisclosedAttribute, error) {
305
	if len(indices) < len(c) {
306
		return false, nil, nil
307
308
	}
	attrs := make([]*DisclosedAttribute, 0, len(c))
309
310
311
	if len(c) == 0 {
		return true, attrs, nil
	}
312
313
314
315
316

	for j := range c {
		index := indices[j]
		attr, val, err := extractAttribute(proofs, index, conf)
		if err != nil {
317
			return false, nil, err
318
319
		}
		if !c[j].Satisfy(attr.Identifier, val) {
320
			return false, nil, nil
321
322
323
		}
		attrs = append(attrs, attr)
	}
324
	return true, attrs, nil
325
326
}

327
328
329
330
331
332
333
334
335
336
337
338
339
func (dc AttributeDisCon) Validate() error {
	if len(dc) == 0 {
		return errors.New("Empty disjunction")
	}
	var err error
	for _, con := range dc {
		if err = con.Validate(); err != nil {
			return err
		}
	}
	return nil
}

340
341
// Satisfy returns true if the attributes specified by proofs and indices satisfies any one of the
// contained AttributeCon's. If so it also returns a list of the disclosed attribute values.
342
func (dc AttributeDisCon) Satisfy(proofs gabi.ProofList, indices []*DisclosedAttributeIndex, conf *Configuration) (bool, []*DisclosedAttribute, error) {
343
	for _, con := range dc {
344
345
346
		satisfied, attrs, err := con.Satisfy(proofs, indices, conf)
		if satisfied || err != nil {
			return true, attrs, err
347
348
		}
	}
349
	return false, nil, nil
350
351
}

352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
func (cdc AttributeConDisCon) Validate(conf *Configuration) error {
	for _, discon := range cdc {
		for _, con := range discon {
			var nonsingleton *CredentialTypeIdentifier
			for _, attr := range con {
				typ := attr.Type.CredentialTypeIdentifier()
				if !conf.CredentialTypes[typ].IsSingleton {
					if nonsingleton != nil && *nonsingleton != typ {
						return errors.New("Multiple non-singletons within one inner conjunction are not allowed")
					} else {
						nonsingleton = &typ
					}
				}
			}
		}
	}
	return nil
}

371
372
// Satisfy returns true if each of the contained AttributeDisCon is satisfied by the specified disclosure.
// If so it also returns the disclosed attributes.
373
374
375
376
377
378
379
380
func (cdc AttributeConDisCon) Satisfy(disclosure *Disclosure, conf *Configuration) (bool, [][]*DisclosedAttribute, error) {
	if len(disclosure.Indices) < len(cdc) {
		return false, nil, nil
	}
	list := make([][]*DisclosedAttribute, len(cdc))
	complete := true

	for i, discon := range cdc {
381
		satisfied, attrs, err := discon.Satisfy(disclosure.Proofs, disclosure.Indices[i], conf)
382
383
384
		if err != nil {
			return false, nil, err
		}
385
		if satisfied {
386
387
388
389
390
391
392
393
			list[i] = attrs
		} else {
			complete = false
			list[i] = nil
		}
	}

	return complete, list, nil
394
395
}

396
397
398
399
400
401
402
403
404
405
406
407
func (cdc AttributeConDisCon) Iterate(f func(attr *AttributeRequest) error) error {
	var err error
	for _, discon := range cdc {
		for _, con := range discon {
			for _, attr := range con {
				if err = f(&attr); err != nil {
					return err
				}
			}
		}
	}
	return nil
408
409
}

410
411
412
413
414
415
416
func (dr *DisclosureRequest) AddSingle(attr AttributeTypeIdentifier, value *string, label TranslatedString) {
	dr.Disclose = append(dr.Disclose, AttributeDisCon{AttributeCon{{Type: attr, Value: value}}})
	dr.Labels[len(dr.Disclose)-1] = label
}

func NewDisclosureRequest(attrs ...AttributeTypeIdentifier) *DisclosureRequest {
	request := &DisclosureRequest{
417
		BaseRequest: BaseRequest{LDContext: LDContextDisclosureRequest},
418
419
420
421
422
423
424
425
426
427
		Labels:      map[int]TranslatedString{},
	}
	for _, attr := range attrs {
		request.AddSingle(attr, nil, nil)
	}
	return request
}

func NewSignatureRequest(message string, attrs ...AttributeTypeIdentifier) *SignatureRequest {
	dr := NewDisclosureRequest(attrs...)
428
	dr.LDContext = LDContextSignatureRequest
429
	return &SignatureRequest{
430
		DisclosureRequest: *dr,
431
432
433
434
435
436
		Message:           message,
	}
}

func NewIssuanceRequest(creds []*CredentialRequest, attrs ...AttributeTypeIdentifier) *IssuanceRequest {
	dr := NewDisclosureRequest(attrs...)
437
	dr.LDContext = LDContextIssuanceRequest
438
	return &IssuanceRequest{
439
		DisclosureRequest: *dr,
440
441
442
443
444
445
446
447
		Credentials:       creds,
	}
}

func (dr *DisclosureRequest) Disclosure() *DisclosureRequest {
	return dr
}

448
449
450
451
452
453
func (dr *DisclosureRequest) identifiers() *IrmaIdentifierSet {
	ids := &IrmaIdentifierSet{
		SchemeManagers:  map[SchemeManagerIdentifier]struct{}{},
		Issuers:         map[IssuerIdentifier]struct{}{},
		CredentialTypes: map[CredentialTypeIdentifier]struct{}{},
		PublicKeys:      map[IssuerIdentifier][]int{},
Leon's avatar
Leon committed
454
		AttributeTypes:  map[AttributeTypeIdentifier]struct{}{},
455
456
457
458
459
460
461
	}

	_ = dr.Disclose.Iterate(func(a *AttributeRequest) error {
		attr := a.Type
		ids.SchemeManagers[attr.CredentialTypeIdentifier().IssuerIdentifier().SchemeManagerIdentifier()] = struct{}{}
		ids.Issuers[attr.CredentialTypeIdentifier().IssuerIdentifier()] = struct{}{}
		ids.CredentialTypes[attr.CredentialTypeIdentifier()] = struct{}{}
Leon's avatar
Leon committed
462
		ids.AttributeTypes[attr] = struct{}{}
463
464
465
466
467
468
		return nil
	})

	return ids
}

469
func (dr *DisclosureRequest) Identifiers() *IrmaIdentifierSet {
470
	if dr.ids == nil {
471
		dr.ids = dr.identifiers()
472
	}
473
	return dr.ids
474
475
476
477
478
479
480
481
482
}

func (dr *DisclosureRequest) Base() *BaseRequest {
	return &dr.BaseRequest
}

func (dr *DisclosureRequest) Action() Action { return ActionDisclosing }

func (dr *DisclosureRequest) Validate() error {
483
	if dr.LDContext != LDContextDisclosureRequest {
484
485
486
487
488
		return errors.New("Not a disclosure request")
	}
	if len(dr.Disclose) == 0 {
		return errors.New("Disclosure request had no attributes")
	}
489
	var err error
490
	for _, discon := range dr.Disclose {
491
492
		if err = discon.Validate(); err != nil {
			return err
493
494
		}
	}
495
496
	return nil
}
Sietse Ringers's avatar
Sietse Ringers committed
497

498
499
func (cr *CredentialRequest) Info(conf *Configuration, metadataVersion byte) (*CredentialInfo, error) {
	list, err := cr.AttributeList(conf, metadataVersion)
500
501
502
	if err != nil {
		return nil, err
	}
503
	return NewCredentialInfo(list.Ints, conf), nil
504
505
}

506
507
508
509
// Validate checks that this credential request is consistent with the specified Configuration:
// the credential type is known, all required attributes are present and no unknown attributes
// are given.
func (cr *CredentialRequest) Validate(conf *Configuration) error {
510
	credtype := conf.CredentialTypes[cr.CredentialTypeID]
Sietse Ringers's avatar
Sietse Ringers committed
511
	if credtype == nil {
512
		return errors.New("Credential request of unknown credential type")
Sietse Ringers's avatar
Sietse Ringers committed
513
	}
514
515
516
517
518

	// Check that there are no attributes in the credential request that aren't
	// in the credential descriptor.
	for crName := range cr.Attributes {
		found := false
519
		for _, ad := range credtype.AttributeTypes {
520
521
522
523
524
525
			if ad.ID == crName {
				found = true
				break
			}
		}
		if !found {
526
			return errors.New("Credential request contains unknown attribute")
527
		}
Sietse Ringers's avatar
Sietse Ringers committed
528
529
	}

530
	for _, attrtype := range credtype.AttributeTypes {
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
		if _, present := cr.Attributes[attrtype.ID]; !present && attrtype.Optional != "true" {
			return errors.New("Required attribute not present in credential request")
		}
	}

	return nil
}

// AttributeList returns the list of attributes from this credential request.
func (cr *CredentialRequest) AttributeList(conf *Configuration, metadataVersion byte) (*AttributeList, error) {
	if err := cr.Validate(conf); err != nil {
		return nil, err
	}

	// Compute metadata attribute
	meta := NewMetadataAttribute(metadataVersion)
	meta.setKeyCounter(cr.KeyCounter)
	meta.setCredentialTypeIdentifier(cr.CredentialTypeID.String())
	meta.setSigningDate()
	if err := meta.setExpiryDate(cr.Validity); err != nil {
		return nil, err
	}

	// Compute other attributes
555
	credtype := conf.CredentialTypes[cr.CredentialTypeID]
556
	attrs := make([]*big.Int, len(credtype.AttributeTypes)+1)
Sietse Ringers's avatar
Sietse Ringers committed
557
	attrs[0] = meta.Int
558
	for i, attrtype := range credtype.AttributeTypes {
559
		attrs[i+1] = new(big.Int)
Sietse Ringers's avatar
Sietse Ringers committed
560
		if str, present := cr.Attributes[attrtype.ID]; present {
561
			// Set attribute to str << 1 + 1
562
			attrs[i+1].SetBytes([]byte(str))
563
564
565
566
			if meta.Version() >= 0x03 {
				attrs[i+1].Lsh(attrs[i+1], 1)             // attr <<= 1
				attrs[i+1].Add(attrs[i+1], big.NewInt(1)) // attr += 1
			}
Sietse Ringers's avatar
Sietse Ringers committed
567
568
569
		}
	}

570
	return NewAttributeListFromInts(attrs, conf), nil
Sietse Ringers's avatar
Sietse Ringers committed
571
572
}

Sietse Ringers's avatar
Sietse Ringers committed
573
func (ir *IssuanceRequest) Identifiers() *IrmaIdentifierSet {
574
575
	if ir.ids == nil {
		ir.ids = &IrmaIdentifierSet{
576
577
578
			SchemeManagers:  map[SchemeManagerIdentifier]struct{}{},
			Issuers:         map[IssuerIdentifier]struct{}{},
			CredentialTypes: map[CredentialTypeIdentifier]struct{}{},
Leon's avatar
Leon committed
579
			AttributeTypes:  map[AttributeTypeIdentifier]struct{}{},
580
			PublicKeys:      map[IssuerIdentifier][]int{},
Sietse Ringers's avatar
Sietse Ringers committed
581
582
		}

Sietse Ringers's avatar
Sietse Ringers committed
583
		for _, credreq := range ir.Credentials {
Sietse Ringers's avatar
Sietse Ringers committed
584
			issuer := credreq.CredentialTypeID.IssuerIdentifier()
585
586
			ir.ids.SchemeManagers[issuer.SchemeManagerIdentifier()] = struct{}{}
			ir.ids.Issuers[issuer] = struct{}{}
Leon's avatar
Leon committed
587
588
589
590
591
			credID := credreq.CredentialTypeID
			ir.ids.CredentialTypes[credID] = struct{}{}
			for attr, _ := range credreq.Attributes { // this is kind of ugly
				ir.ids.AttributeTypes[NewAttributeTypeIdentifier(credID.String()+"."+attr)] = struct{}{}
			}
592
593
			if ir.ids.PublicKeys[issuer] == nil {
				ir.ids.PublicKeys[issuer] = []int{}
594
			}
595
			ir.ids.PublicKeys[issuer] = append(ir.ids.PublicKeys[issuer], credreq.KeyCounter)
596
597
		}

598
		ir.ids.join(ir.DisclosureRequest.identifiers())
Sietse Ringers's avatar
Sietse Ringers committed
599
	}
600
	return ir.ids
Sietse Ringers's avatar
Sietse Ringers committed
601
602
}

Tomas's avatar
Tomas committed
603
604
605
606
607
608
609
610
611
612
613
614
615
func (ir *IssuanceRequest) GetCredentialInfoList(conf *Configuration, version *ProtocolVersion) (CredentialInfoList, error) {
	if ir.CredentialInfoList == nil {
		for _, credreq := range ir.Credentials {
			info, err := credreq.Info(conf, GetMetadataVersion(version))
			if err != nil {
				return nil, err
			}
			ir.CredentialInfoList = append(ir.CredentialInfoList, info)
		}
	}
	return ir.CredentialInfoList, nil
}

616
617
func (ir *IssuanceRequest) Action() Action { return ActionIssuing }

618
func (ir *IssuanceRequest) Validate() error {
619
	if ir.LDContext != LDContextIssuanceRequest {
620
621
622
623
624
		return errors.New("Not an issuance request")
	}
	if len(ir.Credentials) == 0 {
		return errors.New("Empty issuance request")
	}
625
	for _, cred := range ir.Credentials {
626
		if cred.Validity != nil && cred.Validity.Floor().Before(Timestamp(time.Now())) {
627
628
629
			return errors.New("Expired credential request")
		}
	}
630
631
632
633
634
635
	var err error
	for _, discon := range ir.Disclose {
		if err = discon.Validate(); err != nil {
			return err
		}
	}
636
637
638
	return nil
}

Sietse Ringers's avatar
Sietse Ringers committed
639
640
// GetNonce returns the nonce of this signature session
// (with the message already hashed into it).
641
642
func (sr *SignatureRequest) GetNonce(timestamp *atum.Timestamp) *big.Int {
	return ASN1ConvertSignatureNonce(sr.Message, sr.BaseRequest.GetNonce(nil), timestamp)
643
644
}

645
func (sr *SignatureRequest) SignatureFromMessage(message interface{}, timestamp *atum.Timestamp) (*SignedMessage, error) {
646
	signature, ok := message.(*Disclosure)
647
648
649
650
651

	if !ok {
		return nil, errors.Errorf("Type assertion failed")
	}

652
653
654
655
	nonce := sr.Nonce
	if nonce == nil {
		nonce = bigZero
	}
656
	return &SignedMessage{
657
		LDContext: LDContextSignedMessage,
658
		Signature: signature.Proofs,
659
		Indices:   signature.Indices,
660
661
		Nonce:     nonce,
		Context:   sr.GetContext(),
662
		Message:   sr.Message,
663
		Timestamp: timestamp,
664
665
666
	}, nil
}

667
668
func (sr *SignatureRequest) Action() Action { return ActionSigning }

669
func (sr *SignatureRequest) Validate() error {
670
	if sr.LDContext != LDContextSignatureRequest {
671
672
673
674
675
		return errors.New("Not a signature request")
	}
	if sr.Message == "" {
		return errors.New("Signature request had empty message")
	}
676
677
	if len(sr.Disclose) == 0 {
		return errors.New("Signature request had no attributes")
678
	}
679
	var err error
680
	for _, discon := range sr.Disclose {
681
682
		if err = discon.Validate(); err != nil {
			return err
683
684
		}
	}
685
686
687
	return nil
}

688
689
690
691
692
// Check if Timestamp is before other Timestamp. Used for checking expiry of attributes
func (t Timestamp) Before(u Timestamp) bool {
	return time.Time(t).Before(time.Time(u))
}

693
694
695
696
func (t Timestamp) After(u Timestamp) bool {
	return time.Time(t).After(time.Time(u))
}

697
698
699
700
701
// To check whether Timestamp is uninitialized
func (t Timestamp) IsZero() bool {
	return time.Time(t).IsZero()
}

702
703
704
705
706
707
708
709
710
711
712
713
714
func (t *Timestamp) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	return e.EncodeElement(t.String(), start)
}

func (t *Timestamp) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var ts int64
	if err := d.DecodeElement(&ts, &start); err != nil {
		return err
	}
	*t = Timestamp(time.Unix(ts, 0))
	return nil
}

715
716
// MarshalJSON marshals a timestamp.
func (t *Timestamp) MarshalJSON() ([]byte, error) {
717
	return []byte(t.String()), nil
718
719
720
721
722
723
724
725
726
727
728
}

// UnmarshalJSON unmarshals a timestamp.
func (t *Timestamp) UnmarshalJSON(b []byte) error {
	ts, err := strconv.Atoi(string(b))
	if err != nil {
		return err
	}
	*t = Timestamp(time.Unix(int64(ts), 0))
	return nil
}
Sietse Ringers's avatar
Sietse Ringers committed
729

730
731
732
733
734
// Timestamp implements Stringer.
func (t *Timestamp) String() string {
	return fmt.Sprint(time.Time(*t).Unix())
}

735
736
737
738
func (t *Timestamp) Floor() Timestamp {
	return Timestamp(time.Unix((time.Time(*t).Unix()/ExpiryFactor)*ExpiryFactor, 0))
}

739
740
741
742
743
744
745
746
func readTimestamp(path string) (*Timestamp, bool, error) {
	exists, err := fs.PathExists(path)
	if err != nil {
		return nil, false, err
	}
	if !exists {
		return nil, false, nil
	}
747
748
	bts, err := ioutil.ReadFile(path)
	if err != nil {
749
		return nil, true, errors.New("Could not read scheme manager timestamp")
750
	}
751
752
	ts, err := parseTimestamp(bts)
	return ts, true, err
753
754
}

755
func parseTimestamp(bts []byte) (*Timestamp, error) {
756
757
758
759
760
761
	// Remove final character \n if present
	if bts[len(bts)-1] == '\n' {
		bts = bts[:len(bts)-1]
	}
	// convert from byte slice to string; parse as int
	str, err := strconv.ParseInt(string(bts), 10, 64)
762
	if err != nil {
763
		return nil, err
764
	}
765
766
	ts := Timestamp(time.Unix(str, 0))
	return &ts, nil
767
768
}

Sietse Ringers's avatar
Sietse Ringers committed
769
770
771
772
773
774
775
776
// NewServiceProviderJwt returns a new ServiceProviderJwt.
func NewServiceProviderJwt(servername string, dr *DisclosureRequest) *ServiceProviderJwt {
	return &ServiceProviderJwt{
		ServerJwt: ServerJwt{
			ServerName: servername,
			IssuedAt:   Timestamp(time.Now()),
			Type:       "verification_request",
		},
777
778
779
780
		Request: &ServiceProviderRequest{
			RequestorBaseRequest: RequestorBaseRequest{ResultJwtValidity: 120},
			Request:              dr,
		},
Sietse Ringers's avatar
Sietse Ringers committed
781
782
783
784
785
786
787
788
789
790
791
	}
}

// NewSignatureRequestorJwt returns a new SignatureRequestorJwt.
func NewSignatureRequestorJwt(servername string, sr *SignatureRequest) *SignatureRequestorJwt {
	return &SignatureRequestorJwt{
		ServerJwt: ServerJwt{
			ServerName: servername,
			IssuedAt:   Timestamp(time.Now()),
			Type:       "signature_request",
		},
792
793
794
795
		Request: &SignatureRequestorRequest{
			RequestorBaseRequest: RequestorBaseRequest{ResultJwtValidity: 120},
			Request:              sr,
		},
Sietse Ringers's avatar
Sietse Ringers committed
796
797
798
799
800
801
802
803
804
805
806
	}
}

// NewIdentityProviderJwt returns a new IdentityProviderJwt.
func NewIdentityProviderJwt(servername string, ir *IssuanceRequest) *IdentityProviderJwt {
	return &IdentityProviderJwt{
		ServerJwt: ServerJwt{
			ServerName: servername,
			IssuedAt:   Timestamp(time.Now()),
			Type:       "issue_request",
		},
807
808
809
810
		Request: &IdentityProviderRequest{
			RequestorBaseRequest: RequestorBaseRequest{ResultJwtValidity: 120},
			Request:              ir,
		},
Sietse Ringers's avatar
Sietse Ringers committed
811
812
813
	}
}

814
815
816
817
818
819
820
func (jwt *ServerJwt) Requestor() string { return jwt.ServerName }

func (r *ServiceProviderRequest) Validate() error {
	if r.Request == nil {
		return errors.New("Not a ServiceProviderRequest")
	}
	return r.Request.Validate()
Sietse Ringers's avatar
Sietse Ringers committed
821
822
}

823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
func (r *SignatureRequestorRequest) Validate() error {
	if r.Request == nil {
		return errors.New("Not a SignatureRequestorRequest")
	}
	return r.Request.Validate()
}

func (r *IdentityProviderRequest) Validate() error {
	if r.Request == nil {
		return errors.New("Not a IdentityProviderRequest")
	}
	return r.Request.Validate()
}

func (r *ServiceProviderRequest) SessionRequest() SessionRequest {
	return r.Request
}

func (r *SignatureRequestorRequest) SessionRequest() SessionRequest {
	return r.Request
}

func (r *IdentityProviderRequest) SessionRequest() SessionRequest {
	return r.Request
}

func (r *ServiceProviderRequest) Base() RequestorBaseRequest {
	return r.RequestorBaseRequest
}

func (r *SignatureRequestorRequest) Base() RequestorBaseRequest {
	return r.RequestorBaseRequest
}

func (r *IdentityProviderRequest) Base() RequestorBaseRequest {
	return r.RequestorBaseRequest
}
860

861
// SessionRequest returns an IRMA session object.
862
func (claims *ServiceProviderJwt) SessionRequest() SessionRequest { return claims.Request.Request }
Sietse Ringers's avatar
Sietse Ringers committed
863

864
// SessionRequest returns an IRMA session object.
865
func (claims *SignatureRequestorJwt) SessionRequest() SessionRequest { return claims.Request.Request }
Sietse Ringers's avatar
Sietse Ringers committed
866

867
// SessionRequest returns an IRMA session object.
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
func (claims *IdentityProviderJwt) SessionRequest() SessionRequest { return claims.Request.Request }

func (claims *ServiceProviderJwt) Sign(method jwt.SigningMethod, key interface{}) (string, error) {
	return jwt.NewWithClaims(method, claims).SignedString(key)
}

func (claims *SignatureRequestorJwt) Sign(method jwt.SigningMethod, key interface{}) (string, error) {
	return jwt.NewWithClaims(method, claims).SignedString(key)
}

func (claims *IdentityProviderJwt) Sign(method jwt.SigningMethod, key interface{}) (string, error) {
	return jwt.NewWithClaims(method, claims).SignedString(key)
}

func (claims *ServiceProviderJwt) RequestorRequest() RequestorRequest { return claims.Request }

func (claims *SignatureRequestorJwt) RequestorRequest() RequestorRequest { return claims.Request }

func (claims *IdentityProviderJwt) RequestorRequest() RequestorRequest { return claims.Request }

func (claims *ServiceProviderJwt) Valid() error {
	if claims.Type != "verification_request" {
890
891
892

		return errors.New("Verification jwt has invalid subject")
	}
893
	if time.Time(claims.IssuedAt).After(time.Now()) {
894
895
896
897
898
		return errors.New("Verification jwt not yet valid")
	}
	return nil
}

899
900
func (claims *SignatureRequestorJwt) Valid() error {
	if claims.Type != "signature_request" {
901
902
		return errors.New("Signature jwt has invalid subject")
	}
903
	if time.Time(claims.IssuedAt).After(time.Now()) {
904
905
906
907
908
		return errors.New("Signature jwt not yet valid")
	}
	return nil
}

909
910
func (claims *IdentityProviderJwt) Valid() error {
	if claims.Type != "issue_request" {
911
912
		return errors.New("Issuance jwt has invalid subject")
	}
913
	if time.Time(claims.IssuedAt).After(time.Now()) {
914
915
916
917
918
		return errors.New("Issuance jwt not yet valid")
	}
	return nil
}

919
920
921
922
923
924
925
func (claims *RevocationJwt) Valid() error {
	if time.Time(claims.IssuedAt).After(time.Now()) {
		return errors.New("Signature jwt not yet valid")
	}
	return nil
}

926
927
928
func (claims *ServiceProviderJwt) Action() Action { return ActionDisclosing }

func (claims *SignatureRequestorJwt) Action() Action { return ActionSigning }
929

930
func (claims *IdentityProviderJwt) Action() Action { return ActionIssuing }
931

932
func SignSessionRequest(request SessionRequest, alg jwt.SigningMethod, key interface{}, name string) (string, error) {
933
934
935
936
937
938
939
940
941
942
943
	var jwtcontents RequestorJwt
	switch r := request.(type) {
	case *IssuanceRequest:
		jwtcontents = NewIdentityProviderJwt(name, r)
	case *DisclosureRequest:
		jwtcontents = NewServiceProviderJwt(name, r)
	case *SignatureRequest:
		jwtcontents = NewSignatureRequestorJwt(name, r)
	}
	return jwtcontents.Sign(alg, key)
}
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959

func SignRequestorRequest(request RequestorRequest, alg jwt.SigningMethod, key interface{}, name string) (string, error) {
	var jwtcontents RequestorJwt
	switch r := request.(type) {
	case *IdentityProviderRequest:
		jwtcontents = NewIdentityProviderJwt(name, nil)
		jwtcontents.(*IdentityProviderJwt).Request = r
	case *ServiceProviderRequest:
		jwtcontents = NewServiceProviderJwt(name, nil)
		jwtcontents.(*ServiceProviderJwt).Request = r
	case *SignatureRequestorRequest:
		jwtcontents = NewSignatureRequestorJwt(name, nil)
		jwtcontents.(*SignatureRequestorJwt).Request = r
	}
	return jwtcontents.Sign(alg, key)
}
960
961
962
963
964

// NewAttributeRequest requests the specified attribute.
func NewAttributeRequest(attr string) AttributeRequest {
	return AttributeRequest{Type: NewAttributeTypeIdentifier(attr)}
}