Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add signature checks for Verifiable Presentations #353

Merged
merged 14 commits into from
Apr 18, 2023

Conversation

decentralgabe
Copy link
Member

@decentralgabe decentralgabe commented Apr 14, 2023

Fixes #71

@decentralgabe decentralgabe marked this pull request as ready for review April 14, 2023 23:38

// VerifyCredentialSignature verifies the signature of a credential of any type
// TODO(gabe) support other types of credentials https://github.com/TBD54566975/ssi-sdk/issues/352
func VerifyCredentialSignature(ctx context.Context, genericCred any, resolver did.Resolver) (bool, error) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

important stuff here

@codecov-commenter
Copy link

codecov-commenter commented Apr 14, 2023

Codecov Report

Merging #353 (92684a2) into main (dd225d5) will increase coverage by 0.42%.
The diff coverage is 63.21%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #353      +/-   ##
==========================================
+ Coverage   57.38%   57.80%   +0.42%     
==========================================
  Files          51       52       +1     
  Lines        6410     6566     +156     
==========================================
+ Hits         3678     3795     +117     
- Misses       2032     2063      +31     
- Partials      700      708       +8     
Impacted Files Coverage Δ
credential/exchange/request.go 40.24% <0.00%> (-2.06%) ⬇️
cryptosuite/bbsplussignaturesuite.go 52.83% <ø> (ø)
credential/verification/verifiers.go 45.00% <20.00%> (-15.00%) ⬇️
credential/exchange/verification.go 50.81% <45.45%> (-2.19%) ⬇️
credential/util.go 46.81% <46.81%> (ø)
crypto/jwt.go 44.78% <66.67%> (ø)
credential/jwt.go 39.66% <68.42%> (ø)
credential/signature.go 80.00% <80.00%> (ø)
credential/exchange/submission.go 72.62% <84.62%> (-0.43%) ⬇️
credential/jws.go 52.63% <100.00%> (ø)
... and 4 more

... and 3 files with indirect coverage changes

return fmt.Errorf("verifier<%T> is not a JWT verifier", verifier)
}
// verify the VP, which in turn verifies all credentials in it
_, _, vp, err := credential.VerifyVerifiablePresentationJWT(context.Background(), jwtVerifier, resolver, string(submission))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eventually context.background should be top level

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I will make it top level here

// After decoding the signature of each credential in the presentation is verified. If there are any issues during
// decoding or signature validation, an error is returned. As a result, a successfully decoded VerifiablePresentation
// object is returned.
func VerifyVerifiablePresentationJWT(ctx context.Context, verifier crypto.JWTVerifier, resolver did.Resolver, token string) (jws.Headers, jwt.Token, *VerifiablePresentation, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

if genericCred == nil {
return false, errors.New("credential cannot be empty")
}
if resolver == nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the resolver was empty could there be a default one we load?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if we should, because that would imply supporting DID methods that the caller may not want to resolve

case *VerifiableCredential:
return VerifyCredentialSignature(ctx, *genericCred.(*VerifiableCredential), resolver)
case VerifiableCredential:
cred := genericCred.(VerifiableCredential)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no ok checking here?
cred, ok := genericCred.(VerifiableCredential)
I guess we know the type so not needed

Copy link
Member Author

@decentralgabe decentralgabe Apr 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah since the switch was hit we know the type

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how to make it nicer without some crazy generic stuff


// if that fails, try as a JWT
if _, _, _, err := VCJWTJSONToVC(credMapBytes); err == nil {
return false, errors.New("JWT credentials must include a signature to be verified")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the right error message here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could just be an invalid map[string]any

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed this bit

)

// ToCredential turn a generic cred into its known object model
func ToCredential(genericCred any) (jws.Headers, jwt.Token, *VerifiableCredential, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of code reuse, would it be possible to Call this funciton in the signature.go VerifyCredentialSignature?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea, I think it can be used for everything but the JWT case

_, _, vp, err := signing.VerifyVerifiablePresentationJWT(verifier, string(credBytes))
// 1. That the VP is valid
// 2. All VCs in the VP are valid
// 2. That the VC was issued by a trusted entity (implied by the presentation, according to the Presentation Definition)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ty

Copy link
Contributor

@nitro-neal nitro-neal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

Copy link
Contributor

@nitro-neal nitro-neal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Just a few spots to look over and think about:
Biggest stuff is perhaps infinite loop / stack overflow problem if we are not careful with the return VerifyCredentialSignature

With the context, I wonder if we can extract it away and it will only be created once in the resolver or something

}
switch genericCred.(type) {
case *VerifiableCredential:
return VerifyCredentialSignature(ctx, *genericCred.(*VerifiableCredential), resolver)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure we won't run into an infinite loop problem here or at the other
return VerifyCredentialSignature spots?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure...maybe not. I have each case covered in a test that should be "good enough"

@decentralgabe decentralgabe merged commit 5d3dce1 into main Apr 18, 2023
@decentralgabe decentralgabe deleted the pe-signature-checks-71 branch April 18, 2023 15:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Presentation Exchange: validate claim signatures in presentation submissions
3 participants