Skip to content

Commit

Permalink
feat: support holder as map (#75)
Browse files Browse the repository at this point in the history
* feat: support holder as map

* fix: nil

* fix: test
  • Loading branch information
skynet2 authored Nov 25, 2024
1 parent c4e1c4c commit 693669b
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 7 deletions.
26 changes: 26 additions & 0 deletions verifiable/credential_ldp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/google/uuid"
jsonld "github.com/piprate/json-gold/ld"
"github.com/stretchr/testify/require"
"github.com/trustbloc/did-go/method/key"
"github.com/trustbloc/did-go/method/web"
vdrpkg "github.com/trustbloc/did-go/vdr"

Expand Down Expand Up @@ -1168,6 +1169,9 @@ func TestCredential_AddLinkedDataProof(t *testing.T) {
//go:embed testdata/example-uscis.json
var exampleUscis []byte

//go:embed testdata/example-vcs.json
var exampleVCS []byte

func TestIntegrationCred(t *testing.T) {
vdr := vdrpkg.New(vdrpkg.WithVDR(web.New()))

Expand All @@ -1189,3 +1193,25 @@ func TestIntegrationCred(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, resp)
}

func TestVCSCred(t *testing.T) {
vdr := vdrpkg.New(vdrpkg.WithVDR(web.New()), vdrpkg.WithVDR(key.New()))

docLoaded := jsonld.NewDefaultDocumentLoader(http.DefaultClient)
verifier, err := dataintegrity.NewVerifier(&dataintegrity.Options{
DIDResolver: vdr,
}, eddsa2022.NewVerifierInitializer(&eddsa2022.VerifierInitializerOptions{
LDDocumentLoader: docLoaded,
}), ecdsa2019.NewVerifierInitializer(&ecdsa2019.VerifierInitializerOptions{
LDDocumentLoader: docLoaded,
}))
require.NoError(t, err)

resp, err := ParseCredential(exampleVCS,
WithJSONLDDocumentLoader(jsonld.NewDefaultDocumentLoader(http.DefaultClient)),
WithDataIntegrityVerifier(verifier),
)

require.NoError(t, err)
require.NotNil(t, resp)
}
30 changes: 30 additions & 0 deletions verifiable/data_integrity_proof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,9 @@ var examplePresentation []byte
//go:embed testdata/example_presentation_2.json
var examplePresentation2 []byte

//go:embed testdata/example_presentation_3.json
var examplePresentation3 []byte

//go:embed testdata/context/credential_v2.jsonld
var credentialV2Context []byte

Expand Down Expand Up @@ -244,6 +247,33 @@ func TestCanParsePlaygroundPresentation(t *testing.T) {
assert.NotNil(t, resp)
}

func TestCanParsePlaygroundPresentation2(t *testing.T) {
vdr := vdrpkg.New(vdrpkg.WithVDR(jwk.New()), vdrpkg.WithVDR(key.New()))

loader := ld.NewDefaultDocumentLoader(http.DefaultClient)
verifier, err := dataintegrity.NewVerifier(&dataintegrity.Options{
DIDResolver: vdr,
}, eddsa2022.NewVerifierInitializer(&eddsa2022.VerifierInitializerOptions{
LDDocumentLoader: loader,
}), ecdsa2019.NewVerifierInitializer(&ecdsa2019.VerifierInitializerOptions{
LDDocumentLoader: loader,
}))

proofChecker := defaults.NewDefaultProofChecker(vermethod.NewVDRResolver(vdr))

resp, err := ParsePresentation(examplePresentation3,
WithPresDataIntegrityVerifier(verifier),
WithPresJSONLDDocumentLoader(loader),
WithPresProofChecker(proofChecker),
WithPresExpectedDataIntegrityFields("authentication",
"https://playground.chapi.io",
"3779e883a51a8086039db1d4e773aec26faeb3ee99643706345c572cddded857",
),
)
require.NoError(t, err)
assert.NotNil(t, resp)
}

type resolveFunc func(id string) (*did.DocResolution, error)

func (f resolveFunc) Resolve(id string, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) {
Expand Down
19 changes: 14 additions & 5 deletions verifiable/presentation.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,6 @@ const v1BasePresentationSchema = `
}
]
},
"holder": {
"type": "string",
"format": "uri"
},
"proof": {
"anyOf": [
{
Expand Down Expand Up @@ -713,6 +709,19 @@ func getPresentationOpts(opts []PresentationOpt) *presentationOpts {
return vpOpts
}

func decodeHolder(holder any) (string, error) {
switch val := holder.(type) {
case nil:
return "", nil
case string:
return val, nil
case map[string]interface{}:
return parseStringFld(val, "id")
default:
return "", fmt.Errorf("holder must be string or map[string]interface{}, got: %T", holder)
}
}

func newPresentation(vpRaw rawPresentation, vpOpts *presentationOpts) (*Presentation, error) {
types, err := decodeType(vpRaw[vpFldType])
if err != nil {
Expand All @@ -739,7 +748,7 @@ func newPresentation(vpRaw rawPresentation, vpOpts *presentationOpts) (*Presenta
return nil, fmt.Errorf("fill presentation id from raw: %w", err)
}

holder, err := parseStringFld(vpRaw, vpFldHolder)
holder, err := decodeHolder(vpRaw[vpFldHolder])
if err != nil {
return nil, fmt.Errorf("fill presentation holder from raw: %w", err)
}
Expand Down
4 changes: 2 additions & 2 deletions verifiable/presentation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -740,12 +740,12 @@ func TestValidateVP_Holder(t *testing.T) {
t.Run("rejects verifiable presentation with non-url holder", func(t *testing.T) {
var raw rawPresentation
require.NoError(t, json.Unmarshal([]byte(validPresentation), &raw))
raw[vpFldHolder] = "not valid presentation Holder URL"
raw[vpFldHolder] = 1234
bytes, err := json.Marshal(raw)
require.NoError(t, err)
vp, err := newTestPresentation(t, bytes, WithPresDisabledProofCheck())
require.Error(t, err)
require.Contains(t, err.Error(), "holder: Does not match format 'uri'")
require.Contains(t, err.Error(), "holder must be string or map[string]interface{}")
require.Nil(t, vp)
})
}
Expand Down
52 changes: 52 additions & 0 deletions verifiable/testdata/example-vcs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
{
"@protected": true,
"DriverLicense": {
"@context": {
"@protected": true,
"dateOfBirth": "urn:example:dateOfBirth",
"documentIdentifier": "urn:example:documentIdentifier",
"expirationDate": "urn:example:expiration",
"id": "@id",
"issuingAuthority": "urn:example:issuingAuthority",
"type": "@type"
},
"@id": "urn:example:DriverLicense"
},
"DriverLicenseCredential": "urn:example:DriverLicenseCredential",
"driverLicense": {
"@id": "urn:example:driverLicense",
"@type": "@id"
}
}
],
"credentialSubject": {
"driverLicense": {
"dateOfBirth": "01-01-1990",
"documentIdentifier": "T21387yc328c7y32h23f23",
"expirationDate": "01-01-2030",
"issuingAuthority": "VA",
"type": "DriverLicense"
},
"id": "urn:uuid:1a0e4ef5-091f-4060-842e-18e519ab9440"
},
"id": "urn:uuid:8fff3a44-df43-49cf-88d1-613d7e01cf84",
"issuer": {
"id": "did:key:z82Lm1Lzm8tFZvUaA3egHh3MAbiPiD6LSGSi8X6yzQ9yH7zaxNt7JfDcVKLhVnn5pRPAkh4",
"name": "ecdsa-test-suite-issuer"
},
"proof": {
"created": "2024-11-25T12:06:55Z",
"cryptosuite": "ecdsa-rdfc-2019",
"proofPurpose": "assertionMethod",
"proofValue": "z3nj9tns6ZptdGiAC99azefeaKmbxLMHcF6S868922a6ghNF9dfDX1boevtEetH4cUsLU6wcfZ8nc3tmFnkmv6Pk5Bq3SGsaZfysKPXukgtE7cTeHDc3XZfWsAeNwZwmHYLkX2qAGucZDU",
"type": "DataIntegrityProof",
"verificationMethod": "did:key:z82Lm1Lzm8tFZvUaA3egHh3MAbiPiD6LSGSi8X6yzQ9yH7zaxNt7JfDcVKLhVnn5pRPAkh4#z82Lm1Lzm8tFZvUaA3egHh3MAbiPiD6LSGSi8X6yzQ9yH7zaxNt7JfDcVKLhVnn5pRPAkh4"
},
"type": [
"VerifiableCredential",
"DriverLicenseCredential"
]
}
78 changes: 78 additions & 0 deletions verifiable/testdata/example_presentation_3.json

Large diffs are not rendered by default.

0 comments on commit 693669b

Please sign in to comment.