Skip to content

Commit

Permalink
feat: improve jsonpath with RFC 9535 support (#92)
Browse files Browse the repository at this point in the history
* feat: replace jsonpath lib

* fix: optional

* fix: adjust fields

* feat: use go 1.22

* feat: update go 1.23
  • Loading branch information
skynet2 authored Jan 13, 2025
1 parent bf13c82 commit 013fe7d
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 66 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ jobs:
timeout-minutes: 10
steps:
- uses: actions/checkout@v3
- name: Setup Go 1.22
- name: Setup Go 1.23
uses: actions/setup-go@v4
with:
go-version: '1.22'
go-version: '1.23'
- name: Run checks
run: |
echo $PATH
Expand All @@ -45,10 +45,10 @@ jobs:
timeout-minutes: 10
steps:

- name: Setup Go 1.22
- name: Setup Go 1.23
uses: actions/setup-go@v4
with:
go-version: '1.22'
go-version: '1.23'
id: go

- uses: actions/checkout@v3
Expand All @@ -61,4 +61,4 @@ jobs:
timeout-minutes: 10
uses: codecov/codecov-action@v3.1.6
with:
file: ./coverage.out
file: ./coverage.out
7 changes: 5 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

module github.com/trustbloc/vc-go

go 1.22
go 1.23

toolchain go1.23.4

require (
github.com/PaesslerAG/gval v1.2.2
github.com/PaesslerAG/jsonpath v0.1.1
github.com/PaesslerAG/jsonpath v0.1.2-0.20240726212847-3a740cf7976f
github.com/VictoriaMetrics/fastcache v1.5.7
github.com/btcsuite/btcd/btcec/v2 v2.3.4
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
Expand All @@ -23,6 +25,7 @@ require (
github.com/piprate/json-gold v0.5.1-0.20230111113000-6ddbe6e6f19f
github.com/samber/lo v1.47.0
github.com/stretchr/testify v1.10.0
github.com/theory/jsonpath v0.3.0
github.com/tidwall/gjson v1.14.3
github.com/tidwall/sjson v1.1.4
github.com/trustbloc/bbs-signature-go v1.0.2
Expand Down
11 changes: 6 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
github.com/IBM/mathlib v0.0.3-0.20231011094432-44ee0eb539da h1:qqGozq4tF6EOVnWoTgBoJGudRKKZXSAYnEtDggzTnsw=
github.com/IBM/mathlib v0.0.3-0.20231011094432-44ee0eb539da/go.mod h1:Tco9QzE3fQzjMS7nPbHDeFfydAzctStf1Pa8hsh6Hjs=
github.com/PaesslerAG/gval v1.0.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I=
github.com/PaesslerAG/gval v1.2.2 h1:Y7iBzhgE09IGTt5QgGQ2IdaYYYOU134YGHBThD+wm9E=
github.com/PaesslerAG/gval v1.2.2/go.mod h1:XRFLwvmkTEdYziLdaCeCa5ImcGVrfQbeNUbVR+C6xac=
github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8=
github.com/PaesslerAG/jsonpath v0.1.1 h1:c1/AToHQMVsduPAa4Vh6xp2U0evy4t8SWp8imEsylIk=
github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY=
github.com/PaesslerAG/jsonpath v0.1.2-0.20240726212847-3a740cf7976f h1:TxDCeKRCgHea2hUiMOjWwqzWmrIGqSOZYkEPuClXzDo=
github.com/PaesslerAG/jsonpath v0.1.2-0.20240726212847-3a740cf7976f/go.mod h1:zTyVtYhYjcHpfCtqnCMxejgp0pEEwb/xJzhn05NrkJk=
github.com/VictoriaMetrics/fastcache v1.5.7 h1:4y6y0G8PRzszQUYIQHHssv/jgPHAb5qQuuDNdCbyAgw=
github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
Expand Down Expand Up @@ -101,8 +100,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/cachecontrol v0.2.0 h1:vBXSNuE5MYP9IJ5kjsdo8uq+w41jSPgvba2DEnkRx9k=
github.com/pquerna/cachecontrol v0.2.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
Expand All @@ -115,6 +114,8 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/teserakt-io/golang-ed25519 v0.0.0-20210104091850-3888c087a4c8 h1:RBkacARv7qY5laaXGlF4wFB/tk5rnthhPb8oIBGoagY=
github.com/teserakt-io/golang-ed25519 v0.0.0-20210104091850-3888c087a4c8/go.mod h1:9PdLyPiZIiW3UopXyRnPYyjUXSpiQNHRLu8fOsR3o8M=
github.com/theory/jsonpath v0.3.0 h1:XFCAOLynMKKNosAv9sfcFEVYFRxQqQDE7Hyx1+atm/w=
github.com/theory/jsonpath v0.3.0/go.mod h1:yv+crL58A+g3yxLr1sbOyn8H+L/6kS4AMXlXeVGOuNU=
github.com/tidwall/gjson v1.6.7/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI=
github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw=
github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
Expand Down
2 changes: 0 additions & 2 deletions presexch/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@ func (pd *PresentationDefinition) Match(
contextLoader ld.DocumentLoader,
options ...MatchOption,
) ([]*MatchValue, error) {
pd.adjustFields()

opts := &MatchOptions{}

for i := range options {
Expand Down
110 changes: 59 additions & 51 deletions presexch/definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"strings"
"time"

"github.com/PaesslerAG/jsonpath"
"github.com/google/uuid"
jsonpathkeys "github.com/kawamuray/jsonpath"
"github.com/piprate/json-gold/ld"
Expand All @@ -30,6 +29,8 @@ import (

"github.com/trustbloc/vc-go/sdjwt/common"
"github.com/trustbloc/vc-go/verifiable"

pathv2 "github.com/theory/jsonpath"
)

const (
Expand Down Expand Up @@ -475,36 +476,12 @@ func makeRequirement(requirements []*SubmissionRequirement, descriptors []*Input
return req, nil
}

func (pd *PresentationDefinition) adjustFields() {
if pd == nil || pd.InputDescriptors == nil {
return
}

for _, descriptor := range pd.InputDescriptors {
if descriptor.Constraints == nil {
continue
}

for _, f := range descriptor.Constraints.Fields {
var updatedPath []string

for _, path := range f.Path {
updatedPath = append(updatedPath, strings.ReplaceAll(path, "'", "\""))
}

f.Path = updatedPath
}
}
}

// CreateVP creates verifiable presentation.
func (pd *PresentationDefinition) CreateVP(
credentials []*verifiable.Credential,
documentLoader ld.DocumentLoader,
opts ...MatchRequirementsOpt,
) (*verifiable.Presentation, error) {
pd.adjustFields()

matchOpts := &matchRequirementsOpts{defaultVPFormat: FormatLDPVP}
for _, opt := range opts {
opt(matchOpts)
Expand Down Expand Up @@ -871,8 +848,6 @@ func (pd *PresentationDefinition) filterCredentialsThatMatchDescriptor(
format = descriptor.Format
}

pd.adjustFields()

vpFormat := ""
filtered := creds

Expand Down Expand Up @@ -1501,43 +1476,76 @@ func filterField(f *Field, credential map[string]interface{}, isJWTCredential bo
var lastErr error

for _, path := range f.Path {
if isJWTCredential {
if strings.Contains(path, "$.vc.") {
path = strings.Replace(path, "$.vc.", "$.", 1)
}
err := checkPathValue(isJWTCredential, path, credential, f, schema)
if err == nil { // if at least 1 path is valid, we are good
return nil
}

if strings.EqualFold(path, "$.issuer") {
switch issuerFld := credential["issuer"].(type) {
case map[string]interface{}:
if _, ok := issuerFld["id"]; ok {
path = "$.issuer.id"
}
lastErr = errors.Join(lastErr, checkPathValue(isJWTCredential, path, credential, f, schema))
}

return lastErr
}

//nolint:gocyclo
func checkPathValue(
isJWTCredential bool,
path string,
credential map[string]any,
field *Field,
schema gojsonschema.JSONLoader,
) error {
if isJWTCredential { // compatibility
if strings.Contains(path, "$.vc.") {
path = strings.Replace(path, "$.vc.", "$.", 1)
}

if strings.EqualFold(path, "$.issuer") {
switch issuerFld := credential["issuer"].(type) {
case map[string]interface{}:
if _, ok := issuerFld["id"]; ok {
path = "$.issuer.id"
}
}
}
}

patch, err := jsonpath.Get(path, credential)
if err == nil {
// TODO: refactor this + selective disclosure so that the accepted path for a constraint field
// is the only path revealed, instead of revealing all paths for the field.
err = validatePatch(schema, patch, f, isJWTCredential)
if err == nil {
return nil
}
if !strings.HasPrefix(path, "$") && !strings.HasPrefix("@", path) {
return errors.New("expected $ or @ at start of path")
}

lastErr = err
} else if f.Optional {
pathParsed, err := pathv2.Parse(path)
if err != nil {
return err
}

selected := pathParsed.Select(credential)
if len(selected) == 0 {
if field.Optional { // we are good
return nil
} else {
lastErr = errPathNotApplicable
}

return errors.Join(errPathNotApplicable, fmt.Errorf("no value found for path %s", path))
}

return lastErr
var raw any

if len(selected) == 1 {
raw = selected[0]
} else {
var arr []any
for _, s := range selected {
arr = append(arr, s)
}

raw = arr
}

return validatePath(schema, raw, field, isJWTCredential)
}

//nolint:gocyclo
func validatePatch(schema gojsonschema.JSONLoader, patch interface{}, field *Field, isJWTCredential bool) error {
func validatePath(schema gojsonschema.JSONLoader, patch interface{}, field *Field, isJWTCredential bool) error {
if schema == nil {
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion presexch/definition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1305,7 +1305,7 @@ func TestPresentationDefinition_CreateVP_V1Credential(t *testing.T) {

require.Error(t, err)
require.Nil(t, vp)
require.Contains(t, err.Error(), "Expected $ or @ at start of path instead of U+0031")
require.Contains(t, err.Error(), "expected $ or @ at start of path")
})

t.Run("SD-JWT: Limit Disclosure (credentials don't meet requirement)", func(t *testing.T) {
Expand Down

0 comments on commit 013fe7d

Please sign in to comment.