requests.go 26.4 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"`
	Required bool                    `json:"required"`
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
252
253
func (ar *AttributeRequest) MarshalJSON() ([]byte, error) {
	if !ar.Required && ar.Value == nil {
		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
261
262
	return ar.Type == attr &&
		(!ar.Required || val != nil) &&
		(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
411
		Credentials:       creds,
	}
}

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

func (dr *DisclosureRequest) Identifiers() *IrmaIdentifierSet {
412
413
	if dr.ids == nil {
		dr.ids = &IrmaIdentifierSet{
414
415
416
417
418
419
420
421
			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
422
423
424
			dr.ids.SchemeManagers[attr.CredentialTypeIdentifier().IssuerIdentifier().SchemeManagerIdentifier()] = struct{}{}
			dr.ids.Issuers[attr.CredentialTypeIdentifier().IssuerIdentifier()] = struct{}{}
			dr.ids.CredentialTypes[attr.CredentialTypeIdentifier()] = struct{}{}
425
426
427
			return nil
		})
	}
428
	return dr.ids
429
430
431
432
433
434
435
436
437
}

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

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

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

453
454
func (cr *CredentialRequest) Info(conf *Configuration, metadataVersion byte) (*CredentialInfo, error) {
	list, err := cr.AttributeList(conf, metadataVersion)
455
456
457
	if err != nil {
		return nil, err
	}
458
	return NewCredentialInfo(list.Ints, conf), nil
459
460
}

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

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

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

525
	return NewAttributeListFromInts(attrs, conf), nil
Sietse Ringers's avatar
Sietse Ringers committed
526
527
}

Sietse Ringers's avatar
Sietse Ringers committed
528
func (ir *IssuanceRequest) Identifiers() *IrmaIdentifierSet {
529
530
	if ir.ids == nil {
		ir.ids = &IrmaIdentifierSet{
531
532
533
534
			SchemeManagers:  map[SchemeManagerIdentifier]struct{}{},
			Issuers:         map[IssuerIdentifier]struct{}{},
			CredentialTypes: map[CredentialTypeIdentifier]struct{}{},
			PublicKeys:      map[IssuerIdentifier][]int{},
Sietse Ringers's avatar
Sietse Ringers committed
535
536
		}

Sietse Ringers's avatar
Sietse Ringers committed
537
		for _, credreq := range ir.Credentials {
Sietse Ringers's avatar
Sietse Ringers committed
538
			issuer := credreq.CredentialTypeID.IssuerIdentifier()
539
540
541
542
543
			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{}
544
			}
545
			ir.ids.PublicKeys[issuer] = append(ir.ids.PublicKeys[issuer], credreq.KeyCounter)
546
547
		}

548
		ir.ids.join(ir.DisclosureRequest.Identifiers())
Sietse Ringers's avatar
Sietse Ringers committed
549
	}
550
	return ir.ids
Sietse Ringers's avatar
Sietse Ringers committed
551
552
}

Tomas's avatar
Tomas committed
553
554
555
556
557
558
559
560
561
562
563
564
565
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
}

566
567
func (ir *IssuanceRequest) Action() Action { return ActionIssuing }

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

Sietse Ringers's avatar
Sietse Ringers committed
589
590
// GetNonce returns the nonce of this signature session
// (with the message already hashed into it).
591
592
func (sr *SignatureRequest) GetNonce(timestamp *atum.Timestamp) *big.Int {
	return ASN1ConvertSignatureNonce(sr.Message, sr.BaseRequest.GetNonce(nil), timestamp)
593
594
}

595
func (sr *SignatureRequest) SignatureFromMessage(message interface{}, timestamp *atum.Timestamp) (*SignedMessage, error) {
596
	signature, ok := message.(*Disclosure)
597
598
599
600
601

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

602
603
604
605
	nonce := sr.Nonce
	if nonce == nil {
		nonce = bigZero
	}
606
	return &SignedMessage{
607
		LDContext: LDContextSignedMessage,
608
		Signature: signature.Proofs,
609
		Indices:   signature.Indices,
610
611
		Nonce:     nonce,
		Context:   sr.GetContext(),
612
		Message:   sr.Message,
613
		Timestamp: timestamp,
614
615
616
	}, nil
}

617
618
func (sr *SignatureRequest) Action() Action { return ActionSigning }

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

638
639
640
641
642
// 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))
}

643
644
645
646
func (t Timestamp) After(u Timestamp) bool {
	return time.Time(t).After(time.Time(u))
}

647
648
// MarshalJSON marshals a timestamp.
func (t *Timestamp) MarshalJSON() ([]byte, error) {
649
	return []byte(t.String()), nil
650
651
652
653
654
655
656
657
658
659
660
}

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

662
663
664
665
666
// Timestamp implements Stringer.
func (t *Timestamp) String() string {
	return fmt.Sprint(time.Time(*t).Unix())
}

667
668
669
670
func (t *Timestamp) Floor() Timestamp {
	return Timestamp(time.Unix((time.Time(*t).Unix()/ExpiryFactor)*ExpiryFactor, 0))
}

671
672
673
674
675
676
677
678
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
	}
679
680
	bts, err := ioutil.ReadFile(path)
	if err != nil {
681
		return nil, true, errors.New("Could not read scheme manager timestamp")
682
	}
683
684
	ts, err := parseTimestamp(bts)
	return ts, true, err
685
686
}

687
func parseTimestamp(bts []byte) (*Timestamp, error) {
688
689
690
691
692
693
	// 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)
694
	if err != nil {
695
		return nil, err
696
	}
697
698
	ts := Timestamp(time.Unix(str, 0))
	return &ts, nil
699
700
}

Sietse Ringers's avatar
Sietse Ringers committed
701
702
703
704
705
706
707
708
// 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",
		},
709
710
711
712
		Request: &ServiceProviderRequest{
			RequestorBaseRequest: RequestorBaseRequest{ResultJwtValidity: 120},
			Request:              dr,
		},
Sietse Ringers's avatar
Sietse Ringers committed
713
714
715
716
717
718
719
720
721
722
723
	}
}

// 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",
		},
724
725
726
727
		Request: &SignatureRequestorRequest{
			RequestorBaseRequest: RequestorBaseRequest{ResultJwtValidity: 120},
			Request:              sr,
		},
Sietse Ringers's avatar
Sietse Ringers committed
728
729
730
731
732
733
734
735
736
737
738
	}
}

// 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",
		},
739
740
741
742
		Request: &IdentityProviderRequest{
			RequestorBaseRequest: RequestorBaseRequest{ResultJwtValidity: 120},
			Request:              ir,
		},
Sietse Ringers's avatar
Sietse Ringers committed
743
744
745
	}
}

746
747
748
749
750
751
752
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
753
754
}

755
756
757
758
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
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
}
792

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

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

799
// SessionRequest returns an IRMA session object.
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
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" {
822
823
824

		return errors.New("Verification jwt has invalid subject")
	}
825
	if time.Time(claims.IssuedAt).After(time.Now()) {
826
827
828
829
830
		return errors.New("Verification jwt not yet valid")
	}
	return nil
}

831
832
func (claims *SignatureRequestorJwt) Valid() error {
	if claims.Type != "signature_request" {
833
834
		return errors.New("Signature jwt has invalid subject")
	}
835
	if time.Time(claims.IssuedAt).After(time.Now()) {
836
837
838
839
840
		return errors.New("Signature jwt not yet valid")
	}
	return nil
}

841
842
func (claims *IdentityProviderJwt) Valid() error {
	if claims.Type != "issue_request" {
843
844
		return errors.New("Issuance jwt has invalid subject")
	}
845
	if time.Time(claims.IssuedAt).After(time.Now()) {
846
847
848
849
850
		return errors.New("Issuance jwt not yet valid")
	}
	return nil
}

851
852
853
func (claims *ServiceProviderJwt) Action() Action { return ActionDisclosing }

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

855
func (claims *IdentityProviderJwt) Action() Action { return ActionIssuing }
856

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

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)
}
885
886
887
888
889

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