github.com/hyperledger/aries-framework-go@v0.3.2/pkg/doc/presexch/definition_test.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package presexch_test
     8  
     9  import (
    10  	"bytes"
    11  	"context"
    12  	"crypto/sha256"
    13  	"encoding/json"
    14  	"fmt"
    15  	"io/ioutil"
    16  	"os"
    17  	"strings"
    18  	"testing"
    19  	"time"
    20  
    21  	"github.com/PaesslerAG/gval"
    22  	"github.com/PaesslerAG/jsonpath"
    23  	"github.com/google/uuid"
    24  	"github.com/stretchr/testify/require"
    25  
    26  	"github.com/hyperledger/aries-framework-go/pkg/crypto/primitive/bbs12381g2pub"
    27  	"github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto"
    28  	"github.com/hyperledger/aries-framework-go/pkg/doc/ld"
    29  	. "github.com/hyperledger/aries-framework-go/pkg/doc/presexch"
    30  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/jsonld"
    31  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite"
    32  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/bbsblssignature2020"
    33  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/verifier"
    34  	"github.com/hyperledger/aries-framework-go/pkg/doc/util"
    35  	"github.com/hyperledger/aries-framework-go/pkg/doc/util/signature"
    36  	"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
    37  	"github.com/hyperledger/aries-framework-go/pkg/internal/ldtestutil"
    38  	"github.com/hyperledger/aries-framework-go/pkg/kms"
    39  	"github.com/hyperledger/aries-framework-go/pkg/kms/localkms"
    40  	mockkms "github.com/hyperledger/aries-framework-go/pkg/mock/kms"
    41  	"github.com/hyperledger/aries-framework-go/pkg/mock/storage"
    42  	"github.com/hyperledger/aries-framework-go/pkg/secretlock/noop"
    43  	"github.com/hyperledger/aries-framework-go/pkg/vdr/fingerprint"
    44  )
    45  
    46  const errMsgSchema = "credentials do not satisfy requirements"
    47  
    48  // nolint: gochecknoglobals
    49  var (
    50  	strFilterType = "string"
    51  	arrFilterType = "array"
    52  	intFilterType = "integer"
    53  
    54  	subIsIssuerRequired = Required
    55  )
    56  
    57  func TestPresentationDefinition_IsValid(t *testing.T) {
    58  	samples := []string{"sample_1.json", "sample_2.json", "sample_3.json"}
    59  
    60  	for _, sample := range samples {
    61  		file := sample
    62  		t.Run(file, func(t *testing.T) {
    63  			var pd *PresentationDefinition
    64  			parseJSONFile(t, "testdata/"+file, &pd)
    65  
    66  			require.NoError(t, pd.ValidateSchema())
    67  		})
    68  	}
    69  
    70  	t.Run("id is required", func(t *testing.T) {
    71  		errMsg := "presentation_definition: id is required,presentation_definition: input_descriptors is required"
    72  		pd := &PresentationDefinition{
    73  			SubmissionRequirements: []*SubmissionRequirement{{Rule: All, From: "A"}},
    74  		}
    75  		require.EqualError(t, pd.ValidateSchema(), errMsg)
    76  	})
    77  }
    78  
    79  func TestPresentationDefinition_CreateVP(t *testing.T) {
    80  	lddl := createTestJSONLDDocumentLoader(t)
    81  
    82  	t.Run("Checks schema", func(t *testing.T) {
    83  		pd := &PresentationDefinition{ID: uuid.New().String()}
    84  
    85  		vp, err := pd.CreateVP(nil, nil)
    86  
    87  		require.EqualError(t, err, "presentation_definition: input_descriptors is required")
    88  		require.Nil(t, vp)
    89  	})
    90  
    91  	t.Run("Checks submission requirements", func(t *testing.T) {
    92  		issuerID := "did:example:76e12ec712ebc6f1c221ebfeb1f"
    93  
    94  		vc1JWT := &verifiable.Credential{
    95  			Issued:  util.NewTime(time.Now()),
    96  			Context: []string{verifiable.ContextURI},
    97  			Types:   []string{verifiable.VCType},
    98  			ID:      "http://example.edu/credentials/1872",
    99  			Subject: []verifiable.Subject{{ID: issuerID}},
   100  			Issuer:  verifiable.Issuer{ID: issuerID},
   101  			CustomFields: map[string]interface{}{
   102  				"first_name": "Jesse",
   103  				"last_name":  "Travis",
   104  				"age":        17,
   105  			},
   106  			// vc as jwt does not use proof, do not set it here.
   107  		}
   108  
   109  		ed25519Signer, err := newCryptoSigner(kms.ED25519Type)
   110  		require.NoError(t, err)
   111  
   112  		vc1JWT.JWT = createEdDSAJWS(t, vc1JWT, ed25519Signer, "76e12ec712ebc6f1c221ebfeb1f", true)
   113  
   114  		candidateVCs := []*verifiable.Credential{
   115  			vc1JWT,
   116  			{
   117  				Context: []string{verifiable.ContextURI},
   118  				Types:   []string{verifiable.VCType},
   119  				ID:      "http://example.edu/credentials/1872",
   120  				CustomFields: map[string]interface{}{
   121  					"first_name": "Jesse",
   122  				},
   123  				Proofs: []verifiable.Proof{{"type": "JsonWebSignature2020"}},
   124  			},
   125  			{
   126  				Context: []string{verifiable.ContextURI},
   127  				Types:   []string{verifiable.VCType},
   128  				ID:      "http://example.edu/credentials/1872",
   129  				Subject: []verifiable.Subject{{ID: issuerID}},
   130  				Issuer:  verifiable.Issuer{ID: issuerID},
   131  				CustomFields: map[string]interface{}{
   132  					"first_name": "Jesse",
   133  					"last_name":  "Travis",
   134  					"age":        17,
   135  				},
   136  				Proofs: []verifiable.Proof{{"type": "JsonWebSignature2020"}},
   137  			},
   138  			{
   139  				Context: []string{verifiable.ContextURI},
   140  				Types:   []string{verifiable.VCType},
   141  				ID:      "http://example.edu/credentials/1872",
   142  				Subject: []verifiable.Subject{{ID: issuerID}},
   143  				Issuer:  verifiable.Issuer{ID: issuerID},
   144  				CustomFields: map[string]interface{}{
   145  					"first_name": "Jesse",
   146  					"last_name":  "Travis",
   147  					"age":        2,
   148  				},
   149  				Proofs: []verifiable.Proof{{"type": "JsonWebSignature2020"}},
   150  			},
   151  		}
   152  
   153  		tests := []struct {
   154  			name    string
   155  			format  string
   156  			vFormat *Format
   157  		}{
   158  			/*{
   159  				name:   "test LDP format",
   160  				format: FormatLDP,
   161  				vFormat: &Format{
   162  					Ldp: &LdpType{ProofType: []string{"JsonWebSignature2020"}},
   163  				},
   164  			},
   165  			{
   166  				name:   "test LDPVP format",
   167  				format: FormatLDPVP,
   168  				vFormat: &Format{
   169  					LdpVP: &LdpType{ProofType: []string{"JsonWebSignature2020"}},
   170  				},
   171  			},
   172  			{
   173  				name:   "test LDPVC format",
   174  				format: FormatLDPVC,
   175  				vFormat: &Format{
   176  					LdpVC: &LdpType{ProofType: []string{"JsonWebSignature2020"}},
   177  				},
   178  			},
   179  			{
   180  				name:   "test JWT format",
   181  				format: FormatJWT,
   182  				vFormat: &Format{
   183  					Jwt: &JwtType{Alg: []string{"EdDSA"}},
   184  				},
   185  			},
   186  			{
   187  				name:   "test JWTVC format",
   188  				format: FormatJWTVC,
   189  				vFormat: &Format{
   190  					JwtVC: &JwtType{Alg: []string{"EdDSA"}},
   191  				},
   192  			},*/
   193  			{
   194  				name:   "test JWTVP format",
   195  				format: FormatJWTVP,
   196  				vFormat: &Format{
   197  					JwtVP: &JwtType{Alg: []string{"EdDSA"}},
   198  				},
   199  			},
   200  		}
   201  
   202  		for _, tc := range tests {
   203  			t.Run(tc.name, func(t *testing.T) {
   204  				pd := &PresentationDefinition{
   205  					ID: uuid.New().String(),
   206  					SubmissionRequirements: []*SubmissionRequirement{
   207  						{
   208  							Rule: "all",
   209  							From: "A",
   210  						},
   211  						{
   212  							Rule:  "pick",
   213  							Count: 1,
   214  							FromNested: []*SubmissionRequirement{
   215  								{
   216  									Rule: "all",
   217  									From: "teenager",
   218  								},
   219  								{
   220  									Rule: "all",
   221  									From: "child",
   222  								},
   223  								{
   224  									Rule: "pick",
   225  									From: "adult",
   226  									Min:  2,
   227  								},
   228  							},
   229  						},
   230  					},
   231  					InputDescriptors: []*InputDescriptor{{
   232  						ID:    uuid.New().String(),
   233  						Group: []string{"A"},
   234  						Schema: []*Schema{{
   235  							URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
   236  						}},
   237  						Constraints: &Constraints{
   238  							SubjectIsIssuer: &subIsIssuerRequired,
   239  							Fields: []*Field{{
   240  								Path: []string{"$.first_name", "$.last_name"},
   241  							}},
   242  						},
   243  					}, {
   244  						ID:    uuid.New().String(),
   245  						Group: []string{"child"},
   246  						Schema: []*Schema{{
   247  							URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
   248  						}},
   249  						Constraints: &Constraints{
   250  							SubjectIsIssuer: &subIsIssuerRequired,
   251  							Fields: []*Field{{
   252  								Path: []string{"$.age"},
   253  								Filter: &Filter{
   254  									Type:    &intFilterType,
   255  									Minimum: 3,
   256  									Maximum: 12,
   257  								},
   258  							}},
   259  						},
   260  					}, {
   261  						ID:    uuid.New().String(),
   262  						Group: []string{"teenager"},
   263  						Schema: []*Schema{{
   264  							URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
   265  						}},
   266  						Constraints: &Constraints{
   267  							SubjectIsIssuer: &subIsIssuerRequired,
   268  							Fields: []*Field{{
   269  								Path: []string{"$.age"},
   270  								Filter: &Filter{
   271  									Type:    &intFilterType,
   272  									Minimum: 13,
   273  									Maximum: 17,
   274  								},
   275  							}},
   276  						},
   277  					}, {
   278  						ID:    uuid.New().String(),
   279  						Group: []string{"adult"},
   280  						Schema: []*Schema{{
   281  							URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
   282  						}},
   283  						Constraints: &Constraints{
   284  							SubjectIsIssuer: &subIsIssuerRequired,
   285  							Fields: []*Field{{
   286  								Path: []string{"$.age"},
   287  								Filter: &Filter{
   288  									Type:    &intFilterType,
   289  									Minimum: 18,
   290  									Maximum: 23,
   291  								},
   292  							}},
   293  						},
   294  					}},
   295  					Format: tc.vFormat,
   296  				}
   297  
   298  				vp, err := pd.CreateVP(candidateVCs, lddl)
   299  
   300  				require.NoError(t, err)
   301  				require.NotNil(t, vp)
   302  				require.Equal(t, 1, len(vp.Credentials()))
   303  
   304  				checkSubmission(t, vp, pd)
   305  				checkVP(t, vp)
   306  			})
   307  		}
   308  	})
   309  
   310  	t.Run("Checks submission requirements (no descriptor)", func(t *testing.T) {
   311  		issuerID := uuid.New().String()
   312  
   313  		pd := &PresentationDefinition{
   314  			ID: uuid.New().String(),
   315  			SubmissionRequirements: []*SubmissionRequirement{
   316  				{
   317  					Rule: "all",
   318  					From: "A",
   319  				},
   320  				{
   321  					Rule:  "pick",
   322  					Count: 1,
   323  					FromNested: []*SubmissionRequirement{
   324  						{
   325  							Rule: "all",
   326  							From: "teenager",
   327  						},
   328  					},
   329  				},
   330  			},
   331  			InputDescriptors: []*InputDescriptor{{
   332  				ID:    uuid.New().String(),
   333  				Group: []string{"A"},
   334  				Schema: []*Schema{{
   335  					URI: verifiable.ContextURI,
   336  				}},
   337  				Constraints: &Constraints{
   338  					SubjectIsIssuer: &subIsIssuerRequired,
   339  					Fields: []*Field{{
   340  						Path: []string{"$.first_name", "$.last_name"},
   341  					}},
   342  				},
   343  			}},
   344  		}
   345  
   346  		vp, err := pd.CreateVP([]*verifiable.Credential{
   347  			{
   348  				Context: []string{verifiable.ContextURI},
   349  				Types:   []string{verifiable.VCType},
   350  				ID:      uuid.New().String(),
   351  				CustomFields: map[string]interface{}{
   352  					"first_name": "Jesse",
   353  				},
   354  			}, {
   355  				ID:      uuid.New().String(),
   356  				Subject: []verifiable.Subject{{ID: issuerID}},
   357  				Issuer:  verifiable.Issuer{ID: issuerID},
   358  				CustomFields: map[string]interface{}{
   359  					"first_name": "Jesse",
   360  					"last_name":  "Travis",
   361  					"age":        17,
   362  				},
   363  			},
   364  		}, lddl)
   365  
   366  		require.EqualError(t, err, "no descriptors for from: teenager")
   367  		require.Nil(t, vp)
   368  	})
   369  
   370  	t.Run("Predicate", func(t *testing.T) {
   371  		predicate := Required
   372  
   373  		pd := &PresentationDefinition{
   374  			ID: uuid.New().String(),
   375  			InputDescriptors: []*InputDescriptor{{
   376  				ID: uuid.New().String(),
   377  				Schema: []*Schema{{
   378  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
   379  				}},
   380  				Constraints: &Constraints{
   381  					Fields: []*Field{{
   382  						Path:      []string{"$.first_name", "$.last_name"},
   383  						Predicate: &predicate,
   384  						Filter:    &Filter{Type: &strFilterType},
   385  					}},
   386  				},
   387  			}},
   388  		}
   389  
   390  		vp, err := pd.CreateVP([]*verifiable.Credential{
   391  			{
   392  				Context: []string{verifiable.ContextURI},
   393  				Types:   []string{verifiable.VCType},
   394  				ID:      "http://example.edu/credentials/1872",
   395  				Subject: "did:example:76e12ec712ebc6f1c221ebfeb1f",
   396  				Issued: &util.TimeWrapper{
   397  					Time: time.Now(),
   398  				},
   399  				Issuer: verifiable.Issuer{
   400  					ID: "did:example:76e12ec712ebc6f1c221ebfeb1f",
   401  				},
   402  				CustomFields: map[string]interface{}{
   403  					"first_name": "First name",
   404  					"last_name":  "Last name",
   405  					"info":       "Info",
   406  				},
   407  			},
   408  		}, lddl, verifiable.WithJSONLDDocumentLoader(createTestJSONLDDocumentLoader(t)))
   409  
   410  		require.NoError(t, err)
   411  		require.NotNil(t, vp)
   412  		require.Equal(t, 1, len(vp.Credentials()))
   413  
   414  		vc, ok := vp.Credentials()[0].(*verifiable.Credential)
   415  		require.True(t, ok)
   416  
   417  		require.True(t, vc.CustomFields["first_name"].(bool))
   418  		require.True(t, vc.CustomFields["last_name"].(bool))
   419  		require.EqualValues(t, "Info", vc.CustomFields["info"])
   420  
   421  		checkSubmission(t, vp, pd)
   422  		checkVP(t, vp)
   423  	})
   424  
   425  	t.Run("Get By Credential Type", func(t *testing.T) {
   426  		const queryByCredType = `{
   427  				   "id": "69ddc987-55c2-4f1f-acea-f2838be10607",
   428  				   "input_descriptors": [
   429  					   {
   430  						   "id": "26b00531-caa1-49f3-a5a1-4a0eae8c0925",
   431  						   "constraints": {
   432  							   "fields": [
   433  								   {
   434  									   "path": [
   435  										   "$.type",
   436  										   "$.vc.type"
   437  									   ],
   438  								 "filter": {
   439  									"type": "array",
   440  									"contains": {
   441  											"type": "string",
   442  											"const": "DemoCred"
   443  											}
   444  								   		}
   445  								   }
   446  							   ]
   447  						   }
   448  					   }
   449  				   ]
   450  				}`
   451  
   452  		var pd PresentationDefinition
   453  		require.NoError(t, json.Unmarshal([]byte(queryByCredType), &pd))
   454  
   455  		vp, err := pd.CreateVP([]*verifiable.Credential{
   456  			{
   457  				Context: []string{verifiable.ContextURI},
   458  				Types:   []string{verifiable.VCType, "DemoCred"},
   459  				ID:      "http://example.edu/credentials/1872",
   460  				Subject: "did:example:76e12ec712ebc6f1c221ebfeb1f",
   461  				Issued: &util.TimeWrapper{
   462  					Time: time.Now(),
   463  				},
   464  				Issuer: verifiable.Issuer{
   465  					ID: "did:example:76e12ec712ebc6f1c221ebfeb1f",
   466  				},
   467  				CustomFields: map[string]interface{}{
   468  					"first_name": "First name",
   469  					"last_name":  "Last name",
   470  					"info":       "Info",
   471  				},
   472  			},
   473  		}, lddl, verifiable.WithJSONLDDocumentLoader(createTestJSONLDDocumentLoader(t)))
   474  
   475  		require.NoError(t, err)
   476  		require.NotNil(t, vp)
   477  		require.Equal(t, 1, len(vp.Credentials()))
   478  
   479  		checkSubmission(t, vp, &pd)
   480  		checkVP(t, vp)
   481  	})
   482  
   483  	t.Run("Predicate (limit disclosure)", func(t *testing.T) {
   484  		required := Required
   485  
   486  		pd := &PresentationDefinition{
   487  			ID: uuid.New().String(),
   488  			InputDescriptors: []*InputDescriptor{{
   489  				ID: uuid.New().String(),
   490  				Schema: []*Schema{{
   491  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
   492  				}},
   493  				Constraints: &Constraints{
   494  					LimitDisclosure: &required,
   495  					Fields: []*Field{{
   496  						Path:      []string{"$.first_name", "$.last_name"},
   497  						Predicate: &required,
   498  						Filter:    &Filter{Type: &strFilterType},
   499  					}},
   500  				},
   501  			}},
   502  		}
   503  
   504  		vp, err := pd.CreateVP([]*verifiable.Credential{
   505  			{
   506  				Context: []string{verifiable.ContextURI},
   507  				Types:   []string{verifiable.VCType},
   508  				ID:      "http://example.edu/credentials/1872",
   509  				Subject: "did:example:76e12ec712ebc6f1c221ebfeb1f",
   510  				Issued: &util.TimeWrapper{
   511  					Time: time.Now(),
   512  				},
   513  				Issuer: verifiable.Issuer{
   514  					ID: "did:example:76e12ec712ebc6f1c221ebfeb1f",
   515  				},
   516  				CustomFields: map[string]interface{}{
   517  					"first_name": "First name",
   518  					"last_name":  "Last name",
   519  					"info":       "Info",
   520  				},
   521  			},
   522  		}, lddl, verifiable.WithJSONLDDocumentLoader(createTestJSONLDDocumentLoader(t)))
   523  
   524  		require.NoError(t, err)
   525  		require.NotNil(t, vp)
   526  		require.Equal(t, 1, len(vp.Credentials()))
   527  
   528  		vc, ok := vp.Credentials()[0].(*verifiable.Credential)
   529  		require.True(t, ok)
   530  
   531  		require.True(t, vc.CustomFields["first_name"].(bool))
   532  		require.True(t, vc.CustomFields["last_name"].(bool))
   533  
   534  		_, ok = vc.CustomFields["info"]
   535  		require.False(t, ok)
   536  
   537  		checkSubmission(t, vp, pd)
   538  		checkVP(t, vp)
   539  	})
   540  
   541  	t.Run("SD-JWT: Limit Disclosure + SD Claim paths", func(t *testing.T) {
   542  		required := Required
   543  
   544  		pd := &PresentationDefinition{
   545  			ID: uuid.New().String(),
   546  			InputDescriptors: []*InputDescriptor{{
   547  				ID: uuid.New().String(),
   548  				Schema: []*Schema{{
   549  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
   550  				}},
   551  				Constraints: &Constraints{
   552  					LimitDisclosure: &required,
   553  					Fields: []*Field{{
   554  						Path: []string{
   555  							"$.credentialSubject.family_name",
   556  							"$.credentialSubject.given_name",
   557  							"$.credentialSubject.address.country",
   558  						},
   559  					}},
   560  				},
   561  			}},
   562  		}
   563  
   564  		testVC := getTestVC()
   565  
   566  		ed25519Signer, err := newCryptoSigner(kms.ED25519Type)
   567  		require.NoError(t, err)
   568  
   569  		sdJwtVC := newSdJwtVC(t, testVC, ed25519Signer)
   570  
   571  		vp, err := pd.CreateVP([]*verifiable.Credential{sdJwtVC},
   572  			lddl, verifiable.WithJSONLDDocumentLoader(createTestJSONLDDocumentLoader(t)))
   573  
   574  		require.NoError(t, err)
   575  		require.NotNil(t, vp)
   576  		require.Equal(t, 1, len(vp.Credentials()))
   577  
   578  		vc, ok := vp.Credentials()[0].(*verifiable.Credential)
   579  		require.True(t, ok)
   580  
   581  		require.Len(t, vc.SDJWTDisclosures, 3)
   582  
   583  		require.Len(t, vc.Subject.([]verifiable.Subject)[0].CustomFields["_sd"].([]interface{}), 6)
   584  		require.NotNil(t, vc.Subject.([]verifiable.Subject)[0].CustomFields["address"])
   585  
   586  		_, ok = vc.Subject.([]verifiable.Subject)[0].CustomFields["email"]
   587  		require.False(t, ok)
   588  
   589  		displayVC, err := vc.CreateDisplayCredential(verifiable.DisplayAllDisclosures())
   590  		require.NoError(t, err)
   591  
   592  		printObject(t, "Display VC - Limited", displayVC)
   593  
   594  		require.Equal(t, "John", displayVC.Subject.([]verifiable.Subject)[0].CustomFields["given_name"])
   595  		require.Equal(t, "Doe", displayVC.Subject.([]verifiable.Subject)[0].CustomFields["family_name"])
   596  
   597  		checkSubmission(t, vp, pd)
   598  		checkVP(t, vp)
   599  	})
   600  
   601  	t.Run("SD-JWT: Limit Disclosure + SD Claim paths + additional filter", func(t *testing.T) {
   602  		required := Required
   603  
   604  		pd := &PresentationDefinition{
   605  			ID: uuid.New().String(),
   606  			InputDescriptors: []*InputDescriptor{{
   607  				ID: uuid.New().String(),
   608  				Schema: []*Schema{{
   609  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
   610  				}},
   611  				Constraints: &Constraints{
   612  					LimitDisclosure: &required,
   613  					Fields: []*Field{
   614  						{
   615  							Path: []string{
   616  								"$.credentialSubject.family_name",
   617  								"$.credentialSubject.given_name",
   618  								"$.credentialSubject.address.country",
   619  							},
   620  						},
   621  						{
   622  							Path: []string{
   623  								"$.credentialSchema[0].id",
   624  							},
   625  							Filter: &Filter{
   626  								Type:  &strFilterType,
   627  								Const: "https://www.w3.org/TR/vc-data-model/2.0/#types",
   628  							},
   629  						},
   630  					},
   631  				},
   632  			}},
   633  		}
   634  
   635  		testVC := getTestVC()
   636  
   637  		ed25519Signer, err := newCryptoSigner(kms.ED25519Type)
   638  		require.NoError(t, err)
   639  
   640  		sdJwtVC := newSdJwtVC(t, testVC, ed25519Signer)
   641  
   642  		vp, err := pd.CreateVP([]*verifiable.Credential{sdJwtVC},
   643  			lddl, verifiable.WithJSONLDDocumentLoader(createTestJSONLDDocumentLoader(t)))
   644  
   645  		require.NoError(t, err)
   646  		require.NotNil(t, vp)
   647  		require.Equal(t, 1, len(vp.Credentials()))
   648  
   649  		vc, ok := vp.Credentials()[0].(*verifiable.Credential)
   650  		require.True(t, ok)
   651  
   652  		require.Len(t, vc.SDJWTDisclosures, 3)
   653  
   654  		require.Len(t, vc.Subject.([]verifiable.Subject)[0].CustomFields["_sd"].([]interface{}), 6)
   655  		require.NotNil(t, vc.Subject.([]verifiable.Subject)[0].CustomFields["address"])
   656  
   657  		_, ok = vc.Subject.([]verifiable.Subject)[0].CustomFields["email"]
   658  		require.False(t, ok)
   659  
   660  		displayVC, err := vc.CreateDisplayCredential(verifiable.DisplayAllDisclosures())
   661  		require.NoError(t, err)
   662  
   663  		printObject(t, "Display VC", displayVC)
   664  
   665  		require.Equal(t, "John", displayVC.Subject.([]verifiable.Subject)[0].CustomFields["given_name"])
   666  		require.Equal(t, "Doe", displayVC.Subject.([]verifiable.Subject)[0].CustomFields["family_name"])
   667  
   668  		checkSubmission(t, vp, pd)
   669  		checkVP(t, vp)
   670  	})
   671  
   672  	t.Run("SD-JWT: Limit Disclosure + non-SD claim path", func(t *testing.T) {
   673  		required := Required
   674  
   675  		pd := &PresentationDefinition{
   676  			ID: uuid.New().String(),
   677  			InputDescriptors: []*InputDescriptor{{
   678  				ID: uuid.New().String(),
   679  				Schema: []*Schema{{
   680  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
   681  				}},
   682  				Constraints: &Constraints{
   683  					LimitDisclosure: &required,
   684  					Fields: []*Field{{
   685  						Path: []string{
   686  							"$.id",
   687  						},
   688  					}},
   689  				},
   690  			}},
   691  		}
   692  
   693  		testVC := getTestVC()
   694  
   695  		ed25519Signer, err := newCryptoSigner(kms.ED25519Type)
   696  		require.NoError(t, err)
   697  
   698  		sdJwtVC := newSdJwtVC(t, testVC, ed25519Signer)
   699  
   700  		vp, err := pd.CreateVP([]*verifiable.Credential{sdJwtVC},
   701  			lddl, verifiable.WithJSONLDDocumentLoader(createTestJSONLDDocumentLoader(t)))
   702  
   703  		require.NoError(t, err)
   704  		require.NotNil(t, vp)
   705  		require.Equal(t, 1, len(vp.Credentials()))
   706  
   707  		vc, ok := vp.Credentials()[0].(*verifiable.Credential)
   708  		require.True(t, ok)
   709  
   710  		// there is only one non-SD claim path is in the fields array - hence no selective disclosures
   711  		require.Len(t, vc.SDJWTDisclosures, 0)
   712  
   713  		require.Len(t, vc.Subject.([]verifiable.Subject)[0].CustomFields["_sd"].([]interface{}), 6)
   714  
   715  		displayVC, err := vc.CreateDisplayCredential(verifiable.DisplayAllDisclosures())
   716  		require.NoError(t, err)
   717  
   718  		printObject(t, "Display VC - No Selective Disclosures", displayVC)
   719  
   720  		require.Nil(t, displayVC.Subject.([]verifiable.Subject)[0].CustomFields["given_name"])
   721  		require.Nil(t, displayVC.Subject.([]verifiable.Subject)[0].CustomFields["email"])
   722  
   723  		checkSubmission(t, vp, pd)
   724  		checkVP(t, vp)
   725  	})
   726  
   727  	t.Run("SD-JWT: No Limit Disclosure + Predicate Satisfied", func(t *testing.T) {
   728  		required := Required
   729  
   730  		pd := &PresentationDefinition{
   731  			ID: uuid.New().String(),
   732  			InputDescriptors: []*InputDescriptor{{
   733  				ID: uuid.New().String(),
   734  				Schema: []*Schema{{
   735  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
   736  				}},
   737  				Constraints: &Constraints{
   738  					Fields: []*Field{{
   739  						Path: []string{
   740  							"$.credentialSubject.family_name",
   741  						},
   742  						Predicate: &required,
   743  						Filter:    &Filter{Type: &strFilterType},
   744  					}},
   745  				},
   746  			}},
   747  		}
   748  
   749  		testVC := getTestVC()
   750  
   751  		ed25519Signer, err := newCryptoSigner(kms.ED25519Type)
   752  		require.NoError(t, err)
   753  
   754  		sdJwtVC := newSdJwtVC(t, testVC, ed25519Signer)
   755  
   756  		vp, err := pd.CreateVP([]*verifiable.Credential{sdJwtVC},
   757  			lddl, verifiable.WithJSONLDDocumentLoader(createTestJSONLDDocumentLoader(t)))
   758  
   759  		require.NoError(t, err)
   760  		require.NotNil(t, vp)
   761  		require.Equal(t, 1, len(vp.Credentials()))
   762  
   763  		vc, ok := vp.Credentials()[0].(*verifiable.Credential)
   764  		require.True(t, ok)
   765  
   766  		require.Len(t, vc.SDJWTDisclosures, 10)
   767  
   768  		require.Len(t, vc.Subject.([]verifiable.Subject)[0].CustomFields["_sd"].([]interface{}), 6)
   769  		require.NotNil(t, vc.Subject.([]verifiable.Subject)[0].CustomFields["address"])
   770  
   771  		_, ok = vc.Subject.([]verifiable.Subject)[0].CustomFields["email"]
   772  		require.False(t, ok)
   773  
   774  		displayVC, err := vc.CreateDisplayCredential(verifiable.DisplayAllDisclosures())
   775  		require.NoError(t, err)
   776  
   777  		printObject(t, "Display VC - No Limit Disclosure (all fields displayed)", displayVC)
   778  
   779  		require.Equal(t, "John", displayVC.Subject.([]verifiable.Subject)[0].CustomFields["given_name"])
   780  		require.Equal(t, "Doe", displayVC.Subject.([]verifiable.Subject)[0].CustomFields["family_name"])
   781  		require.Equal(t, "johndoe@example.com", displayVC.Subject.([]verifiable.Subject)[0].CustomFields["email"])
   782  
   783  		checkSubmission(t, vp, pd)
   784  		checkVP(t, vp)
   785  	})
   786  
   787  	t.Run("SD-JWT: hash algorithm not supported", func(t *testing.T) {
   788  		required := Required
   789  
   790  		pd := &PresentationDefinition{
   791  			ID: uuid.New().String(),
   792  			InputDescriptors: []*InputDescriptor{{
   793  				ID: uuid.New().String(),
   794  				Schema: []*Schema{{
   795  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
   796  				}},
   797  				Constraints: &Constraints{
   798  					LimitDisclosure: &required,
   799  					Fields: []*Field{{
   800  						Path: []string{
   801  							"$.credentialSubject.given_name",
   802  						},
   803  					}},
   804  				},
   805  			}},
   806  		}
   807  
   808  		testVC := getTestVC()
   809  
   810  		ed25519Signer, err := newCryptoSigner(kms.ED25519Type)
   811  		require.NoError(t, err)
   812  
   813  		sdJwtVC := newSdJwtVC(t, testVC, ed25519Signer)
   814  
   815  		sdJwtVC.SDJWTHashAlg = "sha-128"
   816  
   817  		vp, err := pd.CreateVP([]*verifiable.Credential{sdJwtVC},
   818  			lddl, verifiable.WithJSONLDDocumentLoader(createTestJSONLDDocumentLoader(t)))
   819  
   820  		require.Error(t, err)
   821  		require.Nil(t, vp)
   822  		require.Contains(t, err.Error(), "_sd_alg 'sha-128' not supported")
   823  	})
   824  
   825  	t.Run("SD-JWT: invalid JSON path ", func(t *testing.T) {
   826  		required := Required
   827  
   828  		pd := &PresentationDefinition{
   829  			ID: uuid.New().String(),
   830  			InputDescriptors: []*InputDescriptor{{
   831  				ID: uuid.New().String(),
   832  				Schema: []*Schema{{
   833  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
   834  				}},
   835  				Constraints: &Constraints{
   836  					LimitDisclosure: &required,
   837  					Fields: []*Field{{
   838  						Path: []string{
   839  							"123",
   840  						},
   841  					}},
   842  				},
   843  			}},
   844  		}
   845  
   846  		testVC := getTestVC()
   847  
   848  		ed25519Signer, err := newCryptoSigner(kms.ED25519Type)
   849  		require.NoError(t, err)
   850  
   851  		sdJwtVC := newSdJwtVC(t, testVC, ed25519Signer)
   852  
   853  		vp, err := pd.CreateVP([]*verifiable.Credential{sdJwtVC},
   854  			lddl, verifiable.WithJSONLDDocumentLoader(createTestJSONLDDocumentLoader(t)))
   855  
   856  		require.Error(t, err)
   857  		require.Nil(t, vp)
   858  		require.Contains(t, err.Error(), "Expected $ or @ at start of path instead of  U+0031")
   859  	})
   860  
   861  	t.Run("SD-JWT: Limit Disclosure (credentials don't meet requirement)", func(t *testing.T) {
   862  		required := Required
   863  
   864  		pd := &PresentationDefinition{
   865  			ID: uuid.New().String(),
   866  			InputDescriptors: []*InputDescriptor{{
   867  				ID: uuid.New().String(),
   868  				Schema: []*Schema{{
   869  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
   870  				}},
   871  				Constraints: &Constraints{
   872  					LimitDisclosure: &required,
   873  					Fields: []*Field{{
   874  						Path: []string{
   875  							"$.credentialSubject.family_name",
   876  							"$.credentialSubject.given_name",
   877  							"$.credentialSubject.address.country",
   878  						},
   879  						Predicate: &required,
   880  						Filter:    &Filter{Type: &arrFilterType},
   881  					}},
   882  				},
   883  			}},
   884  		}
   885  
   886  		testVC := getTestVC()
   887  
   888  		ed25519Signer, err := newCryptoSigner(kms.ED25519Type)
   889  		require.NoError(t, err)
   890  
   891  		sdJwtVC := newSdJwtVC(t, testVC, ed25519Signer)
   892  
   893  		vp, err := pd.CreateVP([]*verifiable.Credential{sdJwtVC},
   894  			lddl, verifiable.WithJSONLDDocumentLoader(createTestJSONLDDocumentLoader(t)))
   895  
   896  		require.Error(t, err)
   897  		require.Nil(t, vp)
   898  		require.Contains(t, err.Error(), "credentials do not satisfy requirements")
   899  	})
   900  
   901  	t.Run("SD-JWT: No Limit Disclosure (credentials don't meet requirement)", func(t *testing.T) {
   902  		required := Required
   903  
   904  		pd := &PresentationDefinition{
   905  			ID: uuid.New().String(),
   906  			InputDescriptors: []*InputDescriptor{{
   907  				ID: uuid.New().String(),
   908  				Schema: []*Schema{{
   909  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
   910  				}},
   911  				Constraints: &Constraints{
   912  					Fields: []*Field{{
   913  						Path: []string{
   914  							"$.credentialSubject.family_name",
   915  							"$.credentialSubject.given_name",
   916  							"$.credentialSubject.address.country",
   917  						},
   918  						Predicate: &required,
   919  						Filter:    &Filter{Type: &arrFilterType},
   920  					}},
   921  				},
   922  			}},
   923  		}
   924  
   925  		testVC := getTestVC()
   926  
   927  		ed25519Signer, err := newCryptoSigner(kms.ED25519Type)
   928  		require.NoError(t, err)
   929  
   930  		sdJwtVC := newSdJwtVC(t, testVC, ed25519Signer)
   931  
   932  		vp, err := pd.CreateVP([]*verifiable.Credential{sdJwtVC},
   933  			lddl, verifiable.WithJSONLDDocumentLoader(createTestJSONLDDocumentLoader(t)))
   934  
   935  		require.Error(t, err)
   936  		require.Nil(t, vp)
   937  		require.Contains(t, err.Error(), "credentials do not satisfy requirements")
   938  	})
   939  
   940  	t.Run("SD-JWT: Limit Disclosure with invalid field (credentials don't meet requirement)", func(t *testing.T) {
   941  		required := Required
   942  
   943  		pd := &PresentationDefinition{
   944  			ID: uuid.New().String(),
   945  			InputDescriptors: []*InputDescriptor{{
   946  				ID: uuid.New().String(),
   947  				Schema: []*Schema{{
   948  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
   949  				}},
   950  				Constraints: &Constraints{
   951  					LimitDisclosure: &required,
   952  					Fields: []*Field{{
   953  						Path: []string{
   954  							"$.credentialSubject.invalid",
   955  						},
   956  					}},
   957  				},
   958  			}},
   959  		}
   960  
   961  		testVC := getTestVC()
   962  
   963  		ed25519Signer, err := newCryptoSigner(kms.ED25519Type)
   964  		require.NoError(t, err)
   965  
   966  		sdJwtVC := newSdJwtVC(t, testVC, ed25519Signer)
   967  
   968  		vp, err := pd.CreateVP([]*verifiable.Credential{sdJwtVC},
   969  			lddl, verifiable.WithJSONLDDocumentLoader(createTestJSONLDDocumentLoader(t)))
   970  
   971  		require.Error(t, err)
   972  		require.Nil(t, vp)
   973  		require.Contains(t, err.Error(), "credentials do not satisfy requirements")
   974  	})
   975  
   976  	t.Run("Limit disclosure BBS+", func(t *testing.T) {
   977  		required := Required
   978  
   979  		pd := &PresentationDefinition{
   980  			ID: uuid.New().String(),
   981  			InputDescriptors: []*InputDescriptor{{
   982  				Schema: []*Schema{{
   983  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
   984  				}},
   985  				ID: uuid.New().String(),
   986  				Constraints: &Constraints{
   987  					LimitDisclosure: &required,
   988  					Fields: []*Field{{
   989  						Path:   []string{"$.credentialSubject.degree.degreeSchool"},
   990  						Filter: &Filter{Type: &strFilterType},
   991  					}},
   992  				},
   993  			}},
   994  		}
   995  
   996  		vc := &verifiable.Credential{
   997  			ID: "https://issuer.oidp.uscis.gov/credentials/83627465",
   998  			Context: []string{
   999  				verifiable.ContextURI,
  1000  				"https://www.w3.org/2018/credentials/examples/v1",
  1001  				"https://w3id.org/security/bbs/v1",
  1002  			},
  1003  			Types: []string{
  1004  				"VerifiableCredential",
  1005  				"UniversityDegreeCredential",
  1006  			},
  1007  			Subject: verifiable.Subject{
  1008  				ID: "did:example:b34ca6cd37bbf23",
  1009  				CustomFields: map[string]interface{}{
  1010  					"name":   "Jayden Doe",
  1011  					"spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1",
  1012  					"degree": map[string]interface{}{
  1013  						"degree":       "MIT",
  1014  						"degreeSchool": "MIT school",
  1015  						"type":         "BachelorDegree",
  1016  					},
  1017  				},
  1018  			},
  1019  			Issued: &util.TimeWrapper{
  1020  				Time: time.Now(),
  1021  			},
  1022  			Expired: &util.TimeWrapper{
  1023  				Time: time.Now().AddDate(1, 0, 0),
  1024  			},
  1025  			Issuer: verifiable.Issuer{
  1026  				ID: "did:example:489398593",
  1027  			},
  1028  			CustomFields: map[string]interface{}{
  1029  				"identifier":  "83627465",
  1030  				"name":        "Permanent Resident Card",
  1031  				"description": "Government of Example Permanent Resident Card.",
  1032  			},
  1033  		}
  1034  
  1035  		publicKey, privateKey, err := bbs12381g2pub.GenerateKeyPair(sha256.New, nil)
  1036  		require.NoError(t, err)
  1037  
  1038  		srcPublicKey, err := publicKey.Marshal()
  1039  		require.NoError(t, err)
  1040  
  1041  		signer, err := newBBSSigner(privateKey)
  1042  		require.NoError(t, err)
  1043  
  1044  		require.NoError(t, vc.AddLinkedDataProof(&verifiable.LinkedDataProofContext{
  1045  			SignatureType:           "BbsBlsSignature2020",
  1046  			SignatureRepresentation: verifiable.SignatureProofValue,
  1047  			Suite:                   bbsblssignature2020.New(suite.WithSigner(signer)),
  1048  			VerificationMethod:      "did:example:123456#key1",
  1049  		}, jsonld.WithDocumentLoader(createTestJSONLDDocumentLoader(t))))
  1050  
  1051  		vp, err := pd.CreateVP([]*verifiable.Credential{vc}, lddl,
  1052  			verifiable.WithJSONLDDocumentLoader(createTestJSONLDDocumentLoader(t)),
  1053  			verifiable.WithPublicKeyFetcher(verifiable.SingleKey(srcPublicKey, "Bls12381G2Key2020")),
  1054  		)
  1055  		require.NoError(t, err)
  1056  		require.NotNil(t, vp)
  1057  		require.Equal(t, 1, len(vp.Credentials()))
  1058  
  1059  		vc, ok := vp.Credentials()[0].(*verifiable.Credential)
  1060  		require.True(t, ok)
  1061  
  1062  		subject := vc.Subject.([]verifiable.Subject)[0]
  1063  		degree := subject.CustomFields["degree"]
  1064  		require.NotNil(t, degree)
  1065  
  1066  		degreeMap, ok := degree.(map[string]interface{})
  1067  		require.True(t, ok)
  1068  
  1069  		require.Equal(t, "MIT school", degreeMap["degreeSchool"])
  1070  		require.Equal(t, "BachelorDegree", degreeMap["type"])
  1071  		require.Empty(t, degreeMap["degree"])
  1072  		require.Equal(t, "did:example:b34ca6cd37bbf23", subject.ID)
  1073  		require.Empty(t, subject.CustomFields["spouse"])
  1074  		require.Empty(t, vc.CustomFields["name"])
  1075  
  1076  		require.NotEmpty(t, vc.Proofs)
  1077  
  1078  		checkSubmission(t, vp, pd)
  1079  		checkVP(t, vp)
  1080  	})
  1081  
  1082  	t.Run("Predicate and limit disclosure BBS+ (no proof)", func(t *testing.T) {
  1083  		required := Required
  1084  
  1085  		pd := &PresentationDefinition{
  1086  			ID: uuid.New().String(),
  1087  			InputDescriptors: []*InputDescriptor{{
  1088  				Schema: []*Schema{{
  1089  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
  1090  				}},
  1091  				ID: uuid.New().String(),
  1092  				Constraints: &Constraints{
  1093  					LimitDisclosure: &required,
  1094  					Fields: []*Field{{
  1095  						Path:      []string{"$.credentialSubject.givenName", "$.credentialSubject.familyName"},
  1096  						Filter:    &Filter{Type: &strFilterType},
  1097  						Predicate: &required,
  1098  					}, {
  1099  						Path:   []string{"$.credentialSubject.type"},
  1100  						Filter: &Filter{Type: &arrFilterType},
  1101  					}},
  1102  				},
  1103  			}},
  1104  		}
  1105  
  1106  		vc := &verifiable.Credential{
  1107  			ID: "https://issuer.oidp.uscis.gov/credentials/83627465",
  1108  			Context: []string{
  1109  				verifiable.ContextURI,
  1110  				"https://w3id.org/citizenship/v1",
  1111  				"https://w3id.org/security/bbs/v1",
  1112  			},
  1113  			Types: []string{
  1114  				"VerifiableCredential",
  1115  				"PermanentResidentCard",
  1116  			},
  1117  			Subject: verifiable.Subject{
  1118  				ID: "did:example:b34ca6cd37bbf23",
  1119  				CustomFields: map[string]interface{}{
  1120  					"type": []string{
  1121  						"PermanentResident",
  1122  						"Person",
  1123  					},
  1124  					"givenName":              "JOHN",
  1125  					"familyName":             "SMITH",
  1126  					"gender":                 "Male",
  1127  					"image":                  "data:image/png;base64,iVBORw0KGgokJggg==",
  1128  					"residentSince":          "2015-01-01",
  1129  					"lprCategory":            "C09",
  1130  					"lprNumber":              "999-999-999",
  1131  					"commuterClassification": "C1",
  1132  					"birthCountry":           "Bahamas",
  1133  					"birthDate":              "1958-07-17",
  1134  				},
  1135  			},
  1136  			Issued: &util.TimeWrapper{
  1137  				Time: time.Now(),
  1138  			},
  1139  			Expired: &util.TimeWrapper{
  1140  				Time: time.Now().AddDate(1, 0, 0),
  1141  			},
  1142  			Issuer: verifiable.Issuer{
  1143  				ID: "did:example:489398593",
  1144  			},
  1145  			CustomFields: map[string]interface{}{
  1146  				"identifier":  "83627465",
  1147  				"name":        "Permanent Resident Card",
  1148  				"description": "Government of Example Permanent Resident Card.",
  1149  			},
  1150  		}
  1151  
  1152  		publicKey, privateKey, err := bbs12381g2pub.GenerateKeyPair(sha256.New, nil)
  1153  		require.NoError(t, err)
  1154  
  1155  		srcPublicKey, err := publicKey.Marshal()
  1156  		require.NoError(t, err)
  1157  
  1158  		signer, err := newBBSSigner(privateKey)
  1159  		require.NoError(t, err)
  1160  
  1161  		require.NoError(t, vc.AddLinkedDataProof(&verifiable.LinkedDataProofContext{
  1162  			SignatureType:           "BbsBlsSignature2020",
  1163  			SignatureRepresentation: verifiable.SignatureProofValue,
  1164  			Suite:                   bbsblssignature2020.New(suite.WithSigner(signer)),
  1165  			VerificationMethod:      "did:example:123456#key1",
  1166  		}, jsonld.WithDocumentLoader(createTestJSONLDDocumentLoader(t))))
  1167  
  1168  		vp, err := pd.CreateVP([]*verifiable.Credential{vc}, lddl,
  1169  			verifiable.WithJSONLDDocumentLoader(createTestJSONLDDocumentLoader(t)),
  1170  			verifiable.WithPublicKeyFetcher(verifiable.SingleKey(srcPublicKey, "Bls12381G2Key2020")),
  1171  		)
  1172  		require.NoError(t, err)
  1173  		require.NotNil(t, vp)
  1174  		require.Equal(t, 1, len(vp.Credentials()))
  1175  
  1176  		vc, ok := vp.Credentials()[0].(*verifiable.Credential)
  1177  		require.True(t, ok)
  1178  
  1179  		require.Equal(t, true, vc.Subject.([]verifiable.Subject)[0].CustomFields["givenName"])
  1180  		require.Equal(t, true, vc.Subject.([]verifiable.Subject)[0].CustomFields["familyName"])
  1181  		require.Empty(t, vc.Subject.([]verifiable.Subject)[0].CustomFields["gender"])
  1182  		require.Empty(t, vc.Proofs)
  1183  
  1184  		checkSubmission(t, vp, pd)
  1185  		checkVP(t, vp)
  1186  	})
  1187  
  1188  	t.Run("Predicate (marshal error)", func(t *testing.T) {
  1189  		pd := &PresentationDefinition{
  1190  			ID: uuid.New().String(),
  1191  			InputDescriptors: []*InputDescriptor{{
  1192  				ID: uuid.New().String(),
  1193  				Schema: []*Schema{{
  1194  					URI: verifiable.ContextID,
  1195  				}},
  1196  				Constraints: &Constraints{
  1197  					Fields: []*Field{{
  1198  						Path:   []string{"$.last_name"},
  1199  						Filter: &Filter{Type: &strFilterType},
  1200  					}},
  1201  				},
  1202  			}},
  1203  		}
  1204  
  1205  		vp, err := pd.CreateVP([]*verifiable.Credential{
  1206  			{
  1207  				Context: []string{verifiable.ContextURI},
  1208  				Types:   []string{verifiable.VCType},
  1209  				ID:      uuid.New().String(),
  1210  				CustomFields: map[string]interface{}{
  1211  					"first_name": make(chan struct{}),
  1212  					"last_name":  "Jon",
  1213  				},
  1214  			},
  1215  		}, lddl)
  1216  
  1217  		require.EqualError(t, err, errMsgSchema)
  1218  		require.Nil(t, vp)
  1219  	})
  1220  
  1221  	t.Run("No matches (path)", func(t *testing.T) {
  1222  		pd := &PresentationDefinition{
  1223  			ID: uuid.New().String(),
  1224  			InputDescriptors: []*InputDescriptor{{
  1225  				ID: uuid.New().String(),
  1226  				Schema: []*Schema{{
  1227  					URI: verifiable.ContextID,
  1228  				}},
  1229  				Constraints: &Constraints{
  1230  					Fields: []*Field{{
  1231  						Path: []string{"$.first_name", "$.last_name"},
  1232  					}},
  1233  				},
  1234  			}},
  1235  		}
  1236  
  1237  		vp, err := pd.CreateVP([]*verifiable.Credential{
  1238  			{
  1239  				Context: []string{verifiable.ContextURI},
  1240  				Types:   []string{verifiable.VCType},
  1241  				ID:      uuid.New().String(),
  1242  				CustomFields: map[string]interface{}{
  1243  					"first_name": "Jesse",
  1244  				},
  1245  			},
  1246  			{
  1247  				ID: uuid.New().String(),
  1248  				CustomFields: map[string]interface{}{
  1249  					"last_name": "Travis",
  1250  				},
  1251  			},
  1252  		}, lddl)
  1253  
  1254  		require.EqualError(t, err, errMsgSchema)
  1255  		require.Nil(t, vp)
  1256  	})
  1257  
  1258  	t.Run("No matches (one field path)", func(t *testing.T) {
  1259  		pd := &PresentationDefinition{
  1260  			ID: uuid.New().String(),
  1261  			InputDescriptors: []*InputDescriptor{{
  1262  				ID: uuid.New().String(),
  1263  				Schema: []*Schema{{
  1264  					URI: verifiable.ContextID,
  1265  				}},
  1266  				Constraints: &Constraints{
  1267  					Fields: []*Field{{
  1268  						Path: []string{"$.first_name"},
  1269  					}, {
  1270  						Path: []string{"$.last_name"},
  1271  					}},
  1272  				},
  1273  			}},
  1274  		}
  1275  
  1276  		vp, err := pd.CreateVP([]*verifiable.Credential{
  1277  			{
  1278  				Context: []string{verifiable.ContextURI},
  1279  				Types:   []string{verifiable.VCType},
  1280  				ID:      uuid.New().String(),
  1281  				CustomFields: map[string]interface{}{
  1282  					"first_name": "Jesse",
  1283  				},
  1284  			},
  1285  			{
  1286  				ID: uuid.New().String(),
  1287  				CustomFields: map[string]interface{}{
  1288  					"last_name": "Travis",
  1289  				},
  1290  			},
  1291  		}, lddl)
  1292  
  1293  		require.EqualError(t, err, errMsgSchema)
  1294  		require.Nil(t, vp)
  1295  	})
  1296  
  1297  	t.Run("Matches one credentials (two fields)", func(t *testing.T) {
  1298  		issuerID := uuid.New().String()
  1299  
  1300  		pd := &PresentationDefinition{
  1301  			ID: uuid.New().String(),
  1302  			InputDescriptors: []*InputDescriptor{{
  1303  				ID: uuid.New().String(),
  1304  				Schema: []*Schema{{
  1305  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
  1306  				}},
  1307  				Constraints: &Constraints{
  1308  					SubjectIsIssuer: &subIsIssuerRequired,
  1309  					Fields: []*Field{{
  1310  						Path:   []string{"$.first_name"},
  1311  						Filter: &Filter{Type: &strFilterType},
  1312  					}, {
  1313  						Path:   []string{"$.last_name"},
  1314  						Filter: &Filter{Type: &strFilterType},
  1315  					}},
  1316  				},
  1317  			}},
  1318  		}
  1319  
  1320  		vp, err := pd.CreateVP([]*verifiable.Credential{
  1321  			{
  1322  				Context: []string{verifiable.ContextURI},
  1323  				Types:   []string{verifiable.VCType},
  1324  				ID:      uuid.New().String(),
  1325  				Subject: map[string]interface{}{},
  1326  				CustomFields: map[string]interface{}{
  1327  					"first_name": "Jesse",
  1328  				},
  1329  			}, {
  1330  				Context: []string{verifiable.ContextURI},
  1331  				Types:   []string{verifiable.VCType},
  1332  				ID:      uuid.New().String(),
  1333  				Subject: verifiable.Subject{ID: issuerID},
  1334  				Issuer:  verifiable.Issuer{ID: issuerID},
  1335  				CustomFields: map[string]interface{}{
  1336  					"first_name": "Jesse",
  1337  					"last_name":  "Travis",
  1338  				},
  1339  			},
  1340  		}, lddl)
  1341  
  1342  		require.NoError(t, err)
  1343  		require.NotNil(t, vp)
  1344  		require.Equal(t, 1, len(vp.Credentials()))
  1345  
  1346  		checkSubmission(t, vp, pd)
  1347  		checkVP(t, vp)
  1348  	})
  1349  
  1350  	t.Run("Matches one credentials (three fields - disclosure)", func(t *testing.T) {
  1351  		issuerID := "did:example:76e12ec712ebc6f1c221ebfeb1f"
  1352  		required := Required
  1353  
  1354  		pd := &PresentationDefinition{
  1355  			ID: uuid.New().String(),
  1356  			InputDescriptors: []*InputDescriptor{{
  1357  				ID: uuid.New().String(),
  1358  				Schema: []*Schema{{
  1359  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
  1360  				}},
  1361  				Constraints: &Constraints{
  1362  					SubjectIsIssuer: &subIsIssuerRequired,
  1363  					LimitDisclosure: &required,
  1364  					Fields: []*Field{{
  1365  						Path:   []string{"$.first_name"},
  1366  						Filter: &Filter{Type: &strFilterType},
  1367  					}, {
  1368  						Path:   []string{"$.issuer"},
  1369  						Filter: &Filter{Type: &strFilterType},
  1370  					}, {
  1371  						Path: []string{"$.all[*].authors[*].name"},
  1372  						Filter: &Filter{
  1373  							Type: &arrFilterType,
  1374  						},
  1375  					}},
  1376  				},
  1377  			}},
  1378  		}
  1379  
  1380  		vp, err := pd.CreateVP([]*verifiable.Credential{
  1381  			{
  1382  				Context: []string{verifiable.ContextURI},
  1383  				Types:   []string{verifiable.VCType},
  1384  				ID:      uuid.New().String(),
  1385  				Subject: []map[string]interface{}{{}},
  1386  				Issuer:  verifiable.Issuer{ID: uuid.New().String()},
  1387  				CustomFields: map[string]interface{}{
  1388  					"last_name": "Travis",
  1389  				},
  1390  			},
  1391  			{
  1392  				ID:      "http://example.edu/credentials/1872",
  1393  				Context: []string{verifiable.ContextURI},
  1394  				Types:   []string{"VerifiableCredential"},
  1395  				Subject: []map[string]interface{}{{"id": issuerID}},
  1396  				Issuer:  verifiable.Issuer{ID: issuerID},
  1397  				Issued: &util.TimeWrapper{
  1398  					Time: time.Now(),
  1399  				},
  1400  				CustomFields: map[string]interface{}{
  1401  					"first_name": "Jesse",
  1402  					"ssn":        "000-00-000",
  1403  					"last_name":  "Travis",
  1404  					"all": []interface{}{
  1405  						map[string]interface{}{
  1406  							"authors": []interface{}{map[string]interface{}{
  1407  								"name":    "Andrew",
  1408  								"license": "yes",
  1409  							}, map[string]interface{}{
  1410  								"name":    "Jessy",
  1411  								"license": "no",
  1412  							}},
  1413  						},
  1414  						map[string]interface{}{
  1415  							"authors": []interface{}{map[string]interface{}{
  1416  								"license": "unknown",
  1417  							}},
  1418  						},
  1419  						map[string]interface{}{
  1420  							"authors": []interface{}{map[string]interface{}{
  1421  								"name":    "Bob",
  1422  								"license": "yes",
  1423  							}, map[string]interface{}{
  1424  								"name":    "Carol",
  1425  								"license": "no",
  1426  							}},
  1427  						},
  1428  					},
  1429  				},
  1430  			},
  1431  		}, lddl, verifiable.WithJSONLDDocumentLoader(createTestJSONLDDocumentLoader(t)))
  1432  
  1433  		require.NoError(t, err)
  1434  		require.NotNil(t, vp)
  1435  		require.Equal(t, 1, len(vp.Credentials()))
  1436  
  1437  		cred, ok := vp.Credentials()[0].(*verifiable.Credential)
  1438  		require.True(t, ok)
  1439  		require.NotEmpty(t, cred.Issuer)
  1440  
  1441  		require.EqualValues(t, []interface{}{
  1442  			map[string]interface{}{
  1443  				"authors": []interface{}{map[string]interface{}{
  1444  					"name": "Andrew",
  1445  				}, map[string]interface{}{
  1446  					"name": "Jessy",
  1447  				}},
  1448  			},
  1449  			map[string]interface{}{
  1450  				"authors": []interface{}{map[string]interface{}{
  1451  					"name": "Bob",
  1452  				}, map[string]interface{}{
  1453  					"name": "Carol",
  1454  				}},
  1455  			},
  1456  		}, cred.CustomFields["all"])
  1457  
  1458  		checkSubmission(t, vp, pd)
  1459  		checkVP(t, vp)
  1460  	})
  1461  
  1462  	t.Run("Create new credential (error)", func(t *testing.T) {
  1463  		required := Required
  1464  
  1465  		pd := &PresentationDefinition{
  1466  			ID: uuid.New().String(),
  1467  			InputDescriptors: []*InputDescriptor{{
  1468  				ID: uuid.New().String(),
  1469  				Schema: []*Schema{{
  1470  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
  1471  				}},
  1472  				Constraints: &Constraints{
  1473  					LimitDisclosure: &required,
  1474  					Fields: []*Field{{
  1475  						Path: []string{"$.first_name"},
  1476  						Filter: &Filter{
  1477  							Type:    &strFilterType,
  1478  							Pattern: "^Jesse",
  1479  						},
  1480  					}},
  1481  				},
  1482  			}},
  1483  		}
  1484  
  1485  		vp, err := pd.CreateVP([]*verifiable.Credential{
  1486  			{
  1487  				Context: []string{verifiable.ContextURI},
  1488  				Types:   []string{verifiable.VCType},
  1489  				ID:      uuid.New().String(),
  1490  				Issuer:  verifiable.Issuer{CustomFields: map[string]interface{}{"k": "v"}},
  1491  				CustomFields: map[string]interface{}{
  1492  					"first_name": "Jesse",
  1493  				},
  1494  			},
  1495  		}, lddl)
  1496  
  1497  		require.Error(t, err)
  1498  		require.True(t, strings.HasPrefix(err.Error(), "create new credential"))
  1499  		require.Nil(t, vp)
  1500  	})
  1501  
  1502  	t.Run("Matches one credentials (field pattern)", func(t *testing.T) {
  1503  		issuerID := uuid.New().String()
  1504  
  1505  		pd := &PresentationDefinition{
  1506  			ID: uuid.New().String(),
  1507  			InputDescriptors: []*InputDescriptor{{
  1508  				ID: uuid.New().String(),
  1509  				Schema: []*Schema{{
  1510  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
  1511  				}},
  1512  				Constraints: &Constraints{
  1513  					SubjectIsIssuer: &subIsIssuerRequired,
  1514  					Fields: []*Field{{
  1515  						Path: []string{"$.first_name"},
  1516  						Filter: &Filter{
  1517  							Type:    &strFilterType,
  1518  							Pattern: "^Jesse",
  1519  						},
  1520  					}},
  1521  				},
  1522  			}},
  1523  		}
  1524  
  1525  		vp, err := pd.CreateVP([]*verifiable.Credential{
  1526  			{
  1527  				Context: []string{verifiable.ContextURI},
  1528  				Types:   []string{verifiable.VCType},
  1529  				ID:      uuid.New().String(),
  1530  				Subject: map[string]interface{}{"id": issuerID},
  1531  				Issuer:  verifiable.Issuer{ID: issuerID},
  1532  				CustomFields: map[string]interface{}{
  1533  					"first_name": "Jesse",
  1534  				},
  1535  			},
  1536  			{
  1537  				Context: []string{verifiable.ContextURI},
  1538  				Types:   []string{verifiable.VCType},
  1539  				ID:      uuid.New().String(),
  1540  				Subject: map[string]interface{}{"id": 123},
  1541  				CustomFields: map[string]interface{}{
  1542  					"first_name": "Travis",
  1543  					"last_name":  "Jesse",
  1544  				},
  1545  			},
  1546  		}, lddl)
  1547  
  1548  		require.NoError(t, err)
  1549  		require.NotNil(t, vp)
  1550  		require.Equal(t, 1, len(vp.Credentials()))
  1551  
  1552  		checkSubmission(t, vp, pd)
  1553  		checkVP(t, vp)
  1554  	})
  1555  
  1556  	t.Run("Matches one credentials", func(t *testing.T) {
  1557  		issuerID := uuid.New().String()
  1558  
  1559  		pd := &PresentationDefinition{
  1560  			ID: uuid.New().String(),
  1561  			InputDescriptors: []*InputDescriptor{{
  1562  				ID: uuid.New().String(),
  1563  				Schema: []*Schema{{
  1564  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
  1565  				}},
  1566  				Constraints: &Constraints{
  1567  					SubjectIsIssuer: &subIsIssuerRequired,
  1568  					Fields: []*Field{{
  1569  						Path: []string{"$.first_name", "$.last_name"},
  1570  					}},
  1571  				},
  1572  			}},
  1573  		}
  1574  
  1575  		vp, err := pd.CreateVP([]*verifiable.Credential{
  1576  			{
  1577  				Context: []string{verifiable.ContextURI},
  1578  				Types:   []string{verifiable.VCType},
  1579  				ID:      uuid.New().String(),
  1580  				CustomFields: map[string]interface{}{
  1581  					"first_name": "Jesse",
  1582  				},
  1583  			},
  1584  			{
  1585  				Context: []string{verifiable.ContextURI},
  1586  				Types:   []string{verifiable.VCType},
  1587  				ID:      uuid.New().String(),
  1588  				Subject: []verifiable.Subject{{ID: issuerID}},
  1589  				Issuer:  verifiable.Issuer{ID: issuerID},
  1590  				CustomFields: map[string]interface{}{
  1591  					"first_name": "Jesse",
  1592  					"last_name":  "Travis",
  1593  				},
  1594  			},
  1595  		}, lddl)
  1596  
  1597  		require.NoError(t, err)
  1598  		require.NotNil(t, vp)
  1599  		require.Equal(t, 1, len(vp.Credentials()))
  1600  
  1601  		checkSubmission(t, vp, pd)
  1602  		checkVP(t, vp)
  1603  	})
  1604  
  1605  	t.Run("Matches one credentials (two descriptors)", func(t *testing.T) {
  1606  		issuerID := uuid.New().String()
  1607  
  1608  		pd := &PresentationDefinition{
  1609  			ID: uuid.New().String(),
  1610  			InputDescriptors: []*InputDescriptor{{
  1611  				ID: uuid.New().String(),
  1612  				Schema: []*Schema{{
  1613  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
  1614  				}},
  1615  				Constraints: &Constraints{
  1616  					SubjectIsIssuer: &subIsIssuerRequired,
  1617  					Fields: []*Field{{
  1618  						Path: []string{"$.first_name"},
  1619  					}, {
  1620  						Path: []string{"$.last_name"},
  1621  					}},
  1622  				},
  1623  			}, {
  1624  				ID: uuid.New().String(),
  1625  				Schema: []*Schema{{
  1626  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
  1627  				}},
  1628  				Constraints: &Constraints{
  1629  					Fields: []*Field{{
  1630  						Path: []string{"$.first_name"},
  1631  					}, {
  1632  						Path: []string{"$.last_name"},
  1633  					}},
  1634  				},
  1635  			}},
  1636  		}
  1637  
  1638  		vp, err := pd.CreateVP([]*verifiable.Credential{
  1639  			{
  1640  				Context: []string{verifiable.ContextURI},
  1641  				Types:   []string{verifiable.VCType},
  1642  				ID:      uuid.New().String(),
  1643  				Subject: issuerID,
  1644  				Issuer:  verifiable.Issuer{ID: issuerID},
  1645  				CustomFields: map[string]interface{}{
  1646  					"first_name": "Jesse",
  1647  				},
  1648  			},
  1649  			{
  1650  				Context: []string{verifiable.ContextURI},
  1651  				Types:   []string{verifiable.VCType},
  1652  				ID:      uuid.New().String(),
  1653  				Subject: issuerID,
  1654  				Issuer:  verifiable.Issuer{ID: issuerID},
  1655  				CustomFields: map[string]interface{}{
  1656  					"first_name": "Jesse",
  1657  					"last_name":  "Travis",
  1658  				},
  1659  			},
  1660  		}, lddl)
  1661  
  1662  		require.NoError(t, err)
  1663  		require.NotNil(t, vp)
  1664  		require.Equal(t, 1, len(vp.Credentials()))
  1665  
  1666  		checkSubmission(t, vp, pd)
  1667  		checkVP(t, vp)
  1668  	})
  1669  
  1670  	t.Run("Matches two credentials (one descriptor)", func(t *testing.T) {
  1671  		pd := &PresentationDefinition{
  1672  			ID: uuid.New().String(),
  1673  			InputDescriptors: []*InputDescriptor{{
  1674  				ID: uuid.New().String(),
  1675  				Schema: []*Schema{{
  1676  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
  1677  				}},
  1678  				Constraints: &Constraints{
  1679  					Fields: []*Field{{
  1680  						Path: []string{"$.first_name"},
  1681  					}},
  1682  				},
  1683  			}},
  1684  		}
  1685  
  1686  		vp, err := pd.CreateVP([]*verifiable.Credential{
  1687  			{
  1688  				Context: []string{verifiable.ContextURI},
  1689  				Types:   []string{verifiable.VCType},
  1690  				ID:      uuid.New().String(),
  1691  				CustomFields: map[string]interface{}{
  1692  					"first_name": "Jesse",
  1693  				},
  1694  			},
  1695  			{
  1696  				Context: []string{verifiable.ContextURI},
  1697  				Types:   []string{verifiable.VCType},
  1698  				ID:      uuid.New().String(),
  1699  				CustomFields: map[string]interface{}{
  1700  					"first_name": "Jesse",
  1701  					"last_name":  "Travis",
  1702  				},
  1703  			},
  1704  		}, lddl)
  1705  
  1706  		require.NoError(t, err)
  1707  		require.NotNil(t, vp)
  1708  		require.Equal(t, 2, len(vp.Credentials()))
  1709  
  1710  		checkSubmission(t, vp, pd)
  1711  		checkVP(t, vp)
  1712  	})
  1713  
  1714  	t.Run("Matches two credentials", func(t *testing.T) {
  1715  		pd := &PresentationDefinition{
  1716  			ID: uuid.New().String(),
  1717  			InputDescriptors: []*InputDescriptor{{
  1718  				ID: uuid.New().String(),
  1719  				Schema: []*Schema{{
  1720  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
  1721  				}},
  1722  			}},
  1723  		}
  1724  
  1725  		vp, err := pd.CreateVP([]*verifiable.Credential{
  1726  			{
  1727  				Context: []string{verifiable.ContextURI},
  1728  				Types:   []string{verifiable.VCType},
  1729  				ID:      uuid.New().String(),
  1730  			},
  1731  			{
  1732  				Context: []string{verifiable.ContextURI},
  1733  				Types:   []string{verifiable.VCType},
  1734  				ID:      uuid.New().String(),
  1735  			},
  1736  		}, lddl)
  1737  
  1738  		require.NoError(t, err)
  1739  		require.NotNil(t, vp)
  1740  		require.Equal(t, 2, len(vp.Credentials()))
  1741  
  1742  		checkSubmission(t, vp, pd)
  1743  		checkVP(t, vp)
  1744  	})
  1745  
  1746  	t.Run("Matches one credentials (one ignored)", func(t *testing.T) {
  1747  		pd := &PresentationDefinition{
  1748  			ID: uuid.New().String(),
  1749  			InputDescriptors: []*InputDescriptor{{
  1750  				ID: uuid.New().String(),
  1751  				Schema: []*Schema{{
  1752  					URI: "https://example.org/examples#UniversityDegreeCredential",
  1753  				}},
  1754  			}},
  1755  		}
  1756  
  1757  		vp, err := pd.CreateVP([]*verifiable.Credential{
  1758  			{
  1759  				Context: []string{verifiable.ContextURI},
  1760  				Types:   []string{verifiable.VCType},
  1761  				ID:      uuid.New().String(),
  1762  			},
  1763  			{
  1764  				Context: []string{verifiable.ContextURI, "https://www.w3.org/2018/credentials/examples/v1"},
  1765  				Types:   []string{verifiable.VCType, "UniversityDegreeCredential"},
  1766  				ID:      uuid.New().String(),
  1767  			},
  1768  		}, lddl)
  1769  
  1770  		require.NoError(t, err)
  1771  		require.NotNil(t, vp)
  1772  		require.Equal(t, 1, len(vp.Credentials()))
  1773  
  1774  		checkSubmission(t, vp, pd)
  1775  		checkVP(t, vp)
  1776  	})
  1777  
  1778  	t.Run("No matches", func(t *testing.T) {
  1779  		pd := &PresentationDefinition{
  1780  			ID: uuid.New().String(),
  1781  			InputDescriptors: []*InputDescriptor{{
  1782  				ID: uuid.New().String(),
  1783  				Schema: []*Schema{{
  1784  					URI: "https://www.w3.org/TR/vc-data-model/1.0/#types",
  1785  				}},
  1786  			}},
  1787  		}
  1788  
  1789  		vp, err := pd.CreateVP([]*verifiable.Credential{
  1790  			{
  1791  				Context: []string{verifiable.ContextURI},
  1792  				Types:   []string{verifiable.VCType},
  1793  				ID:      uuid.New().String(),
  1794  				Schemas: []verifiable.TypedID{{
  1795  					ID:   "https://www.w3.org/TR/vc-data-model/2.0/#types",
  1796  					Type: "JsonSchemaValidator2018",
  1797  				}},
  1798  			},
  1799  			{
  1800  				ID: uuid.New().String(),
  1801  				Schemas: []verifiable.TypedID{{
  1802  					ID:   "https://www.w3.org/TR/vc-data-model/3.0/#types",
  1803  					Type: "JsonSchemaValidator2018",
  1804  				}},
  1805  			},
  1806  		}, lddl)
  1807  
  1808  		require.EqualError(t, err, errMsgSchema)
  1809  		require.Nil(t, vp)
  1810  	})
  1811  
  1812  	t.Run("Matches two descriptors", func(t *testing.T) {
  1813  		pd := &PresentationDefinition{
  1814  			ID: uuid.New().String(),
  1815  			InputDescriptors: []*InputDescriptor{{
  1816  				ID: uuid.New().String(),
  1817  				Schema: []*Schema{{
  1818  					URI: "https://example.org/examples#UniversityDegreeCredential",
  1819  				}},
  1820  			}, {
  1821  				ID: uuid.New().String(),
  1822  				Schema: []*Schema{{
  1823  					URI: "https://example.org/examples#DocumentVerification",
  1824  				}},
  1825  			}},
  1826  		}
  1827  
  1828  		vp, err := pd.CreateVP([]*verifiable.Credential{
  1829  			{
  1830  				Context: []string{verifiable.ContextURI, "https://www.w3.org/2018/credentials/examples/v1"},
  1831  				Types:   []string{verifiable.VCType, "UniversityDegreeCredential"},
  1832  				ID:      uuid.New().String(),
  1833  			},
  1834  			{
  1835  				Context: []string{verifiable.ContextURI, "https://trustbloc.github.io/context/vc/examples-v1.jsonld"},
  1836  				Types:   []string{verifiable.VCType, "DocumentVerification"},
  1837  				ID:      uuid.New().String(),
  1838  			},
  1839  		}, lddl)
  1840  
  1841  		require.NoError(t, err)
  1842  		require.NotNil(t, vp)
  1843  		require.Equal(t, 2, len(vp.Credentials()))
  1844  
  1845  		checkSubmission(t, vp, pd)
  1846  		checkVP(t, vp)
  1847  	})
  1848  
  1849  	t.Run("Does not match one of descriptors", func(t *testing.T) {
  1850  		pd := &PresentationDefinition{
  1851  			ID: uuid.New().String(),
  1852  			InputDescriptors: []*InputDescriptor{{
  1853  				ID: uuid.New().String(),
  1854  				Schema: []*Schema{{
  1855  					URI: "https://www.w3.org/TR/vc-data-model/1.0/#types",
  1856  				}},
  1857  			}, {
  1858  				ID: uuid.New().String(),
  1859  				Schema: []*Schema{{
  1860  					URI: "https://www.w3.org/TR/vc-data-model/2.0/#types",
  1861  				}},
  1862  			}},
  1863  		}
  1864  
  1865  		vp, err := pd.CreateVP([]*verifiable.Credential{
  1866  			{
  1867  				Context: []string{verifiable.ContextURI},
  1868  				Types:   []string{verifiable.VCType},
  1869  				ID:      uuid.New().String(),
  1870  				Schemas: []verifiable.TypedID{{
  1871  					ID:   "https://www.w3.org/TR/vc-data-model/1.0/#types",
  1872  					Type: "JsonSchemaValidator2018",
  1873  				}},
  1874  			},
  1875  			{
  1876  				Context: []string{verifiable.ContextURI},
  1877  				Types:   []string{verifiable.VCType},
  1878  				ID:      uuid.New().String(),
  1879  				Schemas: []verifiable.TypedID{{
  1880  					ID:   "https://www.w3.org/TR/vc-data-model/3.0/#types",
  1881  					Type: "JsonSchemaValidator2018",
  1882  				}},
  1883  			},
  1884  		}, lddl)
  1885  
  1886  		require.EqualError(t, err, errMsgSchema)
  1887  		require.Nil(t, vp)
  1888  	})
  1889  
  1890  	t.Run("Does not match one of descriptors (required)", func(t *testing.T) {
  1891  		pd := &PresentationDefinition{
  1892  			ID: uuid.New().String(),
  1893  			InputDescriptors: []*InputDescriptor{{
  1894  				ID: uuid.New().String(),
  1895  				Schema: []*Schema{{
  1896  					URI: "https://www.w3.org/TR/vc-data-model/1.0/#types",
  1897  				}},
  1898  			}, {
  1899  				ID: uuid.New().String(),
  1900  				Schema: []*Schema{{
  1901  					URI: "https://www.w3.org/TR/vc-data-model/2.0/#types",
  1902  				}, {
  1903  					URI:      "https://www.w3.org/TR/vc-data-model/3.0/#types",
  1904  					Required: true,
  1905  				}},
  1906  			}},
  1907  		}
  1908  		vp, err := pd.CreateVP([]*verifiable.Credential{
  1909  			{
  1910  				Context: []string{verifiable.ContextURI},
  1911  				Types:   []string{verifiable.VCType},
  1912  				ID:      uuid.New().String(),
  1913  				Schemas: []verifiable.TypedID{{
  1914  					ID:   "https://www.w3.org/TR/vc-data-model/1.0/#types",
  1915  					Type: "JsonSchemaValidator2018",
  1916  				}},
  1917  			},
  1918  			{
  1919  				Context: []string{verifiable.ContextURI},
  1920  				Types:   []string{verifiable.VCType},
  1921  				ID:      uuid.New().String(),
  1922  				Schemas: []verifiable.TypedID{{
  1923  					ID: "https://www.w3.org/TR/vc-data-model/2.0/#types",
  1924  				}},
  1925  			},
  1926  		}, lddl)
  1927  
  1928  		require.EqualError(t, err, errMsgSchema)
  1929  		require.Nil(t, vp)
  1930  	})
  1931  
  1932  	t.Run("Ignores schema that is not required", func(t *testing.T) {
  1933  		pd := &PresentationDefinition{
  1934  			ID: uuid.New().String(),
  1935  			InputDescriptors: []*InputDescriptor{{
  1936  				ID: uuid.New().String(),
  1937  				Schema: []*Schema{{
  1938  					URI: "https://example.org/examples#DocumentVerification",
  1939  				}},
  1940  			}, {
  1941  				ID: uuid.New().String(),
  1942  				Schema: []*Schema{{
  1943  					URI: "https://www.w3.org/TR/vc-data-model/2.0/#types",
  1944  				}, {
  1945  					URI:      fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
  1946  					Required: true,
  1947  				}},
  1948  			}},
  1949  		}
  1950  		vp, err := pd.CreateVP([]*verifiable.Credential{
  1951  			{
  1952  				Context: []string{verifiable.ContextURI},
  1953  				Types:   []string{verifiable.VCType},
  1954  				ID:      uuid.New().String(),
  1955  			},
  1956  			{
  1957  				Context: []string{verifiable.ContextURI, "https://trustbloc.github.io/context/vc/examples-v1.jsonld"},
  1958  				Types:   []string{verifiable.VCType, "DocumentVerification"},
  1959  				ID:      uuid.New().String(),
  1960  			},
  1961  		}, lddl)
  1962  
  1963  		require.NoError(t, err)
  1964  		require.NotNil(t, vp)
  1965  		require.Equal(t, 2, len(vp.Credentials()))
  1966  
  1967  		checkSubmission(t, vp, pd)
  1968  		checkVP(t, vp)
  1969  	})
  1970  
  1971  	t.Run("Requires two schemas", func(t *testing.T) {
  1972  		pd := &PresentationDefinition{
  1973  			ID: uuid.New().String(),
  1974  			InputDescriptors: []*InputDescriptor{{
  1975  				ID: uuid.New().String(),
  1976  				Schema: []*Schema{{
  1977  					URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
  1978  				}},
  1979  			}, {
  1980  				ID: uuid.New().String(),
  1981  				Schema: []*Schema{{
  1982  					URI:      "https://example.org/examples#UniversityDegreeCredential",
  1983  					Required: true,
  1984  				}, {
  1985  					URI:      "https://example.org/examples#DocumentVerification",
  1986  					Required: true,
  1987  				}},
  1988  			}},
  1989  		}
  1990  		vp, err := pd.CreateVP([]*verifiable.Credential{
  1991  			{
  1992  				Context: []string{verifiable.ContextURI},
  1993  				Types:   []string{verifiable.VCType},
  1994  				ID:      uuid.New().String(),
  1995  				Schemas: []verifiable.TypedID{{
  1996  					ID:   "https://www.w3.org/TR/vc-data-model/1.0/#types",
  1997  					Type: "JsonSchemaValidator2018",
  1998  				}},
  1999  			},
  2000  			{
  2001  				Context: []string{
  2002  					verifiable.ContextURI,
  2003  					"https://www.w3.org/2018/credentials/examples/v1",
  2004  					"https://trustbloc.github.io/context/vc/examples-v1.jsonld",
  2005  				},
  2006  				Types: []string{verifiable.VCType, "UniversityDegreeCredential", "DocumentVerification"},
  2007  				ID:    uuid.New().String(),
  2008  			},
  2009  		}, lddl)
  2010  
  2011  		require.NoError(t, err)
  2012  		require.NotNil(t, vp)
  2013  		require.Equal(t, 2, len(vp.Credentials()))
  2014  
  2015  		checkSubmission(t, vp, pd)
  2016  		checkVP(t, vp)
  2017  	})
  2018  }
  2019  
  2020  func TestPresentationDefinition_CreateVPArray(t *testing.T) {
  2021  	lddl := createTestJSONLDDocumentLoader(t)
  2022  
  2023  	t.Run("Matches two descriptors", func(t *testing.T) {
  2024  		pd := &PresentationDefinition{
  2025  			ID: uuid.New().String(),
  2026  			InputDescriptors: []*InputDescriptor{{
  2027  				ID: uuid.New().String(),
  2028  				Schema: []*Schema{{
  2029  					URI: "https://example.org/examples#UniversityDegreeCredential",
  2030  				}},
  2031  			}, {
  2032  				ID: uuid.New().String(),
  2033  				Schema: []*Schema{{
  2034  					URI: "https://example.org/examples#DocumentVerification",
  2035  				}},
  2036  			}},
  2037  		}
  2038  
  2039  		vpList, ps, err := pd.CreateVPArray([]*verifiable.Credential{
  2040  			{
  2041  				Context: []string{verifiable.ContextURI, "https://www.w3.org/2018/credentials/examples/v1"},
  2042  				Types:   []string{verifiable.VCType, "UniversityDegreeCredential"},
  2043  				ID:      uuid.New().String(),
  2044  			},
  2045  			{
  2046  				Context: []string{verifiable.ContextURI, "https://trustbloc.github.io/context/vc/examples-v1.jsonld"},
  2047  				Types:   []string{verifiable.VCType, "DocumentVerification"},
  2048  				ID:      uuid.New().String(),
  2049  			},
  2050  		}, lddl)
  2051  
  2052  		require.NoError(t, err)
  2053  		require.NotNil(t, vpList)
  2054  		require.Len(t, vpList, 2)
  2055  
  2056  		checkExternalSubmission(t, vpList, ps, pd)
  2057  
  2058  		for _, vp := range vpList {
  2059  			checkVP(t, vp)
  2060  		}
  2061  	})
  2062  }
  2063  
  2064  func createEdDSAJWS(t *testing.T, cred *verifiable.Credential, signer verifiable.Signer,
  2065  	keyID string, minimize bool) string {
  2066  	t.Helper()
  2067  
  2068  	jwtClaims, err := cred.JWTClaims(minimize)
  2069  	require.NoError(t, err)
  2070  	vcJWT, err := jwtClaims.MarshalJWS(verifiable.EdDSA, signer, cred.Issuer.ID+"#keys-"+keyID)
  2071  	require.NoError(t, err)
  2072  
  2073  	return vcJWT
  2074  }
  2075  
  2076  func getTestVCWithContext(ctx []string) *verifiable.Credential {
  2077  	subject := map[string]interface{}{
  2078  		"id":           uuid.New().String(),
  2079  		"sub":          "john_doe_42",
  2080  		"given_name":   "John",
  2081  		"family_name":  "Doe",
  2082  		"email":        "johndoe@example.com",
  2083  		"phone_number": "+1-202-555-0101",
  2084  		"birthdate":    "1940-01-01",
  2085  		"address": map[string]interface{}{
  2086  			"street_address": "123 Main St",
  2087  			"locality":       "Anytown",
  2088  			"region":         "Anystate",
  2089  			"country":        "US",
  2090  		},
  2091  	}
  2092  
  2093  	vc := verifiable.Credential{
  2094  		Context: []string{verifiable.ContextURI},
  2095  		Types:   []string{verifiable.VCType},
  2096  		ID:      "http://example.edu/credentials/1872",
  2097  		Issued: &util.TimeWrapper{
  2098  			Time: time.Now(),
  2099  		},
  2100  		Issuer: verifiable.Issuer{
  2101  			ID: "did:example:76e12ec712ebc6f1c221ebfeb1f",
  2102  		},
  2103  		Schemas: []verifiable.TypedID{{
  2104  			ID:   "https://www.w3.org/TR/vc-data-model/2.0/#types",
  2105  			Type: "JsonSchemaValidator2018",
  2106  		}},
  2107  		Subject: subject,
  2108  	}
  2109  
  2110  	if ctx != nil {
  2111  		vc.Context = append(vc.Context, ctx...)
  2112  	}
  2113  
  2114  	return &vc
  2115  }
  2116  
  2117  func getTestVC() *verifiable.Credential {
  2118  	return getTestVCWithContext(nil)
  2119  }
  2120  
  2121  func newSdJwtVC(t *testing.T, vc *verifiable.Credential, signer signature.Signer) *verifiable.Credential {
  2122  	t.Helper()
  2123  
  2124  	pubKey := signer.PublicKeyBytes()
  2125  
  2126  	issuer, verMethod := fingerprint.CreateDIDKeyByCode(fingerprint.ED25519PubKeyMultiCodec, pubKey)
  2127  
  2128  	vc.Issuer = verifiable.Issuer{ID: issuer}
  2129  
  2130  	jwsAlgo, err := verifiable.KeyTypeToJWSAlgo(kms.ED25519Type)
  2131  	require.NoError(t, err)
  2132  
  2133  	algName, err := jwsAlgo.Name()
  2134  	require.NoError(t, err)
  2135  
  2136  	combinedFormatForIssuance, err := vc.MakeSDJWT(verifiable.GetJWTSigner(signer, algName), verMethod)
  2137  	require.NoError(t, err)
  2138  
  2139  	parsed, err := verifiable.ParseCredential([]byte(combinedFormatForIssuance),
  2140  		verifiable.WithPublicKeyFetcher(holderPublicKeyFetcher(pubKey)))
  2141  	require.NoError(t, err)
  2142  
  2143  	return parsed
  2144  }
  2145  
  2146  func holderPublicKeyFetcher(pubKeyBytes []byte) verifiable.PublicKeyFetcher {
  2147  	return func(issuerID, keyID string) (*verifier.PublicKey, error) {
  2148  		return &verifier.PublicKey{
  2149  			Type:  kms.RSARS256,
  2150  			Value: pubKeyBytes,
  2151  		}, nil
  2152  	}
  2153  }
  2154  
  2155  func createKMS() (*localkms.LocalKMS, error) {
  2156  	p, err := mockkms.NewProviderForKMS(storage.NewMockStoreProvider(), &noop.NoLock{})
  2157  	if err != nil {
  2158  		return nil, err
  2159  	}
  2160  
  2161  	return localkms.New("local-lock://custom/master/key/", p)
  2162  }
  2163  
  2164  func newCryptoSigner(keyType kms.KeyType) (signature.Signer, error) { // nolint:unparam
  2165  	localKMS, err := createKMS()
  2166  	if err != nil {
  2167  		return nil, err
  2168  	}
  2169  
  2170  	tinkCrypto, err := tinkcrypto.New()
  2171  	if err != nil {
  2172  		return nil, err
  2173  	}
  2174  
  2175  	return signature.NewCryptoSigner(tinkCrypto, localKMS, keyType)
  2176  }
  2177  
  2178  func checkSubmission(t *testing.T, vp *verifiable.Presentation, pd *PresentationDefinition) {
  2179  	t.Helper()
  2180  
  2181  	ps, ok := vp.CustomFields["presentation_submission"].(*PresentationSubmission)
  2182  	require.True(t, ok)
  2183  	require.NotEmpty(t, ps.ID)
  2184  	require.Equal(t, ps.DefinitionID, pd.ID)
  2185  
  2186  	src, err := json.Marshal(vp)
  2187  	require.NoError(t, err)
  2188  
  2189  	vpAsMap := map[string]interface{}{}
  2190  	require.NoError(t, json.Unmarshal(src, &vpAsMap))
  2191  
  2192  	builder := gval.Full(jsonpath.PlaceholderExtension())
  2193  
  2194  	for _, descriptor := range ps.DescriptorMap {
  2195  		require.NotEmpty(t, descriptor.ID)
  2196  		require.NotEmpty(t, descriptor.Path)
  2197  		require.NotEmpty(t, descriptor.Format)
  2198  
  2199  		path, err := builder.NewEvaluable(descriptor.Path)
  2200  		require.NoError(t, err)
  2201  		_, err = path(context.TODO(), vpAsMap)
  2202  		require.NoError(t, err)
  2203  	}
  2204  }
  2205  
  2206  func checkExternalSubmission(
  2207  	t *testing.T,
  2208  	vpList []*verifiable.Presentation,
  2209  	ps *PresentationSubmission,
  2210  	pd *PresentationDefinition,
  2211  ) {
  2212  	t.Helper()
  2213  
  2214  	require.NotEmpty(t, ps.ID)
  2215  	require.Equal(t, ps.DefinitionID, pd.ID)
  2216  
  2217  	src, err := json.Marshal(vpList)
  2218  	require.NoError(t, err)
  2219  
  2220  	rawVPList := []interface{}{}
  2221  	require.NoError(t, json.Unmarshal(src, &rawVPList))
  2222  
  2223  	builder := gval.Full(jsonpath.PlaceholderExtension())
  2224  
  2225  	for _, descriptor := range ps.DescriptorMap {
  2226  		require.NotEmpty(t, descriptor.ID)
  2227  		require.NotEmpty(t, descriptor.Path)
  2228  		require.NotEmpty(t, descriptor.Format)
  2229  
  2230  		path, err := builder.NewEvaluable(descriptor.Path)
  2231  		require.NoError(t, err)
  2232  		_, err = path(context.TODO(), rawVPList)
  2233  		require.NoError(t, err)
  2234  	}
  2235  }
  2236  
  2237  func checkVP(t *testing.T, vp *verifiable.Presentation) {
  2238  	t.Helper()
  2239  
  2240  	src, err := json.Marshal(vp)
  2241  	require.NoError(t, err)
  2242  
  2243  	_, err = verifiable.ParsePresentation(src,
  2244  		verifiable.WithPresDisabledProofCheck(),
  2245  		verifiable.WithPresJSONLDDocumentLoader(createTestJSONLDDocumentLoader(t)))
  2246  	require.NoError(t, err)
  2247  }
  2248  
  2249  func parseJSONFile(t *testing.T, name string, v interface{}) {
  2250  	t.Helper()
  2251  
  2252  	jf, err := os.Open(name) // nolint: gosec
  2253  	if err != nil {
  2254  		t.Error(err)
  2255  	}
  2256  
  2257  	defer func() {
  2258  		if err = jf.Close(); err != nil {
  2259  			t.Error(err)
  2260  		}
  2261  	}()
  2262  
  2263  	byteValue, err := ioutil.ReadAll(jf)
  2264  	if err != nil {
  2265  		t.Error(err)
  2266  	}
  2267  
  2268  	if err = json.Unmarshal(byteValue, &v); err != nil {
  2269  		t.Error(err)
  2270  	}
  2271  }
  2272  
  2273  type bbsSigner struct {
  2274  	privateKey []byte
  2275  }
  2276  
  2277  func newBBSSigner(key *bbs12381g2pub.PrivateKey) (*bbsSigner, error) {
  2278  	src, err := key.Marshal()
  2279  	if err != nil {
  2280  		return nil, err
  2281  	}
  2282  
  2283  	return &bbsSigner{privateKey: src}, nil
  2284  }
  2285  
  2286  func (s *bbsSigner) Sign(data []byte) ([]byte, error) {
  2287  	return bbs12381g2pub.New().Sign(s.textToLines(string(data)), s.privateKey)
  2288  }
  2289  
  2290  func (s *bbsSigner) Alg() string {
  2291  	return ""
  2292  }
  2293  
  2294  func (s *bbsSigner) textToLines(txt string) [][]byte {
  2295  	lines := strings.Split(txt, "\n")
  2296  	linesBytes := make([][]byte, 0, len(lines))
  2297  
  2298  	for i := range lines {
  2299  		if strings.TrimSpace(lines[i]) != "" {
  2300  			linesBytes = append(linesBytes, []byte(lines[i]))
  2301  		}
  2302  	}
  2303  
  2304  	return linesBytes
  2305  }
  2306  
  2307  func createTestJSONLDDocumentLoader(t *testing.T) *ld.DocumentLoader {
  2308  	t.Helper()
  2309  
  2310  	loader, err := ldtestutil.DocumentLoader()
  2311  	require.NoError(t, err)
  2312  
  2313  	return loader
  2314  }
  2315  
  2316  func prettyPrint(msg []byte) (string, error) {
  2317  	var prettyJSON bytes.Buffer
  2318  
  2319  	err := json.Indent(&prettyJSON, msg, "", "\t")
  2320  	if err != nil {
  2321  		return "", err
  2322  	}
  2323  
  2324  	return prettyJSON.String(), nil
  2325  }
  2326  
  2327  func printObject(t *testing.T, name string, obj interface{}) {
  2328  	t.Helper()
  2329  
  2330  	objBytes, err := json.Marshal(obj)
  2331  	require.NoError(t, err)
  2332  
  2333  	prettyJSON, err := prettyPrint(objBytes)
  2334  	require.NoError(t, err)
  2335  
  2336  	fmt.Println(name + ":")
  2337  	fmt.Println(prettyJSON)
  2338  }