Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
IRMA
Github mirrors
irmago
Commits
35fb735e
Commit
35fb735e
authored
Sep 29, 2017
by
Sietse Ringers
Browse files
Load Idemix public keys on demand
parent
4b0c6374
Changes
7
Hide whitespace changes
Inline
Side-by-side
attributes.go
View file @
35fb735e
...
...
@@ -134,11 +134,15 @@ func (attr *MetadataAttribute) Bytes() []byte {
// PublicKey extracts identifier of the Idemix public key with which this instance was signed,
// and returns this public key.
func
(
attr
*
MetadataAttribute
)
PublicKey
()
*
gabi
.
PublicKey
{
func
(
attr
*
MetadataAttribute
)
PublicKey
()
(
*
gabi
.
PublicKey
,
error
)
{
if
attr
.
pk
==
nil
{
attr
.
pk
=
attr
.
store
.
PublicKey
(
attr
.
CredentialType
()
.
IssuerIdentifier
(),
attr
.
KeyCounter
())
var
err
error
attr
.
pk
,
err
=
attr
.
store
.
PublicKey
(
attr
.
CredentialType
()
.
IssuerIdentifier
(),
attr
.
KeyCounter
())
if
err
!=
nil
{
return
nil
,
err
}
}
return
attr
.
pk
return
attr
.
pk
,
nil
}
// Version returns the metadata version of this instance
...
...
credential.go
View file @
35fb735e
...
...
@@ -53,14 +53,18 @@ func NewCredentialInfo(ints []*big.Int, store *ConfigurationStore) *CredentialIn
}
}
func
newCredential
(
gabicred
*
gabi
.
Credential
,
store
*
ConfigurationStore
)
(
cred
*
credential
)
{
func
newCredential
(
gabicred
*
gabi
.
Credential
,
store
*
ConfigurationStore
)
(
*
credential
,
error
)
{
meta
:=
MetadataFromInt
(
gabicred
.
Attributes
[
1
],
store
)
cred
=
&
credential
{
cred
:
=
&
credential
{
Credential
:
gabicred
,
MetadataAttribute
:
meta
,
}
cred
.
Pk
=
store
.
PublicKey
(
meta
.
CredentialType
()
.
IssuerIdentifier
(),
cred
.
KeyCounter
())
return
var
err
error
cred
.
Pk
,
err
=
store
.
PublicKey
(
meta
.
CredentialType
()
.
IssuerIdentifier
(),
cred
.
KeyCounter
())
if
err
!=
nil
{
return
nil
,
err
}
return
cred
,
nil
}
// Len implements sort.Interface.
...
...
descriptions.go
View file @
35fb735e
...
...
@@ -4,8 +4,6 @@ import (
"encoding/xml"
"errors"
"github.com/mhe/gabi"
)
// SchemeManager describes a scheme manager.
...
...
@@ -131,21 +129,3 @@ func (sm *SchemeManager) Identifier() SchemeManagerIdentifier {
func
(
sm
*
SchemeManager
)
Distributed
()
bool
{
return
len
(
sm
.
KeyshareServer
)
>
0
}
// CurrentPublicKey returns the latest known public key of the issuer identified by this instance.
func
(
id
*
Issuer
)
CurrentPublicKey
(
store
*
ConfigurationStore
)
*
gabi
.
PublicKey
{
keys
:=
store
.
PublicKeys
[
id
.
Identifier
()]
if
keys
==
nil
||
len
(
keys
)
==
0
{
return
nil
}
return
keys
[
len
(
keys
)
-
1
]
}
// PublicKey returns the specified public key of the issuer identified by this instance.
func
(
id
*
Issuer
)
PublicKey
(
index
int
,
store
*
ConfigurationStore
)
*
gabi
.
PublicKey
{
keys
:=
store
.
PublicKeys
[
id
.
Identifier
()]
if
keys
==
nil
||
index
>=
len
(
keys
)
{
return
nil
}
return
keys
[
index
]
}
irmago_test.go
View file @
35fb735e
...
...
@@ -10,7 +10,6 @@ import (
"encoding/json"
"github.com/mhe/gabi"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
...
...
@@ -47,7 +46,7 @@ func parseStorage(t *testing.T) *CredentialManager {
}
func
teardown
(
t
*
testing
.
T
)
{
assert
.
NoError
(
t
,
os
.
RemoveAll
(
"testdata/storage/test"
))
require
.
NoError
(
t
,
os
.
RemoveAll
(
"testdata/storage/test"
))
}
// A convenience function for initializing big integers from known correct (10
...
...
@@ -58,33 +57,39 @@ func s2big(s string) (r *big.Int) {
}
func
parseAndroidStorage
(
t
*
testing
.
T
,
manager
*
CredentialManager
)
{
assert
.
NoError
(
t
,
manager
.
ParseAndroidStorage
(),
"ParseAndroidStorage() failed"
)
require
.
NoError
(
t
,
manager
.
ParseAndroidStorage
(),
"ParseAndroidStorage() failed"
)
}
func
verifyManagerIsUnmarshaled
(
t
*
testing
.
T
,
manager
*
CredentialManager
)
{
cred
,
err
:=
manager
.
credential
(
NewCredentialTypeIdentifier
(
"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"
)
require
.
NoError
(
t
,
err
,
"could not fetch credential"
)
require
.
NotNil
(
t
,
cred
,
"Credential should exist"
)
require
.
NotNil
(
t
,
cred
.
Attributes
[
0
],
"Metadata attribute of irma-demo.RU.studentCard should not be nil"
)
cred
,
err
=
manager
.
credential
(
NewCredentialTypeIdentifier
(
"test.test.mijnirma"
),
0
)
assert
.
NoError
(
t
,
err
,
"could not fetch credential"
)
assert
.
NotNil
(
t
,
cred
,
"Credential should exist"
)
assert
.
NotNil
(
t
,
cred
.
Signature
.
KeyshareP
)
require
.
NoError
(
t
,
err
,
"could not fetch credential"
)
require
.
NotNil
(
t
,
cred
,
"Credential should exist"
)
require
.
NotNil
(
t
,
cred
.
Signature
.
KeyshareP
)
assert
.
NotEmpty
(
t
,
manager
.
CredentialInfoList
())
require
.
NotEmpty
(
t
,
manager
.
CredentialInfoList
())
assert
.
True
(
t
,
cred
.
Signature
.
Verify
(
cred
.
PublicKey
(),
cred
.
Attributes
),
pk
,
err
:=
cred
.
PublicKey
()
require
.
NoError
(
t
,
err
)
require
.
True
(
t
,
cred
.
Signature
.
Verify
(
pk
,
cred
.
Attributes
),
"Credential should be valid"
,
)
}
func
verifyCredentials
(
t
*
testing
.
T
,
manager
*
CredentialManager
)
{
var
pk
*
gabi
.
PublicKey
var
err
error
for
credtype
,
credsmap
:=
range
manager
.
credentials
{
for
index
,
cred
:=
range
credsmap
{
pk
,
err
=
cred
.
PublicKey
()
require
.
NoError
(
t
,
err
)
require
.
True
(
t
,
cred
.
Credential
.
Signature
.
Verify
(
cred
.
PublicKey
()
,
cred
.
Attributes
),
cred
.
Credential
.
Signature
.
Verify
(
pk
,
cred
.
Attributes
),
"Credential %s-%d was invalid"
,
credtype
.
String
(),
index
,
)
require
.
Equal
(
t
,
cred
.
Attributes
[
0
],
manager
.
secretkey
,
...
...
@@ -123,30 +128,33 @@ func verifyKeyshareIsUnmarshaled(t *testing.T, manager *CredentialManager) {
}
func
verifyStoreIsLoaded
(
t
*
testing
.
T
,
store
*
ConfigurationStore
)
{
assert
.
NotNil
(
t
,
store
.
Issuers
[
NewIssuerIdentifier
(
"irma-demo.RU"
)]
.
CurrentPublicKey
(
store
)
.
N
,
"irma-demo.RU public key has no modulus"
)
assert
.
Equal
(
t
,
pk
,
err
:=
store
.
PublicKey
(
NewIssuerIdentifier
(
"irma-demo.RU"
),
0
)
require
.
NoError
(
t
,
err
)
require
.
NotNil
(
t
,
pk
)
require
.
NotNil
(
t
,
pk
.
N
,
"irma-demo.RU public key has no modulus"
)
require
.
Equal
(
t
,
"Irma Demo"
,
store
.
SchemeManagers
[
NewSchemeManagerIdentifier
(
"irma-demo"
)]
.
Name
[
"en"
],
"irma-demo scheme manager has unexpected name"
)
assert
.
Equal
(
t
,
require
.
Equal
(
t
,
"Radboud Universiteit Nijmegen"
,
store
.
Issuers
[
NewIssuerIdentifier
(
"irma-demo.RU"
)]
.
Name
[
"en"
],
"irma-demo.RU issuer has unexpected name"
)
assert
.
Equal
(
t
,
require
.
Equal
(
t
,
"Student Card"
,
store
.
Credentials
[
NewCredentialTypeIdentifier
(
"irma-demo.RU.studentCard"
)]
.
ShortName
[
"en"
],
"irma-demo.RU.studentCard has unexpected name"
)
assert
.
Equal
(
t
,
require
.
Equal
(
t
,
"studentID"
,
store
.
Credentials
[
NewCredentialTypeIdentifier
(
"irma-demo.RU.studentCard"
)]
.
Attributes
[
2
]
.
ID
,
"irma-demo.RU.studentCard.studentID has unexpected name"
)
// Hash algorithm pseudocode:
// Base64(SHA256("irma-demo.RU.studentCard")[0:16])
assert
.
Contains
(
t
,
store
.
reverseHashes
,
"1stqlPad5edpfS1Na1U+DA=="
,
require
.
Contains
(
t
,
store
.
reverseHashes
,
"1stqlPad5edpfS1Na1U+DA=="
,
"irma-demo.RU.studentCard had improper hash"
)
assert
.
Contains
(
t
,
store
.
reverseHashes
,
"CLjnADMBYlFcuGOT7Z0xRg=="
,
require
.
Contains
(
t
,
store
.
reverseHashes
,
"CLjnADMBYlFcuGOT7Z0xRg=="
,
"irma-demo.MijnOverheid.root had improper hash"
)
}
...
...
@@ -198,17 +206,17 @@ func TestMetadataCompatibility(t *testing.T) {
// An actual metadata attribute of an IRMA credential extracted from the IRMA app
attr
:=
MetadataFromInt
(
s2big
(
"49043481832371145193140299771658227036446546573739245068"
),
store
)
assert
.
NotNil
(
t
,
attr
.
CredentialType
(),
"attr.CredentialType() should not be nil"
)
require
.
NotNil
(
t
,
attr
.
CredentialType
(),
"attr.CredentialType() should not be nil"
)
assert
.
Equal
(
t
,
require
.
Equal
(
t
,
NewCredentialTypeIdentifier
(
"irma-demo.RU.studentCard"
),
attr
.
CredentialType
()
.
Identifier
(),
"Metadata credential type was not irma-demo.RU.studentCard"
,
)
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"
)
require
.
Equal
(
t
,
byte
(
0x02
),
attr
.
Version
(),
"Unexpected metadata version"
)
require
.
Equal
(
t
,
time
.
Unix
(
1499904000
,
0
),
attr
.
SigningDate
(),
"Unexpected signing date"
)
require
.
Equal
(
t
,
time
.
Unix
(
1516233600
,
0
),
attr
.
Expiry
(),
"Unexpected expiry date"
)
require
.
Equal
(
t
,
2
,
attr
.
KeyCounter
(),
"Unexpected key counter"
)
teardown
(
t
)
}
...
...
manager.go
View file @
35fb735e
...
...
@@ -95,15 +95,21 @@ func (cm *CredentialManager) credential(id CredentialTypeIdentifier, counter int
return
nil
,
err
}
meta
:=
MetadataFromInt
(
ints
[
1
],
cm
.
Store
)
pk
:=
meta
.
PublicKey
()
pk
,
err
:=
meta
.
PublicKey
()
if
err
!=
nil
{
return
nil
,
err
}
if
pk
==
nil
{
return
nil
,
errors
.
New
(
"unknown public key"
)
}
cred
:=
newCredential
(
&
gabi
.
Credential
{
cred
,
err
:=
newCredential
(
&
gabi
.
Credential
{
Attributes
:
ints
,
Signature
:
sig
,
Pk
:
pk
,
},
cm
.
Store
)
if
err
!=
nil
{
return
nil
,
err
}
cm
.
credentials
[
id
][
counter
]
=
cred
}
...
...
@@ -263,7 +269,10 @@ func (cm *CredentialManager) IssuanceProofBuilders(request *IssuanceRequest) (ga
proofBuilders
:=
gabi
.
ProofBuilderList
([]
gabi
.
ProofBuilder
{})
for
_
,
futurecred
:=
range
request
.
Credentials
{
pk
:=
cm
.
Store
.
PublicKey
(
futurecred
.
Credential
.
IssuerIdentifier
(),
futurecred
.
KeyCounter
)
pk
,
err
:=
cm
.
Store
.
PublicKey
(
futurecred
.
Credential
.
IssuerIdentifier
(),
futurecred
.
KeyCounter
)
if
err
!=
nil
{
return
nil
,
err
}
credBuilder
:=
gabi
.
NewCredentialBuilder
(
pk
,
request
.
GetContext
(),
cm
.
secretkey
,
state
.
nonce2
)
request
.
state
.
builders
=
append
(
request
.
state
.
builders
,
credBuilder
)
proofBuilders
=
append
(
proofBuilders
,
credBuilder
)
...
...
@@ -297,7 +306,7 @@ func (cm *CredentialManager) ConstructCredentials(msg []*gabi.IssueSignatureMess
// First collect all credentials in a slice, so that if one of them induces an error,
// we save none of them to fail the session cleanly
creds
:=
[]
*
gabi
.
Credential
{}
gabi
creds
:=
[]
*
gabi
.
Credential
{}
for
i
,
sig
:=
range
msg
{
attrs
,
err
:=
request
.
Credentials
[
i
]
.
AttributeList
(
cm
.
Store
)
if
err
!=
nil
{
...
...
@@ -307,11 +316,15 @@ func (cm *CredentialManager) ConstructCredentials(msg []*gabi.IssueSignatureMess
if
err
!=
nil
{
return
err
}
creds
=
append
(
creds
,
cred
)
gabi
creds
=
append
(
gabi
creds
,
cred
)
}
for
_
,
cred
:=
range
creds
{
cm
.
addCredential
(
newCredential
(
cred
,
cm
.
Store
),
true
)
for
_
,
gabicred
:=
range
gabicreds
{
newcred
,
err
:=
newCredential
(
gabicred
,
cm
.
Store
)
if
err
!=
nil
{
return
err
}
cm
.
addCredential
(
newcred
,
true
)
}
return
nil
...
...
oldstorage.go
View file @
35fb735e
...
...
@@ -76,7 +76,10 @@ func (cm *CredentialManager) ParseAndroidStorage() (err error) {
if
oldcred
.
SharedPoints
!=
nil
&&
len
(
oldcred
.
SharedPoints
)
>
0
{
gabicred
.
Signature
.
KeyshareP
=
oldcred
.
SharedPoints
[
0
]
}
cred
:=
newCredential
(
gabicred
,
cm
.
Store
)
cred
,
err
:=
newCredential
(
gabicred
,
cm
.
Store
)
if
err
!=
nil
{
return
err
}
if
cred
.
CredentialType
()
==
nil
{
return
errors
.
New
(
"cannot add unknown credential type"
)
}
...
...
store.go
View file @
35fb735e
...
...
@@ -17,9 +17,10 @@ type ConfigurationStore struct {
SchemeManagers
map
[
SchemeManagerIdentifier
]
*
SchemeManager
Issuers
map
[
IssuerIdentifier
]
*
Issuer
Credentials
map
[
CredentialTypeIdentifier
]
*
CredentialType
PublicKeys
map
[
IssuerIdentifier
][]
*
gabi
.
PublicKey
publicKeys
map
[
IssuerIdentifier
][]
*
gabi
.
PublicKey
reverseHashes
map
[
string
]
CredentialTypeIdentifier
path
string
initialized
bool
}
...
...
@@ -28,20 +29,28 @@ func NewConfigurationStore() (store *ConfigurationStore) {
SchemeManagers
:
make
(
map
[
SchemeManagerIdentifier
]
*
SchemeManager
),
Issuers
:
make
(
map
[
IssuerIdentifier
]
*
Issuer
),
Credentials
:
make
(
map
[
CredentialTypeIdentifier
]
*
CredentialType
),
P
ublicKeys
:
make
(
map
[
IssuerIdentifier
][]
*
gabi
.
PublicKey
),
p
ublicKeys
:
make
(
map
[
IssuerIdentifier
][]
*
gabi
.
PublicKey
),
reverseHashes
:
make
(
map
[
string
]
CredentialTypeIdentifier
),
}
return
}
// PublicKey returns the specified public key, or nil if not present in the ConfigurationStore.
func
(
store
*
ConfigurationStore
)
PublicKey
(
id
IssuerIdentifier
,
counter
int
)
*
gabi
.
PublicKey
{
if
list
,
ok
:=
store
.
PublicKeys
[
id
];
ok
{
if
len
(
list
)
>
counter
{
return
list
[
counter
]
func
(
store
*
ConfigurationStore
)
PublicKey
(
id
IssuerIdentifier
,
counter
int
)
(
*
gabi
.
PublicKey
,
error
)
{
if
_
,
contains
:=
store
.
publicKeys
[
id
];
!
contains
{
store
.
publicKeys
[
id
]
=
[]
*
gabi
.
PublicKey
{}
err
:=
store
.
parseKeysFolder
(
id
)
if
err
!=
nil
{
return
nil
,
err
}
}
return
nil
list
:=
store
.
publicKeys
[
id
]
if
len
(
list
)
>
counter
{
return
list
[
counter
],
nil
}
return
nil
,
nil
}
func
(
store
*
ConfigurationStore
)
addReverseHash
(
credid
CredentialTypeIdentifier
)
{
...
...
@@ -64,6 +73,7 @@ func (store *ConfigurationStore) IsInitialized() bool {
// ParseFolder populates the current store by parsing the specified irma_configuration folder,
// listing the containing scheme managers, issuers, credential types and public keys.
func
(
store
*
ConfigurationStore
)
ParseFolder
(
path
string
)
error
{
store
.
path
=
path
err
:=
iterateSubfolders
(
path
,
func
(
dir
string
)
error
{
manager
:=
&
SchemeManager
{}
exists
,
err
:=
pathToDescription
(
dir
+
"/description.xml"
,
manager
)
...
...
@@ -95,13 +105,17 @@ func (store *ConfigurationStore) parseIssuerFolders(path string) error {
if
err
=
store
.
parseCredentialsFolder
(
dir
+
"/Issues/"
);
err
!=
nil
{
return
err
}
return
store
.
parseKeysFolder
(
issuer
,
dir
+
"/PublicKeys/"
)
}
return
nil
})
}
func
(
store
*
ConfigurationStore
)
parseKeysFolder
(
issuer
*
Issuer
,
path
string
)
error
{
func
(
store
*
ConfigurationStore
)
parseKeysFolder
(
issuerid
IssuerIdentifier
)
error
{
issuer
:=
store
.
Issuers
[
issuerid
]
path
:=
store
.
path
+
"/"
+
issuer
.
Identifier
()
.
SchemeManagerIdentifier
()
.
String
()
+
"/"
+
issuer
.
ID
+
"/PublicKeys/"
for
i
:=
0
;
;
i
++
{
file
:=
path
+
strconv
.
Itoa
(
i
)
+
".xml"
if
_
,
err
:=
os
.
Stat
(
file
);
err
!=
nil
{
...
...
@@ -112,7 +126,7 @@ func (store *ConfigurationStore) parseKeysFolder(issuer *Issuer, path string) er
return
err
}
pk
.
Issuer
=
issuer
.
Identifier
()
.
String
()
store
.
P
ublicKeys
[
issuer
.
Identifier
()]
=
append
(
store
.
P
ublicKeys
[
issuer
.
Identifier
()],
pk
)
store
.
p
ublicKeys
[
issuer
.
Identifier
()]
=
append
(
store
.
p
ublicKeys
[
issuer
.
Identifier
()],
pk
)
}
return
nil
}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment