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

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package verifiable_test
     8  
     9  import (
    10  	"crypto/ed25519"
    11  	"encoding/json"
    12  	"errors"
    13  	"fmt"
    14  
    15  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/jsonld"
    16  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite"
    17  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/ed25519signature2018"
    18  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/verifier"
    19  	"github.com/hyperledger/aries-framework-go/pkg/doc/util"
    20  	"github.com/hyperledger/aries-framework-go/pkg/doc/util/signature"
    21  	"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
    22  	"github.com/hyperledger/aries-framework-go/pkg/kms"
    23  )
    24  
    25  // The keys are generated by ed25519.GenerateKey(rand.Reader)
    26  //
    27  //nolint:gochecknoglobals
    28  var (
    29  	holderPrivKey = ed25519.PrivateKey{10, 192, 72, 230, 66, 255, 51, 97, 14, 57, 149, 164, 232, 251, 31, 164, 168, 82, 239, 155, 253, 223, 111, 148, 165, 76, 60, 17, 3, 63, 76, 192, 61, 133, 23, 17, 77, 132, 169, 196, 47, 203, 19, 71, 145, 144, 92, 145, 131, 101, 36, 251, 89, 216, 117, 140, 132, 226, 78, 187, 59, 58, 200, 255}
    30  	holderPubKey  = ed25519.PublicKey{61, 133, 23, 17, 77, 132, 169, 196, 47, 203, 19, 71, 145, 144, 92, 145, 131, 101, 36, 251, 89, 216, 117, 140, 132, 226, 78, 187, 59, 58, 200, 255}
    31  )
    32  
    33  func ExamplePresentation_JWTClaims() {
    34  	// The Holder kept the presentation serialized to JSON in her personal verifiable credential wallet.
    35  	vpStrFromWallet := `
    36  {
    37    "@context": [
    38      "https://www.w3.org/2018/credentials/v1",
    39      "https://www.w3.org/2018/credentials/examples/v1"
    40    ],
    41    "id": "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c5",
    42    "type": [
    43      "VerifiablePresentation",
    44      "UniversityDegreeCredential"
    45    ],
    46    "verifiableCredential": [
    47      {
    48        "@context": [
    49          "https://www.w3.org/2018/credentials/v1",
    50          "https://www.w3.org/2018/credentials/examples/v1"
    51        ],
    52        "credentialSchema": [],
    53        "credentialSubject": {
    54          "degree": {
    55            "type": "BachelorDegree",
    56            "university": "MIT"
    57          },
    58          "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    59          "name": "Jayden Doe",
    60          "spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1"
    61        },
    62        "expirationDate": "2020-01-01T19:23:24Z",
    63        "id": "http://example.edu/credentials/1872",
    64        "issuanceDate": "2010-01-01T19:23:24Z",
    65        "issuer": {
    66          "id": "did:example:76e12ec712ebc6f1c221ebfeb1f",
    67          "name": "Example University"
    68        },
    69        "referenceNumber": 83294847,
    70        "type": [
    71          "VerifiableCredential",
    72          "UniversityDegreeCredential"
    73        ]
    74      }
    75    ],
    76    "holder": "did:example:ebfeb1f712ebc6f1c276e12ec21"
    77  }
    78  `
    79  
    80  	// The Holder wants to send the presentation to the Verifier in JWS.
    81  	vp, err := verifiable.ParsePresentation([]byte(vpStrFromWallet), verifiable.WithPresDisabledProofCheck(),
    82  		verifiable.WithPresJSONLDDocumentLoader(getJSONLDDocumentLoader()))
    83  	if err != nil {
    84  		panic(fmt.Errorf("failed to decode VP JSON: %w", err))
    85  	}
    86  
    87  	aud := []string{"did:example:4a57546973436f6f6c4a4a57573"}
    88  
    89  	jwtClaims, err := vp.JWTClaims(aud, true)
    90  	if err != nil {
    91  		panic(fmt.Errorf("failed to create JWT claims of VP: %w", err))
    92  	}
    93  
    94  	signer := signature.GetEd25519Signer(holderPrivKey, holderPubKey)
    95  
    96  	jws, err := jwtClaims.MarshalJWS(verifiable.EdDSA, signer, "")
    97  	if err != nil {
    98  		panic(fmt.Errorf("failed to sign VP inside JWT: %w", err))
    99  	}
   100  
   101  	fmt.Println(jws)
   102  
   103  	// Output: eyJhbGciOiJFZERTQSIsImtpZCI6IiJ9.eyJhdWQiOiJkaWQ6ZXhhbXBsZTo0YTU3NTQ2OTczNDM2ZjZmNmM0YTRhNTc1NzMiLCJpc3MiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJqdGkiOiJ1cm46dXVpZDozOTc4MzQ0Zi04NTk2LTRjM2EtYTk3OC04ZmNhYmEzOTAzYzUiLCJ2cCI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL2V4YW1wbGVzL3YxIl0sInR5cGUiOlsiVmVyaWZpYWJsZVByZXNlbnRhdGlvbiIsIlVuaXZlcnNpdHlEZWdyZWVDcmVkZW50aWFsIl0sInZlcmlmaWFibGVDcmVkZW50aWFsIjpbeyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL2V4YW1wbGVzL3YxIl0sImNyZWRlbnRpYWxTY2hlbWEiOltdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJkZWdyZWUiOnsidHlwZSI6IkJhY2hlbG9yRGVncmVlIiwidW5pdmVyc2l0eSI6Ik1JVCJ9LCJpZCI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsIm5hbWUiOiJKYXlkZW4gRG9lIiwic3BvdXNlIjoiZGlkOmV4YW1wbGU6YzI3NmUxMmVjMjFlYmZlYjFmNzEyZWJjNmYxIn0sImV4cGlyYXRpb25EYXRlIjoiMjAyMC0wMS0wMVQxOToyMzoyNFoiLCJpZCI6Imh0dHA6Ly9leGFtcGxlLmVkdS9jcmVkZW50aWFscy8xODcyIiwiaXNzdWFuY2VEYXRlIjoiMjAxMC0wMS0wMVQxOToyMzoyNFoiLCJpc3N1ZXIiOnsiaWQiOiJkaWQ6ZXhhbXBsZTo3NmUxMmVjNzEyZWJjNmYxYzIyMWViZmViMWYiLCJuYW1lIjoiRXhhbXBsZSBVbml2ZXJzaXR5In0sInJlZmVyZW5jZU51bWJlciI6ODMyOTQ4NDcsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJVbml2ZXJzaXR5RGVncmVlQ3JlZGVudGlhbCJdfV19fQ.TFDBa7VYD4dgduu7LlMWZzk20oU-cc3X7S3AKAJJsX6_Jok3lE6v-24tdCNJsc4eMVlBs6a43J3aq5MDIyiIDg
   104  }
   105  
   106  func ExamplePresentation() {
   107  	// A Holder loads the credential from verifiable credential wallet in order to send to Verifier.
   108  	// She embedded the credential into presentation and sends it to the Verifier in JWS form.
   109  	vcStrFromWallet := `
   110  {
   111    "@context": [
   112      "https://www.w3.org/2018/credentials/v1",
   113      "https://www.w3.org/2018/credentials/examples/v1"
   114    ],
   115    "credentialSubject": {
   116      "degree": {
   117        "type": "BachelorDegree",
   118        "university": "MIT"
   119      },
   120      "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   121      "name": "Jayden Doe",
   122      "spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1"
   123    },
   124    "expirationDate": "2020-01-01T19:23:24Z",
   125    "id": "http://example.edu/credentials/1872",
   126    "issuanceDate": "2010-01-01T19:23:24Z",
   127    "issuer": {
   128      "id": "did:example:76e12ec712ebc6f1c221ebfeb1f",
   129      "name": "Example University"
   130    },
   131    "referenceNumber": 83294847,
   132    "type": [
   133      "VerifiableCredential",
   134      "UniversityDegreeCredential"
   135    ]
   136  }
   137  `
   138  
   139  	vc, err := verifiable.ParseCredential([]byte(vcStrFromWallet),
   140  		verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()))
   141  	if err != nil {
   142  		panic(fmt.Errorf("failed to decode VC JSON: %w", err))
   143  	}
   144  
   145  	vp, err := verifiable.NewPresentation(verifiable.WithCredentials(vc))
   146  	if err != nil {
   147  		panic(fmt.Errorf("failed to build VP from VC: %w", err))
   148  	}
   149  
   150  	vp.ID = "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c5"
   151  	vp.Holder = "did:example:ebfeb1f712ebc6f1c276e12ec21"
   152  
   153  	aud := []string{"did:example:4a57546973436f6f6c4a4a57573"}
   154  
   155  	jwtClaims, err := vp.JWTClaims(aud, true)
   156  	if err != nil {
   157  		panic(fmt.Errorf("failed to create JWT claims of VP: %w", err))
   158  	}
   159  
   160  	signer := signature.GetEd25519Signer(holderPrivKey, holderPubKey)
   161  
   162  	jws, err := jwtClaims.MarshalJWS(verifiable.EdDSA, signer, "")
   163  	if err != nil {
   164  		panic(fmt.Errorf("failed to sign VP inside JWT: %w", err))
   165  	}
   166  
   167  	fmt.Println(jws)
   168  
   169  	// Output: eyJhbGciOiJFZERTQSIsImtpZCI6IiJ9.eyJhdWQiOiJkaWQ6ZXhhbXBsZTo0YTU3NTQ2OTczNDM2ZjZmNmM0YTRhNTc1NzMiLCJpc3MiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJqdGkiOiJ1cm46dXVpZDozOTc4MzQ0Zi04NTk2LTRjM2EtYTk3OC04ZmNhYmEzOTAzYzUiLCJ2cCI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ0eXBlIjoiVmVyaWZpYWJsZVByZXNlbnRhdGlvbiIsInZlcmlmaWFibGVDcmVkZW50aWFsIjpbeyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL2V4YW1wbGVzL3YxIl0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImRlZ3JlZSI6eyJ0eXBlIjoiQmFjaGVsb3JEZWdyZWUiLCJ1bml2ZXJzaXR5IjoiTUlUIn0sImlkIjoiZGlkOmV4YW1wbGU6ZWJmZWIxZjcxMmViYzZmMWMyNzZlMTJlYzIxIiwibmFtZSI6IkpheWRlbiBEb2UiLCJzcG91c2UiOiJkaWQ6ZXhhbXBsZTpjMjc2ZTEyZWMyMWViZmViMWY3MTJlYmM2ZjEifSwiZXhwaXJhdGlvbkRhdGUiOiIyMDIwLTAxLTAxVDE5OjIzOjI0WiIsImlkIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJpc3N1YW5jZURhdGUiOiIyMDEwLTAxLTAxVDE5OjIzOjI0WiIsImlzc3VlciI6eyJpZCI6ImRpZDpleGFtcGxlOjc2ZTEyZWM3MTJlYmM2ZjFjMjIxZWJmZWIxZiIsIm5hbWUiOiJFeGFtcGxlIFVuaXZlcnNpdHkifSwicmVmZXJlbmNlTnVtYmVyIjo4MzI5NDg0NywidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIlVuaXZlcnNpdHlEZWdyZWVDcmVkZW50aWFsIl19XX19.DnhBKUNbFjNE2ROS8z3CYKr1D5YiL4zEcEaaVF62ASHaueU-pImf36ayReWTWMzhde1PJ_z3K8uzPt3QZUudAQ
   170  }
   171  
   172  func ExamplePresentation_two() {
   173  	// Holder wants to send 2 credentials to Verifier.
   174  	// The first VC is created on fly (or just decoded using ParseCredential).
   175  	vc := &verifiable.Credential{
   176  		Context: []string{
   177  			"https://www.w3.org/2018/credentials/v1",
   178  			"https://www.w3.org/2018/credentials/examples/v1",
   179  		},
   180  		ID: "http://example.edu/credentials/1872",
   181  		Types: []string{
   182  			"VerifiableCredential",
   183  			"UniversityDegreeCredential",
   184  		},
   185  		Subject: UniversityDegreeSubject{
   186  			ID:     "did:example:ebfeb1f712ebc6f1c276e12ec21",
   187  			Name:   "Jayden Doe",
   188  			Spouse: "did:example:c276e12ec21ebfeb1f712ebc6f1",
   189  			Degree: UniversityDegree{
   190  				Type:       "BachelorDegree",
   191  				University: "MIT",
   192  			},
   193  		},
   194  		Issuer: verifiable.Issuer{
   195  			ID:           "did:example:76e12ec712ebc6f1c221ebfeb1f",
   196  			CustomFields: verifiable.CustomFields{"name": "Example University"},
   197  		},
   198  		Issued:  util.NewTime(issued),
   199  		Expired: util.NewTime(expired),
   200  		Schemas: []verifiable.TypedID{},
   201  		CustomFields: map[string]interface{}{
   202  			"referenceNumber": 83294847,
   203  		},
   204  	}
   205  
   206  	vcStr := `
   207  {
   208    "@context": [
   209      "https://www.w3.org/2018/credentials/v1",
   210      "https://www.w3.org/2018/credentials/examples/v1"
   211    ],
   212    "id": "http://example.edu/credentials/58473",
   213    "type": ["VerifiableCredential", "AlumniCredential"],
   214    "issuer": "https://example.edu/issuers/14",
   215    "issuanceDate": "2010-01-01T19:23:24Z",
   216    "credentialSubject": {
   217      "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   218      "alumniOf": "Example University"
   219    },
   220    "proof": {
   221      "type": "RsaSignature2018"
   222    }
   223  }
   224  `
   225  
   226  	// The second VC is provided in JWS form (e.g. kept in the wallet in that form).
   227  	vcJWS := "eyJhbGciOiJFZERTQSIsImtpZCI6IiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1Nzc5MDY2MDQsImlhdCI6MTI2MjM3MzgwNCwiaXNzIjoiZGlkOmV4YW1wbGU6NzZlMTJlYzcxMmViYzZmMWMyMjFlYmZlYjFmIiwianRpIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJuYmYiOjEyNjIzNzM4MDQsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvZXhhbXBsZXMvdjEiXSwiY3JlZGVudGlhbFNjaGVtYSI6W10sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImRlZ3JlZSI6eyJ0eXBlIjoiQmFjaGVsb3JEZWdyZWUiLCJ1bml2ZXJzaXR5IjoiTUlUIn0sImlkIjoiZGlkOmV4YW1wbGU6ZWJmZWIxZjcxMmViYzZmMWMyNzZlMTJlYzIxIiwibmFtZSI6IkpheWRlbiBEb2UiLCJzcG91c2UiOiJkaWQ6ZXhhbXBsZTpjMjc2ZTEyZWMyMWViZmViMWY3MTJlYmM2ZjEifSwiaXNzdWVyIjp7Im5hbWUiOiJFeGFtcGxlIFVuaXZlcnNpdHkifSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIlVuaXZlcnNpdHlEZWdyZWVDcmVkZW50aWFsIl19fQ.AHn2A2q5DL1heX3_izq_2yrsBDhoZ6BGGKhoRvhfMnMUuuOnBOdekdTg-dfUMJgipXRql_6WzBUIj4wTFehXCw"
   228  
   229  	vc2, err := verifiable.ParseCredential([]byte(vcStr),
   230  		verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()),
   231  		verifiable.WithDisabledProofCheck())
   232  	if err != nil {
   233  		panic(fmt.Errorf("failed to decode VC JSON: %w", err))
   234  	}
   235  
   236  	vp, err := verifiable.NewPresentation(verifiable.WithCredentials(vc),
   237  		verifiable.WithJWTCredentials(vcJWS), verifiable.WithCredentials(vc2))
   238  	if err != nil {
   239  		panic(fmt.Errorf("failed to set credentials of VP: %w", err))
   240  	}
   241  
   242  	vp.ID = "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c"
   243  	vp.Holder = "did:example:ebfeb1f712ebc6f1c276e12ec21"
   244  
   245  	vpBytes, err := json.MarshalIndent(vp, "", "\t")
   246  	if err != nil {
   247  		panic(err)
   248  	}
   249  
   250  	fmt.Print(string(vpBytes))
   251  
   252  	// Output:
   253  	// {
   254  	// 	"@context": [
   255  	// 		"https://www.w3.org/2018/credentials/v1"
   256  	// 	],
   257  	// 	"holder": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   258  	// 	"id": "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c",
   259  	// 	"type": "VerifiablePresentation",
   260  	// 	"verifiableCredential": [
   261  	// 		{
   262  	// 			"@context": [
   263  	// 				"https://www.w3.org/2018/credentials/v1",
   264  	// 				"https://www.w3.org/2018/credentials/examples/v1"
   265  	// 			],
   266  	// 			"credentialSubject": {
   267  	// 				"degree": {
   268  	// 					"type": "BachelorDegree",
   269  	// 					"university": "MIT"
   270  	// 				},
   271  	// 				"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   272  	// 				"name": "Jayden Doe",
   273  	// 				"spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1"
   274  	// 			},
   275  	// 			"expirationDate": "2020-01-01T19:23:24Z",
   276  	// 			"id": "http://example.edu/credentials/1872",
   277  	// 			"issuanceDate": "2010-01-01T19:23:24Z",
   278  	// 			"issuer": {
   279  	// 				"id": "did:example:76e12ec712ebc6f1c221ebfeb1f",
   280  	// 				"name": "Example University"
   281  	// 			},
   282  	// 			"referenceNumber": 83294847,
   283  	// 			"type": [
   284  	// 				"VerifiableCredential",
   285  	// 				"UniversityDegreeCredential"
   286  	// 			]
   287  	// 		},
   288  	// 		"eyJhbGciOiJFZERTQSIsImtpZCI6IiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1Nzc5MDY2MDQsImlhdCI6MTI2MjM3MzgwNCwiaXNzIjoiZGlkOmV4YW1wbGU6NzZlMTJlYzcxMmViYzZmMWMyMjFlYmZlYjFmIiwianRpIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJuYmYiOjEyNjIzNzM4MDQsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvZXhhbXBsZXMvdjEiXSwiY3JlZGVudGlhbFNjaGVtYSI6W10sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImRlZ3JlZSI6eyJ0eXBlIjoiQmFjaGVsb3JEZWdyZWUiLCJ1bml2ZXJzaXR5IjoiTUlUIn0sImlkIjoiZGlkOmV4YW1wbGU6ZWJmZWIxZjcxMmViYzZmMWMyNzZlMTJlYzIxIiwibmFtZSI6IkpheWRlbiBEb2UiLCJzcG91c2UiOiJkaWQ6ZXhhbXBsZTpjMjc2ZTEyZWMyMWViZmViMWY3MTJlYmM2ZjEifSwiaXNzdWVyIjp7Im5hbWUiOiJFeGFtcGxlIFVuaXZlcnNpdHkifSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIlVuaXZlcnNpdHlEZWdyZWVDcmVkZW50aWFsIl19fQ.AHn2A2q5DL1heX3_izq_2yrsBDhoZ6BGGKhoRvhfMnMUuuOnBOdekdTg-dfUMJgipXRql_6WzBUIj4wTFehXCw",
   289  	// 		{
   290  	// 			"@context": [
   291  	// 				"https://www.w3.org/2018/credentials/v1",
   292  	// 				"https://www.w3.org/2018/credentials/examples/v1"
   293  	// 			],
   294  	// 			"credentialSubject": {
   295  	// 				"alumniOf": "Example University",
   296  	// 				"id": "did:example:ebfeb1f712ebc6f1c276e12ec21"
   297  	// 			},
   298  	// 			"id": "http://example.edu/credentials/58473",
   299  	// 			"issuanceDate": "2010-01-01T19:23:24Z",
   300  	// 			"issuer": "https://example.edu/issuers/14",
   301  	// 			"proof": {
   302  	// 				"type": "RsaSignature2018"
   303  	// 			},
   304  	// 			"type": [
   305  	// 				"VerifiableCredential",
   306  	// 				"AlumniCredential"
   307  	// 			]
   308  	// 		}
   309  	// 	]
   310  	// }
   311  }
   312  
   313  func ExamplePresentation_MarshalJSON() {
   314  	vc := &verifiable.Credential{
   315  		Context: []string{
   316  			"https://www.w3.org/2018/credentials/v1",
   317  			"https://www.w3.org/2018/credentials/examples/v1",
   318  		},
   319  		ID: "http://example.edu/credentials/1872",
   320  		Types: []string{
   321  			"VerifiableCredential",
   322  			"UniversityDegreeCredential",
   323  		},
   324  		Subject: UniversityDegreeSubject{
   325  			ID:     "did:example:ebfeb1f712ebc6f1c276e12ec21",
   326  			Name:   "Jayden Doe",
   327  			Spouse: "did:example:c276e12ec21ebfeb1f712ebc6f1",
   328  			Degree: UniversityDegree{
   329  				Type:       "BachelorDegree",
   330  				University: "MIT",
   331  			},
   332  		},
   333  		Issuer: verifiable.Issuer{
   334  			ID:           "did:example:76e12ec712ebc6f1c221ebfeb1f",
   335  			CustomFields: verifiable.CustomFields{"name": "Example University"},
   336  		},
   337  		Issued:  util.NewTime(issued),
   338  		Expired: util.NewTime(expired),
   339  		Schemas: []verifiable.TypedID{},
   340  		CustomFields: map[string]interface{}{
   341  			"referenceNumber": 83294847,
   342  		},
   343  	}
   344  
   345  	vp, err := verifiable.NewPresentation(verifiable.WithCredentials(vc))
   346  	if err != nil {
   347  		panic(fmt.Errorf("failed to set credentials of VP: %w", err))
   348  	}
   349  
   350  	vp.ID = "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c"
   351  	vp.Holder = "did:example:ebfeb1f712ebc6f1c276e12ec21"
   352  
   353  	// json.MarshalIndent() calls Presentation.MarshalJSON()
   354  	vpJSON, err := json.MarshalIndent(vp, "", "\t")
   355  	if err != nil {
   356  		panic(fmt.Errorf("failed to marshal VP to JSON: %w", err))
   357  	}
   358  
   359  	fmt.Println(string(vpJSON))
   360  
   361  	// Output:
   362  	// {
   363  	// 	"@context": [
   364  	// 		"https://www.w3.org/2018/credentials/v1"
   365  	// 	],
   366  	// 	"holder": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   367  	// 	"id": "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c",
   368  	// 	"type": "VerifiablePresentation",
   369  	// 	"verifiableCredential": [
   370  	// 		{
   371  	// 			"@context": [
   372  	// 				"https://www.w3.org/2018/credentials/v1",
   373  	// 				"https://www.w3.org/2018/credentials/examples/v1"
   374  	// 			],
   375  	// 			"credentialSubject": {
   376  	// 				"degree": {
   377  	// 					"type": "BachelorDegree",
   378  	// 					"university": "MIT"
   379  	// 				},
   380  	// 				"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   381  	// 				"name": "Jayden Doe",
   382  	// 				"spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1"
   383  	// 			},
   384  	// 			"expirationDate": "2020-01-01T19:23:24Z",
   385  	// 			"id": "http://example.edu/credentials/1872",
   386  	// 			"issuanceDate": "2010-01-01T19:23:24Z",
   387  	// 			"issuer": {
   388  	// 				"id": "did:example:76e12ec712ebc6f1c221ebfeb1f",
   389  	// 				"name": "Example University"
   390  	// 			},
   391  	// 			"referenceNumber": 83294847,
   392  	// 			"type": [
   393  	// 				"VerifiableCredential",
   394  	// 				"UniversityDegreeCredential"
   395  	// 			]
   396  	// 		}
   397  	// 	]
   398  	// }
   399  }
   400  
   401  //nolint:gocyclo
   402  func ExamplePresentation_MarshalledCredentials() {
   403  	vc := verifiable.Credential{
   404  		Context: []string{
   405  			"https://www.w3.org/2018/credentials/v1",
   406  			"https://www.w3.org/2018/credentials/examples/v1",
   407  		},
   408  		ID: "http://example.edu/credentials/1872",
   409  		Types: []string{
   410  			"VerifiableCredential",
   411  			"UniversityDegreeCredential",
   412  		},
   413  		Subject: UniversityDegreeSubject{
   414  			ID:     "did:example:ebfeb1f712ebc6f1c276e12ec21",
   415  			Name:   "Jayden Doe",
   416  			Spouse: "did:example:c276e12ec21ebfeb1f712ebc6f1",
   417  			Degree: UniversityDegree{
   418  				Type:       "BachelorDegree",
   419  				University: "MIT",
   420  			},
   421  		},
   422  		Issuer: verifiable.Issuer{
   423  			ID:           "did:example:76e12ec712ebc6f1c221ebfeb1f",
   424  			CustomFields: verifiable.CustomFields{"name": "Example University"},
   425  		},
   426  		Issued:  util.NewTime(issued),
   427  		Expired: util.NewTime(expired),
   428  		Schemas: []verifiable.TypedID{},
   429  	}
   430  
   431  	// Put JWS form of VC into VP.
   432  	vcJWTClaims, err := vc.JWTClaims(true)
   433  	if err != nil {
   434  		panic(fmt.Errorf("failed to set credentials of VP: %w", err))
   435  	}
   436  
   437  	issuerSigner := signature.GetEd25519Signer(issuerPrivKey, issuerPubKey)
   438  
   439  	vcJWS, err := vcJWTClaims.MarshalJWS(verifiable.EdDSA, issuerSigner, "did:123#i-kid")
   440  	if err != nil {
   441  		panic(fmt.Errorf("failed to sign VC JWT: %w", err))
   442  	}
   443  
   444  	vp, err := verifiable.NewPresentation(verifiable.WithJWTCredentials(vcJWS))
   445  	if err != nil {
   446  		panic(fmt.Errorf("failed to set credentials of VP: %w", err))
   447  	}
   448  
   449  	vp.ID = "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c"
   450  	vp.Holder = "did:example:ebfeb1f712ebc6f1c276e12ec21"
   451  
   452  	// Marshal VP to JWS as well.
   453  
   454  	vpJWTClaims, err := vp.JWTClaims(nil, true)
   455  	if err != nil {
   456  		panic(fmt.Errorf("failed to create JWT claims of VP: %w", err))
   457  	}
   458  
   459  	holderSigner := signature.GetEd25519Signer(holderPrivKey, holderPubKey)
   460  
   461  	vpJWS, err := vpJWTClaims.MarshalJWS(verifiable.EdDSA, holderSigner, "did:123#h-kid")
   462  	if err != nil {
   463  		panic(fmt.Errorf("failed to sign VP inside JWT: %w", err))
   464  	}
   465  
   466  	// Decode VP from JWS.
   467  	// Note that VC-s inside will be decoded as well. If they are JWS, their signature is verified
   468  	// and thus we need to make sure the public key fetcher can retrieve the public key.
   469  	vp, err = verifiable.ParsePresentation(
   470  		[]byte(vpJWS),
   471  		verifiable.WithPresPublicKeyFetcher(func(issuerID, keyID string) (*verifier.PublicKey, error) {
   472  			switch keyID {
   473  			case "i-kid":
   474  				return &verifier.PublicKey{
   475  					Type:  kms.ED25519,
   476  					Value: issuerPubKey,
   477  				}, nil
   478  			case "h-kid":
   479  				return &verifier.PublicKey{
   480  					Type:  kms.ED25519,
   481  					Value: holderPubKey,
   482  				}, nil
   483  			default:
   484  				return nil, fmt.Errorf("unexpected key: %s", keyID)
   485  			}
   486  		}), verifiable.WithPresJSONLDDocumentLoader(getJSONLDDocumentLoader()))
   487  	if err != nil {
   488  		panic(fmt.Errorf("failed to decode VP JWS: %w", err))
   489  	}
   490  
   491  	// Get credentials in binary form.
   492  	vpCreds, err := vp.MarshalledCredentials()
   493  	if err != nil {
   494  		panic(fmt.Errorf("failed to get marshalled credentials from decoded presentation: %w", err))
   495  	}
   496  
   497  	if len(vpCreds) != 1 {
   498  		panic("Expected 1 credential inside presentation")
   499  	}
   500  
   501  	// Decoded credential.
   502  	vcDecoded, err := verifiable.ParseCredential(vpCreds[0],
   503  		verifiable.WithDisabledProofCheck(),
   504  		verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()))
   505  	if err != nil {
   506  		panic(fmt.Errorf("failed to decode VC: %w", err))
   507  	}
   508  
   509  	vcDecodedJSON, err := json.MarshalIndent(vcDecoded, "", "\t")
   510  	if err != nil {
   511  		panic(fmt.Errorf("failed to marshal VP to JSON: %w", err))
   512  	}
   513  
   514  	fmt.Println(string(vcDecodedJSON))
   515  
   516  	// Output: "eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDoxMjMjaS1raWQifQ.eyJleHAiOjE1Nzc5MDY2MDQsImlhdCI6MTI2MjM3MzgwNCwiaXNzIjoiZGlkOmV4YW1wbGU6NzZlMTJlYzcxMmViYzZmMWMyMjFlYmZlYjFmIiwianRpIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJuYmYiOjEyNjIzNzM4MDQsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvZXhhbXBsZXMvdjEiXSwiY3JlZGVudGlhbFN1YmplY3QiOnsiZGVncmVlIjp7InR5cGUiOiJCYWNoZWxvckRlZ3JlZSIsInVuaXZlcnNpdHkiOiJNSVQifSwiaWQiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJuYW1lIjoiSmF5ZGVuIERvZSIsInNwb3VzZSI6ImRpZDpleGFtcGxlOmMyNzZlMTJlYzIxZWJmZWIxZjcxMmViYzZmMSJ9LCJpc3N1ZXIiOnsibmFtZSI6IkV4YW1wbGUgVW5pdmVyc2l0eSJ9LCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiVW5pdmVyc2l0eURlZ3JlZUNyZWRlbnRpYWwiXX19.K7MhsyiuJMWen87MKyjHFEEH_866xXnD3IlY4L-nF3sKsUInZRuqyqU3pORbDCefpIx1fL3HLi2GFSRcXQvEDA"
   517  }
   518  
   519  //nolint:gocyclo
   520  func ExamplePresentation_AddLinkedDataProof() {
   521  	// 1. ISSUER issues a VC.
   522  	vcToIssue := `
   523  {
   524    "@context": [
   525      "https://www.w3.org/2018/credentials/v1",
   526      "https://www.w3.org/2018/credentials/examples/v1"
   527    ],
   528    "credentialSubject": {
   529      "degree": {
   530        "type": "BachelorDegree",
   531        "university": "MIT"
   532      },
   533      "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   534      "name": "Jayden Doe",
   535      "spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1"
   536    },
   537    "expirationDate": "2020-01-01T19:23:24Z",
   538    "id": "http://example.edu/credentials/1872",
   539    "issuanceDate": "2010-01-01T19:23:24Z",
   540    "issuer": {
   541      "id": "did:example:76e12ec712ebc6f1c221ebfeb1f",
   542      "name": "Example University"
   543    },
   544    "type": [
   545      "VerifiableCredential",
   546      "UniversityDegreeCredential"
   547    ]
   548  }
   549  `
   550  
   551  	issuedVC, err := verifiable.ParseCredential([]byte(vcToIssue),
   552  		verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()),
   553  		verifiable.WithDisabledProofCheck())
   554  	if err != nil {
   555  		panic(fmt.Errorf("failed to decode VC JSON: %w", err))
   556  	}
   557  
   558  	issuerSigner := signature.GetEd25519Signer(issuerPrivKey, issuerPubKey)
   559  
   560  	err = issuedVC.AddLinkedDataProof(&verifiable.LinkedDataProofContext{
   561  		Created:                 &issued,
   562  		SignatureType:           "Ed25519Signature2018",
   563  		Suite:                   ed25519signature2018.New(suite.WithSigner(issuerSigner)),
   564  		SignatureRepresentation: verifiable.SignatureJWS,
   565  		VerificationMethod:      "did:example:123456#key1",
   566  	}, jsonld.WithDocumentLoader(getJSONLDDocumentLoader()))
   567  	if err != nil {
   568  		panic(fmt.Errorf("failed to add linked data proof: %w", err))
   569  	}
   570  
   571  	issuedVCBytes, err := issuedVC.MarshalJSON()
   572  	if err != nil {
   573  		panic(fmt.Errorf("failed to marshal VC to JSON: %w", err))
   574  	}
   575  
   576  	// 2. ISSUER creates a VP with the VC enclosed.
   577  	vcFromHolderWallet, err := verifiable.ParseCredential(issuedVCBytes,
   578  		verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()),
   579  		verifiable.WithDisabledProofCheck())
   580  	if err != nil {
   581  		panic(fmt.Errorf("failed to decode VC JSON: %w", err))
   582  	}
   583  
   584  	vpToVerify, err := verifiable.NewPresentation(verifiable.WithCredentials(vcFromHolderWallet))
   585  	if err != nil {
   586  		panic(fmt.Errorf("failed to build VP from VC: %w", err))
   587  	}
   588  
   589  	vpToVerify.Holder = "did:example:ebfeb1f712ebc6f1c276e12ec22"
   590  	vpToVerify.ID = "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c6"
   591  
   592  	holderVerifier := signature.GetEd25519Signer(holderPrivKey, holderPubKey)
   593  
   594  	err = vpToVerify.AddLinkedDataProof(&verifiable.LinkedDataProofContext{
   595  		Created:                 &issued,
   596  		SignatureType:           "Ed25519Signature2018",
   597  		Suite:                   ed25519signature2018.New(suite.WithSigner(holderVerifier)),
   598  		SignatureRepresentation: verifiable.SignatureJWS,
   599  		VerificationMethod:      "did:example:987654#key1",
   600  	}, jsonld.WithDocumentLoader(getJSONLDDocumentLoader()))
   601  	if err != nil {
   602  		panic(fmt.Errorf("failed to add linked data proof: %w", err))
   603  	}
   604  
   605  	vpJSONWithProof, err := vpToVerify.MarshalJSON()
   606  	if err != nil {
   607  		panic(fmt.Errorf("failed to marshal VP to JSON: %w", err))
   608  	}
   609  
   610  	// 3. VERIFIER verifies the presentation.
   611  	ed25519Suite := ed25519signature2018.New(suite.WithVerifier(ed25519signature2018.NewPublicKeyVerifier()))
   612  
   613  	vp, err := verifiable.ParsePresentation(vpJSONWithProof,
   614  		verifiable.WithPresPublicKeyFetcher(func(issuerID, keyID string) (*verifier.PublicKey, error) {
   615  			// both VP and enclosed VC signatures are verified, so we need to provide key resolving for all
   616  			switch issuerID {
   617  			case "did:example:123456": // issuer
   618  				return &verifier.PublicKey{
   619  					Type:  "Ed25519Signature2018",
   620  					Value: issuerPubKey,
   621  				}, nil
   622  
   623  			case "did:example:987654":
   624  				return &verifier.PublicKey{
   625  					Type:  "Ed25519Signature2018",
   626  					Value: holderPubKey,
   627  				}, nil
   628  			}
   629  
   630  			return nil, errors.New("unsupported issuer")
   631  		}),
   632  		verifiable.WithPresEmbeddedSignatureSuites(ed25519Suite),
   633  		verifiable.WithPresJSONLDDocumentLoader(getJSONLDDocumentLoader()))
   634  	if err != nil {
   635  		panic(fmt.Errorf("failed to decode VP JWS: %w", err))
   636  	}
   637  
   638  	vpJSON, err := json.MarshalIndent(vp, "", "\t")
   639  	if err != nil {
   640  		panic(fmt.Errorf("failed to marshal VC to JSON: %w", err))
   641  	}
   642  
   643  	fmt.Println(string(vpJSON))
   644  
   645  	// Output: {
   646  	//	"@context": [
   647  	//		"https://www.w3.org/2018/credentials/v1"
   648  	//	],
   649  	//	"holder": "did:example:ebfeb1f712ebc6f1c276e12ec22",
   650  	//	"id": "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c6",
   651  	//	"proof": {
   652  	//		"created": "2010-01-01T19:23:24Z",
   653  	//		"jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..8stDRasAcYjkQiqiczyFJdkff8VJIF3Lbaq5BNTaC-PcvJHGo2Xja8GTsHByTOx7QNCwC3bNiboPgfXtmm8aBA",
   654  	//		"proofPurpose": "assertionMethod",
   655  	//		"type": "Ed25519Signature2018",
   656  	//		"verificationMethod": "did:example:987654#key1"
   657  	//	},
   658  	//	"type": "VerifiablePresentation",
   659  	//	"verifiableCredential": [
   660  	//		{
   661  	//			"@context": [
   662  	//				"https://www.w3.org/2018/credentials/v1",
   663  	//				"https://www.w3.org/2018/credentials/examples/v1"
   664  	//			],
   665  	//			"credentialSubject": {
   666  	//				"degree": {
   667  	//					"type": "BachelorDegree",
   668  	//					"university": "MIT"
   669  	//				},
   670  	//				"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   671  	//				"name": "Jayden Doe",
   672  	//				"spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1"
   673  	//			},
   674  	//			"expirationDate": "2020-01-01T19:23:24Z",
   675  	//			"id": "http://example.edu/credentials/1872",
   676  	//			"issuanceDate": "2010-01-01T19:23:24Z",
   677  	//			"issuer": {
   678  	//				"id": "did:example:76e12ec712ebc6f1c221ebfeb1f",
   679  	//				"name": "Example University"
   680  	//			},
   681  	//			"proof": {
   682  	//				"created": "2010-01-01T19:23:24Z",
   683  	//				"jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..mQCxgQDvAYI-2YYCkHHe-at9eNI_wN03R6CRyjycb3CnfPWezbo6zEGe94W2AdYsBhC_Zzedcn_ZKgccMYFnCQ",
   684  	//				"proofPurpose": "assertionMethod",
   685  	//				"type": "Ed25519Signature2018",
   686  	//				"verificationMethod": "did:example:123456#key1"
   687  	//			},
   688  	//			"type": [
   689  	//				"VerifiableCredential",
   690  	//				"UniversityDegreeCredential"
   691  	//			]
   692  	//		}
   693  	//	]
   694  	//}
   695  }