github.com/hyperledger/aries-framework-go@v0.3.2/pkg/doc/verifiable/example_credential_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/base64"
    12  	"encoding/json"
    13  	"errors"
    14  	"fmt"
    15  	"time"
    16  
    17  	"github.com/hyperledger/aries-framework-go/pkg/common/log"
    18  	"github.com/hyperledger/aries-framework-go/pkg/doc/jose/jwk/jwksupport"
    19  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/jsonld"
    20  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite"
    21  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/bbsblssignature2020"
    22  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/ed25519signature2018"
    23  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/jsonwebsignature2020"
    24  	sigverifier "github.com/hyperledger/aries-framework-go/pkg/doc/signature/verifier"
    25  	"github.com/hyperledger/aries-framework-go/pkg/doc/util"
    26  	"github.com/hyperledger/aries-framework-go/pkg/doc/util/signature"
    27  	"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
    28  	"github.com/hyperledger/aries-framework-go/pkg/kms"
    29  	spi "github.com/hyperledger/aries-framework-go/spi/log"
    30  )
    31  
    32  //nolint:gochecknoglobals
    33  var (
    34  	// Private key generated by ed25519.GenerateKey(rand.Reader).
    35  	issuerPrivKey = ed25519.PrivateKey{72, 67, 163, 188, 235, 199, 239, 146, 129, 52, 228, 34, 44, 106, 23, 144, 189, 57, 115, 171, 4, 217, 54, 121, 41, 155, 251, 83, 1, 240, 238, 65, 234, 100, 192, 93, 251, 181, 198, 73, 122, 220, 27, 48, 93, 73, 166, 33, 152, 140, 168, 36, 9, 205, 59, 161, 137, 7, 164, 9, 176, 252, 1, 171}
    36  	issuerPubKey  = ed25519.PublicKey{234, 100, 192, 93, 251, 181, 198, 73, 122, 220, 27, 48, 93, 73, 166, 33, 152, 140, 168, 36, 9, 205, 59, 161, 137, 7, 164, 9, 176, 252, 1, 171}
    37  	issued        = time.Date(2010, time.January, 1, 19, 23, 24, 0, time.UTC)
    38  	expired       = time.Date(2020, time.January, 1, 19, 23, 24, 0, time.UTC)
    39  
    40  	bbsPrivKeyB64 = "PcVroyzTlmnYIIq8In8QOZhpK72AdTjj3EitB9tSNrg"
    41  	bbsPubKeyB64  = "l0Wtf3gy5f140G5vCoCJw2420hwk6Xw65/DX3ycv1W7/eMky8DyExw+o1s2bmq3sEIJatkiN8f5D4k0766x0UvfbupFX+vVkeqnlOvT6o2cag2osQdMFbBQqAybOM4Gm"
    42  )
    43  
    44  const vcJSON = `
    45  {
    46    "@context": [
    47      "https://www.w3.org/2018/credentials/v1",
    48      "https://www.w3.org/2018/credentials/examples/v1"
    49    ],
    50    "credentialSchema": [],
    51    "credentialSubject": {
    52      "degree": {
    53        "type": "BachelorDegree",
    54        "university": "MIT"
    55      },
    56      "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    57      "name": "Jayden Doe",
    58      "spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1"
    59    },
    60    "expirationDate": "2020-01-01T19:23:24Z",
    61    "id": "http://example.edu/credentials/1872",
    62    "issuanceDate": "2009-01-01T19:23:24Z",
    63    "issuer": {
    64      "id": "did:example:76e12ec712ebc6f1c221ebfeb1f",
    65      "name": "Example University"
    66    },
    67    "referenceNumber": 83294849,
    68    "type": [
    69      "VerifiableCredential",
    70      "UniversityDegreeCredential"
    71    ]
    72  }
    73  `
    74  
    75  func ExampleCredential_embedding() {
    76  	vc := &UniversityDegreeCredential{
    77  		Credential: &verifiable.Credential{
    78  			Context: []string{
    79  				"https://www.w3.org/2018/credentials/v1",
    80  				"https://www.w3.org/2018/credentials/examples/v1",
    81  			},
    82  			ID: "http://example.edu/credentials/1872",
    83  			Types: []string{
    84  				"VerifiableCredential",
    85  				"UniversityDegreeCredential",
    86  			},
    87  			Subject: UniversityDegreeSubject{
    88  				ID:     "did:example:ebfeb1f712ebc6f1c276e12ec21",
    89  				Name:   "Jayden Doe",
    90  				Spouse: "did:example:c276e12ec21ebfeb1f712ebc6f1",
    91  				Degree: UniversityDegree{
    92  					Type:       "BachelorDegree",
    93  					University: "MIT",
    94  				},
    95  			},
    96  			Issuer: verifiable.Issuer{
    97  				ID:           "did:example:76e12ec712ebc6f1c221ebfeb1f",
    98  				CustomFields: verifiable.CustomFields{"name": "Example University"},
    99  			},
   100  			Issued:  util.NewTime(issued),
   101  			Expired: util.NewTime(expired),
   102  			Schemas: []verifiable.TypedID{},
   103  		},
   104  		ReferenceNumber: 83294847,
   105  	}
   106  
   107  	// Marshal to JSON to verify the result of decoding.
   108  	vcBytes, err := json.Marshal(vc)
   109  	if err != nil {
   110  		panic("failed to marshal VC to JSON")
   111  	}
   112  
   113  	fmt.Println(string(vcBytes))
   114  
   115  	// Marshal to JWS.
   116  	jwtClaims, err := vc.JWTClaims(true)
   117  	if err != nil {
   118  		panic(fmt.Errorf("failed to marshal JWT claims of VC: %w", err))
   119  	}
   120  
   121  	signer := signature.GetEd25519Signer(issuerPrivKey, issuerPubKey)
   122  
   123  	jws, err := jwtClaims.MarshalJWS(verifiable.EdDSA, signer, "did:123#key1")
   124  	if err != nil {
   125  		panic(fmt.Errorf("failed to sign VC inside JWT: %w", err))
   126  	}
   127  
   128  	fmt.Println(jws)
   129  
   130  	// Parse JWS and make sure it's coincide with JSON.
   131  	vcParsed, err := verifiable.ParseCredential(
   132  		[]byte(jws),
   133  		verifiable.WithPublicKeyFetcher(verifiable.SingleKey(issuerPubKey, kms.ED25519)),
   134  		verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()))
   135  	if err != nil {
   136  		panic(fmt.Errorf("failed to encode VC from JWS: %w", err))
   137  	}
   138  
   139  	// When a Credential was parsed from JWS, it Marshals into a JSON string containing the original JWS.
   140  
   141  	vcBytesFromJWS, err := vcParsed.MarshalJSON()
   142  	if err != nil {
   143  		panic(fmt.Errorf("failed to marshal VC: %w", err))
   144  	}
   145  
   146  	// todo missing referenceNumber here (https://github.com/hyperledger/aries-framework-go/issues/847)
   147  	fmt.Println(string(vcBytesFromJWS))
   148  
   149  	// To marshal the Credential into JSON-LD form, clear the JWT field.
   150  
   151  	vcParsed.JWT = ""
   152  
   153  	vcBytesFromJWS, err = vcParsed.MarshalJSON()
   154  	if err != nil {
   155  		panic(fmt.Errorf("failed to marshal VC: %w", err))
   156  	}
   157  
   158  	fmt.Println(string(vcBytesFromJWS))
   159  
   160  	// Output:
   161  	// {"@context":["https://www.w3.org/2018/credentials/v1","https://www.w3.org/2018/credentials/examples/v1"],"credentialSubject":{"degree":{"type":"BachelorDegree","university":"MIT"},"id":"did:example:ebfeb1f712ebc6f1c276e12ec21","name":"Jayden Doe","spouse":"did:example:c276e12ec21ebfeb1f712ebc6f1"},"expirationDate":"2020-01-01T19:23:24Z","id":"http://example.edu/credentials/1872","issuanceDate":"2010-01-01T19:23:24Z","issuer":{"id":"did:example:76e12ec712ebc6f1c221ebfeb1f","name":"Example University"},"referenceNumber":83294847,"type":["VerifiableCredential","UniversityDegreeCredential"]}
   162  	// eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDoxMjMja2V5MSJ9.eyJleHAiOjE1Nzc5MDY2MDQsImlhdCI6MTI2MjM3MzgwNCwiaXNzIjoiZGlkOmV4YW1wbGU6NzZlMTJlYzcxMmViYzZmMWMyMjFlYmZlYjFmIiwianRpIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJuYmYiOjEyNjIzNzM4MDQsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvZXhhbXBsZXMvdjEiXSwiY3JlZGVudGlhbFN1YmplY3QiOnsiZGVncmVlIjp7InR5cGUiOiJCYWNoZWxvckRlZ3JlZSIsInVuaXZlcnNpdHkiOiJNSVQifSwiaWQiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJuYW1lIjoiSmF5ZGVuIERvZSIsInNwb3VzZSI6ImRpZDpleGFtcGxlOmMyNzZlMTJlYzIxZWJmZWIxZjcxMmViYzZmMSJ9LCJpc3N1ZXIiOnsibmFtZSI6IkV4YW1wbGUgVW5pdmVyc2l0eSJ9LCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiVW5pdmVyc2l0eURlZ3JlZUNyZWRlbnRpYWwiXX19.4VSZj1tPovsqtBihcWHxlGaE25bBNOqNdH85UoAz7XbV1rZ9hPYklwuV_sRRbcQOcEjTaRik2tzwsOPOz5EDAg
   163  	// "eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDoxMjMja2V5MSJ9.eyJleHAiOjE1Nzc5MDY2MDQsImlhdCI6MTI2MjM3MzgwNCwiaXNzIjoiZGlkOmV4YW1wbGU6NzZlMTJlYzcxMmViYzZmMWMyMjFlYmZlYjFmIiwianRpIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJuYmYiOjEyNjIzNzM4MDQsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvZXhhbXBsZXMvdjEiXSwiY3JlZGVudGlhbFN1YmplY3QiOnsiZGVncmVlIjp7InR5cGUiOiJCYWNoZWxvckRlZ3JlZSIsInVuaXZlcnNpdHkiOiJNSVQifSwiaWQiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJuYW1lIjoiSmF5ZGVuIERvZSIsInNwb3VzZSI6ImRpZDpleGFtcGxlOmMyNzZlMTJlYzIxZWJmZWIxZjcxMmViYzZmMSJ9LCJpc3N1ZXIiOnsibmFtZSI6IkV4YW1wbGUgVW5pdmVyc2l0eSJ9LCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiVW5pdmVyc2l0eURlZ3JlZUNyZWRlbnRpYWwiXX19.4VSZj1tPovsqtBihcWHxlGaE25bBNOqNdH85UoAz7XbV1rZ9hPYklwuV_sRRbcQOcEjTaRik2tzwsOPOz5EDAg"
   164  	// {"@context":["https://www.w3.org/2018/credentials/v1","https://www.w3.org/2018/credentials/examples/v1"],"credentialSubject":{"degree":{"type":"BachelorDegree","university":"MIT"},"id":"did:example:ebfeb1f712ebc6f1c276e12ec21","name":"Jayden Doe","spouse":"did:example:c276e12ec21ebfeb1f712ebc6f1"},"expirationDate":"2020-01-01T19:23:24Z","id":"http://example.edu/credentials/1872","issuanceDate":"2010-01-01T19:23:24Z","issuer":{"id":"did:example:76e12ec712ebc6f1c221ebfeb1f","name":"Example University"},"type":["VerifiableCredential","UniversityDegreeCredential"]}
   165  }
   166  
   167  func ExampleCredential_extraFields() {
   168  	vc := &verifiable.Credential{
   169  		Context: []string{
   170  			"https://www.w3.org/2018/credentials/v1",
   171  			"https://www.w3.org/2018/credentials/examples/v1",
   172  		},
   173  		ID: "http://example.edu/credentials/1872",
   174  		Types: []string{
   175  			"VerifiableCredential",
   176  			"UniversityDegreeCredential",
   177  		},
   178  		Subject: UniversityDegreeSubject{
   179  			ID:     "did:example:ebfeb1f712ebc6f1c276e12ec21",
   180  			Name:   "Jayden Doe",
   181  			Spouse: "did:example:c276e12ec21ebfeb1f712ebc6f1",
   182  			Degree: UniversityDegree{
   183  				Type:       "BachelorDegree",
   184  				University: "MIT",
   185  			},
   186  		},
   187  		Issuer: verifiable.Issuer{
   188  			ID:           "did:example:76e12ec712ebc6f1c221ebfeb1f",
   189  			CustomFields: verifiable.CustomFields{"name": "Example University"},
   190  		},
   191  		Issued:  util.NewTime(issued),
   192  		Expired: util.NewTime(expired),
   193  		Schemas: []verifiable.TypedID{},
   194  		CustomFields: map[string]interface{}{
   195  			"referenceNumber": 83294847,
   196  		},
   197  	}
   198  
   199  	// Marshal to JSON.
   200  	vcBytes, err := json.Marshal(vc)
   201  	if err != nil {
   202  		panic("failed to marshal VC to JSON")
   203  	}
   204  
   205  	fmt.Println(string(vcBytes))
   206  
   207  	// Marshal to JWS.
   208  	jwtClaims, err := vc.JWTClaims(true)
   209  	if err != nil {
   210  		panic(fmt.Errorf("failed to marshal JWT claims of VC: %w", err))
   211  	}
   212  
   213  	signer := signature.GetEd25519Signer(issuerPrivKey, issuerPubKey)
   214  
   215  	jws, err := jwtClaims.MarshalJWS(verifiable.EdDSA, signer, "did:123#key1")
   216  	if err != nil {
   217  		panic(fmt.Errorf("failed to sign VC inside JWT: %w", err))
   218  	}
   219  
   220  	fmt.Println(jws)
   221  
   222  	// Parse JWS and make sure it's coincide with JSON.
   223  	vcParsed, err := verifiable.ParseCredential(
   224  		[]byte(jws),
   225  		verifiable.WithPublicKeyFetcher(verifiable.SingleKey(issuerPubKey, kms.ED25519)),
   226  		verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()))
   227  	if err != nil {
   228  		panic(fmt.Errorf("failed to encode VC from JWS: %w", err))
   229  	}
   230  
   231  	vcParsed.JWT = ""
   232  
   233  	vcBytesFromJWS, err := vcParsed.MarshalJSON()
   234  	if err != nil {
   235  		panic(fmt.Errorf("failed to marshal VC: %w", err))
   236  	}
   237  
   238  	fmt.Println(string(vcBytesFromJWS))
   239  
   240  	// Output:
   241  	// {"@context":["https://www.w3.org/2018/credentials/v1","https://www.w3.org/2018/credentials/examples/v1"],"credentialSubject":{"degree":{"type":"BachelorDegree","university":"MIT"},"id":"did:example:ebfeb1f712ebc6f1c276e12ec21","name":"Jayden Doe","spouse":"did:example:c276e12ec21ebfeb1f712ebc6f1"},"expirationDate":"2020-01-01T19:23:24Z","id":"http://example.edu/credentials/1872","issuanceDate":"2010-01-01T19:23:24Z","issuer":{"id":"did:example:76e12ec712ebc6f1c221ebfeb1f","name":"Example University"},"referenceNumber":83294847,"type":["VerifiableCredential","UniversityDegreeCredential"]}
   242  	// eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDoxMjMja2V5MSJ9.eyJleHAiOjE1Nzc5MDY2MDQsImlhdCI6MTI2MjM3MzgwNCwiaXNzIjoiZGlkOmV4YW1wbGU6NzZlMTJlYzcxMmViYzZmMWMyMjFlYmZlYjFmIiwianRpIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJuYmYiOjEyNjIzNzM4MDQsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvZXhhbXBsZXMvdjEiXSwiY3JlZGVudGlhbFN1YmplY3QiOnsiZGVncmVlIjp7InR5cGUiOiJCYWNoZWxvckRlZ3JlZSIsInVuaXZlcnNpdHkiOiJNSVQifSwiaWQiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJuYW1lIjoiSmF5ZGVuIERvZSIsInNwb3VzZSI6ImRpZDpleGFtcGxlOmMyNzZlMTJlYzIxZWJmZWIxZjcxMmViYzZmMSJ9LCJpc3N1ZXIiOnsibmFtZSI6IkV4YW1wbGUgVW5pdmVyc2l0eSJ9LCJyZWZlcmVuY2VOdW1iZXIiOjguMzI5NDg0N2UrMDcsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJVbml2ZXJzaXR5RGVncmVlQ3JlZGVudGlhbCJdfX0.rmOsOJbKp68XeAw3SR93A67bgDYeOdLP3VDFIwbaNguE9eGQgdYjyAA2q07RbUD-uPoQMIpQDH6uhVAWYBDWCg
   243  	// {"@context":["https://www.w3.org/2018/credentials/v1","https://www.w3.org/2018/credentials/examples/v1"],"credentialSubject":{"degree":{"type":"BachelorDegree","university":"MIT"},"id":"did:example:ebfeb1f712ebc6f1c276e12ec21","name":"Jayden Doe","spouse":"did:example:c276e12ec21ebfeb1f712ebc6f1"},"expirationDate":"2020-01-01T19:23:24Z","id":"http://example.edu/credentials/1872","issuanceDate":"2010-01-01T19:23:24Z","issuer":{"id":"did:example:76e12ec712ebc6f1c221ebfeb1f","name":"Example University"},"referenceNumber":83294847,"type":["VerifiableCredential","UniversityDegreeCredential"]}
   244  }
   245  
   246  func ExampleParseCredential() {
   247  	// Issuer is about to issue the university degree credential for the Holder
   248  	vcEncoded := &verifiable.Credential{
   249  		Context: []string{
   250  			"https://www.w3.org/2018/credentials/v1",
   251  			"https://www.w3.org/2018/credentials/examples/v1",
   252  		},
   253  		ID: "http://example.edu/credentials/1872",
   254  		Types: []string{
   255  			"VerifiableCredential",
   256  			"UniversityDegreeCredential",
   257  		},
   258  		Subject: UniversityDegreeSubject{
   259  			ID:     "did:example:ebfeb1f712ebc6f1c276e12ec21",
   260  			Name:   "Jayden Doe",
   261  			Spouse: "did:example:c276e12ec21ebfeb1f712ebc6f1",
   262  			Degree: UniversityDegree{
   263  				Type:       "BachelorDegree",
   264  				University: "MIT",
   265  			},
   266  		},
   267  		Issuer: verifiable.Issuer{
   268  			ID:           "did:example:76e12ec712ebc6f1c221ebfeb1f",
   269  			CustomFields: verifiable.CustomFields{"name": "Example University"},
   270  		},
   271  		Issued:  util.NewTime(issued),
   272  		Expired: util.NewTime(expired),
   273  		Schemas: []verifiable.TypedID{},
   274  		CustomFields: map[string]interface{}{
   275  			"referenceNumber": 83294847,
   276  		},
   277  	}
   278  
   279  	// ... in JWS form.
   280  	jwtClaims, err := vcEncoded.JWTClaims(true)
   281  	if err != nil {
   282  		panic(fmt.Errorf("failed to marshal JWT claims of VC: %w", err))
   283  	}
   284  
   285  	signer := signature.GetEd25519Signer(issuerPrivKey, issuerPubKey)
   286  
   287  	jws, err := jwtClaims.MarshalJWS(verifiable.EdDSA, signer, "did:123#key1")
   288  	if err != nil {
   289  		panic(fmt.Errorf("failed to sign VC inside JWT: %w", err))
   290  	}
   291  
   292  	// The Holder receives JWS and decodes it.
   293  	vcParsed, err := verifiable.ParseCredential(
   294  		[]byte(jws),
   295  		verifiable.WithPublicKeyFetcher(verifiable.SingleKey(issuerPubKey, kms.ED25519)),
   296  		verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()))
   297  	if err != nil {
   298  		panic(fmt.Errorf("failed to decode VC JWS: %w", err))
   299  	}
   300  
   301  	// When parsing a verifiable.Credential from JWS, Credential.JWT is set to the raw JWS value.
   302  	// This allows the user to save the Credential and verify it later.
   303  
   304  	// When Credential.JWT is set, the Credential Marshals into a JSON string containing the original JWS.
   305  
   306  	vcDecodedBytes, err := vcParsed.MarshalJSON()
   307  	if err != nil {
   308  		panic(fmt.Errorf("failed to marshal VC: %w", err))
   309  	}
   310  
   311  	// The Holder then e.g. can save the credential to her personal verifiable credential wallet.
   312  	fmt.Println(string(vcDecodedBytes))
   313  
   314  	// To marshal the Credential into JSON-LD form, clear the JWT field.
   315  	vcParsed.JWT = ""
   316  
   317  	vcDecodedBytes, err = vcParsed.MarshalJSON()
   318  	if err != nil {
   319  		panic(fmt.Errorf("failed to marshal VC: %w", err))
   320  	}
   321  
   322  	// The Credential is now in JSON-LD form..
   323  	fmt.Println(string(vcDecodedBytes))
   324  
   325  	// Output:
   326  	// "eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDoxMjMja2V5MSJ9.eyJleHAiOjE1Nzc5MDY2MDQsImlhdCI6MTI2MjM3MzgwNCwiaXNzIjoiZGlkOmV4YW1wbGU6NzZlMTJlYzcxMmViYzZmMWMyMjFlYmZlYjFmIiwianRpIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJuYmYiOjEyNjIzNzM4MDQsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvZXhhbXBsZXMvdjEiXSwiY3JlZGVudGlhbFN1YmplY3QiOnsiZGVncmVlIjp7InR5cGUiOiJCYWNoZWxvckRlZ3JlZSIsInVuaXZlcnNpdHkiOiJNSVQifSwiaWQiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJuYW1lIjoiSmF5ZGVuIERvZSIsInNwb3VzZSI6ImRpZDpleGFtcGxlOmMyNzZlMTJlYzIxZWJmZWIxZjcxMmViYzZmMSJ9LCJpc3N1ZXIiOnsibmFtZSI6IkV4YW1wbGUgVW5pdmVyc2l0eSJ9LCJyZWZlcmVuY2VOdW1iZXIiOjguMzI5NDg0N2UrMDcsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJVbml2ZXJzaXR5RGVncmVlQ3JlZGVudGlhbCJdfX0.rmOsOJbKp68XeAw3SR93A67bgDYeOdLP3VDFIwbaNguE9eGQgdYjyAA2q07RbUD-uPoQMIpQDH6uhVAWYBDWCg"
   327  	// {"@context":["https://www.w3.org/2018/credentials/v1","https://www.w3.org/2018/credentials/examples/v1"],"credentialSubject":{"degree":{"type":"BachelorDegree","university":"MIT"},"id":"did:example:ebfeb1f712ebc6f1c276e12ec21","name":"Jayden Doe","spouse":"did:example:c276e12ec21ebfeb1f712ebc6f1"},"expirationDate":"2020-01-01T19:23:24Z","id":"http://example.edu/credentials/1872","issuanceDate":"2010-01-01T19:23:24Z","issuer":{"id":"did:example:76e12ec712ebc6f1c221ebfeb1f","name":"Example University"},"referenceNumber":83294847,"type":["VerifiableCredential","UniversityDegreeCredential"]}
   328  }
   329  
   330  func ExampleCredential_JWTClaims() {
   331  	// The Holder wants to send the credential to the Verifier in JWS.
   332  	vc, err := verifiable.ParseCredential([]byte(vcJSON),
   333  		verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()))
   334  	if err != nil {
   335  		panic(fmt.Errorf("failed to decode VC JSON: %w", err))
   336  	}
   337  
   338  	jwtClaims, err := vc.JWTClaims(true)
   339  	if err != nil {
   340  		panic(fmt.Errorf("failed to marshal JWT claims of VC: %w", err))
   341  	}
   342  
   343  	signer := signature.GetEd25519Signer(issuerPrivKey, issuerPubKey)
   344  
   345  	jws, err := jwtClaims.MarshalJWS(verifiable.EdDSA, signer, "")
   346  	if err != nil {
   347  		panic(fmt.Errorf("failed to sign VC inside JWT: %w", err))
   348  	}
   349  
   350  	// The Holder passes JWS to Verifier
   351  	fmt.Println(jws)
   352  
   353  	// Output: eyJhbGciOiJFZERTQSIsImtpZCI6IiJ9.eyJleHAiOjE1Nzc5MDY2MDQsImlhdCI6MTIzMDgzNzgwNCwiaXNzIjoiZGlkOmV4YW1wbGU6NzZlMTJlYzcxMmViYzZmMWMyMjFlYmZlYjFmIiwianRpIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJuYmYiOjEyMzA4Mzc4MDQsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvZXhhbXBsZXMvdjEiXSwiY3JlZGVudGlhbFN1YmplY3QiOnsiZGVncmVlIjp7InR5cGUiOiJCYWNoZWxvckRlZ3JlZSIsInVuaXZlcnNpdHkiOiJNSVQifSwiaWQiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJuYW1lIjoiSmF5ZGVuIERvZSIsInNwb3VzZSI6ImRpZDpleGFtcGxlOmMyNzZlMTJlYzIxZWJmZWIxZjcxMmViYzZmMSJ9LCJpc3N1ZXIiOnsibmFtZSI6IkV4YW1wbGUgVW5pdmVyc2l0eSJ9LCJyZWZlcmVuY2VOdW1iZXIiOjguMzI5NDg0OWUrMDcsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJVbml2ZXJzaXR5RGVncmVlQ3JlZGVudGlhbCJdfX0.3rENm7FBKgw-04J5_RRKS_36UNdiD9DT2-zqdy2mJbpQvKalAt-r49LTSWU50XVxuCUepbo6K_SWDBErsIZ2Aw
   354  }
   355  
   356  func ExampleCredential_AddLinkedDataProof() {
   357  	vc, err := verifiable.ParseCredential([]byte(vcJSON),
   358  		verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()))
   359  	if err != nil {
   360  		panic(fmt.Errorf("failed to decode VC JSON: %w", err))
   361  	}
   362  
   363  	signer := signature.GetEd25519Signer(issuerPrivKey, issuerPubKey)
   364  
   365  	err = vc.AddLinkedDataProof(&verifiable.LinkedDataProofContext{
   366  		Created:                 &issued,
   367  		SignatureType:           "Ed25519Signature2018",
   368  		Suite:                   ed25519signature2018.New(suite.WithSigner(signer)),
   369  		SignatureRepresentation: verifiable.SignatureJWS,
   370  		VerificationMethod:      "did:example:123456#key1",
   371  	}, jsonld.WithDocumentLoader(getJSONLDDocumentLoader()))
   372  	if err != nil {
   373  		panic(fmt.Errorf("failed to add linked data proof: %w", err))
   374  	}
   375  
   376  	vcJSONWithProof, err := json.MarshalIndent(vc, "", "\t")
   377  	if err != nil {
   378  		panic(fmt.Errorf("failed to marshal VC to JSON: %w", err))
   379  	}
   380  
   381  	fmt.Println(string(vcJSONWithProof))
   382  
   383  	// Output: {
   384  	//	"@context": [
   385  	//		"https://www.w3.org/2018/credentials/v1",
   386  	//		"https://www.w3.org/2018/credentials/examples/v1"
   387  	//	],
   388  	//	"credentialSubject": {
   389  	//		"degree": {
   390  	//			"type": "BachelorDegree",
   391  	//			"university": "MIT"
   392  	//		},
   393  	//		"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   394  	//		"name": "Jayden Doe",
   395  	//		"spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1"
   396  	//	},
   397  	//	"expirationDate": "2020-01-01T19:23:24Z",
   398  	//	"id": "http://example.edu/credentials/1872",
   399  	//	"issuanceDate": "2009-01-01T19:23:24Z",
   400  	//	"issuer": {
   401  	//		"id": "did:example:76e12ec712ebc6f1c221ebfeb1f",
   402  	//		"name": "Example University"
   403  	//	},
   404  	//	"proof": {
   405  	//		"created": "2010-01-01T19:23:24Z",
   406  	//		"jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..lrkhpRH4tWl6KzQKHlcyAwSm8qUTXIMSKmD3QASF_uI5QW8NWLxLebXmnQpIM8H7umhLA6dINSYVowcaPdpwBw",
   407  	//		"proofPurpose": "assertionMethod",
   408  	//		"type": "Ed25519Signature2018",
   409  	//		"verificationMethod": "did:example:123456#key1"
   410  	//	},
   411  	//	"referenceNumber": 83294849,
   412  	//	"type": [
   413  	//		"VerifiableCredential",
   414  	//		"UniversityDegreeCredential"
   415  	//	]
   416  	//}
   417  }
   418  
   419  //nolint:govet
   420  func ExampleCredential_AddLinkedDataProofMultiProofs() {
   421  	log.SetLevel("aries-framework/json-ld-processor", spi.ERROR)
   422  
   423  	vc, err := verifiable.ParseCredential([]byte(vcJSON),
   424  		verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()))
   425  	if err != nil {
   426  		panic(fmt.Errorf("failed to decode VC JSON: %w", err))
   427  	}
   428  
   429  	ed25519Signer := signature.GetEd25519Signer(issuerPrivKey, issuerPubKey)
   430  
   431  	err = vc.AddLinkedDataProof(&verifiable.LinkedDataProofContext{
   432  		Created:                 &issued,
   433  		SignatureType:           "Ed25519Signature2018",
   434  		Suite:                   ed25519signature2018.New(suite.WithSigner(ed25519Signer)),
   435  		SignatureRepresentation: verifiable.SignatureJWS,
   436  		VerificationMethod:      "did:example:123456#key1",
   437  	}, jsonld.WithDocumentLoader(getJSONLDDocumentLoader()))
   438  	if err != nil {
   439  		panic(err)
   440  	}
   441  
   442  	ecdsaSigner, err := signature.NewSigner(kms.ECDSASecp256k1TypeIEEEP1363)
   443  	if err != nil {
   444  		panic(err)
   445  	}
   446  
   447  	err = vc.AddLinkedDataProof(&verifiable.LinkedDataProofContext{
   448  		Created:                 &issued,
   449  		SignatureType:           "JsonWebSignature2020",
   450  		Suite:                   jsonwebsignature2020.New(suite.WithSigner(ecdsaSigner)),
   451  		SignatureRepresentation: verifiable.SignatureJWS,
   452  		VerificationMethod:      "did:example:123456#key2",
   453  	}, jsonld.WithDocumentLoader(getJSONLDDocumentLoader()))
   454  	if err != nil {
   455  		panic(err)
   456  	}
   457  
   458  	vcBytes, err := json.Marshal(vc)
   459  	if err != nil {
   460  		panic(err)
   461  	}
   462  
   463  	// Verify the VC with two embedded proofs.
   464  	ed25519Suite := ed25519signature2018.New(suite.WithVerifier(ed25519signature2018.NewPublicKeyVerifier()))
   465  	jsonWebSignatureSuite := jsonwebsignature2020.New(suite.WithVerifier(jsonwebsignature2020.NewPublicKeyVerifier()))
   466  
   467  	j, err := jwksupport.JWKFromKey(ecdsaSigner.PublicKey())
   468  	if err != nil {
   469  		panic(err)
   470  	}
   471  
   472  	_, err = verifiable.ParseCredential(vcBytes,
   473  		verifiable.WithEmbeddedSignatureSuites(ed25519Suite, jsonWebSignatureSuite),
   474  		verifiable.WithPublicKeyFetcher(func(issuerID, keyID string) (*sigverifier.PublicKey, error) {
   475  			switch keyID {
   476  			case "#key1":
   477  				return &sigverifier.PublicKey{
   478  					Type:  "Ed25519Signature2018",
   479  					Value: issuerPubKey,
   480  				}, nil
   481  
   482  			case "#key2":
   483  				return &sigverifier.PublicKey{
   484  					Type:  "JsonWebKey2020",
   485  					Value: ecdsaSigner.PublicKeyBytes(),
   486  					JWK:   j,
   487  				}, nil
   488  			}
   489  
   490  			return nil, errors.New("unsupported keyID")
   491  		}),
   492  		verifiable.WithJSONLDOnlyValidRDF(),
   493  		verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()))
   494  	if err != nil {
   495  		panic(err)
   496  	}
   497  	// Output:
   498  }
   499  
   500  //nolint:gocyclo
   501  func ExampleCredential_GenerateBBSSelectiveDisclosure() {
   502  	log.SetLevel("aries-framework/json-ld-processor", spi.ERROR)
   503  
   504  	vcStr := `
   505  	{
   506  	 "@context": [
   507  	   "https://www.w3.org/2018/credentials/v1",
   508  	   "https://w3id.org/citizenship/v1",
   509  	   "https://w3id.org/security/bbs/v1"
   510  	 ],
   511  	 "id": "https://issuer.oidp.uscis.gov/credentials/83627465",
   512  	 "type": [
   513  	   "VerifiableCredential",
   514  	   "PermanentResidentCard"
   515  	 ],
   516  	 "issuer": "did:example:b34ca6cd37bbf23",
   517  	 "identifier": "83627465",
   518  	 "name": "Permanent Resident Card",
   519  	 "description": "Government of Example Permanent Resident Card.",
   520  	 "issuanceDate": "2019-12-03T12:19:52Z",
   521  	 "expirationDate": "2029-12-03T12:19:52Z",
   522  	 "credentialSubject": {
   523  	   "id": "did:example:b34ca6cd37bbf23",
   524  	   "type": [
   525  	     "PermanentResident",
   526  	     "Person"
   527  	   ],
   528  	   "givenName": "JOHN",
   529  	   "familyName": "SMITH",
   530  	   "gender": "Male",
   531  	   "image": "data:image/png;base64,iVBORw0KGgokJggg==",
   532  	   "residentSince": "2015-01-01",
   533  	   "lprCategory": "C09",
   534  	   "lprNumber": "999-999-999",
   535  	   "commuterClassification": "C1",
   536  	   "birthCountry": "Bahamas",
   537  	   "birthDate": "1958-07-17"
   538  	 }
   539  	}
   540  `
   541  
   542  	vc, err := verifiable.ParseCredential([]byte(vcStr),
   543  		verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()),
   544  		verifiable.WithDisabledProofCheck())
   545  	if err != nil {
   546  		panic(fmt.Errorf("failed to decode VC JSON: %w", err))
   547  	}
   548  
   549  	ed25519Signer := signature.GetEd25519Signer(issuerPrivKey, issuerPubKey)
   550  
   551  	err = vc.AddLinkedDataProof(&verifiable.LinkedDataProofContext{
   552  		Created:                 &issued,
   553  		SignatureType:           "Ed25519Signature2018",
   554  		Suite:                   ed25519signature2018.New(suite.WithSigner(ed25519Signer)),
   555  		SignatureRepresentation: verifiable.SignatureJWS,
   556  		VerificationMethod:      "did:example:123456#key1",
   557  	}, jsonld.WithDocumentLoader(getJSONLDDocumentLoader()))
   558  	if err != nil {
   559  		panic(err)
   560  	}
   561  
   562  	pubKey, privKey, err := loadBBSKeyPair(bbsPubKeyB64, bbsPrivKeyB64)
   563  	if err != nil {
   564  		panic(err)
   565  	}
   566  
   567  	bbsSigner, err := newBBSSigner(privKey)
   568  	if err != nil {
   569  		panic(err)
   570  	}
   571  
   572  	err = vc.AddLinkedDataProof(&verifiable.LinkedDataProofContext{
   573  		Created:                 &issued,
   574  		SignatureType:           "BbsBlsSignature2020",
   575  		Suite:                   bbsblssignature2020.New(suite.WithSigner(bbsSigner)),
   576  		SignatureRepresentation: verifiable.SignatureProofValue,
   577  		VerificationMethod:      "did:example:123456#key1",
   578  	}, jsonld.WithDocumentLoader(getJSONLDDocumentLoader()))
   579  	if err != nil {
   580  		panic(err)
   581  	}
   582  
   583  	// BBS+ signature is generated each time unique, that's why we substitute it with some constant value
   584  	// for a reason of keeping constant test output.
   585  	originalProofValue := hideProofValue(vc.Proofs[1], "dummy signature value")
   586  
   587  	vcJSONWithProof, err := json.MarshalIndent(vc, "", "\t")
   588  	if err != nil {
   589  		panic(fmt.Errorf("failed to marshal VC to JSON: %w", err))
   590  	}
   591  
   592  	fmt.Println(string(vcJSONWithProof))
   593  
   594  	restoreProofValue(vc.Proofs[1], originalProofValue)
   595  
   596  	// Create BBS+ selective disclosure. We explicitly state the fields we want to reveal in the output document.
   597  	// For example, "credentialSubject.birthDate" is not mentioned and thus will be hidden.
   598  	// To hide top-level VC fields, "@explicit": true is used on top level of reveal doc.
   599  	// For example, we can reveal "identifier" top-level VC field only. "issuer" and "issuanceDate" are mandatory
   600  	// and thus must be defined in reveal doc in case of hiding top-level VC fields.
   601  	revealDoc := `
   602  {
   603    "@context": [
   604      "https://www.w3.org/2018/credentials/v1",
   605      "https://w3id.org/citizenship/v1",
   606      "https://w3id.org/security/bbs/v1"
   607    ],
   608    "type": ["VerifiableCredential", "PermanentResidentCard"],
   609    "@explicit": true,
   610    "identifier": {},
   611    "issuer": {},
   612    "issuanceDate": {},
   613    "credentialSubject": {
   614      "@explicit": true,
   615      "type": ["PermanentResident", "Person"],
   616      "givenName": {},
   617      "familyName": {},
   618      "gender": {}
   619    }
   620  }
   621  `
   622  
   623  	var revealDocMap map[string]interface{}
   624  
   625  	err = json.Unmarshal([]byte(revealDoc), &revealDocMap)
   626  	if err != nil {
   627  		panic(err)
   628  	}
   629  
   630  	pubKeyBytes, err := pubKey.Marshal()
   631  	if err != nil {
   632  		panic(err)
   633  	}
   634  
   635  	vcWithSelectiveDisclosure, err := vc.GenerateBBSSelectiveDisclosure(revealDocMap, []byte("some nonce"),
   636  		verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()),
   637  		verifiable.WithPublicKeyFetcher(verifiable.SingleKey(pubKeyBytes, "Bls12381G2Key2020")))
   638  	if err != nil {
   639  		panic(err)
   640  	}
   641  
   642  	// Only BBS+ related proof left.
   643  	hideProofValue(vcWithSelectiveDisclosure.Proofs[0], "dummy signature proof value")
   644  
   645  	vcJSONWithProof, err = json.MarshalIndent(vcWithSelectiveDisclosure, "", "\t")
   646  	if err != nil {
   647  		panic(fmt.Errorf("failed to marshal VC to JSON: %w", err))
   648  	}
   649  
   650  	fmt.Println()
   651  	fmt.Println(string(vcJSONWithProof))
   652  	// Output:{
   653  	//	"@context": [
   654  	//		"https://www.w3.org/2018/credentials/v1",
   655  	//		"https://w3id.org/citizenship/v1",
   656  	//		"https://w3id.org/security/bbs/v1"
   657  	//	],
   658  	//	"credentialSubject": {
   659  	//		"birthCountry": "Bahamas",
   660  	//		"birthDate": "1958-07-17",
   661  	//		"commuterClassification": "C1",
   662  	//		"familyName": "SMITH",
   663  	//		"gender": "Male",
   664  	//		"givenName": "JOHN",
   665  	//		"id": "did:example:b34ca6cd37bbf23",
   666  	//		"image": "data:image/png;base64,iVBORw0KGgokJggg==",
   667  	//		"lprCategory": "C09",
   668  	//		"lprNumber": "999-999-999",
   669  	//		"residentSince": "2015-01-01",
   670  	//		"type": [
   671  	//			"PermanentResident",
   672  	//			"Person"
   673  	//		]
   674  	//	},
   675  	//	"description": "Government of Example Permanent Resident Card.",
   676  	//	"expirationDate": "2029-12-03T12:19:52Z",
   677  	//	"id": "https://issuer.oidp.uscis.gov/credentials/83627465",
   678  	//	"identifier": "83627465",
   679  	//	"issuanceDate": "2019-12-03T12:19:52Z",
   680  	//	"issuer": "did:example:b34ca6cd37bbf23",
   681  	//	"name": "Permanent Resident Card",
   682  	//	"proof": [
   683  	//		{
   684  	//			"created": "2010-01-01T19:23:24Z",
   685  	//			"jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..HsBapUAZDdaZZy6hrn951768kJaRmNAwTWvVnTDM-Bp5k08eEnnxrii5n47AeWVLDJJo7P0dEPafyC_gMjFPAA",
   686  	//			"proofPurpose": "assertionMethod",
   687  	//			"type": "Ed25519Signature2018",
   688  	//			"verificationMethod": "did:example:123456#key1"
   689  	//		},
   690  	//		{
   691  	//			"created": "2010-01-01T19:23:24Z",
   692  	//			"proofPurpose": "assertionMethod",
   693  	//			"proofValue": "ZHVtbXkgc2lnbmF0dXJlIHZhbHVl",
   694  	//			"type": "BbsBlsSignature2020",
   695  	//			"verificationMethod": "did:example:123456#key1"
   696  	//		}
   697  	//	],
   698  	//	"type": [
   699  	//		"VerifiableCredential",
   700  	//		"PermanentResidentCard"
   701  	//	]
   702  	//}
   703  	//
   704  	//{
   705  	//	"@context": [
   706  	//		"https://www.w3.org/2018/credentials/v1",
   707  	//		"https://w3id.org/citizenship/v1",
   708  	//		"https://w3id.org/security/bbs/v1"
   709  	//	],
   710  	//	"credentialSubject": {
   711  	//		"familyName": "SMITH",
   712  	//		"gender": "Male",
   713  	//		"givenName": "JOHN",
   714  	//		"id": "did:example:b34ca6cd37bbf23",
   715  	//		"type": [
   716  	//			"Person",
   717  	//			"PermanentResident"
   718  	//		]
   719  	//	},
   720  	//	"id": "https://issuer.oidp.uscis.gov/credentials/83627465",
   721  	//	"identifier": "83627465",
   722  	//	"issuanceDate": "2019-12-03T12:19:52Z",
   723  	//	"issuer": "did:example:b34ca6cd37bbf23",
   724  	//	"proof": {
   725  	//		"created": "2010-01-01T19:23:24Z",
   726  	//		"nonce": "c29tZSBub25jZQ==",
   727  	//		"proofPurpose": "assertionMethod",
   728  	//		"proofValue": "ZHVtbXkgc2lnbmF0dXJlIHByb29mIHZhbHVl",
   729  	//		"type": "BbsBlsSignatureProof2020",
   730  	//		"verificationMethod": "did:example:123456#key1"
   731  	//	},
   732  	//	"type": [
   733  	//		"PermanentResidentCard",
   734  	//		"VerifiableCredential"
   735  	//	]
   736  	//}
   737  }
   738  
   739  func hideProofValue(proof verifiable.Proof, dummyValue string) interface{} {
   740  	oldProofValue := proof["proofValue"]
   741  	proof["proofValue"] = base64.StdEncoding.EncodeToString([]byte(dummyValue))
   742  
   743  	return oldProofValue
   744  }
   745  
   746  func restoreProofValue(proof verifiable.Proof, proofValue interface{}) {
   747  	proof["proofValue"] = proofValue
   748  }