Skip to content
GitLab
Menu
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
dfc27bea
Commit
dfc27bea
authored
Feb 22, 2018
by
Koen van Ingen
Browse files
Refactor and use different types for proof results
parent
1ac28e84
Changes
6
Hide whitespace changes
Inline
Side-by-side
attributes.go
View file @
dfc27bea
...
...
@@ -22,18 +22,18 @@ const (
type
AttributeResultList
struct
{
AttributeResults
[]
*
AttributeResult
}
type
AttributeResult
struct
{
AttributeValue
TranslatedString
// Value of the disclosed attribute
AttributeId
AttributeTypeIdentifier
AttributeProofStatus
AttributeProofStatus
AttributeValue
string
`json:"value"`
// Value of the disclosed attribute
AttributeId
AttributeTypeIdentifier
`json:"id"`
AttributeProofStatus
AttributeProofStatus
`json:"status"`
}
// AttributeProofStatus is the proof status of a single attribute
type
AttributeProofStatus
string
const
(
PRESENT
=
AttributeProofStatus
(
"PRESENT"
)
// Attribute is disclosed and matches the value
UNKNOWN
=
AttributeProofStatus
(
"
UNKNOWN"
)
// Attribute is disclosed, but status is yet unknown
PRESENT
=
AttributeProofStatus
(
"PRESENT"
)
// Attribute is disclosed and matches the value
EXTRA
=
AttributeProofStatus
(
"
EXTRA"
)
MISSING
=
AttributeProofStatus
(
"MISSING"
)
// Attribute is NOT disclosed, but should be according to request
INVALID_VALUE
=
AttributeProofStatus
(
"INVALID_VALUE"
)
// Attribute is disclosed, but has invalid value according to request
)
...
...
@@ -54,7 +54,7 @@ type metadataField struct {
offset
int
}
//
M
etadataAttribute represent a metadata attribute. Contains the credential type, signing date, validity, and the public key counter.
//
m
etadataAttribute represent
s
a metadata attribute. Contains the credential type, signing date, validity, and the public key counter.
type
MetadataAttribute
struct
{
Int
*
big
.
Int
pk
*
gabi
.
PublicKey
...
...
@@ -79,16 +79,6 @@ func NewAttributeListFromInts(ints []*big.Int, conf *Configuration) *AttributeLi
}
}
// NewAttributeListFromInts initializes a new AttributeList from disclosed attributes of a prooflist
func
NewAttributeListFromADisclosed
(
aResponses
map
[
int
]
*
big
.
Int
,
aDisclosed
map
[
int
]
*
big
.
Int
,
conf
*
Configuration
)
(
*
AttributeList
,
error
)
{
ints
,
err
:=
convertProofResponsesToInts
(
aResponses
,
aDisclosed
)
if
err
!=
nil
{
return
nil
,
err
}
return
NewAttributeListFromInts
(
ints
,
conf
),
nil
}
func
(
al
*
AttributeList
)
Info
()
*
CredentialInfo
{
if
al
.
info
==
nil
{
al
.
info
=
NewCredentialInfo
(
al
.
Ints
,
al
.
Conf
)
...
...
@@ -323,9 +313,27 @@ type AttributeDisjunction struct {
selected
*
AttributeTypeIdentifier
}
// AttributeDisjunction with the disclosed value. Label, Attributes,Valued can be nil if there is no matching disjunction
type
DisclosedAttributeDisjunction
struct
{
AttributeDisjunction
DisclosedValue
string
DisclosedId
AttributeTypeIdentifier
ProofStatus
AttributeProofStatus
}
// An AttributeDisjunctionList is a list of AttributeDisjunctions.
type
AttributeDisjunctionList
[]
*
AttributeDisjunction
func
NewDisclosedDisjunctionFromList
(
ad
*
AttributeDisjunction
,
ar
*
AttributeResult
)
*
DisclosedAttributeDisjunction
{
return
&
DisclosedAttributeDisjunction
{
AttributeDisjunction
:
*
ad
,
DisclosedValue
:
ar
.
AttributeValue
,
DisclosedId
:
ar
.
AttributeId
,
ProofStatus
:
ar
.
AttributeProofStatus
,
}
}
// HasValues indicates if the attributes of this disjunction have values
// that should be satisfied.
func
(
disjunction
*
AttributeDisjunction
)
HasValues
()
bool
{
...
...
@@ -350,58 +358,60 @@ func (disjunction *AttributeDisjunction) Satisfied() bool {
// This is the case if:
// attribute is contained in disclosed AND if a value is present: equal to that value
// al can be nil if you don't want to include attribute status for proof
func
isAttributeSatisfied
(
attribute
AttributeTypeIdentifier
,
value
string
,
disclosed
[]
*
CredentialInfo
,
conf
*
Configuration
,
al
*
AttributeResultList
)
bool
{
func
isAttributeSatisfied
(
attributeId
AttributeTypeIdentifier
,
requestedValue
string
,
disclosed
[]
*
DisclosedCredential
)
(
bool
,
*
AttributeResult
)
{
ar
:=
AttributeResult
{
AttributeId
:
attributeId
,
}
for
_
,
cred
:=
range
disclosed
{
credentialType
:=
cred
.
GetCredentialType
(
conf
)
index
,
err
:=
credentialType
.
IndexOf
(
attribute
)
disclosedAttributeValue
:=
cred
.
GetAttributeValue
(
attributeId
)
if
err
!=
nil
{
// Specified credential does not contain this attribute, move to next cred in list of disclosed credentials
// Continue to next credential if requested attribute isn't disclosed in this credential
if
disclosedAttributeValue
==
""
{
continue
}
disclosedAttributeValue
:=
cred
.
Attributes
[
index
]
// If it contains this attribute, check if value matches (it must be disclosed (i.e. not nil) and match the value)
// If this is the disclosed attribute, check if value matches
// Attribute is satisfied if:
// - Attribute is disclosed (i.e. not nil)
// - Value is empty OR value equal to disclosedValue
if
disclosedAttributeValue
!=
nil
{
if
value
==
""
||
disclosedAttributeValue
[
"en"
]
==
value
{
// TODO: fix translation/attr typing
al
.
SetProofStatus
(
attribute
,
disclosedAttributeValue
,
PRESENT
)
return
true
}
else
{
// If attribute is disclosed and present, but not equal to required value, mark it as invalid_value
//
We won't return true and continue searching in other disclosed attributes
al
.
SetProofStatus
(
attribute
,
disclosed
A
ttribute
Value
,
INVALID_VALUE
)
}
ar
.
AttributeValue
=
disclosedAttributeValue
if
requestedValue
==
""
||
disclosedAttributeValue
==
requestedValue
{
ar
.
AttributeProofStatus
=
PRESENT
return
true
,
&
ar
}
else
{
//
If attribute is disclosed and present, but not equal to required value, mark it as invalid_value
// We won't return true and continue searching in other
disclosed
a
ttribute
s
ar
.
AttributeProofStatus
=
INVALID_VALUE
}
}
return
false
// If there is never a value assigned, then this attribute isn't disclosed, and thus missing
if
ar
.
AttributeValue
==
""
{
ar
.
AttributeProofStatus
=
MISSING
}
return
false
,
&
ar
}
// Check whether specified attributedisjunction satisfy a list of disclosed attributes
// We return true if one of the attributes in the disjunction is satisfied
func
(
disjunction
*
AttributeDisjunction
)
SatisfyDisclosed
(
disclosed
[]
*
CredentialInfo
,
conf
*
Configuration
,
al
*
AttributeResultList
)
bool
{
func
(
disjunction
*
AttributeDisjunction
)
SatisfyDisclosed
(
disclosed
[]
*
DisclosedCredential
,
conf
*
Configuration
)
(
bool
,
*
DisclosedAttributeDisjunction
)
{
var
attributeResult
*
AttributeResult
for
_
,
attr
:=
range
disjunction
.
Attributes
{
v
alue
:=
disjunction
.
Values
[
attr
]
requestedV
alue
:=
disjunction
.
Values
[
attr
]
if
isAttributeSatisfied
(
attr
,
value
,
disclosed
,
conf
,
al
)
{
return
true
}
}
var
isSatisfied
bool
isSatisfied
,
attributeResult
=
isAttributeSatisfied
(
attr
,
requestedValue
,
disclosed
)
// Add all missing attributes
for
_
,
attr
:=
range
disjunction
.
Attributes
{
ar
:=
AttributeResult
{
AttributeId
:
attr
,
AttributeProofStatus
:
MISSING
,
}
if
!
al
.
ContainsAttributeId
(
ar
.
AttributeId
)
{
al
.
Append
(
ar
)
if
isSatisfied
{
return
true
,
NewDisclosedDisjunctionFromList
(
disjunction
,
attributeResult
)
}
}
return
false
// Nothing satisfied, attributeResult will contain the last attribute of the original request
// TODO: do we want this?
return
false
,
NewDisclosedDisjunctionFromList
(
disjunction
,
attributeResult
)
}
// MatchesConfig returns true if all attributes contained in the disjunction are
...
...
@@ -517,19 +527,8 @@ func (disjunction *AttributeDisjunction) UnmarshalJSON(bytes []byte) error {
return
nil
}
// From here attributeResult related functions. TODO: move to separate file?
func
(
al
*
AttributeResultList
)
Append
(
result
AttributeResult
)
{
al
.
AttributeResults
=
append
(
al
.
AttributeResults
,
&
result
)
}
func
(
al
*
AttributeResultList
)
ContainsAttributeId
(
attrId
AttributeTypeIdentifier
)
bool
{
for
_
,
ar
:=
range
al
.
AttributeResults
{
if
ar
.
AttributeId
==
attrId
{
return
true
}
}
return
false
func
(
al
*
AttributeResultList
)
Append
(
result
*
AttributeResult
)
{
al
.
AttributeResults
=
append
(
al
.
AttributeResults
,
result
)
}
func
(
al
*
AttributeResultList
)
String
()
string
{
...
...
@@ -541,62 +540,9 @@ func (al *AttributeResultList) String() string {
return
str
}
// Set the proof status to a new status for a specified attribute. An attribute is specified by an attributeTypeIdentifier
func
(
al
*
AttributeResultList
)
SetProofStatus
(
attrID
AttributeTypeIdentifier
,
attrValue
TranslatedString
,
status
AttributeProofStatus
)
bool
{
for
_
,
ar
:=
range
al
.
AttributeResults
{
// TODO: translation
if
ar
.
AttributeId
==
attrID
&&
ar
.
AttributeValue
[
"en"
]
==
attrValue
[
"en"
]
{
ar
.
AttributeProofStatus
=
status
return
true
}
}
return
false
}
func
(
ar
*
AttributeResult
)
GetAttributeDescription
(
conf
*
Configuration
)
(
*
AttributeDescription
,
error
)
{
cred
:=
conf
.
CredentialTypes
[
NewCredentialTypeIdentifier
(
ar
.
AttributeId
.
Parent
())]
index
,
err
:=
cred
.
IndexOf
(
ar
.
AttributeId
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
cred
.
Attributes
[
index
],
nil
}
func
(
ar
*
AttributeResult
)
String
()
string
{
// TODO: translated string!
return
fmt
.
Sprintf
(
"%v --- %v --- %v"
,
ar
.
AttributeId
,
ar
.
AttributeValue
[
"en"
]
,
ar
.
AttributeValue
,
ar
.
AttributeProofStatus
)
}
func
AttributeResultListFromDisclosed
(
disclosed
[]
*
CredentialInfo
,
conf
*
Configuration
)
*
AttributeResultList
{
al
:=
AttributeResultList
{}
for
_
,
cred
:=
range
disclosed
{
credentialType
:=
cred
.
GetCredentialType
(
conf
)
for
_
,
attr
:=
range
credentialType
.
Attributes
{
attrId
:=
NewAttributeTypeIdentifier
(
cred
.
CredentialTypeID
.
String
()
+
"."
+
attr
.
ID
)
index
,
err
:=
credentialType
.
IndexOf
(
attrId
)
if
err
!=
nil
{
// Specified credential does not contain this attribute, move to next
break
}
disclosedAttributeValue
:=
cred
.
Attributes
[
index
]
if
disclosedAttributeValue
!=
nil
{
al
.
Append
(
AttributeResult
{
AttributeValue
:
disclosedAttributeValue
,
AttributeId
:
attrId
,
AttributeProofStatus
:
UNKNOWN
,
})
}
}
}
return
&
al
}
credinfo.go
View file @
dfc27bea
...
...
@@ -48,41 +48,6 @@ func NewCredentialInfo(ints []*big.Int, conf *Configuration) *CredentialInfo {
}
}
// Convert proof responses to Ints, adding nils for undislosed attributes
func
convertProofResponsesToInts
(
aResponses
map
[
int
]
*
big
.
Int
,
aDisclosed
map
[
int
]
*
big
.
Int
)
([]
*
big
.
Int
,
error
)
{
var
ints
[]
*
big
.
Int
length
:=
len
(
aResponses
)
+
len
(
aDisclosed
)
for
i
:=
1
;
i
<
length
;
i
++
{
if
aResponses
[
i
]
==
nil
{
if
aDisclosed
[
i
]
==
nil
{
// If index not found in aResponses it must be in aDisclosed
return
nil
,
&
SessionError
{
ErrorType
:
ErrorCrypto
,
Info
:
fmt
.
Sprintf
(
"Missing attribute index: %v"
,
i
),
}
// TODO: error type?
}
ints
=
append
(
ints
,
aDisclosed
[
i
])
}
else
{
// Don't include value of hidden attributes
ints
=
append
(
ints
,
nil
)
}
}
return
ints
,
nil
}
// NewAttributeListFromInts initializes a new AttributeList from disclosed attributes of a prooflist
func
NewCredentialInfoFromADisclosed
(
aResponses
map
[
int
]
*
big
.
Int
,
aDisclosed
map
[
int
]
*
big
.
Int
,
conf
*
Configuration
)
(
*
CredentialInfo
,
error
)
{
ints
,
err
:=
convertProofResponsesToInts
(
aResponses
,
aDisclosed
)
if
err
!=
nil
{
return
nil
,
err
}
return
NewCredentialInfo
(
ints
,
conf
),
nil
}
func
(
ci
CredentialInfo
)
GetCredentialType
(
conf
*
Configuration
)
*
CredentialType
{
return
conf
.
CredentialTypes
[
ci
.
CredentialTypeID
]
}
...
...
descriptions.go
View file @
dfc27bea
...
...
@@ -81,6 +81,10 @@ type AttributeDescription struct {
Description
TranslatedString
}
func
(
ad
AttributeDescription
)
GetAttributeTypeIdentifier
(
cred
CredentialTypeIdentifier
)
AttributeTypeIdentifier
{
return
NewAttributeTypeIdentifier
(
cred
.
String
()
+
"."
+
ad
.
ID
)
}
// IndexOf returns the index of the specified attribute if present,
// or an error (and -1) if not present.
func
(
ct
CredentialType
)
IndexOf
(
ai
AttributeTypeIdentifier
)
(
int
,
error
)
{
...
...
irmaclient/manual_session_test.go
View file @
dfc27bea
...
...
@@ -10,17 +10,12 @@ import (
"testing"
)
type
Result
struct
{
proofStatus
ProofStatus
attributes
*
irma
.
AttributeResultList
}
type
ManualSessionHandler
struct
{
permissionHandler
PermissionHandler
pinHandler
PinHandler
t
*
testing
.
T
errorChannel
chan
*
irma
.
SessionError
resultChannel
chan
Result
resultChannel
chan
*
irma
.
SignatureProof
Result
sigRequest
*
irma
.
SignatureRequest
// Request used to create signature
sigVerifyRequest
*
irma
.
SignatureRequest
// Request used to verify signature
}
...
...
@@ -56,7 +51,7 @@ func corruptProofString(proof string) string {
// Create a ManualSessionHandler for unit tests
func
createManualSessionHandler
(
request
string
,
invalidRequest
string
,
t
*
testing
.
T
)
ManualSessionHandler
{
errorChannel
:=
make
(
chan
*
irma
.
SessionError
)
resultChannel
:=
make
(
chan
Result
)
resultChannel
:=
make
(
chan
*
irma
.
SignatureProof
Result
)
sigRequestJSON
:=
[]
byte
(
request
)
invalidSigRequestJSON
:=
[]
byte
(
invalidRequest
)
...
...
@@ -90,11 +85,11 @@ func TestManualSession(t *testing.T) {
// No errors, obtain proof result from channel
result
:=
<-
ms
.
resultChannel
if
ps
:=
result
.
p
roofStatus
;
ps
!=
VALID
{
t
.
Logf
(
"Invalid proof result: %v Expected: %v"
,
ps
,
VALID
)
if
ps
:=
result
.
P
roofStatus
;
ps
!=
irma
.
VALID
{
t
.
Logf
(
"Invalid proof result: %v Expected: %v"
,
ps
,
irma
.
VALID
)
t
.
Fail
()
}
if
attrStatus
:=
result
.
a
ttribute
s
.
AttributeResults
[
0
]
.
AttributeProofStatus
;
attrStatus
!=
irma
.
PRESENT
{
if
attrStatus
:=
result
.
ToA
ttribute
ResultList
()
.
AttributeResults
[
0
]
.
AttributeProofStatus
;
attrStatus
!=
irma
.
PRESENT
{
t
.
Logf
(
"Invalid attribute result value: %v Expected: %v"
,
attrStatus
,
irma
.
PRESENT
)
t
.
Fail
()
}
...
...
@@ -137,8 +132,8 @@ func TestManualSessionInvalidNonce(t *testing.T) {
}
// No errors, obtain proof result from channel
if
result
:=
<-
ms
.
resultChannel
;
result
.
p
roofStatus
!=
INVALID_CRYPTO
{
t
.
Logf
(
"Invalid proof result: %v Expected: %v"
,
result
.
p
roofStatus
,
INVALID_CRYPTO
)
if
result
:=
<-
ms
.
resultChannel
;
result
.
P
roofStatus
!=
irma
.
INVALID_CRYPTO
{
t
.
Logf
(
"Invalid proof result: %v Expected: %v"
,
result
.
P
roofStatus
,
irma
.
INVALID_CRYPTO
)
t
.
Fail
()
}
test
.
ClearTestStorage
(
t
)
...
...
@@ -163,18 +158,19 @@ func TestManualSessionInvalidRequest(t *testing.T) {
// No errors, obtain proof result from channel
result
:=
<-
ms
.
resultChannel
if
ps
:=
result
.
p
roofStatus
;
ps
!=
MISSING_ATTRIBUTES
{
t
.
Logf
(
"Invalid proof result: %v Expected: %v"
,
ps
,
MISSING_ATTRIBUTES
)
if
ps
:=
result
.
P
roofStatus
;
ps
!=
irma
.
MISSING_ATTRIBUTES
{
t
.
Logf
(
"Invalid proof result: %v Expected: %v"
,
ps
,
irma
.
MISSING_ATTRIBUTES
)
t
.
Fail
()
}
// First attribute result is UNKOWN, since it is disclosed, but not matching the sigrequest
if
attrStatus
:=
result
.
attributes
.
AttributeResults
[
0
]
.
AttributeProofStatus
;
attrStatus
!=
irma
.
UNKNOWN
{
t
.
Logf
(
"Invalid attribute result value: %v Expected: %v"
,
attrStatus
,
irma
.
UNKNOWN
)
// First attribute result is MISSING, because it is in the request but not disclosed
if
attrStatus
:=
result
.
ToAttributeResultList
()
.
AttributeResults
[
0
]
.
AttributeProofStatus
;
attrStatus
!=
irma
.
MISSING
{
t
.
Logf
(
"Invalid attribute result value: %v Expected: %v"
,
attrStatus
,
irma
.
MISSING
)
t
.
Fail
()
}
// Second attribute result is
MISSING, because it is in the request but not disclosed
if
attrStatus
:=
result
.
a
ttribute
s
.
AttributeResults
[
1
]
.
AttributeProofStatus
;
attrStatus
!=
irma
.
MISSING
{
t
.
Logf
(
"Invalid attribute result value: %v Expected: %v"
,
attrStatus
,
irma
.
MISSING
)
// Second attribute result is
EXTRA, since it is disclosed, but not matching the sigrequest
if
attrStatus
:=
result
.
ToA
ttribute
ResultList
()
.
AttributeResults
[
1
]
.
AttributeProofStatus
;
attrStatus
!=
irma
.
EXTRA
{
t
.
Logf
(
"Invalid attribute result value: %v Expected: %v"
,
attrStatus
,
irma
.
EXTRA
)
t
.
Fail
()
}
test
.
ClearTestStorage
(
t
)
...
...
@@ -199,11 +195,11 @@ func TestManualSessionInvalidAttributeValue(t *testing.T) {
// No errors, obtain proof result from channel
result
:=
<-
ms
.
resultChannel
if
ps
:=
result
.
p
roofStatus
;
ps
!=
MISSING_ATTRIBUTES
{
t
.
Logf
(
"Invalid proof result: %v Expected: %v"
,
ps
,
MISSING_ATTRIBUTES
)
if
ps
:=
result
.
P
roofStatus
;
ps
!=
irma
.
MISSING_ATTRIBUTES
{
t
.
Logf
(
"Invalid proof result: %v Expected: %v"
,
ps
,
irma
.
MISSING_ATTRIBUTES
)
t
.
Fail
()
}
if
attrStatus
:=
result
.
a
ttribute
s
.
AttributeResults
[
0
]
.
AttributeProofStatus
;
attrStatus
!=
irma
.
INVALID_VALUE
{
if
attrStatus
:=
result
.
ToA
ttribute
ResultList
()
.
AttributeResults
[
0
]
.
AttributeProofStatus
;
attrStatus
!=
irma
.
INVALID_VALUE
{
t
.
Logf
(
"Invalid attribute result value: %v Expected: %v"
,
attrStatus
,
irma
.
INVALID_VALUE
)
t
.
Fail
()
}
...
...
@@ -226,8 +222,8 @@ func TestManualKeyShareSession(t *testing.T) {
}
// No errors, obtain proof result from channel
if
result
:=
<-
ms
.
resultChannel
;
result
.
p
roofStatus
!=
VALID
{
t
.
Logf
(
"Invalid proof result: %v Expected: %v"
,
result
.
p
roofStatus
,
VALID
)
if
result
:=
<-
ms
.
resultChannel
;
result
.
P
roofStatus
!=
irma
.
VALID
{
t
.
Logf
(
"Invalid proof result: %v Expected: %v"
,
result
.
P
roofStatus
,
irma
.
VALID
)
t
.
Fail
()
}
test
.
ClearTestStorage
(
t
)
...
...
@@ -258,8 +254,17 @@ func TestManualSessionMultiProof(t *testing.T) {
}
// No errors, obtain proof result from channel
if
result
:=
<-
ms
.
resultChannel
;
result
.
proofStatus
!=
VALID
{
t
.
Logf
(
"Invalid proof result: %v Expected: %v"
,
result
.
proofStatus
,
VALID
)
result
:=
<-
ms
.
resultChannel
if
ps
:=
result
.
ProofStatus
;
ps
!=
irma
.
VALID
{
t
.
Logf
(
"Invalid proof result: %v Expected: %v"
,
result
.
ProofStatus
,
irma
.
VALID
)
t
.
Fail
()
}
if
attrStatus
:=
result
.
ToAttributeResultList
()
.
AttributeResults
[
0
]
.
AttributeProofStatus
;
attrStatus
!=
irma
.
PRESENT
{
t
.
Logf
(
"Invalid attribute result value: %v Expected: %v"
,
attrStatus
,
irma
.
PRESENT
)
t
.
Fail
()
}
if
attrStatus
:=
result
.
ToAttributeResultList
()
.
AttributeResults
[
1
]
.
AttributeProofStatus
;
attrStatus
!=
irma
.
PRESENT
{
t
.
Logf
(
"Invalid attribute result value: %v Expected: %v"
,
attrStatus
,
irma
.
PRESENT
)
t
.
Fail
()
}
test
.
ClearTestStorage
(
t
)
...
...
@@ -280,8 +285,8 @@ func TestManualSessionInvalidProof(t *testing.T) {
}
// No errors, obtain proof result from channel
if
result
:=
<-
ms
.
resultChannel
;
result
.
p
roofStatus
!=
INVALID_CRYPTO
{
t
.
Logf
(
"Invalid proof result: %v Expected: %v"
,
result
.
p
roofStatus
,
INVALID_CRYPTO
)
if
result
:=
<-
ms
.
resultChannel
;
result
.
P
roofStatus
!=
irma
.
INVALID_CRYPTO
{
t
.
Logf
(
"Invalid proof result: %v Expected: %v"
,
result
.
P
roofStatus
,
irma
.
INVALID_CRYPTO
)
t
.
Fail
()
}
test
.
ClearTestStorage
(
t
)
...
...
@@ -294,8 +299,7 @@ func (sh *ManualSessionHandler) Success(irmaAction irma.Action, result string) {
result
=
corruptProofString
(
result
)
go
func
()
{
proofStatus
,
attributeResultList
:=
VerifySig
(
client
.
Configuration
,
result
,
sh
.
sigVerifyRequest
)
sh
.
resultChannel
<-
Result
{
proofStatus
,
attributeResultList
}
sh
.
resultChannel
<-
irma
.
VerifySig
(
client
.
Configuration
,
result
,
sh
.
sigVerifyRequest
)
}()
}
sh
.
errorChannel
<-
nil
...
...
irmaclient/verify.go
deleted
100644 → 0
View file @
1ac28e84
package
irmaclient
import
(
"fmt"
"github.com/go-errors/errors"
"github.com/mhe/gabi"
"github.com/privacybydesign/irmago"
"math/big"
)
// TODO: move to irma package?
type
ProofResult
struct
{
proofStatus
ProofStatus
// The overall proofstatus, should be VALID in order to accept the proof
attributes
[]
irma
.
AttributeResult
}
type
ProofStatus
string
const
(
VALID
=
ProofStatus
(
"VALID"
)
EXPIRED
=
ProofStatus
(
"EXPIRED"
)
INVALID_CRYPTO
=
ProofStatus
(
"INVALID_CRYPTO"
)
INVALID_JSON
=
ProofStatus
(
"INVALID_JSON"
)
MISSING_ATTRIBUTES
=
ProofStatus
(
"MISSING_ATTRIBUTES"
)
)
func
extractPublicKeys
(
configuration
*
irma
.
Configuration
,
proofList
*
gabi
.
ProofList
)
([]
*
gabi
.
PublicKey
,
error
)
{
var
publicKeys
[]
*
gabi
.
PublicKey
for
_
,
v
:=
range
*
proofList
{
switch
v
.
(
type
)
{
case
*
gabi
.
ProofD
:
proof
:=
v
.
(
*
gabi
.
ProofD
)
metadata
:=
irma
.
MetadataFromInt
(
proof
.
ADisclosed
[
1
],
configuration
)
// index 1 is metadata attribute
publicKey
,
err
:=
metadata
.
PublicKey
()
if
err
!=
nil
{
return
nil
,
err
}
publicKeys
=
append
(
publicKeys
,
publicKey
)
default
:
return
nil
,
errors
.
New
(
"Cannot extract public key, not a disclosure proofD!"
)
}
}
return
publicKeys
,
nil
}
func
extractDisclosedCredentials
(
configuration
*
irma
.
Configuration
,
proofList
*
gabi
.
ProofList
)
([]
*
irma
.
CredentialInfo
,
error
)
{
var
credentials
[]
*
irma
.
CredentialInfo
for
_
,
v
:=
range
*
proofList
{
switch
v
.
(
type
)
{
case
*
gabi
.
ProofD
:
proof
:=
v
.
(
*
gabi
.
ProofD
)
irmaCredentialInfo
,
err
:=
irma
.
NewCredentialInfoFromADisclosed
(
proof
.
AResponses
,
proof
.
ADisclosed
,
configuration
)
if
err
!=
nil
{
return
nil
,
err
}
credentials
=
append
(
credentials
,
irmaCredentialInfo
)
default
:
return
nil
,
errors
.
New
(
"Cannot extract attributes from proof, not a disclosure proofD!"
)
}
}
return
credentials
,
nil
}
func
checkProofWithRequest
(
configuration
*
irma
.
Configuration
,
proofList
*
gabi
.
ProofList
,
sigRequest
*
irma
.
SignatureRequest
)
(
ProofStatus
,
*
irma
.
AttributeResultList
)
{
credentials
,
err
:=
extractDisclosedCredentials
(
configuration
,
proofList
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
return
INVALID_CRYPTO
,
nil
}
al
:=
irma
.
AttributeResultListFromDisclosed
(
credentials
,
configuration
)
for
_
,
content
:=
range
sigRequest
.
Content
{
if
!
content
.
SatisfyDisclosed
(
credentials
,
configuration
,
al
)
{
return
MISSING_ATTRIBUTES
,
al
}
}
// Check if a credential is expired
for
_
,
cred
:=
range
credentials
{
if
cred
.
IsExpired
()
{
return
EXPIRED
,
al
}
}
return
VALID
,
al
}
// Verify an IRMA proof cryptographically
func
verify
(
configuration
*
irma
.
Configuration
,
proofList
*
gabi
.
ProofList
,
context
*
big
.
Int
,
nonce
*
big
.
Int
,
isSig
bool
)
bool
{
// Extract public keys
pks
,
err
:=
extractPublicKeys
(
configuration
,
proofList
)
if
err
!=
nil
{
fmt
.
Printf
(
"Error extracting public key: %v
\n
"
,
err
)
return
false
}
return
proofList
.
Verify
(
pks
,
context
,
nonce
,
true
,
isSig
)
}
// Verify a signature proof and check if the attributes match the attributes in the original request
func
VerifySig
(
configuration
*
irma
.
Configuration
,
proofString
string
,
sigRequest
*
irma
.
SignatureRequest
)
(
ProofStatus
,
*
irma
.
AttributeResultList
)
{
// First, unmarshal proof and check if all the attributes in the proofstring match the signature request
var
proofList
gabi
.
ProofList
proofBytes
:=
[]
byte
(
proofString
)
err
:=
proofList
.
UnmarshalJSON
(
proofBytes
)
if
err
!=
nil
{
fmt
.
Printf
(
"Error unmarshalling JSON: %v
\n
"
,
err
)
return
INVALID_JSON
,
nil
}
// Now, cryptographically verify the signature
if
!
verify
(
configuration
,
&
proofList
,
sigRequest
.
GetContext
(),
sigRequest
.
GetNonce
(),
true
)
{
return
INVALID_CRYPTO
,
nil
}
// Finally, check whether attribute values in proof satisfy the original signature request
return
checkProofWithRequest
(
configuration
,
&
proofList
,
sigRequest
)
}
verify.go
0 → 100644
View file @
dfc27bea
package
irma
import
(
"fmt"
"github.com/go-errors/errors"
"github.com/mhe/gabi"
"math/big"
"time"
)
// ProofStatus is the status of the complete proof
type
ProofStatus
string
const
(
VALID
=
ProofStatus
(
"VALID"
)
EXPIRED
=
ProofStatus
(
"EXPIRED"
)
INVALID_CRYPTO
=
ProofStatus
(
"INVALID_CRYPTO"
)
INVALID_SYNTAX
=
ProofStatus
(
"INVALID_SYNTAX"
)
MISSING_ATTRIBUTES
=
ProofStatus
(
"MISSING_ATTRIBUTES"
)
)
// ProofResult is a result of a complete proof, containing all the disclosed attributes and corresponding request
type
ProofResult
struct
{
disjunctions
[]
*
DisclosedAttributeDisjunction
ProofStatus
ProofStatus
}
type
SignatureProofResult
struct
{
ProofResult
message
string
}
// DisclosedCredential contains raw disclosed credentials, without any extra parsing information