diff --git a/go.mod b/go.mod index 4454447ba6..16bfa1d8b4 100644 --- a/go.mod +++ b/go.mod @@ -30,6 +30,7 @@ require ( github.com/piprate/json-gold v0.4.1 github.com/pkg/errors v0.9.1 github.com/rs/cors v1.7.0 + github.com/santhosh-tekuri/jsonschema v1.2.4 github.com/square/go-jose/v3 v3.0.0-20200630053402-0a67ce9b0693 github.com/stretchr/testify v1.7.2 github.com/teserakt-io/golang-ed25519 v0.0.0-20210104091850-3888c087a4c8 diff --git a/go.sum b/go.sum index f125d1988e..7225c4571d 100644 --- a/go.sum +++ b/go.sum @@ -317,6 +317,8 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/santhosh-tekuri/jsonschema v1.2.4 h1:hNhW8e7t+H1vgY+1QeEQpveR6D4+OwKPXCfD2aieJis= +github.com/santhosh-tekuri/jsonschema v1.2.4/go.mod h1:TEAUOeZSmIxTTuHatJzrvARHiuO9LYd+cIxzgEHCQI4= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/square/go-jose/v3 v3.0.0-20200630053402-0a67ce9b0693 h1:wD1IWQwAhdWclCwaf6DdzgCAe9Bfz1M+4AHRd7N786Y= diff --git a/pkg/doc/verifiable/presentation.go b/pkg/doc/verifiable/presentation.go index 3e31298e34..3b77293497 100644 --- a/pkg/doc/verifiable/presentation.go +++ b/pkg/doc/verifiable/presentation.go @@ -6,12 +6,14 @@ SPDX-License-Identifier: Apache-2.0 package verifiable import ( + "bytes" "encoding/json" "errors" "fmt" + "strings" jsonld "github.com/piprate/json-gold/ld" - "github.com/xeipuuv/gojsonschema" + "github.com/santhosh-tekuri/jsonschema" "github.com/hyperledger/aries-framework-go/pkg/doc/jose" docjsonld "github.com/hyperledger/aries-framework-go/pkg/doc/jsonld" @@ -20,6 +22,7 @@ import ( jsonutil "github.com/hyperledger/aries-framework-go/pkg/doc/util/json" ) +//nolint:gochecknoglobals const basePresentationSchema = ` { "required": [ @@ -157,7 +160,12 @@ const basePresentationSchema = ` ` //nolint:gochecknoglobals -var basePresentationSchemaLoader = gojsonschema.NewStringLoader(basePresentationSchema) +var ( + schemaName = "presentationSchema" + schemaCompiler = jsonschema.NewCompiler() + _ = schemaCompiler.AddResource(schemaName, strings.NewReader(basePresentationSchema)) + presentationSchema = schemaCompiler.MustCompile(schemaName) +) // MarshalledCredential defines marshalled Verifiable Credential enclosed into Presentation. // MarshalledCredential can be passed to verifiable.ParseCredential(). @@ -568,16 +576,9 @@ func validateVPJSONLD(vpBytes []byte, opts *presentationOpts) error { } func validateVPJSONSchema(data []byte) error { - loader := gojsonschema.NewStringLoader(string(data)) - - result, err := gojsonschema.Validate(basePresentationSchemaLoader, loader) + err := presentationSchema.Validate(bytes.NewReader(data)) if err != nil { - return fmt.Errorf("validation of verifiable credential: %w", err) - } - - if !result.Valid() { - errMsg := describeSchemaValidationError(result, "verifiable presentation") - return errors.New(errMsg) + return fmt.Errorf("verifiable presentation is not valid: %w", err) } return nil diff --git a/pkg/doc/verifiable/presentation_test.go b/pkg/doc/verifiable/presentation_test.go index 17043a0832..afd4050ab3 100644 --- a/pkg/doc/verifiable/presentation_test.go +++ b/pkg/doc/verifiable/presentation_test.go @@ -304,7 +304,7 @@ func TestValidateVP_Context(t *testing.T) { require.NoError(t, err) vp, err := newTestPresentation(t, bytes) require.Error(t, err) - require.Contains(t, err.Error(), "@context is required") + require.Contains(t, err.Error(), "missing properties: \"@context\"") require.Nil(t, vp) }) @@ -319,7 +319,7 @@ func TestValidateVP_Context(t *testing.T) { require.NoError(t, err) vp, err := newTestPresentation(t, bytes) require.Error(t, err) - require.Contains(t, err.Error(), "does not match: \"https://www.w3.org/2018/credentials/v1\"") + require.Contains(t, err.Error(), "must be \"https://www.w3.org/2018/credentials/v1\"") require.Nil(t, vp) }) @@ -342,7 +342,7 @@ func TestValidateVP_Context(t *testing.T) { require.NoError(t, err) vp, err := newTestPresentation(t, bytes) require.Error(t, err) - require.Contains(t, err.Error(), "does not match: \"https://www.w3.org/2018/credentials/v1\"") + require.Contains(t, err.Error(), "must be \"https://www.w3.org/2018/credentials/v1\"") require.Nil(t, vp) }) } @@ -356,7 +356,7 @@ func TestValidateVP_ID(t *testing.T) { require.NoError(t, err) vp, err := newTestPresentation(t, bytes) require.Error(t, err) - require.Contains(t, err.Error(), "id: Does not match format 'uri'") + require.Contains(t, err.Error(), "\"not valid presentation ID URL\" is not valid \"uri\"") require.Nil(t, vp) }) } @@ -402,7 +402,7 @@ func TestValidateVP_Type(t *testing.T) { require.NoError(t, err) vp, err := newTestPresentation(t, bytes) require.Error(t, err) - require.Contains(t, err.Error(), "type is required") + require.Contains(t, err.Error(), "missing properties: \"type\"") require.Nil(t, vp) }) @@ -414,7 +414,7 @@ func TestValidateVP_Type(t *testing.T) { require.NoError(t, err) vp, err := newTestPresentation(t, bytes) require.Error(t, err) - require.Contains(t, err.Error(), "Does not match pattern '^VerifiablePresentation$'") + require.Contains(t, err.Error(), "does not match pattern \"^VerifiablePresentation$\"") require.Nil(t, vp) }) } @@ -428,7 +428,7 @@ func TestValidateVP_Holder(t *testing.T) { require.NoError(t, err) vp, err := newTestPresentation(t, bytes) require.Error(t, err) - require.Contains(t, err.Error(), "holder: Does not match format 'uri'") + require.Contains(t, err.Error(), "not valid presentation Holder URL\" is not valid \"uri\"") require.Nil(t, vp) }) }