Commit 31ecb981 authored by Sietse Ringers's avatar Sietse Ringers
Browse files

Return errors in verification api

parent cf4ba926
...@@ -41,7 +41,9 @@ func manualSessionHelper(t *testing.T, client *irmaclient.Client, h *ManualTestH ...@@ -41,7 +41,9 @@ func manualSessionHelper(t *testing.T, client *irmaclient.Client, h *ManualTestH
verifyasRequest := &irma.DisclosureRequest{} verifyasRequest := &irma.DisclosureRequest{}
err := json.Unmarshal([]byte(verifyAs), verifyasRequest) err := json.Unmarshal([]byte(verifyAs), verifyasRequest)
require.NoError(t, err) require.NoError(t, err)
return irma.ProofList(result.VerificationResult).Verify(client.Configuration, verifyasRequest) list, status, err := irma.ProofList(result.VerificationResult).Verify(client.Configuration, verifyasRequest)
require.NoError(t, err)
return list, status
case irma.ActionSigning: case irma.ActionSigning:
var verifyasRequest *irma.SignatureRequest var verifyasRequest *irma.SignatureRequest
if verifyAs != "" { if verifyAs != "" {
...@@ -55,7 +57,9 @@ func manualSessionHelper(t *testing.T, client *irmaclient.Client, h *ManualTestH ...@@ -55,7 +57,9 @@ func manualSessionHelper(t *testing.T, client *irmaclient.Client, h *ManualTestH
i := result.SignatureResult.Signature[0].(*gabi.ProofD).C i := result.SignatureResult.Signature[0].(*gabi.ProofD).C
i.Add(i, big.NewInt(16)) i.Add(i, big.NewInt(16))
} }
return result.SignatureResult.Verify(client.Configuration, verifyasRequest) list, status, err := result.SignatureResult.Verify(client.Configuration, verifyasRequest)
require.NoError(t, err)
return list, status
default: default:
return nil, "" return nil, ""
} }
......
...@@ -290,7 +290,9 @@ func TestVerifyValidSig(t *testing.T) { ...@@ -290,7 +290,9 @@ func TestVerifyValidSig(t *testing.T) {
require.Equal(t, sigRequest.Context, big.NewInt(1337)) require.Equal(t, sigRequest.Context, big.NewInt(1337))
// Test if we can verify it with the original request // Test if we can verify it with the original request
attrs, status := irmaSignedMessage.Verify(conf, sigRequest) var err error
attrs, status, err := irmaSignedMessage.Verify(conf, sigRequest)
require.NoError(t, err)
require.Equal(t, status, ProofStatusValid) require.Equal(t, status, ProofStatusValid)
require.Len(t, attrs, 1) require.Len(t, attrs, 1)
require.Equal(t, attrs[0].Status, AttributeProofStatusPresent) require.Equal(t, attrs[0].Status, AttributeProofStatusPresent)
...@@ -306,7 +308,9 @@ func TestVerifyValidSig(t *testing.T) { ...@@ -306,7 +308,9 @@ func TestVerifyValidSig(t *testing.T) {
require.Equal(t, stringSigRequest.Context, big.NewInt(1337)) require.Equal(t, stringSigRequest.Context, big.NewInt(1337))
// Test if we can verify it with the original request // Test if we can verify it with the original request
attrs, status = irmaSignedMessage.Verify(conf, sigRequest)
attrs, status, err = irmaSignedMessage.Verify(conf, sigRequest)
require.NoError(t, err)
require.Equal(t, status, ProofStatusValid) require.Equal(t, status, ProofStatusValid)
require.Len(t, attrs, 1) require.Len(t, attrs, 1)
require.Equal(t, attrs[0].Status, AttributeProofStatusPresent) require.Equal(t, attrs[0].Status, AttributeProofStatusPresent)
...@@ -317,11 +321,13 @@ func TestVerifyValidSig(t *testing.T) { ...@@ -317,11 +321,13 @@ func TestVerifyValidSig(t *testing.T) {
unmatchedSigRequestJSON := []byte(unmatched) unmatchedSigRequestJSON := []byte(unmatched)
unmatchedSigRequest := &SignatureRequest{} unmatchedSigRequest := &SignatureRequest{}
json.Unmarshal(unmatchedSigRequestJSON, unmatchedSigRequest) json.Unmarshal(unmatchedSigRequestJSON, unmatchedSigRequest)
_, status = irmaSignedMessage.Verify(conf, unmatchedSigRequest) _, status, err = irmaSignedMessage.Verify(conf, unmatchedSigRequest)
require.NoError(t, err)
require.Equal(t, status, ProofStatusUnmatchedRequest) require.Equal(t, status, ProofStatusUnmatchedRequest)
// Test if we can also verify it without using the original request // Test if we can also verify it without using the original request
attrs, status = irmaSignedMessage.Verify(conf, nil) attrs, status, err = irmaSignedMessage.Verify(conf, nil)
require.NoError(t, err)
require.Equal(t, status, ProofStatusValid) require.Equal(t, status, ProofStatusValid)
require.Len(t, attrs, 1) require.Len(t, attrs, 1)
require.Equal(t, attrs[0].Value["en"], "456") require.Equal(t, attrs[0].Value["en"], "456")
...@@ -340,10 +346,13 @@ func TestVerifyInValidSig(t *testing.T) { ...@@ -340,10 +346,13 @@ func TestVerifyInValidSig(t *testing.T) {
sigRequest := &SignatureRequest{} sigRequest := &SignatureRequest{}
json.Unmarshal(sigRequestJSON, sigRequest) json.Unmarshal(sigRequestJSON, sigRequest)
_, status := irmaSignedMessage.Verify(conf, sigRequest) var err error
_, status, err := irmaSignedMessage.Verify(conf, sigRequest)
require.NoError(t, err)
require.Equal(t, status, ProofStatusInvalid) require.Equal(t, status, ProofStatusInvalid)
_, status = irmaSignedMessage.Verify(conf, nil) _, status, err = irmaSignedMessage.Verify(conf, nil)
require.NoError(t, err)
require.Equal(t, status, ProofStatusInvalid) require.Equal(t, status, ProofStatusInvalid)
} }
...@@ -361,10 +370,13 @@ func TestVerifyInValidNonce(t *testing.T) { ...@@ -361,10 +370,13 @@ func TestVerifyInValidNonce(t *testing.T) {
sigRequest := &SignatureRequest{} sigRequest := &SignatureRequest{}
json.Unmarshal(sigRequestJSON, sigRequest) json.Unmarshal(sigRequestJSON, sigRequest)
_, status := irmaSignedMessage.Verify(conf, sigRequest) var err error
_, status, err := irmaSignedMessage.Verify(conf, sigRequest)
require.NoError(t, err)
require.Equal(t, status, ProofStatusInvalid) require.Equal(t, status, ProofStatusInvalid)
_, status = irmaSignedMessage.Verify(conf, nil) _, status, err = irmaSignedMessage.Verify(conf, nil)
require.NoError(t, err)
require.Equal(t, status, ProofStatusInvalid) require.Equal(t, status, ProofStatusInvalid)
} }
......
...@@ -47,6 +47,8 @@ type DisclosedAttribute struct { ...@@ -47,6 +47,8 @@ type DisclosedAttribute struct {
// ProofList is a gabi.ProofList with some extra methods. // ProofList is a gabi.ProofList with some extra methods.
type ProofList gabi.ProofList type ProofList gabi.ProofList
var ErrorMissingPublicKey = errors.New("Missing public key")
// ExtractPublicKeys returns the public keys of each proof in the proofList, in the same order, // ExtractPublicKeys returns the public keys of each proof in the proofList, in the same order,
// for later use in verification of the proofList. If one of the proofs is not a ProofD // for later use in verification of the proofList. If one of the proofs is not a ProofD
// an error is returned. // an error is returned.
...@@ -62,26 +64,29 @@ func (pl ProofList) ExtractPublicKeys(configuration *Configuration) ([]*gabi.Pub ...@@ -62,26 +64,29 @@ func (pl ProofList) ExtractPublicKeys(configuration *Configuration) ([]*gabi.Pub
if err != nil { if err != nil {
return nil, err return nil, err
} }
if publicKey == nil {
return nil, ErrorMissingPublicKey
}
publicKeys = append(publicKeys, publicKey) publicKeys = append(publicKeys, publicKey)
default: default:
return nil, errors.New("Cannot extract public key, not a disclosure proofD!") return nil, errors.New("Cannot extract public key, not a disclosure proofD")
} }
} }
return publicKeys, nil return publicKeys, nil
} }
// VerifyProofs verifies the proofs cryptographically. // VerifyProofs verifies the proofs cryptographically.
func (pl ProofList) VerifyProofs(configuration *Configuration, context *big.Int, nonce *big.Int, publickeys []*gabi.PublicKey, isSig bool) bool { func (pl ProofList) VerifyProofs(configuration *Configuration, context *big.Int, nonce *big.Int, publickeys []*gabi.PublicKey, isSig bool) (bool, error) {
if publickeys == nil { if publickeys == nil {
var err error var err error
publickeys, err = pl.ExtractPublicKeys(configuration) publickeys, err = pl.ExtractPublicKeys(configuration)
if err != nil { if err != nil {
return false return false, err
} }
} }
if len(pl) != len(publickeys) { if len(pl) != len(publickeys) {
return false return false, errors.New("Insufficient public keys to verify the proofs")
} }
// If the secret key comes from a credential whose scheme manager has a keyshare server, // If the secret key comes from a credential whose scheme manager has a keyshare server,
...@@ -101,12 +106,12 @@ func (pl ProofList) VerifyProofs(configuration *Configuration, context *big.Int, ...@@ -101,12 +106,12 @@ func (pl ProofList) VerifyProofs(configuration *Configuration, context *big.Int,
secretkeyResponses[schemeID] = proof.SecretKeyResponse() secretkeyResponses[schemeID] = proof.SecretKeyResponse()
} else { } else {
if response.Cmp(proof.SecretKeyResponse()) != 0 { if response.Cmp(proof.SecretKeyResponse()) != 0 {
return false return false, nil
} }
} }
} }
return gabi.ProofList(pl).Verify(publickeys, context, nonce, isSig) return gabi.ProofList(pl).Verify(publickeys, context, nonce, isSig), nil
} }
// Expired returns true if any of the contained disclosure proofs is specified at the specified time, // Expired returns true if any of the contained disclosure proofs is specified at the specified time,
...@@ -207,34 +212,39 @@ func (pl ProofList) VerifyAgainstDisjunctions( ...@@ -207,34 +212,39 @@ func (pl ProofList) VerifyAgainstDisjunctions(
context, nonce *big.Int, context, nonce *big.Int,
publickeys []*gabi.PublicKey, publickeys []*gabi.PublicKey,
issig bool, issig bool,
) ([]*DisclosedAttribute, ProofStatus) { ) ([]*DisclosedAttribute, ProofStatus, error) {
// Cryptographically verify the IRMA disclosure proofs in the signature // Cryptographically verify the IRMA disclosure proofs in the signature
if !pl.VerifyProofs(configuration, context, nonce, publickeys, issig) { valid, err := pl.VerifyProofs(configuration, context, nonce, publickeys, issig)
return nil, ProofStatusInvalid if !valid || err != nil {
return nil, ProofStatusInvalid, err
} }
// Next extract the contained attributes from the proofs, and match them to the signature request if present // Next extract the contained attributes from the proofs, and match them to the signature request if present
allmatched, list, err := pl.DisclosedAttributes(configuration, required) allmatched, list, err := pl.DisclosedAttributes(configuration, required)
if err != nil { if err != nil {
return nil, ProofStatusInvalid return nil, ProofStatusInvalid, err
} }
// Return MISSING_ATTRIBUTES as proofstatus if one of the disjunctions in the request (if present) is not satisfied // Return MISSING_ATTRIBUTES as proofstatus if one of the disjunctions in the request (if present) is not satisfied
// This status takes priority over 'EXPIRED'
if !allmatched { if !allmatched {
return list, ProofStatusMissingAttributes return list, ProofStatusMissingAttributes, nil
}
return list, ProofStatusValid, nil
}
func (pl ProofList) Verify(configuration *Configuration, request *DisclosureRequest) ([]*DisclosedAttribute, ProofStatus, error) {
list, status, err := pl.VerifyAgainstDisjunctions(configuration, request.Content, request.Context, request.Nonce, nil, false)
if err != nil {
return list, status, err
} }
now := time.Now() now := time.Now()
if expired := pl.Expired(configuration, &now); expired { if expired := pl.Expired(configuration, &now); expired {
return list, ProofStatusExpired return list, ProofStatusExpired, nil
} }
return list, ProofStatusValid return list, status, nil
}
func (pl ProofList) Verify(configuration *Configuration, request *DisclosureRequest) ([]*DisclosedAttribute, ProofStatus) {
return pl.VerifyAgainstDisjunctions(configuration, request.Content, request.Context, request.Nonce, nil, false)
} }
// Verify the attribute-based signature, optionally against a corresponding signature request. If the request is present // Verify the attribute-based signature, optionally against a corresponding signature request. If the request is present
...@@ -246,14 +256,14 @@ func (pl ProofList) Verify(configuration *Configuration, request *DisclosureRequ ...@@ -246,14 +256,14 @@ func (pl ProofList) Verify(configuration *Configuration, request *DisclosureRequ
// //
// The signature request is optional; if it is nil then the attribute-based signature is still verified, and all // The signature request is optional; if it is nil then the attribute-based signature is still verified, and all
// containing attributes returned in the result. // containing attributes returned in the result.
func (sm *SignedMessage) Verify(configuration *Configuration, request *SignatureRequest) ([]*DisclosedAttribute, ProofStatus) { func (sm *SignedMessage) Verify(configuration *Configuration, request *SignatureRequest) ([]*DisclosedAttribute, ProofStatus, error) {
var message string var message string
// First check if this signature matches the request // First check if this signature matches the request
if request != nil { if request != nil {
request.Timestamp = sm.Timestamp request.Timestamp = sm.Timestamp
if !sm.MatchesNonceAndContext(request) { if !sm.MatchesNonceAndContext(request) {
return nil, ProofStatusUnmatchedRequest return nil, ProofStatusUnmatchedRequest, nil
} }
// If there is a request, then the signed message must be that of the request // If there is a request, then the signed message must be that of the request
message = request.Message message = request.Message
...@@ -265,7 +275,7 @@ func (sm *SignedMessage) Verify(configuration *Configuration, request *Signature ...@@ -265,7 +275,7 @@ func (sm *SignedMessage) Verify(configuration *Configuration, request *Signature
// Verify the timestamp // Verify the timestamp
if sm.Timestamp != nil { if sm.Timestamp != nil {
if err := sm.VerifyTimestamp(message, configuration); err != nil { if err := sm.VerifyTimestamp(message, configuration); err != nil {
return nil, ProofStatusInvalidTimestamp return nil, ProofStatusInvalidTimestamp, nil
} }
} }
...@@ -275,9 +285,9 @@ func (sm *SignedMessage) Verify(configuration *Configuration, request *Signature ...@@ -275,9 +285,9 @@ func (sm *SignedMessage) Verify(configuration *Configuration, request *Signature
if request != nil { if request != nil {
required = request.Content required = request.Content
} }
result, status := pl.VerifyAgainstDisjunctions(configuration, required, sm.Context, sm.GetNonce(), nil, true) result, status, err := pl.VerifyAgainstDisjunctions(configuration, required, sm.Context, sm.GetNonce(), nil, true)
if status != ProofStatusValid { if status != ProofStatusValid || err != nil {
return result, status return result, status, err
} }
// Check if a credential is expired // Check if a credential is expired
...@@ -296,9 +306,9 @@ func (sm *SignedMessage) Verify(configuration *Configuration, request *Signature ...@@ -296,9 +306,9 @@ func (sm *SignedMessage) Verify(configuration *Configuration, request *Signature
// This must not happen and in this case the signature is invalid // This must not happen and in this case the signature is invalid
status = ProofStatusInvalid status = ProofStatusInvalid
} }
return result, status return result, status, nil
} }
// All disjunctions satisfied and nothing expired, proof is valid! // All disjunctions satisfied and nothing expired, proof is valid!
return result, ProofStatusValid return result, ProofStatusValid, nil
} }
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment