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

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

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

19 20 21 22 23 24
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"
)

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

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

34 35 36 37
	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
38 39

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

42 43
// An AttributeCon is only satisfied if all of its containing attribute requests are satisfied.
type AttributeCon []AttributeRequest
44

45 46
// An AttributeDisCon is satisfied if at least one of its containing AttributeCon is satisfied.
type AttributeDisCon []AttributeCon
47

48 49
// AttributeConDisCon is only satisfied if all of the containing AttributeDisCon are satisfied.
type AttributeConDisCon []AttributeDisCon
50

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

56 57
	Disclose AttributeConDisCon       `json:"disclose,omitempty"`
	Labels   map[int]TranslatedString `json:"labels,omitempty"`
58 59
}

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

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

	// Derived data
	CredentialInfoList        CredentialInfoList `json:",omitempty"`
76
	RemovalCredentialInfoList CredentialInfoList `json:",omitempty"`
77 78
}

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

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

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

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

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

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

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

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

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

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

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

// IdentityProviderJwt is a requestor JWT for issuance session.
type IdentityProviderJwt struct {
	ServerJwt
158 159 160
	Request *IdentityProviderRequest `json:"iprequest"`
}

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
// 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 {
179 180 181
	Type    AttributeTypeIdentifier `json:"type"`
	Value   *string                 `json:"value,omitempty"`
	NotNull bool                    `json:"notNull,omitempty"`
182 183 184 185 186 187 188
}

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

189 190 191 192
func (b *BaseRequest) Legacy() bool {
	return b.legacy
}

193 194 195
func (b *BaseRequest) GetContext() *big.Int {
	if b.Context == nil {
		return bigOne
196
	}
197
	return b.Context
198 199
}

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

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

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

218
	return result
219 220
}

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

239 240
// AttributeRequest synonym with default JSON (un)marshaler
type jsonAttributeRequest AttributeRequest
241

242 243
func (ar *AttributeRequest) UnmarshalJSON(bts []byte) error {
	var s AttributeTypeIdentifier
244

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

251 252
	return json.Unmarshal(bts, (*jsonAttributeRequest)(ar))
}
253

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

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

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

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

293 294 295 296 297 298 299 300 301 302 303 304 305
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
}

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

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

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

	return complete, list, nil
360 361
}

362 363 364 365 366 367 368 369 370 371 372 373
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
374 375
}

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

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

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

414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
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
}

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

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

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

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

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

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

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

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

534
	return NewAttributeListFromInts(attrs, conf), nil
Sietse Ringers's avatar
Sietse Ringers committed
535 536
}

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

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

557
		ir.ids.join(ir.DisclosureRequest.identifiers())
Sietse Ringers's avatar
Sietse Ringers committed
558
	}
559
	return ir.ids
Sietse Ringers's avatar
Sietse Ringers committed
560 561
}

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

575 576
func (ir *IssuanceRequest) Action() Action { return ActionIssuing }

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

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

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

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

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

626 627
func (sr *SignatureRequest) Action() Action { return ActionSigning }

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

647 648 649 650 651
// 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))
}

652 653 654 655
func (t Timestamp) After(u Timestamp) bool {
	return time.Time(t).After(time.Time(u))
}

656 657 658 659 660
// To check whether Timestamp is uninitialized
func (t Timestamp) IsZero() bool {
	return time.Time(t).IsZero()
}

661 662 663 664 665 666 667 668 669 670 671 672 673
func (t *Timestamp) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	return e.EncodeElement(t.String(), start)
}

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

674 675
// MarshalJSON marshals a timestamp.
func (t *Timestamp) MarshalJSON() ([]byte, error) {
676
	return []byte(t.String()), nil
677 678 679 680 681 682 683 684 685 686 687
}

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

689 690 691 692 693
// Timestamp implements Stringer.
func (t *Timestamp) String() string {
	return fmt.Sprint(time.Time(*t).Unix())
}

694 695 696 697
func (t *Timestamp) Floor() Timestamp {
	return Timestamp(time.Unix((time.Time(*t).Unix()/ExpiryFactor)*ExpiryFactor, 0))
}

698 699 700 701 702 703 704 705
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
	}
706 707
	bts, err := ioutil.ReadFile(path)
	if err != nil {
708
		return nil, true, errors.New("Could not read scheme manager timestamp")
709
	}
710 711
	ts, err := parseTimestamp(bts)
	return ts, true, err
712 713
}

714
func parseTimestamp(bts []byte) (*Timestamp, error) {
715 716 717 718 719 720
	// 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)
721
	if err != nil {
722
		return nil, err
723
	}
724 725
	ts := Timestamp(time.Unix(str, 0))
	return &ts, nil
726 727
}

Sietse Ringers's avatar
Sietse Ringers committed
728 729 730 731 732 733 734 735
// 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",
		},
736 737 738 739
		Request: &ServiceProviderRequest{
			RequestorBaseRequest: RequestorBaseRequest{ResultJwtValidity: 120},
			Request:              dr,
		},
Sietse Ringers's avatar
Sietse Ringers committed
740 741 742 743 744 745 746 747 748 749 750
	}
}

// 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",
		},
751 752 753 754
		Request: &SignatureRequestorRequest{
			RequestorBaseRequest: RequestorBaseRequest{ResultJwtValidity: 120},
			Request:              sr,
		},
Sietse Ringers's avatar
Sietse Ringers committed
755 756 757 758 759 760 761 762 763 764 765
	}
}

// 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",
		},
766 767 768 769
		Request: &IdentityProviderRequest{
			RequestorBaseRequest: RequestorBaseRequest{ResultJwtValidity: 120},
			Request:              ir,
		},
Sietse Ringers's avatar
Sietse Ringers committed
770 771 772
	}
}

773 774 775 776 777 778 779
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
780 781
}

782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
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
}
819

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

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

826
// SessionRequest returns an IRMA session object.
827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848
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" {
849 850 851

		return errors.New("Verification jwt has invalid subject")
	}
852
	if time.Time(claims.IssuedAt).After(time.Now()) {
853 854 855 856 857
		return errors.New("Verification jwt not yet valid")
	}
	return nil
}

858 859
func (claims *SignatureRequestorJwt) Valid() error {
	if claims.Type != "signature_request" {
860 861
		return errors.New("Signature jwt has invalid subject")
	}
862
	if time.Time(claims.IssuedAt).After(time.Now()) {
863 864 865 866 867
		return errors.New("Signature jwt not yet valid")
	}
	return nil
}

868 869
func (claims *IdentityProviderJwt) Valid() error {
	if claims.Type != "issue_request" {
870 871
		return errors.New("Issuance jwt has invalid subject")
	}
872
	if time.Time(claims.IssuedAt).After(time.Now()) {
873 874 875 876 877
		return errors.New("Issuance jwt not yet valid")
	}
	return nil
}

878 879 880
func (claims *ServiceProviderJwt) Action() Action { return ActionDisclosing }

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

882
func (claims *IdentityProviderJwt) Action() Action { return ActionIssuing }
883

884
func SignSessionRequest(request SessionRequest, alg jwt.SigningMethod, key interface{}, name string) (string, error) {
885 886 887 888 889 890 891 892 893 894 895
	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)
}
896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911

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)
}
912 913 914 915 916

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