requests.go 26.5 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,omitempty"`
	Labels   map[int]TranslatedString `json:"labels,omitempty"`
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
178
	Type    AttributeTypeIdentifier `json:"type"`
	Value   *string                 `json:"value,omitempty"`
	NotNull bool                    `json:"notNull,omitempty"`
179
180
181
182
183
184
185
}

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

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

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

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

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

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

215
	return result
216
217
}

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

236
237
// AttributeRequest synonym with default JSON (un)marshaler
type jsonAttributeRequest AttributeRequest
238

239
240
func (ar *AttributeRequest) UnmarshalJSON(bts []byte) error {
	var s AttributeTypeIdentifier
241

242
243
244
	// first try to parse as JSON string into s
	if err := json.Unmarshal(bts, &s); err == nil {
		*ar = AttributeRequest{Type: s}
245
246
247
		return nil
	}

248
249
	return json.Unmarshal(bts, (*jsonAttributeRequest)(ar))
}
250

251
func (ar *AttributeRequest) MarshalJSON() ([]byte, error) {
252
	if !ar.NotNull && ar.Value == nil {
253
		return json.Marshal(ar.Type)
254
	}
255
	return json.Marshal((*jsonAttributeRequest)(ar))
256
257
}

258
// Satisfy indicates whether the given attribute type and value satisfies this AttributeRequest.
259
func (ar *AttributeRequest) Satisfy(attr AttributeTypeIdentifier, val *string) bool {
260
	return ar.Type == attr &&
261
		(!ar.NotNull || val != nil) &&
262
		(ar.Value == nil || (val != nil && *ar.Value == *val))
Sietse Ringers's avatar
Sietse Ringers committed
263
264
}

265
266
// 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.
267
func (c AttributeCon) Satisfy(proofs gabi.ProofList, indices []*DisclosedAttributeIndex, conf *Configuration) (bool, []*DisclosedAttribute, error) {
268
	if len(indices) < len(c) {
269
		return false, nil, nil
270
271
	}
	attrs := make([]*DisclosedAttribute, 0, len(c))
272
273
274
	if len(c) == 0 {
		return true, attrs, nil
	}
275
276
277
278
279

	for j := range c {
		index := indices[j]
		attr, val, err := extractAttribute(proofs, index, conf)
		if err != nil {
280
			return false, nil, err
281
282
		}
		if !c[j].Satisfy(attr.Identifier, val) {
283
			return false, nil, nil
284
285
286
		}
		attrs = append(attrs, attr)
	}
287
	return true, attrs, nil
288
289
}

290
291
292
293
294
295
296
297
298
299
300
301
302
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
}

303
304
// 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.
305
func (dc AttributeDisCon) Satisfy(proofs gabi.ProofList, indices []*DisclosedAttributeIndex, conf *Configuration) (bool, []*DisclosedAttribute, error) {
306
	for _, con := range dc {
307
308
309
		satisfied, attrs, err := con.Satisfy(proofs, indices, conf)
		if satisfied || err != nil {
			return true, attrs, err
310
311
		}
	}
312
	return false, nil, nil
313
314
}

315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
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
}

334
335
// Satisfy returns true if each of the contained AttributeDisCon is satisfied by the specified disclosure.
// If so it also returns the disclosed attributes.
336
337
338
339
340
341
342
343
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 {
344
		satisfied, attrs, err := discon.Satisfy(disclosure.Proofs, disclosure.Indices[i], conf)
345
346
347
		if err != nil {
			return false, nil, err
		}
348
		if satisfied {
349
350
351
352
353
354
355
356
			list[i] = attrs
		} else {
			complete = false
			list[i] = nil
		}
	}

	return complete, list, nil
357
358
}

359
360
361
362
363
364
365
366
367
368
369
370
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
371
372
}

373
374
375
376
377
378
379
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{
380
		BaseRequest: BaseRequest{LDContext: LDContextDisclosureRequest},
381
382
383
384
385
386
387
388
389
390
		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...)
391
	dr.LDContext = LDContextSignatureRequest
392
	return &SignatureRequest{
393
		DisclosureRequest: *dr,
394
395
396
397
398
399
		Message:           message,
	}
}

func NewIssuanceRequest(creds []*CredentialRequest, attrs ...AttributeTypeIdentifier) *IssuanceRequest {
	dr := NewDisclosureRequest(attrs...)
400
	dr.LDContext = LDContextIssuanceRequest
401
	return &IssuanceRequest{
402
		DisclosureRequest: *dr,
403
404
405
406
407
408
409
410
		Credentials:       creds,
	}
}

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

411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
func (dr *DisclosureRequest) identifiers() *IrmaIdentifierSet {
	ids := &IrmaIdentifierSet{
		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
		ids.SchemeManagers[attr.CredentialTypeIdentifier().IssuerIdentifier().SchemeManagerIdentifier()] = struct{}{}
		ids.Issuers[attr.CredentialTypeIdentifier().IssuerIdentifier()] = struct{}{}
		ids.CredentialTypes[attr.CredentialTypeIdentifier()] = struct{}{}
		return nil
	})

	return ids
}

430
func (dr *DisclosureRequest) Identifiers() *IrmaIdentifierSet {
431
	if dr.ids == nil {
432
		dr.ids = dr.identifiers()
433
	}
434
	return dr.ids
435
436
437
438
439
440
441
442
443
}

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

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

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

459
460
func (cr *CredentialRequest) Info(conf *Configuration, metadataVersion byte) (*CredentialInfo, error) {
	list, err := cr.AttributeList(conf, metadataVersion)
461
462
463
	if err != nil {
		return nil, err
	}
464
	return NewCredentialInfo(list.Ints, conf), nil
465
466
}

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

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

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

531
	return NewAttributeListFromInts(attrs, conf), nil
Sietse Ringers's avatar
Sietse Ringers committed
532
533
}

Sietse Ringers's avatar
Sietse Ringers committed
534
func (ir *IssuanceRequest) Identifiers() *IrmaIdentifierSet {
535
536
	if ir.ids == nil {
		ir.ids = &IrmaIdentifierSet{
537
538
539
540
			SchemeManagers:  map[SchemeManagerIdentifier]struct{}{},
			Issuers:         map[IssuerIdentifier]struct{}{},
			CredentialTypes: map[CredentialTypeIdentifier]struct{}{},
			PublicKeys:      map[IssuerIdentifier][]int{},
Sietse Ringers's avatar
Sietse Ringers committed
541
542
		}

Sietse Ringers's avatar
Sietse Ringers committed
543
		for _, credreq := range ir.Credentials {
Sietse Ringers's avatar
Sietse Ringers committed
544
			issuer := credreq.CredentialTypeID.IssuerIdentifier()
545
546
547
548
549
			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{}
550
			}
551
			ir.ids.PublicKeys[issuer] = append(ir.ids.PublicKeys[issuer], credreq.KeyCounter)
552
553
		}

554
		ir.ids.join(ir.DisclosureRequest.identifiers())
Sietse Ringers's avatar
Sietse Ringers committed
555
	}
556
	return ir.ids
Sietse Ringers's avatar
Sietse Ringers committed
557
558
}

Tomas's avatar
Tomas committed
559
560
561
562
563
564
565
566
567
568
569
570
571
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
}

572
573
func (ir *IssuanceRequest) Action() Action { return ActionIssuing }

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

Sietse Ringers's avatar
Sietse Ringers committed
595
596
// GetNonce returns the nonce of this signature session
// (with the message already hashed into it).
597
598
func (sr *SignatureRequest) GetNonce(timestamp *atum.Timestamp) *big.Int {
	return ASN1ConvertSignatureNonce(sr.Message, sr.BaseRequest.GetNonce(nil), timestamp)
599
600
}

601
func (sr *SignatureRequest) SignatureFromMessage(message interface{}, timestamp *atum.Timestamp) (*SignedMessage, error) {
602
	signature, ok := message.(*Disclosure)
603
604
605
606
607

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

608
609
610
611
	nonce := sr.Nonce
	if nonce == nil {
		nonce = bigZero
	}
612
	return &SignedMessage{
613
		LDContext: LDContextSignedMessage,
614
		Signature: signature.Proofs,
615
		Indices:   signature.Indices,
616
617
		Nonce:     nonce,
		Context:   sr.GetContext(),
618
		Message:   sr.Message,
619
		Timestamp: timestamp,
620
621
622
	}, nil
}

623
624
func (sr *SignatureRequest) Action() Action { return ActionSigning }

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

644
645
646
647
648
// 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))
}

649
650
651
652
func (t Timestamp) After(u Timestamp) bool {
	return time.Time(t).After(time.Time(u))
}

653
654
// MarshalJSON marshals a timestamp.
func (t *Timestamp) MarshalJSON() ([]byte, error) {
655
	return []byte(t.String()), nil
656
657
658
659
660
661
662
663
664
665
666
}

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

668
669
670
671
672
// Timestamp implements Stringer.
func (t *Timestamp) String() string {
	return fmt.Sprint(time.Time(*t).Unix())
}

673
674
675
676
func (t *Timestamp) Floor() Timestamp {
	return Timestamp(time.Unix((time.Time(*t).Unix()/ExpiryFactor)*ExpiryFactor, 0))
}

677
678
679
680
681
682
683
684
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
	}
685
686
	bts, err := ioutil.ReadFile(path)
	if err != nil {
687
		return nil, true, errors.New("Could not read scheme manager timestamp")
688
	}
689
690
	ts, err := parseTimestamp(bts)
	return ts, true, err
691
692
}

693
func parseTimestamp(bts []byte) (*Timestamp, error) {
694
695
696
697
698
699
	// 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)
700
	if err != nil {
701
		return nil, err
702
	}
703
704
	ts := Timestamp(time.Unix(str, 0))
	return &ts, nil
705
706
}

Sietse Ringers's avatar
Sietse Ringers committed
707
708
709
710
711
712
713
714
// 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",
		},
715
716
717
718
		Request: &ServiceProviderRequest{
			RequestorBaseRequest: RequestorBaseRequest{ResultJwtValidity: 120},
			Request:              dr,
		},
Sietse Ringers's avatar
Sietse Ringers committed
719
720
721
722
723
724
725
726
727
728
729
	}
}

// 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",
		},
730
731
732
733
		Request: &SignatureRequestorRequest{
			RequestorBaseRequest: RequestorBaseRequest{ResultJwtValidity: 120},
			Request:              sr,
		},
Sietse Ringers's avatar
Sietse Ringers committed
734
735
736
737
738
739
740
741
742
743
744
	}
}

// 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",
		},
745
746
747
748
		Request: &IdentityProviderRequest{
			RequestorBaseRequest: RequestorBaseRequest{ResultJwtValidity: 120},
			Request:              ir,
		},
Sietse Ringers's avatar
Sietse Ringers committed
749
750
751
	}
}

752
753
754
755
756
757
758
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
759
760
}

761
762
763
764
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
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
}
798

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

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

805
// SessionRequest returns an IRMA session object.
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
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" {
828
829
830

		return errors.New("Verification jwt has invalid subject")
	}
831
	if time.Time(claims.IssuedAt).After(time.Now()) {
832
833
834
835
836
		return errors.New("Verification jwt not yet valid")
	}
	return nil
}

837
838
func (claims *SignatureRequestorJwt) Valid() error {
	if claims.Type != "signature_request" {
839
840
		return errors.New("Signature jwt has invalid subject")
	}
841
	if time.Time(claims.IssuedAt).After(time.Now()) {
842
843
844
845
846
		return errors.New("Signature jwt not yet valid")
	}
	return nil
}

847
848
func (claims *IdentityProviderJwt) Valid() error {
	if claims.Type != "issue_request" {
849
850
		return errors.New("Issuance jwt has invalid subject")
	}
851
	if time.Time(claims.IssuedAt).After(time.Now()) {
852
853
854
855
856
		return errors.New("Issuance jwt not yet valid")
	}
	return nil
}

857
858
859
func (claims *ServiceProviderJwt) Action() Action { return ActionDisclosing }

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

861
func (claims *IdentityProviderJwt) Action() Action { return ActionIssuing }
862

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

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)
}
891
892
893
894
895

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