manual_session_test.go 10.3 KB
Newer Older
1
2
3
package irmaclient

import (
4
	"encoding/json"
Koen van Ingen's avatar
Koen van Ingen committed
5
	"fmt"
6

Sietse Ringers's avatar
Sietse Ringers committed
7
8
	"testing"

9
	"github.com/privacybydesign/irmago"
Koen van Ingen's avatar
Koen van Ingen committed
10
	"github.com/privacybydesign/irmago/internal/test"
11
12
13
14
)

var client *Client

15
16
17
18
// Issue BSN credential using sessionHelper
func issue(t *testing.T, ms ManualSessionHandler) {
	name := "testip"

19
	jwtcontents := getIssuanceJwt(name, true, "")
20
21
22
23
24
25
	sessionHandlerHelper(t, jwtcontents, "issue", client, &ms)
}

// Flip one bit in the proof string if invalidate is set to true
var invalidate bool

26
27
func corruptAndConvertProofString(proof string) []byte {
	proofBytes := []byte(proof)
28
	if invalidate {
29
30
		// 42 because this is somewhere in a bigint in the json string
		proofBytes[42] ^= 0x01
31
	}
32
	return proofBytes
33
34
}

35
36
37
// Create a ManualSessionHandler for unit tests
func createManualSessionHandler(request string, invalidRequest string, t *testing.T) ManualSessionHandler {
	errorChannel := make(chan *irma.SessionError)
38
	resultChannel := make(chan *irma.SignatureProofResult)
39

40
	sigRequestJSON := []byte(request)
41
	invalidSigRequestJSON := []byte(invalidRequest)
42
	sigRequest := &irma.SignatureRequest{}
43
	invalidSigRequest := &irma.SignatureRequest{}
44
	json.Unmarshal(sigRequestJSON, sigRequest)
45
46
47
48
49
50
51
52
53
54
55
56
57
	json.Unmarshal(invalidSigRequestJSON, invalidSigRequest)

	return ManualSessionHandler{
		t:                t,
		errorChannel:     errorChannel,
		resultChannel:    resultChannel,
		sigRequest:       sigRequest,
		sigVerifyRequest: invalidSigRequest,
	}
}

func TestManualSession(t *testing.T) {
	invalidate = false
58

59
	request := "{\"nonce\": 42, \"context\": 1337, \"type\": \"signing\", \"message\":\"I owe you everything\",\"content\":[{\"label\":\"Student number (RU)\",\"attributes\":[\"irma-demo.RU.studentCard.studentID\"]}]}"
60
61
62
	ms := createManualSessionHandler(request, request, t)

	client = parseStorage(t)
63
	client.NewSession(request, &ms)
64
65

	if err := <-ms.errorChannel; err != nil {
Koen van Ingen's avatar
Koen van Ingen committed
66
		test.ClearTestStorage(t)
67
68
69
70
		t.Fatal(*err)
	}

	// No errors, obtain proof result from channel
71
	result := <-ms.resultChannel
72
73
	if ps := result.ProofStatus; ps != irma.ProofStatusValid {
		t.Logf("Invalid proof result: %v Expected: %v", ps, irma.ProofStatusValid)
74
		t.Fatal()
75
	}
76
77
	if attrStatus := result.ToAttributeResultList()[0].AttributeProofStatus; attrStatus != irma.AttributeProofStatusPresent {
		t.Logf("Invalid attribute result value: %v Expected: %v", attrStatus, irma.AttributeProofStatusPresent)
78
		t.Fail()
79
	}
80
81
	test.ClearTestStorage(t)
}
82

83
84
85
86
// Test if the session fails with unsatisfiable error if we cannot satify the signature request
func TestManualSessionUnsatisfiable(t *testing.T) {
	invalidate = false

87
	request := "{\"nonce\": 0, \"context\": 0, \"type\": \"signing\", \"message\":\"I owe you everything\",\"content\":[{\"label\":\"Student number (RU)\",\"attributes\":{\"irma-demo.RU.studentCard.studentID\": \"123\"}}]}"
88
89
90
	ms := createManualSessionHandler(request, request, t)

	client = parseStorage(t)
91
	client.NewSession(request, &ms)
92
93
94

	// Fail test if we won't get UnsatisfiableRequest error
	if err := <-ms.errorChannel; err.ErrorType != irma.ErrorType("UnsatisfiableRequest") {
Koen van Ingen's avatar
Koen van Ingen committed
95
		test.ClearTestStorage(t)
96
97
98
99
100
101
102
103
104
		t.Fatal(*err)
	}
	test.ClearTestStorage(t)
}

// Test if proof verification fails with status 'ERROR_CRYPTO' if we verify it with an invalid nonce
func TestManualSessionInvalidNonce(t *testing.T) {
	invalidate = false

105
106
	request := "{\"nonce\": 0, \"context\": 0, \"type\": \"signing\", \"message\":\"I owe you everything\",\"content\":[{\"label\":\"Student number (RU)\",\"attributes\":[\"irma-demo.RU.studentCard.studentID\"]}]}"
	invalidRequest := "{\"nonce\": 1, \"context\": 0, \"type\": \"signing\", \"message\":\"I owe you everything\",\"content\":[{\"label\":\"Student number (RU)\",\"attributes\":[\"irma-demo.RU.studentCard.studentID\"]}]}"
107
108
109
110

	ms := createManualSessionHandler(request, invalidRequest, t)

	client = parseStorage(t)
111
	client.NewSession(request, &ms)
112

113
	if err := <-ms.errorChannel; err != nil {
Koen van Ingen's avatar
Koen van Ingen committed
114
		test.ClearTestStorage(t)
115
116
		t.Fatal(*err)
	}
117

118
	// No errors, obtain proof result from channel
119
120
	if result := <-ms.resultChannel; result.ProofStatus != irma.ProofStatusUnmatchedRequest {
		t.Logf("Invalid proof result: %v Expected: %v", result.ProofStatus, irma.ProofStatusUnmatchedRequest)
121
122
		t.Fail()
	}
123
	test.ClearTestStorage(t)
124
125
}

126
127
// Test if proof verification fails with status 'MISSING_ATTRIBUTES' if we provide it with a non-matching signature request
func TestManualSessionInvalidRequest(t *testing.T) {
128
129
	invalidate = false

130
131
	request := "{\"nonce\": 0, \"context\": 0, \"type\": \"signing\", \"message\":\"I owe you everything\",\"content\":[{\"label\":\"Student number (RU)\",\"attributes\":[\"irma-demo.RU.studentCard.studentID\"]}]}"
	invalidRequest := "{\"nonce\": 0, \"context\": 0, \"type\": \"signing\", \"message\":\"I owe you everything\",\"content\":[{\"label\":\"Student number (RU)\",\"attributes\":[\"irma-demo.RU.studentCard.university\"]}]}"
132
133
134
135

	ms := createManualSessionHandler(request, invalidRequest, t)

	client = parseStorage(t)
136
	client.NewSession(request, &ms)
137
138

	if err := <-ms.errorChannel; err != nil {
Koen van Ingen's avatar
Koen van Ingen committed
139
		test.ClearTestStorage(t)
140
141
		t.Fatal(*err)
	}
142

143
	// No errors, obtain proof result from channel
144
	result := <-ms.resultChannel
145
146
	if ps := result.ProofStatus; ps != irma.ProofStatusMissingAttributes {
		t.Logf("Invalid proof result: %v Expected: %v", ps, irma.ProofStatusMissingAttributes)
147
148
		t.Fail()
	}
149
150

	// First attribute result is MISSING, because it is in the request but not disclosed
151
152
	if attrStatus := result.ToAttributeResultList()[0].AttributeProofStatus; attrStatus != irma.AttributeProofStatusMissing {
		t.Logf("Invalid attribute result value: %v Expected: %v", attrStatus, irma.AttributeProofStatusMissing)
153
154
		t.Fail()
	}
155
	// Second attribute result is EXTRA, since it is disclosed, but not matching the sigrequest
156
157
	if attrStatus := result.ToAttributeResultList()[1].AttributeProofStatus; attrStatus != irma.AttributeProofStatusExtra {
		t.Logf("Invalid attribute result value: %v Expected: %v", attrStatus, irma.AttributeProofStatusExtra)
158
		t.Fail()
159
	}
160
161
162
163
164
165
166
	test.ClearTestStorage(t)
}

// Test if proof verification fails with status 'MISSING_ATTRIBUTES' if we provide it with invalid attribute values
func TestManualSessionInvalidAttributeValue(t *testing.T) {
	invalidate = false

167
168
	request := "{\"nonce\": 0, \"context\": 0, \"type\": \"signing\", \"message\":\"I owe you everything\",\"content\":[{\"label\":\"Student number (RU)\",\"attributes\":{\"irma-demo.RU.studentCard.studentID\": \"456\"}}]}"
	invalidRequest := "{\"nonce\": 0, \"context\": 0, \"type\": \"signing\", \"message\":\"I owe you everything\",\"content\":[{\"label\":\"Student number (RU)\",\"attributes\":{\"irma-demo.RU.studentCard.studentID\": \"123\"}}]}"
169
170

	ms := createManualSessionHandler(request, invalidRequest, t)
171
172

	client = parseStorage(t)
173
	client.NewSession(request, &ms)
174

175
	if err := <-ms.errorChannel; err != nil {
Koen van Ingen's avatar
Koen van Ingen committed
176
		test.ClearTestStorage(t)
177
178
179
180
		t.Fatal(*err)
	}

	// No errors, obtain proof result from channel
181
	result := <-ms.resultChannel
182
183
	if ps := result.ProofStatus; ps != irma.ProofStatusMissingAttributes {
		t.Logf("Invalid proof result: %v Expected: %v", ps, irma.ProofStatusMissingAttributes)
184
185
		t.Fail()
	}
186
187
	if attrStatus := result.ToAttributeResultList()[0].AttributeProofStatus; attrStatus != irma.AttributeProofStatusInvalidValue {
		t.Logf("Invalid attribute result value: %v Expected: %v", attrStatus, irma.AttributeProofStatusInvalidValue)
188
189
190
191
192
193
194
195
		t.Fail()
	}
	test.ClearTestStorage(t)
}

func TestManualKeyShareSession(t *testing.T) {
	invalidate = false

196
	request := "{\"nonce\": 0, \"context\": 0, \"type\": \"signing\", \"message\":\"I owe you everything\",\"content\":[{\"label\":\"Student number (RU)\",\"attributes\":[\"test.test.mijnirma.email\"]}]}"
197

198
199
200
	ms := createManualSessionHandler(request, request, t)

	client = parseStorage(t)
201
	client.NewSession(request, &ms)
202
203

	if err := <-ms.errorChannel; err != nil {
Koen van Ingen's avatar
Koen van Ingen committed
204
		test.ClearTestStorage(t)
205
206
		t.Fatal(*err)
	}
207
208

	// No errors, obtain proof result from channel
209
210
	if result := <-ms.resultChannel; result.ProofStatus != irma.ProofStatusValid {
		t.Logf("Invalid proof result: %v Expected: %v", result.ProofStatus, irma.ProofStatusValid)
211
212
		t.Fail()
	}
213
	test.ClearTestStorage(t)
214
215
216
217
}

func TestManualSessionMultiProof(t *testing.T) {
	invalidate = false
218
219
	client = parseStorage(t)

220
	// First, we need to issue an extra credential (BSN)
221
	is := ManualSessionHandler{t: t, errorChannel: make(chan *irma.SessionError)}
222
	go issue(t, is)
223
	if err := <-is.errorChannel; err != nil {
224
225
226
227
228
		fmt.Println("Error during initial issueing!")
		t.Fatal(*err)
	}

	// Request to sign with both BSN and StudentID
229
	request := "{\"nonce\": 0, \"context\": 0, \"type\": \"signing\", \"message\":\"I owe you everything\",\"content\":[{\"label\":\"Student number (RU)\",\"attributes\":[\"irma-demo.RU.studentCard.studentID\"]},{\"label\":\"BSN\",\"attributes\":[\"irma-demo.MijnOverheid.root.BSN\"]}]}"
230

231
	ms := createManualSessionHandler(request, request, t)
232

233
	client.NewSession(request, &ms)
234

235
	if err := <-ms.errorChannel; err != nil {
Koen van Ingen's avatar
Koen van Ingen committed
236
		test.ClearTestStorage(t)
237
238
		t.Fatal(*err)
	}
239
240

	// No errors, obtain proof result from channel
241
	result := <-ms.resultChannel
242
243
	if ps := result.ProofStatus; ps != irma.ProofStatusValid {
		t.Logf("Invalid proof result: %v Expected: %v", result.ProofStatus, irma.ProofStatusValid)
244
245
		t.Fail()
	}
246
247
	if attrStatus := result.ToAttributeResultList()[0].AttributeProofStatus; attrStatus != irma.AttributeProofStatusPresent {
		t.Logf("Invalid attribute result value: %v Expected: %v", attrStatus, irma.AttributeProofStatusPresent)
248
249
		t.Fail()
	}
250
251
	if attrStatus := result.ToAttributeResultList()[1].AttributeProofStatus; attrStatus != irma.AttributeProofStatusPresent {
		t.Logf("Invalid attribute result value: %v Expected: %v", attrStatus, irma.AttributeProofStatusPresent)
252
253
		t.Fail()
	}
254
	test.ClearTestStorage(t)
255
256
}

257
258
259
func TestManualSessionInvalidProof(t *testing.T) {
	invalidate = true

260
	request := "{\"nonce\": 0, \"context\": 0, \"type\": \"signing\", \"message\":\"I owe you everything\",\"content\":[{\"label\":\"Student number (RU)\",\"attributes\":[\"irma-demo.RU.studentCard.studentID\"]}]}"
261
	ms := createManualSessionHandler(request, request, t)
262

263
	client = parseStorage(t)
264
	client.NewSession(request, &ms)
265

266
	if err := <-ms.errorChannel; err != nil {
Koen van Ingen's avatar
Koen van Ingen committed
267
		test.ClearTestStorage(t)
268
269
		t.Fatal(*err)
	}
270
271

	// No errors, obtain proof result from channel
272
273
	if result := <-ms.resultChannel; result.ProofStatus != irma.ProofStatusInvalidCrypto {
		t.Logf("Invalid proof result: %v Expected: %v", result.ProofStatus, irma.ProofStatusInvalidCrypto)
274
275
		t.Fail()
	}
276
	test.ClearTestStorage(t)
277
}