github.com/hyperledger/aries-framework-go@v0.3.2/pkg/doc/presexch/example_v2_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  	"crypto/sha256"
    11  	"encoding/json"
    12  	"fmt"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/piprate/json-gold/ld"
    17  	"github.com/stretchr/testify/require"
    18  
    19  	"github.com/hyperledger/aries-framework-go/pkg/crypto/primitive/bbs12381g2pub"
    20  	. "github.com/hyperledger/aries-framework-go/pkg/doc/presexch"
    21  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/jsonld"
    22  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite"
    23  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/bbsblssignature2020"
    24  	"github.com/hyperledger/aries-framework-go/pkg/doc/util"
    25  	jsonutil "github.com/hyperledger/aries-framework-go/pkg/doc/util/json"
    26  	"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
    27  	"github.com/hyperledger/aries-framework-go/pkg/internal/ldtestutil"
    28  )
    29  
    30  func ExamplePresentationDefinition_CreateVP_v2() {
    31  	required := Required
    32  
    33  	pd := &PresentationDefinition{
    34  		ID:      "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
    35  		Purpose: "To sell you a drink we need to know that you are an adult.",
    36  		InputDescriptors: []*InputDescriptor{{
    37  			ID:      "age_descriptor",
    38  			Purpose: "Your age should be greater or equal to 18.",
    39  			Constraints: &Constraints{
    40  				LimitDisclosure: &required,
    41  				Fields: []*Field{
    42  					{
    43  						Path:      []string{"$.credentialSubject.age", "$.vc.credentialSubject.age", "$.age"},
    44  						Predicate: &required,
    45  						Filter: &Filter{
    46  							Type:    &intFilterType,
    47  							Minimum: 18,
    48  						},
    49  					},
    50  					{
    51  						Path: []string{"$.credentialSchema[0].id", "$.credentialSchema.id", "$.vc.credentialSchema.id"},
    52  						Filter: &Filter{
    53  							Type:  &strFilterType,
    54  							Const: "hub://did:foo:123/Collections/schema.us.gov/passport.json",
    55  						},
    56  					},
    57  				},
    58  			},
    59  		}},
    60  	}
    61  
    62  	loader, err := ldtestutil.DocumentLoader()
    63  	if err != nil {
    64  		panic(err)
    65  	}
    66  
    67  	vp, err := pd.CreateVP([]*verifiable.Credential{
    68  		{
    69  			ID:      "http://example.edu/credentials/777",
    70  			Context: []string{verifiable.ContextURI},
    71  			Types:   []string{verifiable.VCType},
    72  			Issuer: verifiable.Issuer{
    73  				ID: "did:example:76e12ec712ebc6f1c221ebfeb1f",
    74  			},
    75  			Issued: &util.TimeWrapper{
    76  				Time: time.Time{},
    77  			},
    78  			Schemas: []verifiable.TypedID{{
    79  				ID:   "hub://did:foo:123/Collections/schema.us.gov/passport.json",
    80  				Type: "JsonSchemaValidator2018",
    81  			}},
    82  
    83  			Subject: map[string]interface{}{
    84  				"id":         "did:example:ebfeb1f712ebc6f1c276e12ec21",
    85  				"first_name": "Jesse",
    86  				"last_name":  "Pinkman",
    87  				"age":        21,
    88  			},
    89  		},
    90  	}, loader, verifiable.WithJSONLDDocumentLoader(loader))
    91  	if err != nil {
    92  		panic(err)
    93  	}
    94  
    95  	vp.ID = dummy
    96  	vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy
    97  
    98  	vpBytes, err := json.MarshalIndent(vp, "", "\t")
    99  	if err != nil {
   100  		panic(err)
   101  	}
   102  
   103  	fmt.Println(string(vpBytes))
   104  	// Output:
   105  	// {
   106  	//	"@context": [
   107  	//		"https://www.w3.org/2018/credentials/v1",
   108  	//		"https://identity.foundation/presentation-exchange/submission/v1"
   109  	//	],
   110  	//	"id": "DUMMY",
   111  	//	"presentation_submission": {
   112  	//		"id": "DUMMY",
   113  	//		"definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
   114  	//		"descriptor_map": [
   115  	//			{
   116  	//				"id": "age_descriptor",
   117  	//				"format": "ldp_vp",
   118  	//				"path": "$",
   119  	//				"path_nested": {
   120  	//					"id": "age_descriptor",
   121  	//					"format": "ldp_vc",
   122  	//					"path": "$.verifiableCredential[0]"
   123  	//				}
   124  	//			}
   125  	//		]
   126  	//	},
   127  	//	"type": [
   128  	//		"VerifiablePresentation",
   129  	//		"PresentationSubmission"
   130  	//	],
   131  	//	"verifiableCredential": [
   132  	//		{
   133  	//			"@context": [
   134  	//				"https://www.w3.org/2018/credentials/v1"
   135  	//			],
   136  	//			"credentialSubject": {
   137  	//				"age": true,
   138  	//				"first_name": "Jesse",
   139  	//				"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   140  	//				"last_name": "Pinkman"
   141  	//			},
   142  	//			"id": "http://example.edu/credentials/777",
   143  	//			"issuanceDate": "0001-01-01T00:00:00Z",
   144  	//			"issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f",
   145  	//			"type": "VerifiableCredential"
   146  	//		}
   147  	//	]
   148  	// }
   149  }
   150  
   151  func ExamplePresentationDefinition_CreateVP_with_LdpVC_Format() {
   152  	required := Required
   153  
   154  	pd := &PresentationDefinition{
   155  		ID:      "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
   156  		Purpose: "To sell you a drink we need to know that you are an adult.",
   157  		Format: &Format{
   158  			LdpVC: &LdpType{
   159  				ProofType: []string{"Ed25519Signature2018"},
   160  			},
   161  		},
   162  		InputDescriptors: []*InputDescriptor{{
   163  			ID:      "age_descriptor",
   164  			Purpose: "Your age should be greater or equal to 18.",
   165  			Constraints: &Constraints{
   166  				LimitDisclosure: &required,
   167  				Fields: []*Field{
   168  					{
   169  						Path:      []string{"$.credentialSubject.age", "$.vc.credentialSubject.age", "$.age"},
   170  						Predicate: &required,
   171  						Filter: &Filter{
   172  							Type:    &intFilterType,
   173  							Minimum: 18,
   174  						},
   175  					},
   176  					{
   177  						Path: []string{"$.credentialSchema[0].id", "$.credentialSchema.id", "$.vc.credentialSchema.id"},
   178  						Filter: &Filter{
   179  							Type:  &strFilterType,
   180  							Const: "hub://did:foo:123/Collections/schema.us.gov/passport.json",
   181  						},
   182  					},
   183  				},
   184  			},
   185  		}},
   186  	}
   187  
   188  	loader, err := ldtestutil.DocumentLoader()
   189  	if err != nil {
   190  		panic(err)
   191  	}
   192  
   193  	vp, err := pd.CreateVP([]*verifiable.Credential{
   194  		{
   195  			ID:      "http://example.edu/credentials/777",
   196  			Context: []string{verifiable.ContextURI},
   197  			Types:   []string{verifiable.VCType},
   198  			Issuer: verifiable.Issuer{
   199  				ID: "did:example:76e12ec712ebc6f1c221ebfeb1f",
   200  			},
   201  			Issued: &util.TimeWrapper{
   202  				Time: time.Time{},
   203  			},
   204  			Schemas: []verifiable.TypedID{{
   205  				ID:   "hub://did:foo:123/Collections/schema.us.gov/passport.json",
   206  				Type: "JsonSchemaValidator2018",
   207  			}},
   208  
   209  			Subject: map[string]interface{}{
   210  				"id":         "did:example:ebfeb1f712ebc6f1c276e12ec21",
   211  				"first_name": "Jesse",
   212  				"last_name":  "Pinkman",
   213  				"age":        21,
   214  			},
   215  			Proofs: []verifiable.Proof{
   216  				{"type": "Ed25519Signature2018"},
   217  			},
   218  		},
   219  	}, loader, verifiable.WithJSONLDDocumentLoader(loader))
   220  	if err != nil {
   221  		panic(err)
   222  	}
   223  
   224  	vp.ID = dummy
   225  	vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy
   226  
   227  	vpBytes, err := json.MarshalIndent(vp, "", "\t")
   228  	if err != nil {
   229  		panic(err)
   230  	}
   231  
   232  	fmt.Println(string(vpBytes))
   233  	// Output:
   234  	// {
   235  	//	"@context": [
   236  	//		"https://www.w3.org/2018/credentials/v1",
   237  	//		"https://identity.foundation/presentation-exchange/submission/v1"
   238  	//	],
   239  	//	"id": "DUMMY",
   240  	//	"presentation_submission": {
   241  	//		"id": "DUMMY",
   242  	//		"definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
   243  	//		"descriptor_map": [
   244  	//			{
   245  	//				"id": "age_descriptor",
   246  	//				"format": "ldp_vc",
   247  	//				"path": "$",
   248  	//				"path_nested": {
   249  	//					"id": "age_descriptor",
   250  	//					"format": "ldp_vc",
   251  	//					"path": "$.verifiableCredential[0]"
   252  	//				}
   253  	//			}
   254  	//		]
   255  	//	},
   256  	//	"type": [
   257  	//		"VerifiablePresentation",
   258  	//		"PresentationSubmission"
   259  	//	],
   260  	//	"verifiableCredential": [
   261  	//		{
   262  	//			"@context": [
   263  	//				"https://www.w3.org/2018/credentials/v1"
   264  	//			],
   265  	//			"credentialSubject": {
   266  	//				"age": true,
   267  	//				"first_name": "Jesse",
   268  	//				"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   269  	//				"last_name": "Pinkman"
   270  	//			},
   271  	//			"id": "http://example.edu/credentials/777",
   272  	//			"issuanceDate": "0001-01-01T00:00:00Z",
   273  	//			"issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f",
   274  	//			"type": "VerifiableCredential"
   275  	//		}
   276  	//	]
   277  	// }
   278  }
   279  
   280  func ExamplePresentationDefinition_CreateVP_with_Ldp_Format() {
   281  	required := Required
   282  
   283  	pd := &PresentationDefinition{
   284  		ID:      "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
   285  		Purpose: "To sell you a drink we need to know that you are an adult.",
   286  		Format: &Format{
   287  			Ldp: &LdpType{
   288  				ProofType: []string{"Ed25519Signature2018"},
   289  			},
   290  		},
   291  		InputDescriptors: []*InputDescriptor{{
   292  			ID:      "age_descriptor",
   293  			Purpose: "Your age should be greater or equal to 18.",
   294  			Constraints: &Constraints{
   295  				LimitDisclosure: &required,
   296  				Fields: []*Field{
   297  					{
   298  						Path:      []string{"$.credentialSubject.age", "$.vc.credentialSubject.age", "$.age"},
   299  						Predicate: &required,
   300  						Filter: &Filter{
   301  							Type:    &intFilterType,
   302  							Minimum: 18,
   303  						},
   304  					},
   305  					{
   306  						Path: []string{"$.credentialSchema[0].id", "$.credentialSchema.id", "$.vc.credentialSchema.id"},
   307  						Filter: &Filter{
   308  							Type:  &strFilterType,
   309  							Const: "hub://did:foo:123/Collections/schema.us.gov/passport.json",
   310  						},
   311  					},
   312  				},
   313  			},
   314  		}},
   315  	}
   316  
   317  	loader, err := ldtestutil.DocumentLoader()
   318  	if err != nil {
   319  		panic(err)
   320  	}
   321  
   322  	vp, err := pd.CreateVP([]*verifiable.Credential{
   323  		{
   324  			ID:      "http://example.edu/credentials/777",
   325  			Context: []string{verifiable.ContextURI},
   326  			Types:   []string{verifiable.VCType},
   327  			Issuer: verifiable.Issuer{
   328  				ID: "did:example:76e12ec712ebc6f1c221ebfeb1f",
   329  			},
   330  			Issued: &util.TimeWrapper{
   331  				Time: time.Time{},
   332  			},
   333  			Schemas: []verifiable.TypedID{{
   334  				ID:   "hub://did:foo:123/Collections/schema.us.gov/passport.json",
   335  				Type: "JsonSchemaValidator2018",
   336  			}},
   337  
   338  			Subject: map[string]interface{}{
   339  				"id":         "did:example:ebfeb1f712ebc6f1c276e12ec21",
   340  				"first_name": "Jesse",
   341  				"last_name":  "Pinkman",
   342  				"age":        21,
   343  			},
   344  			Proofs: []verifiable.Proof{
   345  				{"type": "Ed25519Signature2018"},
   346  			},
   347  		},
   348  	}, loader, verifiable.WithJSONLDDocumentLoader(loader))
   349  	if err != nil {
   350  		panic(err)
   351  	}
   352  
   353  	vp.ID = dummy
   354  	vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy
   355  
   356  	vpBytes, err := json.MarshalIndent(vp, "", "\t")
   357  	if err != nil {
   358  		panic(err)
   359  	}
   360  
   361  	fmt.Println(string(vpBytes))
   362  	// Output:
   363  	// {
   364  	//	"@context": [
   365  	//		"https://www.w3.org/2018/credentials/v1",
   366  	//		"https://identity.foundation/presentation-exchange/submission/v1"
   367  	//	],
   368  	//	"id": "DUMMY",
   369  	//	"presentation_submission": {
   370  	//		"id": "DUMMY",
   371  	//		"definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
   372  	//		"descriptor_map": [
   373  	//			{
   374  	//				"id": "age_descriptor",
   375  	//				"format": "ldp",
   376  	//				"path": "$",
   377  	//				"path_nested": {
   378  	//					"id": "age_descriptor",
   379  	//					"format": "ldp_vc",
   380  	//					"path": "$.verifiableCredential[0]"
   381  	//				}
   382  	//			}
   383  	//		]
   384  	//	},
   385  	//	"type": [
   386  	//		"VerifiablePresentation",
   387  	//		"PresentationSubmission"
   388  	//	],
   389  	//	"verifiableCredential": [
   390  	//		{
   391  	//			"@context": [
   392  	//				"https://www.w3.org/2018/credentials/v1"
   393  	//			],
   394  	//			"credentialSubject": {
   395  	//				"age": true,
   396  	//				"first_name": "Jesse",
   397  	//				"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   398  	//				"last_name": "Pinkman"
   399  	//			},
   400  	//			"id": "http://example.edu/credentials/777",
   401  	//			"issuanceDate": "0001-01-01T00:00:00Z",
   402  	//			"issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f",
   403  	//			"type": "VerifiableCredential"
   404  	//		}
   405  	//	]
   406  	// }
   407  }
   408  
   409  func ExamplePresentationDefinition_CreateVP_withFormatInInputDescriptor() {
   410  	required := Required
   411  
   412  	pd := &PresentationDefinition{
   413  		ID:      "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
   414  		Purpose: "To sell you a drink we need to know that you are an adult.",
   415  		InputDescriptors: []*InputDescriptor{{
   416  			ID:      "age_descriptor",
   417  			Purpose: "Your age should be greater or equal to 18.",
   418  			Format: &Format{
   419  				LdpVP: &LdpType{
   420  					ProofType: []string{"Ed25519Signature2018"},
   421  				},
   422  			},
   423  			Constraints: &Constraints{
   424  				LimitDisclosure: &required,
   425  				Fields: []*Field{
   426  					{
   427  						Path:      []string{"$.credentialSubject.age", "$.vc.credentialSubject.age", "$.age"},
   428  						Predicate: &required,
   429  						Filter: &Filter{
   430  							Type:    &intFilterType,
   431  							Minimum: 18,
   432  						},
   433  					},
   434  					{
   435  						Path: []string{"$.credentialSchema[0].id", "$.credentialSchema.id", "$.vc.credentialSchema.id"},
   436  						Filter: &Filter{
   437  							Type:  &strFilterType,
   438  							Const: "hub://did:foo:123/Collections/schema.us.gov/passport.json",
   439  						},
   440  					},
   441  				},
   442  			},
   443  		}},
   444  	}
   445  
   446  	loader, err := ldtestutil.DocumentLoader()
   447  	if err != nil {
   448  		panic(err)
   449  	}
   450  
   451  	vp, err := pd.CreateVP([]*verifiable.Credential{
   452  		{
   453  			ID:      "http://example.edu/credentials/777",
   454  			Context: []string{verifiable.ContextURI},
   455  			Types:   []string{verifiable.VCType},
   456  			Issuer: verifiable.Issuer{
   457  				ID: "did:example:76e12ec712ebc6f1c221ebfeb1f",
   458  			},
   459  			Issued: &util.TimeWrapper{
   460  				Time: time.Time{},
   461  			},
   462  			Schemas: []verifiable.TypedID{{
   463  				ID:   "hub://did:foo:123/Collections/schema.us.gov/passport.json",
   464  				Type: "JsonSchemaValidator2018",
   465  			}},
   466  
   467  			Subject: map[string]interface{}{
   468  				"id":         "did:example:ebfeb1f712ebc6f1c276e12ec21",
   469  				"first_name": "Jesse",
   470  				"last_name":  "Pinkman",
   471  				"age":        21,
   472  			},
   473  			Proofs: []verifiable.Proof{
   474  				{"type": "Ed25519Signature2018"},
   475  			},
   476  		},
   477  	}, loader, verifiable.WithJSONLDDocumentLoader(loader))
   478  	if err != nil {
   479  		panic(err)
   480  	}
   481  
   482  	vp.ID = dummy
   483  	vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy
   484  
   485  	vpBytes, err := json.MarshalIndent(vp, "", "\t")
   486  	if err != nil {
   487  		panic(err)
   488  	}
   489  
   490  	fmt.Println(string(vpBytes))
   491  	// Output:
   492  	// {
   493  	//	"@context": [
   494  	//		"https://www.w3.org/2018/credentials/v1",
   495  	//		"https://identity.foundation/presentation-exchange/submission/v1"
   496  	//	],
   497  	//	"id": "DUMMY",
   498  	//	"presentation_submission": {
   499  	//		"id": "DUMMY",
   500  	//		"definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
   501  	//		"descriptor_map": [
   502  	//			{
   503  	//				"id": "age_descriptor",
   504  	//				"format": "ldp_vp",
   505  	//				"path": "$",
   506  	//				"path_nested": {
   507  	//					"id": "age_descriptor",
   508  	//					"format": "ldp_vc",
   509  	//					"path": "$.verifiableCredential[0]"
   510  	//				}
   511  	//			}
   512  	//		]
   513  	//	},
   514  	//	"type": [
   515  	//		"VerifiablePresentation",
   516  	//		"PresentationSubmission"
   517  	//	],
   518  	//	"verifiableCredential": [
   519  	//		{
   520  	//			"@context": [
   521  	//				"https://www.w3.org/2018/credentials/v1"
   522  	//			],
   523  	//			"credentialSubject": {
   524  	//				"age": true,
   525  	//				"first_name": "Jesse",
   526  	//				"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   527  	//				"last_name": "Pinkman"
   528  	//			},
   529  	//			"id": "http://example.edu/credentials/777",
   530  	//			"issuanceDate": "0001-01-01T00:00:00Z",
   531  	//			"issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f",
   532  	//			"type": "VerifiableCredential"
   533  	//		}
   534  	//	]
   535  	// }
   536  }
   537  
   538  func TestExamplePresentationDefinition_CreateVPWithFormat_NoMatch(t *testing.T) {
   539  	required := Required
   540  
   541  	pd := &PresentationDefinition{
   542  		ID:      "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
   543  		Purpose: "To sell you a drink we need to know that you are an adult.",
   544  		Format: &Format{
   545  			LdpVP: &LdpType{
   546  				ProofType: []string{"Ed25519Signature2018"},
   547  			},
   548  		},
   549  		InputDescriptors: []*InputDescriptor{{
   550  			ID:      "age_descriptor",
   551  			Purpose: "Your age should be greater or equal to 18.",
   552  			Constraints: &Constraints{
   553  				LimitDisclosure: &required,
   554  				Fields: []*Field{
   555  					{
   556  						Path:      []string{"$.credentialSubject.age", "$.vc.credentialSubject.age", "$.age"},
   557  						Predicate: &required,
   558  						Filter: &Filter{
   559  							Type:    &intFilterType,
   560  							Minimum: 18,
   561  						},
   562  					},
   563  					{
   564  						Path: []string{"$.credentialSchema[0].id", "$.credentialSchema.id", "$.vc.credentialSchema.id"},
   565  						Filter: &Filter{
   566  							Type:  &strFilterType,
   567  							Const: "hub://did:foo:123/Collections/schema.us.gov/passport.json",
   568  						},
   569  					},
   570  				},
   571  			},
   572  		}},
   573  	}
   574  
   575  	loader, err := ldtestutil.DocumentLoader()
   576  	if err != nil {
   577  		panic(err)
   578  	}
   579  
   580  	_, err = pd.CreateVP([]*verifiable.Credential{
   581  		{
   582  			ID:      "http://example.edu/credentials/777",
   583  			Context: []string{verifiable.ContextURI},
   584  			Types:   []string{verifiable.VCType},
   585  			Issuer: verifiable.Issuer{
   586  				ID: "did:example:76e12ec712ebc6f1c221ebfeb1f",
   587  			},
   588  			Issued: &util.TimeWrapper{
   589  				Time: time.Time{},
   590  			},
   591  			Schemas: []verifiable.TypedID{{
   592  				ID:   "hub://did:foo:123/Collections/schema.us.gov/passport.json",
   593  				Type: "JsonSchemaValidator2018",
   594  			}},
   595  
   596  			Subject: map[string]interface{}{
   597  				"id":         "did:example:ebfeb1f712ebc6f1c276e12ec21",
   598  				"first_name": "Jesse",
   599  				"last_name":  "Pinkman",
   600  				"age":        21,
   601  			},
   602  			Proofs: []verifiable.Proof{
   603  				{"type": "JsonWebSignature2020"},
   604  			},
   605  		},
   606  	}, loader, verifiable.WithJSONLDDocumentLoader(loader))
   607  
   608  	require.EqualError(t, err, "credentials do not satisfy requirements")
   609  }
   610  
   611  func ExamplePresentationDefinition_CreateVP_withFrame() {
   612  	vcJSON := `
   613  	{
   614  	 "@context": [
   615  	   "https://www.w3.org/2018/credentials/v1",
   616  	   "https://w3id.org/citizenship/v1",
   617  	   "https://w3id.org/security/bbs/v1"
   618  	 ],
   619  	 "id": "https://issuer.oidp.uscis.gov/credentials/83627465",
   620  	 "type": [
   621  	   "VerifiableCredential",
   622  	   "PermanentResidentCard"
   623  	 ],
   624  	 "issuer": "did:example:489398593",
   625  	 "identifier": "83627465",
   626  	 "name": "Permanent Resident Card",
   627  	 "description": "Government of Example Permanent Resident Card.",
   628  	 "issuanceDate": "2019-12-03T12:19:52Z",
   629  	 "expirationDate": "2029-12-03T12:19:52Z",
   630  	 "credentialSubject": {
   631  	   "id": "did:example:b34ca6cd37bbf23",
   632  	   "type": [
   633  	     "PermanentResident",
   634  	     "Person"
   635  	   ],
   636  	   "givenName": "JOHN",
   637  	   "familyName": "SMITH",
   638  	   "gender": "Male",
   639  	   "image": "data:image/png;base64,iVBORw0KGgokJggg==",
   640  	   "residentSince": "2015-01-01",
   641  	   "lprCategory": "C09",
   642  	   "lprNumber": "999-999-999",
   643  	   "commuterClassification": "C1",
   644  	   "birthCountry": "Bahamas",
   645  	   "birthDate": "1958-07-17"
   646  	 }
   647  	}
   648  	`
   649  
   650  	frameJSONWithMissingIssuer := `
   651  {
   652    "@context": [
   653      "https://www.w3.org/2018/credentials/v1",
   654      "https://w3id.org/citizenship/v1",
   655      "https://w3id.org/security/bbs/v1"
   656    ],
   657    "type": ["VerifiableCredential", "PermanentResidentCard"],
   658    "@explicit": true,
   659    "identifier": {},
   660    "issuer": {},
   661    "issuanceDate": {},
   662    "credentialSubject": {
   663      "@explicit": true,
   664      "type": ["PermanentResident", "Person"],
   665      "givenName": {},
   666      "familyName": {},
   667      "gender": {},
   668  	"birthCountry": {}
   669    }
   670  }
   671  `
   672  
   673  	frameDoc, err := jsonutil.ToMap(frameJSONWithMissingIssuer)
   674  	if err != nil {
   675  		panic(err)
   676  	}
   677  
   678  	required := Required
   679  
   680  	pd := &PresentationDefinition{
   681  		ID:    "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
   682  		Frame: frameDoc,
   683  		InputDescriptors: []*InputDescriptor{{
   684  			ID: "country_descriptor",
   685  			Constraints: &Constraints{
   686  				Fields: []*Field{
   687  					{
   688  						Path:      []string{"$.credentialSubject.birthCountry", "$.vc.credentialSubject.birthCountry"},
   689  						Predicate: &required,
   690  						Filter: &Filter{
   691  							Type:  &strFilterType,
   692  							Const: "Bahamas",
   693  						},
   694  					},
   695  				},
   696  			},
   697  		}},
   698  	}
   699  
   700  	loader, err := ldtestutil.DocumentLoader()
   701  	if err != nil {
   702  		panic(err)
   703  	}
   704  
   705  	vc, err := verifiable.ParseCredential([]byte(vcJSON), verifiable.WithJSONLDDocumentLoader(loader))
   706  	if err != nil {
   707  		panic(err)
   708  	}
   709  
   710  	pubKey, privKey, err := bbs12381g2pub.GenerateKeyPair(sha256.New, nil)
   711  	if err != nil {
   712  		panic(err)
   713  	}
   714  
   715  	pubKeyBytes, err := pubKey.Marshal()
   716  	if err != nil {
   717  		panic(err)
   718  	}
   719  
   720  	signVCWithBBS(privKey, vc, loader)
   721  
   722  	vp, err := pd.CreateVP([]*verifiable.Credential{vc}, loader, verifiable.WithJSONLDDocumentLoader(loader), verifiable.WithPublicKeyFetcher(
   723  		verifiable.SingleKey(pubKeyBytes, "Bls12381G2Key2020")))
   724  	if err != nil {
   725  		panic(err)
   726  	}
   727  
   728  	vp.ID = dummy
   729  	vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy
   730  	vp.Credentials()[0].(*verifiable.Credential).Proofs[0]["created"] = dummy
   731  	vp.Credentials()[0].(*verifiable.Credential).Proofs[0]["proofValue"] = dummy
   732  
   733  	vpBytes, err := json.MarshalIndent(vp, "", "\t")
   734  	if err != nil {
   735  		panic(err)
   736  	}
   737  
   738  	fmt.Println(string(vpBytes))
   739  	// Output:
   740  	// {
   741  	//	"@context": [
   742  	//		"https://www.w3.org/2018/credentials/v1",
   743  	//		"https://identity.foundation/presentation-exchange/submission/v1"
   744  	//	],
   745  	//	"id": "DUMMY",
   746  	//	"presentation_submission": {
   747  	//		"id": "DUMMY",
   748  	//		"definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
   749  	//		"descriptor_map": [
   750  	//			{
   751  	//				"id": "country_descriptor",
   752  	//				"format": "ldp_vp",
   753  	//				"path": "$",
   754  	//				"path_nested": {
   755  	//					"id": "country_descriptor",
   756  	//					"format": "ldp_vc",
   757  	//					"path": "$.verifiableCredential[0]"
   758  	//				}
   759  	//			}
   760  	//		]
   761  	//	},
   762  	//	"type": [
   763  	//		"VerifiablePresentation",
   764  	//		"PresentationSubmission"
   765  	//	],
   766  	//	"verifiableCredential": [
   767  	//		{
   768  	//			"@context": [
   769  	//				"https://www.w3.org/2018/credentials/v1",
   770  	//				"https://w3id.org/citizenship/v1",
   771  	//				"https://w3id.org/security/bbs/v1"
   772  	//			],
   773  	//			"credentialSubject": {
   774  	//				"birthCountry": true,
   775  	//				"familyName": "SMITH",
   776  	//				"gender": "Male",
   777  	//				"givenName": "JOHN",
   778  	//				"id": "did:example:b34ca6cd37bbf23",
   779  	//				"type": [
   780  	//					"Person",
   781  	//					"PermanentResident"
   782  	//				]
   783  	//			},
   784  	//			"id": "https://issuer.oidp.uscis.gov/credentials/83627465",
   785  	//			"identifier": "83627465",
   786  	//			"issuanceDate": "2019-12-03T12:19:52Z",
   787  	//			"issuer": "did:example:489398593",
   788  	//			"proof": {
   789  	//				"created": "DUMMY",
   790  	//				"nonce": "",
   791  	//				"proofPurpose": "assertionMethod",
   792  	//				"proofValue": "DUMMY",
   793  	//				"type": "BbsBlsSignatureProof2020",
   794  	//				"verificationMethod": "did:example:123456#key1"
   795  	//			},
   796  	//			"type": [
   797  	//				"PermanentResidentCard",
   798  	//				"VerifiableCredential"
   799  	//			]
   800  	//		}
   801  	//	]
   802  	// }
   803  }
   804  
   805  func signVCWithBBS(privKey *bbs12381g2pub.PrivateKey, vc *verifiable.Credential, documentLoader ld.DocumentLoader) {
   806  	bbsSigner, err := newBBSSigner(privKey)
   807  	if err != nil {
   808  		panic(err)
   809  	}
   810  
   811  	sigSuite := bbsblssignature2020.New(
   812  		suite.WithSigner(bbsSigner),
   813  		suite.WithVerifier(bbsblssignature2020.NewG2PublicKeyVerifier()))
   814  
   815  	ldpContext := &verifiable.LinkedDataProofContext{
   816  		SignatureType:           "BbsBlsSignature2020",
   817  		SignatureRepresentation: verifiable.SignatureProofValue,
   818  		Suite:                   sigSuite,
   819  		VerificationMethod:      "did:example:123456#key1",
   820  	}
   821  
   822  	err = vc.AddLinkedDataProof(ldpContext, jsonld.WithDocumentLoader(documentLoader))
   823  	if err != nil {
   824  		panic(err)
   825  	}
   826  }