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

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

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

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
25
// BaseRequest contains the context and nonce for an IRMA session.
type BaseRequest struct {
26
	LDContext string `json:"@context,omitempty"`
27

28
	// Chosen by the IRMA server during the session
29
30
31
	Context         *big.Int         `json:"context,omitempty"`
	Nonce           *big.Int         `json:"nonce,omitempty"`
	ProtocolVersion *ProtocolVersion `json:"protocolVersion,omitempty"`
32

33
34
35
36
	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
Sietse Ringers's avatar
Sietse Ringers committed
37
38
}

39
40
// An AttributeCon is only satisfied if all of its containing attribute requests are satisfied.
type AttributeCon []AttributeRequest
41

42
43
// An AttributeDisCon is satisfied if at least one of its containing AttributeCon is satisfied.
type AttributeDisCon []AttributeCon
44

45
46
// AttributeConDisCon is only satisfied if all of the containing AttributeDisCon are satisfied.
type AttributeConDisCon []AttributeDisCon
47

48
49
// A DisclosureRequest is a request to disclose certain attributes. Construct new instances using
// NewDisclosureRequest().
50
type DisclosureRequest struct {
51
	BaseRequest
52
53
54

	Disclose AttributeConDisCon       `json:"disclose"`
	Labels   map[int]TranslatedString `json:"labels"`
55
56
}

57
58
// A SignatureRequest is a a request to sign a message with certain attributes. Construct new
// instances using NewSignatureRequest().
59
type SignatureRequest struct {
60
	DisclosureRequest
61
	Message string `json:"message"`
62
63
}

Sietse Ringers's avatar
Sietse Ringers committed
64
// An IssuanceRequest is a request to issue certain credentials,
65
66
// optionally also asking for certain attributes to be simultaneously disclosed. Construct new
// instances using NewIssuanceRequest().
67
type IssuanceRequest struct {
68
	DisclosureRequest
69
	Credentials []*CredentialRequest `json:"credentials"`
Tomas's avatar
Tomas committed
70
71
72

	// Derived data
	CredentialInfoList        CredentialInfoList `json:",omitempty"`
73
	RemovalCredentialInfoList CredentialInfoList `json:",omitempty"`
74
75
}

Sietse Ringers's avatar
Sietse Ringers committed
76
77
// A CredentialRequest contains the attributes and metadata of a credential
// that will be issued in an IssuanceRequest.
78
type CredentialRequest struct {
79
80
	Validity         *Timestamp               `json:"validity,omitempty"`
	KeyCounter       int                      `json:"keyCounter,omitempty"`
81
82
	CredentialTypeID CredentialTypeIdentifier `json:"credential"`
	Attributes       map[string]string        `json:"attributes"`
Sietse Ringers's avatar
Sietse Ringers committed
83
84
}

85
86
87
88
// SessionRequest instances contain all information the irmaclient needs to perform an IRMA session.
type SessionRequest interface {
	Validator
	Base() *BaseRequest
89
	GetNonce(timestamp *atum.Timestamp) *big.Int
90
91
92
	Disclosure() *DisclosureRequest
	Identifiers() *IrmaIdentifierSet
	Action() Action
93
	Legacy() (SessionRequest, error)
94
95
96
97
98
}

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

Sietse Ringers's avatar
Sietse Ringers committed
99
100
101
102
103
104
105
// ServerJwt contains standard JWT fields.
type ServerJwt struct {
	Type       string    `json:"sub"`
	ServerName string    `json:"iss"`
	IssuedAt   Timestamp `json:"iat"`
}

106
107
// RequestorBaseRequest contains fields present in all RequestorRequest types
// with which the requestor configures an IRMA session.
108
type RequestorBaseRequest struct {
Sietse Ringers's avatar
Sietse Ringers committed
109
110
111
	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
	CallbackUrl       string `json:"callbackUrl,omitempty"` // URL to post session result to
112
113
}

114
115
// 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.
116
117
118
type RequestorRequest interface {
	Validator
	SessionRequest() SessionRequest
119
	Base() RequestorBaseRequest
120
121
}

Sietse Ringers's avatar
Sietse Ringers committed
122
123
// A ServiceProviderRequest contains a disclosure request.
type ServiceProviderRequest struct {
124
	RequestorBaseRequest
Sietse Ringers's avatar
Sietse Ringers committed
125
126
127
128
129
	Request *DisclosureRequest `json:"request"`
}

// A SignatureRequestorRequest contains a signing request.
type SignatureRequestorRequest struct {
130
	RequestorBaseRequest
Sietse Ringers's avatar
Sietse Ringers committed
131
132
133
134
135
	Request *SignatureRequest `json:"request"`
}

// An IdentityProviderRequest contains an issuance request.
type IdentityProviderRequest struct {
136
	RequestorBaseRequest
Sietse Ringers's avatar
Sietse Ringers committed
137
138
139
140
141
142
	Request *IssuanceRequest `json:"request"`
}

// ServiceProviderJwt is a requestor JWT for a disclosure session.
type ServiceProviderJwt struct {
	ServerJwt
143
	Request *ServiceProviderRequest `json:"sprequest"`
Sietse Ringers's avatar
Sietse Ringers committed
144
145
146
147
148
}

// SignatureRequestorJwt is a requestor JWT for a signing session.
type SignatureRequestorJwt struct {
	ServerJwt
149
	Request *SignatureRequestorRequest `json:"absrequest"`
Sietse Ringers's avatar
Sietse Ringers committed
150
151
152
153
154
}

// IdentityProviderJwt is a requestor JWT for issuance session.
type IdentityProviderJwt struct {
	ServerJwt
155
156
157
	Request *IdentityProviderRequest `json:"iprequest"`
}

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// 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 {
176
177
	Type  AttributeTypeIdentifier `json:"type"`
	Value *string                 `json:"value"`
178
179
180
181
182
183
184
}

var (
	bigZero = big.NewInt(0)
	bigOne  = big.NewInt(1)
)

185
186
187
188
func (b *BaseRequest) Legacy() bool {
	return b.legacy
}

189
190
191
func (b *BaseRequest) GetContext() *big.Int {
	if b.Context == nil {
		return bigOne
192
	}
193
	return b.Context
194
195
}

196
func (b *BaseRequest) GetNonce(*atum.Timestamp) *big.Int {
197
198
	if b.Nonce == nil {
		return bigZero
199
	}
200
	return b.Nonce
201
202
}

203
204
205
// CredentialTypes returns an array of all credential types occuring in this conjunction.
func (c AttributeCon) CredentialTypes() []CredentialTypeIdentifier {
	var result []CredentialTypeIdentifier
206

207
	for _, attr := range c {
208
209
210
211
		typ := attr.Type.CredentialTypeIdentifier()
		if len(result) == 0 || result[len(result)-1] != typ {
			result = append(result, typ)
		}
212
	}
213

214
	return result
215
216
}

217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
}

235
236
func (c *AttributeCon) MarshalJSON() ([]byte, error) {
	var vals bool
237
	l := make([]AttributeTypeIdentifier, 0, len(*c))
238
239
240
241
242
243

	for _, attr := range *c {
		if attr.Value == nil {
			l = append(l, attr.Type)
		} else {
			vals = true
244
			break
245
246
247
248
		}
	}

	if vals {
249
		return json.Marshal((*[]AttributeRequest)(c))
250
251
252
	} else {
		return json.Marshal(l)
	}
253
254
}

255
256
func (c *AttributeCon) UnmarshalJSON(bts []byte) error {
	var err error
257
258
259
260
261
262
263
264
265

	var l []AttributeTypeIdentifier
	if err = json.Unmarshal(bts, &l); err == nil {
		for _, id := range l {
			*c = append(*c, AttributeRequest{Type: id})
		}
		return nil
	}

266
	if err = json.Unmarshal(bts, (*[]AttributeRequest)(c)); err == nil {
267
268
269
		return nil
	}

270
271
272
273
	var s string
	if err = json.Unmarshal(bts, &s); err == nil {
		*c = append(*c, NewAttributeRequest(s))
		return nil
274
275
	}

276
	return errors.New("Failed to unmarshal attribute conjunction")
277
278
}

279
280
func (ar *AttributeRequest) Satisfy(attr AttributeTypeIdentifier, val *string) bool {
	return ar.Type == attr && (ar.Value == nil || (val != nil && *ar.Value == *val))
Sietse Ringers's avatar
Sietse Ringers committed
281
282
}

283
func (c AttributeCon) Satisfy(proofs gabi.ProofList, indices []*DisclosedAttributeIndex, conf *Configuration) (bool, []*DisclosedAttribute, error) {
284
	if len(indices) < len(c) {
285
		return false, nil, nil
286
287
	}
	attrs := make([]*DisclosedAttribute, 0, len(c))
288
289
290
	if len(c) == 0 {
		return true, attrs, nil
	}
291
292
293
294
295

	for j := range c {
		index := indices[j]
		attr, val, err := extractAttribute(proofs, index, conf)
		if err != nil {
296
			return false, nil, err
297
298
		}
		if !c[j].Satisfy(attr.Identifier, val) {
299
			return false, nil, nil
300
301
302
		}
		attrs = append(attrs, attr)
	}
303
	return true, attrs, nil
304
305
}

306
307
308
309
310
311
312
313
314
315
316
317
318
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
}

319
func (dc AttributeDisCon) Satisfy(proofs gabi.ProofList, indices []*DisclosedAttributeIndex, conf *Configuration) (bool, []*DisclosedAttribute, error) {
320
	for _, con := range dc {
321
322
323
		satisfied, attrs, err := con.Satisfy(proofs, indices, conf)
		if satisfied || err != nil {
			return true, attrs, err
324
325
		}
	}
326
	return false, nil, nil
327
328
}

329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
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
}

348
349
350
351
352
353
354
355
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 {
356
		satisfied, attrs, err := discon.Satisfy(disclosure.Proofs, disclosure.Indices[i], conf)
357
358
359
		if err != nil {
			return false, nil, err
		}
360
		if satisfied {
361
362
363
364
365
366
367
368
			list[i] = attrs
		} else {
			complete = false
			list[i] = nil
		}
	}

	return complete, list, nil
369
370
}

371
372
373
374
375
376
377
378
379
380
381
382
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
383
384
}

385
386
387
388
389
390
391
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{
392
		BaseRequest: BaseRequest{LDContext: LDContextDisclosureRequest},
393
394
395
396
397
398
399
400
401
402
		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...)
403
	dr.LDContext = LDContextSignatureRequest
404
	return &SignatureRequest{
405
		DisclosureRequest: *dr,
406
407
408
409
410
411
		Message:           message,
	}
}

func NewIssuanceRequest(creds []*CredentialRequest, attrs ...AttributeTypeIdentifier) *IssuanceRequest {
	dr := NewDisclosureRequest(attrs...)
412
	dr.LDContext = LDContextIssuanceRequest
413
	return &IssuanceRequest{
414
		DisclosureRequest: *dr,
415
416
417
418
419
420
421
422
423
		Credentials:       creds,
	}
}

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

func (dr *DisclosureRequest) Identifiers() *IrmaIdentifierSet {
424
425
	if dr.ids == nil {
		dr.ids = &IrmaIdentifierSet{
426
427
428
429
430
431
432
433
			SchemeManagers:  map[SchemeManagerIdentifier]struct{}{},
			Issuers:         map[IssuerIdentifier]struct{}{},
			CredentialTypes: map[CredentialTypeIdentifier]struct{}{},
			PublicKeys:      map[IssuerIdentifier][]int{},
		}

		_ = dr.Disclose.Iterate(func(a *AttributeRequest) error {
			attr := a.Type
434
435
436
			dr.ids.SchemeManagers[attr.CredentialTypeIdentifier().IssuerIdentifier().SchemeManagerIdentifier()] = struct{}{}
			dr.ids.Issuers[attr.CredentialTypeIdentifier().IssuerIdentifier()] = struct{}{}
			dr.ids.CredentialTypes[attr.CredentialTypeIdentifier()] = struct{}{}
437
438
439
			return nil
		})
	}
440
	return dr.ids
441
442
443
444
445
446
447
448
449
}

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

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

func (dr *DisclosureRequest) Validate() error {
450
	if dr.LDContext != LDContextDisclosureRequest {
451
452
453
454
455
		return errors.New("Not a disclosure request")
	}
	if len(dr.Disclose) == 0 {
		return errors.New("Disclosure request had no attributes")
	}
456
	var err error
457
	for _, discon := range dr.Disclose {
458
459
		if err = discon.Validate(); err != nil {
			return err
460
461
		}
	}
462
463
	return nil
}
Sietse Ringers's avatar
Sietse Ringers committed
464

465
466
func (cr *CredentialRequest) Info(conf *Configuration, metadataVersion byte) (*CredentialInfo, error) {
	list, err := cr.AttributeList(conf, metadataVersion)
467
468
469
	if err != nil {
		return nil, err
	}
470
	return NewCredentialInfo(list.Ints, conf), nil
471
472
}

473
474
475
476
// 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 {
477
	credtype := conf.CredentialTypes[cr.CredentialTypeID]
Sietse Ringers's avatar
Sietse Ringers committed
478
	if credtype == nil {
479
		return errors.New("Credential request of unknown credential type")
Sietse Ringers's avatar
Sietse Ringers committed
480
	}
481
482
483
484
485

	// Check that there are no attributes in the credential request that aren't
	// in the credential descriptor.
	for crName := range cr.Attributes {
		found := false
486
		for _, ad := range credtype.AttributeTypes {
487
488
489
490
491
492
			if ad.ID == crName {
				found = true
				break
			}
		}
		if !found {
493
			return errors.New("Credential request contaiins unknown attribute")
494
		}
Sietse Ringers's avatar
Sietse Ringers committed
495
496
	}

497
	for _, attrtype := range credtype.AttributeTypes {
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
		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
522
	credtype := conf.CredentialTypes[cr.CredentialTypeID]
523
	attrs := make([]*big.Int, len(credtype.AttributeTypes)+1)
Sietse Ringers's avatar
Sietse Ringers committed
524
	attrs[0] = meta.Int
525
	for i, attrtype := range credtype.AttributeTypes {
526
		attrs[i+1] = new(big.Int)
Sietse Ringers's avatar
Sietse Ringers committed
527
		if str, present := cr.Attributes[attrtype.ID]; present {
528
			// Set attribute to str << 1 + 1
529
			attrs[i+1].SetBytes([]byte(str))
530
531
532
533
			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
534
535
536
		}
	}

537
	return NewAttributeListFromInts(attrs, conf), nil
Sietse Ringers's avatar
Sietse Ringers committed
538
539
}

Sietse Ringers's avatar
Sietse Ringers committed
540
func (ir *IssuanceRequest) Identifiers() *IrmaIdentifierSet {
541
542
	if ir.ids == nil {
		ir.ids = &IrmaIdentifierSet{
543
544
545
546
			SchemeManagers:  map[SchemeManagerIdentifier]struct{}{},
			Issuers:         map[IssuerIdentifier]struct{}{},
			CredentialTypes: map[CredentialTypeIdentifier]struct{}{},
			PublicKeys:      map[IssuerIdentifier][]int{},
Sietse Ringers's avatar
Sietse Ringers committed
547
548
		}

Sietse Ringers's avatar
Sietse Ringers committed
549
		for _, credreq := range ir.Credentials {
Sietse Ringers's avatar
Sietse Ringers committed
550
			issuer := credreq.CredentialTypeID.IssuerIdentifier()
551
552
553
554
555
			ir.ids.SchemeManagers[issuer.SchemeManagerIdentifier()] = struct{}{}
			ir.ids.Issuers[issuer] = struct{}{}
			ir.ids.CredentialTypes[credreq.CredentialTypeID] = struct{}{}
			if ir.ids.PublicKeys[issuer] == nil {
				ir.ids.PublicKeys[issuer] = []int{}
556
			}
557
			ir.ids.PublicKeys[issuer] = append(ir.ids.PublicKeys[issuer], credreq.KeyCounter)
558
559
		}

560
		ir.ids.join(ir.DisclosureRequest.Identifiers())
Sietse Ringers's avatar
Sietse Ringers committed
561
	}
562
	return ir.ids
Sietse Ringers's avatar
Sietse Ringers committed
563
564
}

Tomas's avatar
Tomas committed
565
566
567
568
569
570
571
572
573
574
575
576
577
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
}

578
579
func (ir *IssuanceRequest) Action() Action { return ActionIssuing }

580
func (ir *IssuanceRequest) Validate() error {
581
	if ir.LDContext != LDContextIssuanceRequest {
582
583
584
585
586
		return errors.New("Not an issuance request")
	}
	if len(ir.Credentials) == 0 {
		return errors.New("Empty issuance request")
	}
587
	for _, cred := range ir.Credentials {
588
		if cred.Validity != nil && cred.Validity.Floor().Before(Timestamp(time.Now())) {
589
590
591
			return errors.New("Expired credential request")
		}
	}
592
593
594
595
596
597
	var err error
	for _, discon := range ir.Disclose {
		if err = discon.Validate(); err != nil {
			return err
		}
	}
598
599
600
	return nil
}

Sietse Ringers's avatar
Sietse Ringers committed
601
602
// GetNonce returns the nonce of this signature session
// (with the message already hashed into it).
603
604
func (sr *SignatureRequest) GetNonce(timestamp *atum.Timestamp) *big.Int {
	return ASN1ConvertSignatureNonce(sr.Message, sr.BaseRequest.GetNonce(nil), timestamp)
605
606
}

607
func (sr *SignatureRequest) SignatureFromMessage(message interface{}, timestamp *atum.Timestamp) (*SignedMessage, error) {
608
	signature, ok := message.(*Disclosure)
609
610
611
612
613

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

614
615
616
617
	nonce := sr.Nonce
	if nonce == nil {
		nonce = bigZero
	}
618
	return &SignedMessage{
619
		LDContext: LDContextSignedMessage,
620
		Signature: signature.Proofs,
621
		Indices:   signature.Indices,
622
623
		Nonce:     nonce,
		Context:   sr.GetContext(),
624
		Message:   sr.Message,
625
		Timestamp: timestamp,
626
627
628
	}, nil
}

629
630
func (sr *SignatureRequest) Action() Action { return ActionSigning }

631
func (sr *SignatureRequest) Validate() error {
632
	if sr.LDContext != LDContextSignatureRequest {
633
634
635
636
637
		return errors.New("Not a signature request")
	}
	if sr.Message == "" {
		return errors.New("Signature request had empty message")
	}
638
639
	if len(sr.Disclose) == 0 {
		return errors.New("Signature request had no attributes")
640
	}
641
	var err error
642
	for _, discon := range sr.Disclose {
643
644
		if err = discon.Validate(); err != nil {
			return err
645
646
		}
	}
647
648
649
	return nil
}

650
651
652
653
654
// 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))
}

655
656
657
658
func (t Timestamp) After(u Timestamp) bool {
	return time.Time(t).After(time.Time(u))
}

659
660
// MarshalJSON marshals a timestamp.
func (t *Timestamp) MarshalJSON() ([]byte, error) {
661
	return []byte(t.String()), nil
662
663
664
665
666
667
668
669
670
671
672
}

// 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
673

674
675
676
677
678
// Timestamp implements Stringer.
func (t *Timestamp) String() string {
	return fmt.Sprint(time.Time(*t).Unix())
}

679
680
681
682
func (t *Timestamp) Floor() Timestamp {
	return Timestamp(time.Unix((time.Time(*t).Unix()/ExpiryFactor)*ExpiryFactor, 0))
}

683
684
685
686
687
688
689
690
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
	}
691
692
	bts, err := ioutil.ReadFile(path)
	if err != nil {
693
		return nil, true, errors.New("Could not read scheme manager timestamp")
694
	}
695
696
	ts, err := parseTimestamp(bts)
	return ts, true, err
697
698
}

699
func parseTimestamp(bts []byte) (*Timestamp, error) {
700
701
702
703
704
705
	// 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)
706
	if err != nil {
707
		return nil, err
708
	}
709
710
	ts := Timestamp(time.Unix(str, 0))
	return &ts, nil
711
712
}

Sietse Ringers's avatar
Sietse Ringers committed
713
714
715
716
717
718
719
720
// 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",
		},
721
722
723
724
		Request: &ServiceProviderRequest{
			RequestorBaseRequest: RequestorBaseRequest{ResultJwtValidity: 120},
			Request:              dr,
		},
Sietse Ringers's avatar
Sietse Ringers committed
725
726
727
728
729
730
731
732
733
734
735
	}
}

// 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",
		},
736
737
738
739
		Request: &SignatureRequestorRequest{
			RequestorBaseRequest: RequestorBaseRequest{ResultJwtValidity: 120},
			Request:              sr,
		},
Sietse Ringers's avatar
Sietse Ringers committed
740
741
742
743
744
745
746
747
748
749
750
	}
}

// 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",
		},
751
752
753
754
		Request: &IdentityProviderRequest{
			RequestorBaseRequest: RequestorBaseRequest{ResultJwtValidity: 120},
			Request:              ir,
		},
Sietse Ringers's avatar
Sietse Ringers committed
755
756
757
	}
}

758
759
760
761
762
763
764
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
765
766
}

767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
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
}
804

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

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

811
// SessionRequest returns an IRMA session object.
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
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" {
834
835
836

		return errors.New("Verification jwt has invalid subject")
	}
837
	if time.Time(claims.IssuedAt).After(time.Now()) {
838
839
840
841
842
		return errors.New("Verification jwt not yet valid")
	}
	return nil
}

843
844
func (claims *SignatureRequestorJwt) Valid() error {
	if claims.Type != "signature_request" {
845
846
		return errors.New("Signature jwt has invalid subject")
	}
847
	if time.Time(claims.IssuedAt).After(time.Now()) {
848
849
850
851
852
		return errors.New("Signature jwt not yet valid")
	}
	return nil
}

853
854
func (claims *IdentityProviderJwt) Valid() error {
	if claims.Type != "issue_request" {
855
856
		return errors.New("Issuance jwt has invalid subject")
	}
857
	if time.Time(claims.IssuedAt).After(time.Now()) {
858
859
860
861
862
		return errors.New("Issuance jwt not yet valid")
	}
	return nil
}

863
864
865
func (claims *ServiceProviderJwt) Action() Action { return ActionDisclosing }

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

867
func (claims *IdentityProviderJwt) Action() Action { return ActionIssuing }
868

869
func SignSessionRequest(request SessionRequest, alg jwt.SigningMethod, key interface{}, name string) (string, error) {
870
871
872
873
874
875
876
877
878
879
880
	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)
}
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896

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)
}
897
898
899
900
901

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