irmago_test.go 4.59 KB
Newer Older
Sietse Ringers's avatar
Sietse Ringers committed
1
package irmago
2
3

import (
4
5
	"fmt"
	"math/big"
Sietse Ringers's avatar
Sietse Ringers committed
6
	"os"
7
8
	"testing"
	"time"
Sietse Ringers's avatar
Sietse Ringers committed
9

10
	"github.com/stretchr/testify/assert"
Sietse Ringers's avatar
Sietse Ringers committed
11
	"github.com/stretchr/testify/require"
12
13
)

Sietse Ringers's avatar
Sietse Ringers committed
14
func TestMain(m *testing.M) {
Sietse Ringers's avatar
Sietse Ringers committed
15
16
	retCode := m.Run()

Sietse Ringers's avatar
Sietse Ringers committed
17
18
	err := os.RemoveAll("testdata/storage/test")
	if err != nil {
Sietse Ringers's avatar
Sietse Ringers committed
19
		fmt.Println("Could not delete test storage")
Sietse Ringers's avatar
Sietse Ringers committed
20
21
22
		os.Exit(1)
	}

Sietse Ringers's avatar
Sietse Ringers committed
23
24
	os.Exit(retCode)
}
Sietse Ringers's avatar
Sietse Ringers committed
25

Sietse Ringers's avatar
Sietse Ringers committed
26
27
28
29
30
31
32
33
34
func parseMetaStore(t *testing.T) {
	require.NoError(t, MetaStore.ParseFolder("testdata/irma_configuration"), "MetaStore.ParseFolder() failed")
}

func parseStorage(t *testing.T) {
	exists, err := pathExists("testdata/storage/path")
	require.NoError(t, err, "pathexists() failed")
	if !exists {
		require.NoError(t, os.Mkdir("testdata/storage/test", 0755), "Could not create test storage")
Sietse Ringers's avatar
Sietse Ringers committed
35
	}
Sietse Ringers's avatar
Sietse Ringers committed
36
	require.NoError(t, Manager.Init("testdata/storage/test"), "Manager.Init() failed")
37

Sietse Ringers's avatar
Sietse Ringers committed
38
39
40
41
42
}

func teardown(t *testing.T) {
	MetaStore = newConfigurationStore()
	Manager = newCredentialManager()
43
	assert.NoError(t, os.RemoveAll("testdata/storage/test"))
Sietse Ringers's avatar
Sietse Ringers committed
44
45
}

46
47
48
49
50
51
52
// A convenience function for initializing big integers from known correct (10
// base) strings. Use with care, errors are ignored.
func s2big(s string) (r *big.Int) {
	r, _ = new(big.Int).SetString(s, 10)
	return
}

Sietse Ringers's avatar
Sietse Ringers committed
53
func parseAndroidStorage(t *testing.T) {
54
	assert.NoError(t, Manager.ParseAndroidStorage(), "ParseAndroidStorage() failed")
Sietse Ringers's avatar
Sietse Ringers committed
55
56
57
}

func verifyStoreIsUnmarshaled(t *testing.T) {
58
59
60
61
	cred, err := Manager.Credential(NewCredentialIdentifier("irma-demo.RU.studentCard"), 0)
	assert.NoError(t, err, "could not fetch credential")
	assert.NotNil(t, cred, "Credential should exist")
	assert.NotNil(t, cred.Attributes[0], "Metadata attribute of irma-demo.RU.studentCard should not be nil")
62

63
	assert.True(t,
Sietse Ringers's avatar
Sietse Ringers committed
64
		cred.Signature.Verify(cred.PublicKey(), cred.Attributes),
65
66
67
		"Credential should be valid",
	)
}
Sietse Ringers's avatar
Sietse Ringers committed
68
69

func TestAndroidParse(t *testing.T) {
Sietse Ringers's avatar
Sietse Ringers committed
70
71
	parseMetaStore(t)
	parseStorage(t)
Sietse Ringers's avatar
Sietse Ringers committed
72
73
	parseAndroidStorage(t)
	verifyStoreIsUnmarshaled(t)
Sietse Ringers's avatar
Sietse Ringers committed
74
75

	teardown(t)
Sietse Ringers's avatar
Sietse Ringers committed
76
77
78
}

func TestUnmarshaling(t *testing.T) {
Sietse Ringers's avatar
Sietse Ringers committed
79
80
	parseMetaStore(t)
	parseStorage(t)
Sietse Ringers's avatar
Sietse Ringers committed
81
82
83
84
85
86
	parseAndroidStorage(t)

	Manager = newCredentialManager()
	Manager.Init("testdata/storage/test")

	verifyStoreIsUnmarshaled(t)
Sietse Ringers's avatar
Sietse Ringers committed
87
88

	teardown(t)
Sietse Ringers's avatar
Sietse Ringers committed
89
}
90
91

func TestParseStore(t *testing.T) {
Sietse Ringers's avatar
Sietse Ringers committed
92
	parseMetaStore(t)
93

94
95
	assert.NotNil(t, MetaStore.Issuers[NewIssuerIdentifier("irma-demo.RU")].CurrentPublicKey().N, "irma-demo.RU public key has no modulus")
	assert.Equal(t,
96
		"Irma Demo",
97
		MetaStore.SchemeManagers[NewSchemeManagerIdentifier("irma-demo")].Name.Translation("en"),
98
		"irma-demo scheme manager has unexpected name")
99
	assert.Equal(t,
100
		"Radboud Universiteit Nijmegen",
101
		MetaStore.Issuers[NewIssuerIdentifier("irma-demo.RU")].Name.Translation("en"),
102
		"irma-demo.RU issuer has unexpected name")
103
	assert.Equal(t,
104
		"Student Card",
105
		MetaStore.Credentials[NewCredentialIdentifier("irma-demo.RU.studentCard")].ShortName.Translation("en"),
106
107
		"irma-demo.RU.studentCard has unexpected name")

108
	assert.Equal(t,
109
		"studentID",
110
		MetaStore.Credentials[NewCredentialIdentifier("irma-demo.RU.studentCard")].Attributes[2].ID,
111
112
113
114
		"irma-demo.RU.studentCard.studentID has unexpected name")

	// Hash algorithm pseudocode:
	// Base64(SHA256("irma-demo.RU.studentCard")[0:16])
115
	assert.Contains(t, MetaStore.reverseHashes, "1stqlPad5edpfS1Na1U+DA==",
116
		"irma-demo.RU.studentCard had improper hash")
117
	assert.Contains(t, MetaStore.reverseHashes, "CLjnADMBYlFcuGOT7Z0xRg==",
118
		"irma-demo.MijnOverheid.root had improper hash")
Sietse Ringers's avatar
Sietse Ringers committed
119
120

	teardown(t)
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
}

func TestMetadataAttribute(t *testing.T) {
	metadata := NewMetadataAttribute()
	if metadata.Version() != 0x02 {
		t.Errorf("Unexpected metadata version: %d", metadata.Version())
	}

	expiry := metadata.SigningDate().Unix() + int64(metadata.ValidityDuration()*ExpiryFactor)
	if !time.Unix(expiry, 0).Equal(metadata.Expiry()) {
		t.Errorf("Invalid signing date")
	}

	if metadata.KeyCounter() != 0 {
		t.Errorf("Unexpected key counter")
	}
}

func TestMetadataCompatibility(t *testing.T) {
Sietse Ringers's avatar
Sietse Ringers committed
140
	parseMetaStore(t)
141
142
143

	// An actual metadata attribute of an IRMA credential extracted from the IRMA app
	attr := MetadataFromInt(s2big("49043481832371145193140299771658227036446546573739245068"))
144
	assert.NotNil(t, attr.CredentialType(), "attr.CredentialType() should not be nil")
145

146
147
	assert.Equal(t,
		NewCredentialIdentifier("irma-demo.RU.studentCard"),
148
149
150
		attr.CredentialType().Identifier(),
		"Metadata credential type was not irma-demo.RU.studentCard",
	)
151
152
153
154
	assert.Equal(t, byte(0x02), attr.Version(), "Unexpected metadata version")
	assert.Equal(t, time.Unix(1499904000, 0), attr.SigningDate(), "Unexpected signing date")
	assert.Equal(t, time.Unix(1516233600, 0), attr.Expiry(), "Unexpected expiry date")
	assert.Equal(t, 2, attr.KeyCounter(), "Unexpected key counter")
Sietse Ringers's avatar
Sietse Ringers committed
155
156

	teardown(t)
157
}