verifiable

package
v0.1.6-0...-5c25bcb Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 1, 2021 License: Apache-2.0 Imports: 28 Imported by: 0

Documentation

Overview

Package verifiable implements Verifiable Credential and Presentation data model (https://www.w3.org/TR/vc-data-model). It provides the data structures and functions which allow to process the Verifiable documents on different sides and levels. For example, an Issuer can create verifiable.Credential structure and issue it to a Holder in JWS form. The Holder can decode received Credential and make sure the signature is valid. The Holder can present the Credential to the Verifier or combine one or more Credentials into a Verifiable Presentation. The Verifier can decode and verify the received Credentials and Presentations.

Index

Examples

Constants

View Source
const DefaultSchema = `` /* 3579-byte string literal not displayed */

DefaultSchema describes default schema.

Variables

This section is empty.

Functions

func CachingJSONLDLoader

func CachingJSONLDLoader() *ld.CachingDocumentLoader

CachingJSONLDLoader creates JSON_LD CachingDocumentLoader with preloaded base JSON-LD document.

func CreateCustomCredential

func CreateCustomCredential(vcData []byte, producers []CustomCredentialProducer,
	opts ...CredentialOpt) (interface{}, error)

CreateCustomCredential creates custom extended credentials from bytes which could be marshalled JSON or serialized JWT. It parses input bytes to the base Verifiable Credential using ParseCredential(). It then checks all producers to find the capable one to build extended Credential data model. If none of producers accept the credential, the base credential is returned.

func SubjectID

func SubjectID(subject interface{}) (string, error)

SubjectID gets ID of single subject if present or returns error if there are several subjects or one without ID defined. It can also try to get ID from subject of struct type.

Types

type Credential

type Credential struct {
	Context       []string
	CustomContext []interface{}
	ID            string
	Types         []string
	// Subject can be a string, map, slice of maps, struct (Subject or any custom), slice of structs.
	Subject        interface{}
	Issuer         Issuer
	Issued         *util.TimeWithTrailingZeroMsec
	Expired        *util.TimeWithTrailingZeroMsec
	Proofs         []Proof
	Status         *TypedID
	Schemas        []TypedID
	Evidence       Evidence
	TermsOfUse     []TypedID
	RefreshService []TypedID

	CustomFields CustomFields
}

Credential Verifiable Credential definition.

Example (Embedding)
vc := &UniversityDegreeCredential{
	Credential: &verifiable.Credential{
		Context: []string{
			"https://www.w3.org/2018/credentials/v1",
			"https://www.w3.org/2018/credentials/examples/v1",
		},
		ID: "http://example.edu/credentials/1872",
		Types: []string{
			"VerifiableCredential",
			"UniversityDegreeCredential",
		},
		Subject: UniversityDegreeSubject{
			ID:     "did:example:ebfeb1f712ebc6f1c276e12ec21",
			Name:   "Jayden Doe",
			Spouse: "did:example:c276e12ec21ebfeb1f712ebc6f1",
			Degree: UniversityDegree{
				Type:       "BachelorDegree",
				University: "MIT",
			},
		},
		Issuer: verifiable.Issuer{
			ID:           "did:example:76e12ec712ebc6f1c221ebfeb1f",
			CustomFields: verifiable.CustomFields{"name": "Example University"},
		},
		Issued:  util.NewTime(issued),
		Expired: util.NewTime(expired),
		Schemas: []verifiable.TypedID{},
	},
	ReferenceNumber: 83294847,
}

// Marshal to JSON to verify the result of decoding.
vcBytes, err := json.Marshal(vc)
if err != nil {
	panic("failed to marshal VC to JSON")
}

fmt.Println(string(vcBytes))

// Marshal to JWS.
jwtClaims, err := vc.JWTClaims(true)
if err != nil {
	panic(fmt.Errorf("failed to marshal JWT claims of VC: %w", err))
}

signer := signature.GetEd25519Signer(issuerPrivKey, issuerPubKey)

jws, err := jwtClaims.MarshalJWS(verifiable.EdDSA, signer, "")
if err != nil {
	panic(fmt.Errorf("failed to sign VC inside JWT: %w", err))
}

fmt.Println(jws)

// Parse JWS and make sure it's coincide with JSON.
vcParsed, err := verifiable.ParseCredential(
	[]byte(jws),
	verifiable.WithPublicKeyFetcher(verifiable.SingleKey(issuerPubKey, kms.ED25519)),
	verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()))
if err != nil {
	panic(fmt.Errorf("failed to encode VC from JWS: %w", err))
}

vcBytesFromJWS, err := vcParsed.MarshalJSON()
if err != nil {
	panic(fmt.Errorf("failed to marshal VC: %w", err))
}

// todo missing referenceNumber here (https://github.com/hyperledger/aries-framework-go/issues/847)
fmt.Println(string(vcBytesFromJWS))
Output:

{"@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"]}
eyJhbGciOiJFZERTQSIsImtpZCI6IiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1Nzc5MDY2MDQsImlhdCI6MTI2MjM3MzgwNCwiaXNzIjoiZGlkOmV4YW1wbGU6NzZlMTJlYzcxMmViYzZmMWMyMjFlYmZlYjFmIiwianRpIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJuYmYiOjEyNjIzNzM4MDQsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvZXhhbXBsZXMvdjEiXSwiY3JlZGVudGlhbFN1YmplY3QiOnsiZGVncmVlIjp7InR5cGUiOiJCYWNoZWxvckRlZ3JlZSIsInVuaXZlcnNpdHkiOiJNSVQifSwiaWQiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJuYW1lIjoiSmF5ZGVuIERvZSIsInNwb3VzZSI6ImRpZDpleGFtcGxlOmMyNzZlMTJlYzIxZWJmZWIxZjcxMmViYzZmMSJ9LCJpc3N1ZXIiOnsibmFtZSI6IkV4YW1wbGUgVW5pdmVyc2l0eSJ9LCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiVW5pdmVyc2l0eURlZ3JlZUNyZWRlbnRpYWwiXX19.7He-0-kAUCgjgMUSI-BmH-9MjI-ixuMV6NUnJCtfLpoOJIkdK0Tf1iU6SWGSURpv67Mi91H-pzQCmW6jzEUABQ
{"@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"]}
Example (ExtraFields)
vc := &verifiable.Credential{
	Context: []string{
		"https://www.w3.org/2018/credentials/v1",
		"https://www.w3.org/2018/credentials/examples/v1",
	},
	ID: "http://example.edu/credentials/1872",
	Types: []string{
		"VerifiableCredential",
		"UniversityDegreeCredential",
	},
	Subject: UniversityDegreeSubject{
		ID:     "did:example:ebfeb1f712ebc6f1c276e12ec21",
		Name:   "Jayden Doe",
		Spouse: "did:example:c276e12ec21ebfeb1f712ebc6f1",
		Degree: UniversityDegree{
			Type:       "BachelorDegree",
			University: "MIT",
		},
	},
	Issuer: verifiable.Issuer{
		ID:           "did:example:76e12ec712ebc6f1c221ebfeb1f",
		CustomFields: verifiable.CustomFields{"name": "Example University"},
	},
	Issued:  util.NewTime(issued),
	Expired: util.NewTime(expired),
	Schemas: []verifiable.TypedID{},
	CustomFields: map[string]interface{}{
		"referenceNumber": 83294847,
	},
}

// Marshal to JSON.
vcBytes, err := json.Marshal(vc)
if err != nil {
	panic("failed to marshal VC to JSON")
}

fmt.Println(string(vcBytes))

// Marshal to JWS.
jwtClaims, err := vc.JWTClaims(true)
if err != nil {
	panic(fmt.Errorf("failed to marshal JWT claims of VC: %w", err))
}

signer := signature.GetEd25519Signer(issuerPrivKey, issuerPubKey)

jws, err := jwtClaims.MarshalJWS(verifiable.EdDSA, signer, "")
if err != nil {
	panic(fmt.Errorf("failed to sign VC inside JWT: %w", err))
}

fmt.Println(jws)

// Parse JWS and make sure it's coincide with JSON.
vcParsed, err := verifiable.ParseCredential(
	[]byte(jws),
	verifiable.WithPublicKeyFetcher(verifiable.SingleKey(issuerPubKey, kms.ED25519)),
	verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()))
if err != nil {
	panic(fmt.Errorf("failed to encode VC from JWS: %w", err))
}

vcBytesFromJWS, err := vcParsed.MarshalJSON()
if err != nil {
	panic(fmt.Errorf("failed to marshal VC: %w", err))
}

fmt.Println(string(vcBytesFromJWS))
Output:

{"@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"]}
eyJhbGciOiJFZERTQSIsImtpZCI6IiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1Nzc5MDY2MDQsImlhdCI6MTI2MjM3MzgwNCwiaXNzIjoiZGlkOmV4YW1wbGU6NzZlMTJlYzcxMmViYzZmMWMyMjFlYmZlYjFmIiwianRpIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJuYmYiOjEyNjIzNzM4MDQsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvZXhhbXBsZXMvdjEiXSwiY3JlZGVudGlhbFN1YmplY3QiOnsiZGVncmVlIjp7InR5cGUiOiJCYWNoZWxvckRlZ3JlZSIsInVuaXZlcnNpdHkiOiJNSVQifSwiaWQiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJuYW1lIjoiSmF5ZGVuIERvZSIsInNwb3VzZSI6ImRpZDpleGFtcGxlOmMyNzZlMTJlYzIxZWJmZWIxZjcxMmViYzZmMSJ9LCJpc3N1ZXIiOnsibmFtZSI6IkV4YW1wbGUgVW5pdmVyc2l0eSJ9LCJyZWZlcmVuY2VOdW1iZXIiOjguMzI5NDg0N2UrMDcsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJVbml2ZXJzaXR5RGVncmVlQ3JlZGVudGlhbCJdfX0.a5yKMPmDnEXvM-fG3BaOqfdkqdvU4s2rzeZuOzLmkTH1y9sJT-mgTe7map5E9x7abrNVpyYbaH7JaAb9Yhr1DQ
{"@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"]}

func ParseCredential

func ParseCredential(vcData []byte, opts ...CredentialOpt) (*Credential, error)

ParseCredential parses Verifiable Credential from bytes which could be marshalled JSON or serialized JWT. It also applies miscellaneous options like settings of schema validation. It returns decoded Credential.

Example
// Issuer is about to issue the university degree credential for the Holder
vcEncoded := &verifiable.Credential{
	Context: []string{
		"https://www.w3.org/2018/credentials/v1",
		"https://www.w3.org/2018/credentials/examples/v1",
	},
	ID: "http://example.edu/credentials/1872",
	Types: []string{
		"VerifiableCredential",
		"UniversityDegreeCredential",
	},
	Subject: UniversityDegreeSubject{
		ID:     "did:example:ebfeb1f712ebc6f1c276e12ec21",
		Name:   "Jayden Doe",
		Spouse: "did:example:c276e12ec21ebfeb1f712ebc6f1",
		Degree: UniversityDegree{
			Type:       "BachelorDegree",
			University: "MIT",
		},
	},
	Issuer: verifiable.Issuer{
		ID:           "did:example:76e12ec712ebc6f1c221ebfeb1f",
		CustomFields: verifiable.CustomFields{"name": "Example University"},
	},
	Issued:  util.NewTime(issued),
	Expired: util.NewTime(expired),
	Schemas: []verifiable.TypedID{},
	CustomFields: map[string]interface{}{
		"referenceNumber": 83294847,
	},
}

// ... in JWS form.
jwtClaims, err := vcEncoded.JWTClaims(true)
if err != nil {
	panic(fmt.Errorf("failed to marshal JWT claims of VC: %w", err))
}

signer := signature.GetEd25519Signer(issuerPrivKey, issuerPubKey)

jws, err := jwtClaims.MarshalJWS(verifiable.EdDSA, signer, "")
if err != nil {
	panic(fmt.Errorf("failed to sign VC inside JWT: %w", err))
}

// The Holder receives JWS and decodes it.
vcParsed, err := verifiable.ParseCredential(
	[]byte(jws),
	verifiable.WithPublicKeyFetcher(verifiable.SingleKey(issuerPubKey, kms.ED25519)),
	verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()))
if err != nil {
	panic(fmt.Errorf("failed to decode VC JWS: %w", err))
}

vcDecodedBytes, err := vcParsed.MarshalJSON()
if err != nil {
	panic(fmt.Errorf("failed to marshal VC: %w", err))
}

// The Holder then e.g. can save the credential to her personal verifiable credential wallet.
fmt.Println(string(vcDecodedBytes))
Output:

{"@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"]}

func ParseUnverifiedCredential

func ParseUnverifiedCredential(vcBytes []byte, opts ...CredentialOpt) (*Credential, error)

ParseUnverifiedCredential parses Verifiable Credential from bytes which could be marshalled JSON or serialized JWT. It does not make a proof check though. Can be used for purposes of decoding of VC stored in a wallet. Please use this function with caution.

func (*Credential) AddLinkedDataProof

func (vc *Credential) AddLinkedDataProof(context *LinkedDataProofContext, jsonldOpts ...jsonld.ProcessorOpts) error

AddLinkedDataProof appends proof to the Verifiable Credential.

Example
vc, err := verifiable.ParseCredential([]byte(vcJSON),
	verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()))
if err != nil {
	panic(fmt.Errorf("failed to decode VC JSON: %w", err))
}

signer := signature.GetEd25519Signer(issuerPrivKey, issuerPubKey)

err = vc.AddLinkedDataProof(&verifiable.LinkedDataProofContext{
	Created:                 &issued,
	SignatureType:           "Ed25519Signature2018",
	Suite:                   ed25519signature2018.New(suite.WithSigner(signer)),
	SignatureRepresentation: verifiable.SignatureJWS,
	VerificationMethod:      "did:example:123456#key1",
}, jsonld.WithDocumentLoader(getJSONLDDocumentLoader()))
if err != nil {
	panic(fmt.Errorf("failed to add linked data proof: %w", err))
}

vcJSONWithProof, err := json.MarshalIndent(vc, "", "\t")
if err != nil {
	panic(fmt.Errorf("failed to marshal VC to JSON: %w", err))
}

fmt.Println(string(vcJSONWithProof))
Output:

{
	"@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": "2009-01-01T19:23:24Z",
	"issuer": {
		"id": "did:example:76e12ec712ebc6f1c221ebfeb1f",
		"name": "Example University"
	},
	"proof": {
		"created": "2010-01-01T19:23:24Z",
		"jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..lrkhpRH4tWl6KzQKHlcyAwSm8qUTXIMSKmD3QASF_uI5QW8NWLxLebXmnQpIM8H7umhLA6dINSYVowcaPdpwBw",
		"proofPurpose": "assertionMethod",
		"type": "Ed25519Signature2018",
		"verificationMethod": "did:example:123456#key1"
	},
	"referenceNumber": 83294849,
	"type": [
		"VerifiableCredential",
		"UniversityDegreeCredential"
	]
}

func (*Credential) GenerateBBSSelectiveDisclosure

func (vc *Credential) GenerateBBSSelectiveDisclosure(revealDoc map[string]interface{},
	nonce []byte, opts ...CredentialOpt) (*Credential, error)

GenerateBBSSelectiveDisclosure generate BBS+ selective disclosure from one BBS+ signature.

Example
log.SetLevel("aries-framework/json-ld-processor", log.ERROR)

vcStr := `
	{
	 "@context": [
	   "https://www.w3.org/2018/credentials/v1",
	   "https://w3id.org/citizenship/v1",
	   "https://w3c-ccg.github.io/ldp-bbs2020/context/v1"
	 ],
	 "id": "https://issuer.oidp.uscis.gov/credentials/83627465",
	 "type": [
	   "VerifiableCredential",
	   "PermanentResidentCard"
	 ],
	 "issuer": "did:example:b34ca6cd37bbf23",
	 "identifier": "83627465",
	 "name": "Permanent Resident Card",
	 "description": "Government of Example Permanent Resident Card.",
	 "issuanceDate": "2019-12-03T12:19:52Z",
	 "expirationDate": "2029-12-03T12:19:52Z",
	 "credentialSubject": {
	   "id": "did:example:b34ca6cd37bbf23",
	   "type": [
	     "PermanentResident",
	     "Person"
	   ],
	   "givenName": "JOHN",
	   "familyName": "SMITH",
	   "gender": "Male",
	   "image": "data:image/png;base64,iVBORw0KGgokJggg==",
	   "residentSince": "2015-01-01",
	   "lprCategory": "C09",
	   "lprNumber": "999-999-999",
	   "commuterClassification": "C1",
	   "birthCountry": "Bahamas",
	   "birthDate": "1958-07-17"
	 }
	}
`

vc, err := verifiable.ParseUnverifiedCredential([]byte(vcStr),
	verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()))
if err != nil {
	panic(fmt.Errorf("failed to decode VC JSON: %w", err))
}

ed25519Signer := signature.GetEd25519Signer(issuerPrivKey, issuerPubKey)

err = vc.AddLinkedDataProof(&verifiable.LinkedDataProofContext{
	Created:                 &issued,
	SignatureType:           "Ed25519Signature2018",
	Suite:                   ed25519signature2018.New(suite.WithSigner(ed25519Signer)),
	SignatureRepresentation: verifiable.SignatureJWS,
	VerificationMethod:      "did:example:123456#key1",
}, jsonld.WithDocumentLoader(getJSONLDDocumentLoader()))
if err != nil {
	panic(err)
}

pubKey, privKey, err := loadBBSKeyPair(bbsPubKeyB64, bbsPrivKeyB64)
if err != nil {
	panic(err)
}

bbsSigner, err := newBBSSigner(privKey)
if err != nil {
	panic(err)
}

err = vc.AddLinkedDataProof(&verifiable.LinkedDataProofContext{
	Created:                 &issued,
	SignatureType:           "BbsBlsSignature2020",
	Suite:                   bbsblssignature2020.New(suite.WithSigner(bbsSigner)),
	SignatureRepresentation: verifiable.SignatureProofValue,
	VerificationMethod:      "did:example:123456#key1",
}, jsonld.WithDocumentLoader(getJSONLDDocumentLoader()))
if err != nil {
	panic(err)
}

// BBS+ signature is generated each time unique, that's why we substitute it with some constant value
// for a reason of keeping constant test output.
originalProofValue := hideProofValue(vc.Proofs[1], "dummy signature value")

vcJSONWithProof, err := json.MarshalIndent(vc, "", "\t")
if err != nil {
	panic(fmt.Errorf("failed to marshal VC to JSON: %w", err))
}

fmt.Println(string(vcJSONWithProof))

restoreProofValue(vc.Proofs[1], originalProofValue)

// Create BBS+ selective disclosure. We explicitly state the fields we want to reveal in the output document.
// For example, "credentialSubject.birthDate" is not mentioned and thus will be hidden.
// To hide top-level VC fields, "@explicit": true is used on top level of reveal doc.
// For example, we can reveal "identifier" top-level VC field only. "issuer" and "issuanceDate" are mandatory
// and thus must be defined in reveal doc in case of hiding top-level VC fields.
revealDoc := `
{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/citizenship/v1",
    "https://w3c-ccg.github.io/ldp-bbs2020/context/v1"
  ],
  "type": ["VerifiableCredential", "PermanentResidentCard"],
  "@explicit": true,
  "identifier": {},
  "issuer": {},
  "issuanceDate": {},
  "credentialSubject": {
    "@explicit": true,
    "type": ["PermanentResident", "Person"],
    "givenName": {},
    "familyName": {},
    "gender": {}
  }
}
`

var revealDocMap map[string]interface{}

err = json.Unmarshal([]byte(revealDoc), &revealDocMap)
if err != nil {
	panic(err)
}

pubKeyBytes, err := pubKey.Marshal()
if err != nil {
	panic(err)
}

vcWithSelectiveDisclosure, err := vc.GenerateBBSSelectiveDisclosure(revealDocMap, []byte("some nonce"),
	verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()),
	verifiable.WithPublicKeyFetcher(verifiable.SingleKey(pubKeyBytes, "Bls12381G2Key2020")))
if err != nil {
	panic(err)
}

// Only BBS+ related proof left.
hideProofValue(vcWithSelectiveDisclosure.Proofs[0], "dummy signature proof value")

vcJSONWithProof, err = json.MarshalIndent(vcWithSelectiveDisclosure, "", "\t")
if err != nil {
	panic(fmt.Errorf("failed to marshal VC to JSON: %w", err))
}

fmt.Println()
fmt.Println(string(vcJSONWithProof))
Output:

{
	"@context": [
		"https://www.w3.org/2018/credentials/v1",
		"https://w3id.org/citizenship/v1",
		"https://w3c-ccg.github.io/ldp-bbs2020/context/v1"
	],
	"credentialSubject": {
		"birthCountry": "Bahamas",
		"birthDate": "1958-07-17",
		"commuterClassification": "C1",
		"familyName": "SMITH",
		"gender": "Male",
		"givenName": "JOHN",
		"id": "did:example:b34ca6cd37bbf23",
		"image": "data:image/png;base64,iVBORw0KGgokJggg==",
		"lprCategory": "C09",
		"lprNumber": "999-999-999",
		"residentSince": "2015-01-01",
		"type": [
			"PermanentResident",
			"Person"
		]
	},
	"description": "Government of Example Permanent Resident Card.",
	"expirationDate": "2029-12-03T12:19:52Z",
	"id": "https://issuer.oidp.uscis.gov/credentials/83627465",
	"identifier": "83627465",
	"issuanceDate": "2019-12-03T12:19:52Z",
	"issuer": "did:example:b34ca6cd37bbf23",
	"name": "Permanent Resident Card",
	"proof": [
		{
			"created": "2010-01-01T19:23:24Z",
			"jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..HsBapUAZDdaZZy6hrn951768kJaRmNAwTWvVnTDM-Bp5k08eEnnxrii5n47AeWVLDJJo7P0dEPafyC_gMjFPAA",
			"proofPurpose": "assertionMethod",
			"type": "Ed25519Signature2018",
			"verificationMethod": "did:example:123456#key1"
		},
		{
			"created": "2010-01-01T19:23:24Z",
			"proofPurpose": "assertionMethod",
			"proofValue": "ZHVtbXkgc2lnbmF0dXJlIHZhbHVl",
			"type": "BbsBlsSignature2020",
			"verificationMethod": "did:example:123456#key1"
		}
	],
	"type": [
		"VerifiableCredential",
		"PermanentResidentCard"
	]
}

{
	"@context": [
		"https://www.w3.org/2018/credentials/v1",
		"https://w3id.org/citizenship/v1",
		"https://w3c-ccg.github.io/ldp-bbs2020/context/v1"
	],
	"credentialSubject": {
		"familyName": "SMITH",
		"gender": "Male",
		"givenName": "JOHN",
		"id": "did:example:b34ca6cd37bbf23",
		"type": [
			"PermanentResident",
			"Person"
		]
	},
	"id": "https://issuer.oidp.uscis.gov/credentials/83627465",
	"identifier": "83627465",
	"issuanceDate": "2019-12-03T12:19:52Z",
	"issuer": "did:example:b34ca6cd37bbf23",
	"proof": {
		"created": "2010-01-01T19:23:24Z",
		"nonce": "c29tZSBub25jZQ==",
		"proofPurpose": "assertionMethod",
		"proofValue": "ZHVtbXkgc2lnbmF0dXJlIHByb29mIHZhbHVl",
		"type": "BbsBlsSignatureProof2020",
		"verificationMethod": "did:example:123456#key1"
	},
	"type": [
		"VerifiableCredential",
		"PermanentResidentCard"
	]
}

func (*Credential) JWTClaims

func (vc *Credential) JWTClaims(minimizeVC bool) (*JWTCredClaims, error)

JWTClaims converts Verifiable Credential into JWT Credential claims, which can be than serialized e.g. into JWS.

Example
// The Holder wants to send the credential to the Verifier in JWS.
vc, err := verifiable.ParseCredential([]byte(vcJSON),
	verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()))
if err != nil {
	panic(fmt.Errorf("failed to decode VC JSON: %w", err))
}

jwtClaims, err := vc.JWTClaims(true)
if err != nil {
	panic(fmt.Errorf("failed to marshal JWT claims of VC: %w", err))
}

signer := signature.GetEd25519Signer(issuerPrivKey, issuerPubKey)

jws, err := jwtClaims.MarshalJWS(verifiable.EdDSA, signer, "")
if err != nil {
	panic(fmt.Errorf("failed to sign VC inside JWT: %w", err))
}

// The Holder passes JWS to Verifier
fmt.Println(jws)
Output:

eyJhbGciOiJFZERTQSIsImtpZCI6IiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1Nzc5MDY2MDQsImlhdCI6MTIzMDgzNzgwNCwiaXNzIjoiZGlkOmV4YW1wbGU6NzZlMTJlYzcxMmViYzZmMWMyMjFlYmZlYjFmIiwianRpIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJuYmYiOjEyMzA4Mzc4MDQsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvZXhhbXBsZXMvdjEiXSwiY3JlZGVudGlhbFN1YmplY3QiOnsiZGVncmVlIjp7InR5cGUiOiJCYWNoZWxvckRlZ3JlZSIsInVuaXZlcnNpdHkiOiJNSVQifSwiaWQiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJuYW1lIjoiSmF5ZGVuIERvZSIsInNwb3VzZSI6ImRpZDpleGFtcGxlOmMyNzZlMTJlYzIxZWJmZWIxZjcxMmViYzZmMSJ9LCJpc3N1ZXIiOnsibmFtZSI6IkV4YW1wbGUgVW5pdmVyc2l0eSJ9LCJyZWZlcmVuY2VOdW1iZXIiOjguMzI5NDg0OWUrMDcsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJVbml2ZXJzaXR5RGVncmVlQ3JlZGVudGlhbCJdfX0.9-hiifM2cvfAcK6Olk5JSEnhlcRAAe0LYlpZW4nHat_3jVP4rjvKhP6bLNfTEkJ0271-NZZRd0YsI9Dg_-uKAg

func (*Credential) MarshalJSON

func (vc *Credential) MarshalJSON() ([]byte, error)

MarshalJSON converts Verifiable Credential to JSON bytes.

func (*Credential) Presentation

func (vc *Credential) Presentation() (*Presentation, error)

Presentation encloses credential into presentation.

Example
// A Holder loads the credential from verifiable credential wallet in order to send to Verifier.
// She embedded the credential into presentation and sends it to the Verifier in JWS form.
vcStrFromWallet := `
{
  "@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"
  ]
}
`

vc, err := verifiable.ParseCredential([]byte(vcStrFromWallet),
	verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()))
if err != nil {
	panic(fmt.Errorf("failed to decode VC JSON: %w", err))
}

vp, err := vc.Presentation()
if err != nil {
	panic(fmt.Errorf("failed to build VP from VC: %w", err))
}

vp.ID = "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c5"
vp.Holder = "did:example:ebfeb1f712ebc6f1c276e12ec21"

aud := []string{"did:example:4a57546973436f6f6c4a4a57573"}

jwtClaims, err := vp.JWTClaims(aud, true)
if err != nil {
	panic(fmt.Errorf("failed to create JWT claims of VP: %w", err))
}

signer := signature.GetEd25519Signer(holderPrivKey, holderPubKey)

jws, err := jwtClaims.MarshalJWS(verifiable.EdDSA, signer, "")
if err != nil {
	panic(fmt.Errorf("failed to sign VP inside JWT: %w", err))
}

fmt.Println(jws)
Output:

eyJhbGciOiJFZERTQSIsImtpZCI6IiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJkaWQ6ZXhhbXBsZTo0YTU3NTQ2OTczNDM2ZjZmNmM0YTRhNTc1NzMiLCJpc3MiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJqdGkiOiJ1cm46dXVpZDozOTc4MzQ0Zi04NTk2LTRjM2EtYTk3OC04ZmNhYmEzOTAzYzUiLCJ2cCI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ0eXBlIjoiVmVyaWZpYWJsZVByZXNlbnRhdGlvbiIsInZlcmlmaWFibGVDcmVkZW50aWFsIjpbeyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL2V4YW1wbGVzL3YxIl0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImRlZ3JlZSI6eyJ0eXBlIjoiQmFjaGVsb3JEZWdyZWUiLCJ1bml2ZXJzaXR5IjoiTUlUIn0sImlkIjoiZGlkOmV4YW1wbGU6ZWJmZWIxZjcxMmViYzZmMWMyNzZlMTJlYzIxIiwibmFtZSI6IkpheWRlbiBEb2UiLCJzcG91c2UiOiJkaWQ6ZXhhbXBsZTpjMjc2ZTEyZWMyMWViZmViMWY3MTJlYmM2ZjEifSwiZXhwaXJhdGlvbkRhdGUiOiIyMDIwLTAxLTAxVDE5OjIzOjI0WiIsImlkIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJpc3N1YW5jZURhdGUiOiIyMDEwLTAxLTAxVDE5OjIzOjI0WiIsImlzc3VlciI6eyJpZCI6ImRpZDpleGFtcGxlOjc2ZTEyZWM3MTJlYmM2ZjFjMjIxZWJmZWIxZiIsIm5hbWUiOiJFeGFtcGxlIFVuaXZlcnNpdHkifSwicmVmZXJlbmNlTnVtYmVyIjo4MzI5NDg0NywidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIlVuaXZlcnNpdHlEZWdyZWVDcmVkZW50aWFsIl19XX19.DMayxVTjX-tKwemmIuoJvxw8A0Oj5KMM1xgKF_SaFO4GQHAspQEDT70RJrW37WDHaYnFyVAimTLlGkaxKic-Dg

type CredentialDecoder

type CredentialDecoder func(dataJSON []byte, vc *Credential) error

CredentialDecoder makes a custom decoding of Verifiable Credential in JSON form to existent instance of Credential.

type CredentialOpt

type CredentialOpt func(opts *credentialOpts)

CredentialOpt is the Verifiable Credential decoding option.

func WithBaseContextExtendedValidation

func WithBaseContextExtendedValidation(customContexts, customTypes []string) CredentialOpt

WithBaseContextExtendedValidation validates that fields that are specified in base context are as specified. Additional fields are allowed.

func WithBaseContextValidation

func WithBaseContextValidation() CredentialOpt

WithBaseContextValidation validates that only the fields and values (when applicable) are present in the document. No extra fields are allowed (outside of credentialSubject).

func WithCredentialSchemaLoader

func WithCredentialSchemaLoader(loader *CredentialSchemaLoader) CredentialOpt

WithCredentialSchemaLoader option is used to define custom credentials schema loader. If not defined, the default one is created with default HTTP client to download the schema and no caching of the schemas.

func WithDisabledProofCheck

func WithDisabledProofCheck() CredentialOpt

WithDisabledProofCheck option for disabling of proof check.

func WithEmbeddedSignatureSuites

func WithEmbeddedSignatureSuites(suites ...verifier.SignatureSuite) CredentialOpt

WithEmbeddedSignatureSuites defines the suites which are used to check embedded linked data proof of VC.

func WithExternalJSONLDContext

func WithExternalJSONLDContext(context ...string) CredentialOpt

WithExternalJSONLDContext defines external JSON-LD contexts to be used in JSON-LD validation and Linked Data Signatures verification.

func WithJSONLDDocumentLoader

func WithJSONLDDocumentLoader(documentLoader ld.DocumentLoader) CredentialOpt

WithJSONLDDocumentLoader defines custom JSON-LD document loader. If not defined, when decoding VC a new document loader will be created using CachingJSONLDLoader() if JSON-LD validation is made.

func WithJSONLDOnlyValidRDF

func WithJSONLDOnlyValidRDF() CredentialOpt

WithJSONLDOnlyValidRDF indicates the need to remove all invalid RDF dataset from normalize document when verifying linked data signatures of verifiable credential.

func WithJSONLDValidation

func WithJSONLDValidation() CredentialOpt

WithJSONLDValidation uses the JSON LD parser for validation.

func WithNoCustomSchemaCheck

func WithNoCustomSchemaCheck() CredentialOpt

WithNoCustomSchemaCheck option is for disabling of Credential Schemas download if defined in Verifiable Credential. Instead, the Verifiable Credential is checked against default Schema.

func WithPublicKeyFetcher

func WithPublicKeyFetcher(fetcher PublicKeyFetcher) CredentialOpt

WithPublicKeyFetcher set public key fetcher used when decoding from JWS.

func WithStrictValidation

func WithStrictValidation() CredentialOpt

WithStrictValidation enabled strict validation of VC.

In case of JSON Schema validation, additionalProperties=true is set on the schema.

In case of JSON-LD validation, the comparison of JSON-LD VC document after compaction with original VC one is made. In case of mismatch a validation exception is raised.

type CredentialSchemaLoader

type CredentialSchemaLoader struct {
	// contains filtered or unexported fields
}

CredentialSchemaLoader defines expirable cache.

type CredentialSchemaLoaderBuilder

type CredentialSchemaLoaderBuilder struct {
	// contains filtered or unexported fields
}

CredentialSchemaLoaderBuilder defines a builder of CredentialSchemaLoader.

func NewCredentialSchemaLoaderBuilder

func NewCredentialSchemaLoaderBuilder() *CredentialSchemaLoaderBuilder

NewCredentialSchemaLoaderBuilder creates a new instance of CredentialSchemaLoaderBuilder.

func (*CredentialSchemaLoaderBuilder) Build

Build constructed CredentialSchemaLoader. It creates default HTTP client and JSON schema loader if not defined.

func (*CredentialSchemaLoaderBuilder) SetCache

SetCache defines SchemaCache.

func (*CredentialSchemaLoaderBuilder) SetJSONLoader

SetJSONLoader defines gojsonschema.JSONLoader.

func (*CredentialSchemaLoaderBuilder) SetSchemaDownloadClient

func (b *CredentialSchemaLoaderBuilder) SetSchemaDownloadClient(client *http.Client) *CredentialSchemaLoaderBuilder

SetSchemaDownloadClient sets HTTP client to be used to download the schema.

type CredentialTemplate

type CredentialTemplate func() *Credential

CredentialTemplate defines a factory method to create new Credential template.

type CustomCredentialProducer

type CustomCredentialProducer interface {
	// Accept checks if producer is capable of building extended Credential data model.
	Accept(vc *Credential) bool

	// Apply creates custom credential using base credential and its JSON bytes.
	Apply(vc *Credential, dataJSON []byte) (interface{}, error)
}

CustomCredentialProducer is a factory for Credentials with extended data model.

type CustomFields

type CustomFields map[string]interface{}

CustomFields is a map of extra fields of struct build when unmarshalling JSON which are not mapped to the struct fields.

type DIDKeyResolver

type DIDKeyResolver struct {
	// contains filtered or unexported fields
}

DIDKeyResolver resolves DID in order to find public keys for VC verification using vdr.Registry. A source of DID could be issuer of VC or holder of VP. It can be also obtained from JWS "issuer" claim or "verificationMethod" of Linked Data Proof.

func NewDIDKeyResolver

func NewDIDKeyResolver(vdr vdrapi.Registry) *DIDKeyResolver

NewDIDKeyResolver creates DIDKeyResolver.

func (*DIDKeyResolver) PublicKeyFetcher

func (r *DIDKeyResolver) PublicKeyFetcher() PublicKeyFetcher

PublicKeyFetcher returns Public Key Fetcher via DID resolution mechanism.

type Evidence

type Evidence interface{}

Evidence defines evidence of Verifiable Credential.

type ExpirableSchemaCache

type ExpirableSchemaCache struct {
	// contains filtered or unexported fields
}

ExpirableSchemaCache is an implementation of SchemaCache based fastcache.Cache with expirable elements.

func NewExpirableSchemaCache

func NewExpirableSchemaCache(size int, expiration time.Duration) *ExpirableSchemaCache

NewExpirableSchemaCache creates new instance of ExpirableSchemaCache.

func (*ExpirableSchemaCache) Get

func (sc *ExpirableSchemaCache) Get(k string) ([]byte, bool)

Get element from the cache. If element is present, it checks if the element is expired. If yes, it clears the element from the cache and indicates that the key is not found.

func (*ExpirableSchemaCache) Put

func (sc *ExpirableSchemaCache) Put(k string, v []byte)

Put element to the cache. It also adds a mark of when the element will expire.

type Issuer

type Issuer struct {
	ID string `json:"id,omitempty"`

	CustomFields CustomFields `json:"-"`
}

Issuer of the Verifiable Credential.

func (*Issuer) MarshalJSON

func (i *Issuer) MarshalJSON() ([]byte, error)

MarshalJSON marshals Issuer to JSON.

func (*Issuer) UnmarshalJSON

func (i *Issuer) UnmarshalJSON(bytes []byte) error

UnmarshalJSON unmarshals issuer from JSON.

type JWSAlgorithm

type JWSAlgorithm int

JWSAlgorithm defines JWT signature algorithms of Verifiable Credential.

const (
	// RS256 JWT Algorithm.
	RS256 JWSAlgorithm = iota

	// EdDSA JWT Algorithm.
	EdDSA
)

type JWTCredClaims

type JWTCredClaims struct {
	*jwt.Claims

	VC map[string]interface{} `json:"vc,omitempty"`
}

JWTCredClaims is JWT Claims extension by Verifiable Credential (with custom "vc" claim).

func (*JWTCredClaims) MarshalJWS

func (jcc *JWTCredClaims) MarshalJWS(signatureAlg JWSAlgorithm, signer Signer, keyID string) (string, error)

MarshalJWS serializes JWT into signed form (JWS).

func (*JWTCredClaims) MarshalUnsecuredJWT

func (jcc *JWTCredClaims) MarshalUnsecuredJWT() (string, error)

MarshalUnsecuredJWT serialized JWT into unsecured JWT.

type JWTCredClaimsUnmarshaller

type JWTCredClaimsUnmarshaller func(vcJWTBytes string) (*JWTCredClaims, error)

JWTCredClaimsUnmarshaller unmarshals verifiable credential bytes into JWT claims with extra "vc" claim.

type JWTPresClaims

type JWTPresClaims struct {
	*jwt.Claims

	Presentation *rawPresentation `json:"vp,omitempty"`
}

JWTPresClaims is JWT Claims extension by Verifiable Presentation (with custom "vp" claim).

func (*JWTPresClaims) MarshalJWS

func (jpc *JWTPresClaims) MarshalJWS(signatureAlg JWSAlgorithm, signer Signer, keyID string) (string, error)

MarshalJWS serializes JWT presentation claims into signed form (JWS).

func (*JWTPresClaims) MarshalUnsecuredJWT

func (jpc *JWTPresClaims) MarshalUnsecuredJWT() (string, error)

MarshalUnsecuredJWT serializes JWT presentation claims into unsecured JWT.

type JWTPresClaimsUnmarshaller

type JWTPresClaimsUnmarshaller func(vpJWT string) (*JWTPresClaims, error)

JWTPresClaimsUnmarshaller parses JWT of certain type to JWT Claims containing "vp" (Presentation) claim.

type LinkedDataProofContext

type LinkedDataProofContext struct {
	SignatureType           string                  // required
	Suite                   signer.SignatureSuite   // required
	SignatureRepresentation SignatureRepresentation // required
	Created                 *time.Time              // optional
	VerificationMethod      string                  // optional
	Challenge               string                  // optional
	Domain                  string                  // optional
	Purpose                 string                  // optional
	// CapabilityChain must be an array. Each element is either a string or an object.
	CapabilityChain []interface{}
}

LinkedDataProofContext holds options needed to build a Linked Data Proof.

type MarshalledCredential

type MarshalledCredential []byte

MarshalledCredential defines marshalled Verifiable Credential enclosed into Presentation. MarshalledCredential can be passed to verifiable.ParseCredential().

type Presentation

type Presentation struct {
	Context       []string
	CustomContext []interface{}
	ID            string
	Type          []string

	Holder       string
	Proofs       []Proof
	CustomFields CustomFields
	// contains filtered or unexported fields
}

Presentation Verifiable Presentation base data model definition.

func ParsePresentation

func ParsePresentation(vpData []byte, opts ...PresentationOpt) (*Presentation, error)

ParsePresentation creates an instance of Verifiable Presentation by reading a JSON document from bytes. It also applies miscellaneous options like custom decoders or settings of schema validation.

Example
// A Holder sends to the Verifier a verifiable presentation in JWS form.
vpJWS := "eyJhbGciOiJFZERTQSIsImtpZCI6ImtleS0xIiwidHlwIjoiSldUIn0.eyJpc3MiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJqdGkiOiJ1cm46dXVpZDozOTc4MzQ0Zi04NTk2LTRjM2EtYTk3OC04ZmNhYmEzOTAzYzUiLCJ2cCI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL2V4YW1wbGVzL3YxIl0sInR5cGUiOlsiVmVyaWZpYWJsZVByZXNlbnRhdGlvbiIsIlVuaXZlcnNpdHlEZWdyZWVDcmVkZW50aWFsIl0sInZlcmlmaWFibGVDcmVkZW50aWFsIjpbeyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL2V4YW1wbGVzL3YxIl0sImNyZWRlbnRpYWxTY2hlbWEiOltdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJkZWdyZWUiOnsidHlwZSI6IkJhY2hlbG9yRGVncmVlIiwidW5pdmVyc2l0eSI6Ik1JVCJ9LCJpZCI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsIm5hbWUiOiJKYXlkZW4gRG9lIiwic3BvdXNlIjoiZGlkOmV4YW1wbGU6YzI3NmUxMmVjMjFlYmZlYjFmNzEyZWJjNmYxIn0sImV4cGlyYXRpb25EYXRlIjoiMjAyMC0wMS0wMVQxOToyMzoyNFoiLCJpZCI6Imh0dHA6Ly9leGFtcGxlLmVkdS9jcmVkZW50aWFscy8xODcyIiwiaXNzdWFuY2VEYXRlIjoiMjAxMC0wMS0wMVQxOToyMzoyNFoiLCJpc3N1ZXIiOnsiaWQiOiJkaWQ6ZXhhbXBsZTo3NmUxMmVjNzEyZWJjNmYxYzIyMWViZmViMWYiLCJuYW1lIjoiRXhhbXBsZSBVbml2ZXJzaXR5In0sInJlZmVyZW5jZU51bWJlciI6OC4zMjk0ODQ3ZSswNywidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIlVuaXZlcnNpdHlEZWdyZWVDcmVkZW50aWFsIl19XX19.RlO_1B-7qhQNwo2mmOFUWSa8A6hwaJrtq3q7yJDkKq4k6B-EJ-oyLNM6H_g2_nko2Yg9Im1CiROFm6nK12U_AQ" //nolint:lll

// Holder received and decodes it.
vp, err := verifiable.ParsePresentation(
	[]byte(vpJWS),
	verifiable.WithPresPublicKeyFetcher(verifiable.SingleKey(holderPubKey, kms.ED25519)),
	verifiable.WithPresJSONLDDocumentLoader(getJSONLDDocumentLoader()))
if err != nil {
	panic(fmt.Errorf("failed to decode VP JWS: %w", err))
}

// Marshal the VP to JSON to verify the result of decoding.
vpBytes, err := json.Marshal(vp)
if err != nil {
	panic(fmt.Errorf("failed to marshal VP to JSON: %w", err))
}

fmt.Println(string(vpBytes))
Output:

{"@context":["https://www.w3.org/2018/credentials/v1","https://www.w3.org/2018/credentials/examples/v1"],"holder":"did:example:ebfeb1f712ebc6f1c276e12ec21","id":"urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c5","type":["VerifiablePresentation","UniversityDegreeCredential"],"verifiableCredential":[{"@context":["https://www.w3.org/2018/credentials/v1","https://www.w3.org/2018/credentials/examples/v1"],"credentialSchema":[],"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"]}]}

func ParseUnverifiedPresentation

func ParseUnverifiedPresentation(vpBytes []byte, opts ...PresentationOpt) (*Presentation, error)

ParseUnverifiedPresentation parses Verifiable Presentation from bytes which could be marshalled JSON or serialized JWT. It does not make a proof check though. Can be used for purposes of decoding of VP stored in a wallet. Please use this function with caution.

func (*Presentation) AddLinkedDataProof

func (vp *Presentation) AddLinkedDataProof(context *LinkedDataProofContext, jsonldOpts ...jsonld.ProcessorOpts) error

AddLinkedDataProof appends proof to the Verifiable Presentation.

Example
// 1. ISSUER issues a VC.
vcToIssue := `
{
  "@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"
  ]
}
`

issuedVC, err := verifiable.ParseUnverifiedCredential([]byte(vcToIssue),
	verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()))
if err != nil {
	panic(fmt.Errorf("failed to decode VC JSON: %w", err))
}

issuerSigner := signature.GetEd25519Signer(issuerPrivKey, issuerPubKey)

err = issuedVC.AddLinkedDataProof(&verifiable.LinkedDataProofContext{
	Created:                 &issued,
	SignatureType:           "Ed25519Signature2018",
	Suite:                   ed25519signature2018.New(suite.WithSigner(issuerSigner)),
	SignatureRepresentation: verifiable.SignatureJWS,
	VerificationMethod:      "did:example:123456#key1",
}, jsonld.WithDocumentLoader(getJSONLDDocumentLoader()))
if err != nil {
	panic(fmt.Errorf("failed to add linked data proof: %w", err))
}

issuedVCBytes, err := issuedVC.MarshalJSON()
if err != nil {
	panic(fmt.Errorf("failed to marshal VC to JSON: %w", err))
}

// 2. ISSUER creates a VP with the VC enclosed.
vcFromHolderWallet, err := verifiable.ParseUnverifiedCredential(issuedVCBytes)
if err != nil {
	panic(fmt.Errorf("failed to decode VC JSON: %w", err))
}

vpToVerify, err := vcFromHolderWallet.Presentation()
if err != nil {
	panic(fmt.Errorf("failed to build VP from VC: %w", err))
}

vpToVerify.Holder = "did:example:ebfeb1f712ebc6f1c276e12ec22"
vpToVerify.ID = "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c6"

holderVerifier := signature.GetEd25519Signer(holderPrivKey, holderPubKey)

err = vpToVerify.AddLinkedDataProof(&verifiable.LinkedDataProofContext{
	Created:                 &issued,
	SignatureType:           "Ed25519Signature2018",
	Suite:                   ed25519signature2018.New(suite.WithSigner(holderVerifier)),
	SignatureRepresentation: verifiable.SignatureJWS,
	VerificationMethod:      "did:example:987654#key1",
}, jsonld.WithDocumentLoader(getJSONLDDocumentLoader()))
if err != nil {
	panic(fmt.Errorf("failed to add linked data proof: %w", err))
}

vpJSONWithProof, err := vpToVerify.MarshalJSON()
if err != nil {
	panic(fmt.Errorf("failed to marshal VP to JSON: %w", err))
}

// 3. VERIFIER verifies the presentation.
ed25519Suite := ed25519signature2018.New(suite.WithVerifier(ed25519signature2018.NewPublicKeyVerifier()))

vp, err := verifiable.ParsePresentation(vpJSONWithProof,
	verifiable.WithPresPublicKeyFetcher(func(issuerID, keyID string) (*verifier.PublicKey, error) {
		// both VP and enclosed VC signatures are verified, so we need to provide key resolving for all
		switch issuerID {
		case "did:example:123456": // issuer
			return &verifier.PublicKey{
				Type:  "Ed25519Signature2018",
				Value: issuerPubKey,
			}, nil

		case "did:example:987654":
			return &verifier.PublicKey{
				Type:  "Ed25519Signature2018",
				Value: holderPubKey,
			}, nil
		}

		return nil, errors.New("unsupported issuer")
	}),
	verifiable.WithPresEmbeddedSignatureSuites(ed25519Suite),
	verifiable.WithPresJSONLDDocumentLoader(getJSONLDDocumentLoader()))
if err != nil {
	panic(fmt.Errorf("failed to decode VP JWS: %w", err))
}

vpJSON, err := json.MarshalIndent(vp, "", "\t")
if err != nil {
	panic(fmt.Errorf("failed to marshal VC to JSON: %w", err))
}

fmt.Println(string(vpJSON))
Output:

{
	"@context": [
		"https://www.w3.org/2018/credentials/v1"
	],
	"holder": "did:example:ebfeb1f712ebc6f1c276e12ec22",
	"id": "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c6",
	"proof": {
		"created": "2010-01-01T19:23:24Z",
		"jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..8stDRasAcYjkQiqiczyFJdkff8VJIF3Lbaq5BNTaC-PcvJHGo2Xja8GTsHByTOx7QNCwC3bNiboPgfXtmm8aBA",
		"proofPurpose": "assertionMethod",
		"type": "Ed25519Signature2018",
		"verificationMethod": "did:example:987654#key1"
	},
	"type": "VerifiablePresentation",
	"verifiableCredential": [
		{
			"@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"
			},
			"proof": {
				"created": "2010-01-01T19:23:24Z",
				"jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..mQCxgQDvAYI-2YYCkHHe-at9eNI_wN03R6CRyjycb3CnfPWezbo6zEGe94W2AdYsBhC_Zzedcn_ZKgccMYFnCQ",
				"proofPurpose": "assertionMethod",
				"type": "Ed25519Signature2018",
				"verificationMethod": "did:example:123456#key1"
			},
			"type": [
				"VerifiableCredential",
				"UniversityDegreeCredential"
			]
		}
	]
}

func (*Presentation) Credentials

func (vp *Presentation) Credentials() []interface{}

Credentials returns current credentials of presentation.

func (*Presentation) JWTClaims

func (vp *Presentation) JWTClaims(audience []string, minimizeVP bool) (*JWTPresClaims, error)

JWTClaims converts Verifiable Presentation into JWT Presentation claims, which can be than serialized e.g. into JWS.

Example
package main

import (
	"crypto/ed25519"
	"fmt"

	"github.com/Universal-Health-Chain/aries-framework-go/pkg/doc/util/signature"
	"github.com/Universal-Health-Chain/aries-framework-go/pkg/doc/verifiable"
)

// The keys are generated by ed25519.GenerateKey(rand.Reader)
//
//nolint:gochecknoglobals,lll
var (
	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}
	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}
)

func main() {
	// The Holder kept the presentation serialized to JSON in her personal verifiable credential wallet.
	vpStrFromWallet := `
{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://www.w3.org/2018/credentials/examples/v1"
  ],
  "id": "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c5",
  "type": [
    "VerifiablePresentation",
    "UniversityDegreeCredential"
  ],
  "verifiableCredential": [
    {
      "@context": [
        "https://www.w3.org/2018/credentials/v1",
        "https://www.w3.org/2018/credentials/examples/v1"
      ],
      "credentialSchema": [],
      "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"
      ]
    }
  ],
  "holder": "did:example:ebfeb1f712ebc6f1c276e12ec21"
}
`

	// The Holder wants to send the presentation to the Verifier in JWS.
	vp, err := verifiable.ParseUnverifiedPresentation([]byte(vpStrFromWallet))
	if err != nil {
		panic(fmt.Errorf("failed to decode VP JSON: %w", err))
	}

	aud := []string{"did:example:4a57546973436f6f6c4a4a57573"}

	jwtClaims, err := vp.JWTClaims(aud, true)
	if err != nil {
		panic(fmt.Errorf("failed to create JWT claims of VP: %w", err))
	}

	signer := signature.GetEd25519Signer(holderPrivKey, holderPubKey)

	jws, err := jwtClaims.MarshalJWS(verifiable.EdDSA, signer, "")
	if err != nil {
		panic(fmt.Errorf("failed to sign VP inside JWT: %w", err))
	}

	fmt.Println(jws)

}
Output:

eyJhbGciOiJFZERTQSIsImtpZCI6IiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJkaWQ6ZXhhbXBsZTo0YTU3NTQ2OTczNDM2ZjZmNmM0YTRhNTc1NzMiLCJpc3MiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJqdGkiOiJ1cm46dXVpZDozOTc4MzQ0Zi04NTk2LTRjM2EtYTk3OC04ZmNhYmEzOTAzYzUiLCJ2cCI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL2V4YW1wbGVzL3YxIl0sInR5cGUiOlsiVmVyaWZpYWJsZVByZXNlbnRhdGlvbiIsIlVuaXZlcnNpdHlEZWdyZWVDcmVkZW50aWFsIl0sInZlcmlmaWFibGVDcmVkZW50aWFsIjpbeyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL2V4YW1wbGVzL3YxIl0sImNyZWRlbnRpYWxTY2hlbWEiOltdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJkZWdyZWUiOnsidHlwZSI6IkJhY2hlbG9yRGVncmVlIiwidW5pdmVyc2l0eSI6Ik1JVCJ9LCJpZCI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsIm5hbWUiOiJKYXlkZW4gRG9lIiwic3BvdXNlIjoiZGlkOmV4YW1wbGU6YzI3NmUxMmVjMjFlYmZlYjFmNzEyZWJjNmYxIn0sImV4cGlyYXRpb25EYXRlIjoiMjAyMC0wMS0wMVQxOToyMzoyNFoiLCJpZCI6Imh0dHA6Ly9leGFtcGxlLmVkdS9jcmVkZW50aWFscy8xODcyIiwiaXNzdWFuY2VEYXRlIjoiMjAxMC0wMS0wMVQxOToyMzoyNFoiLCJpc3N1ZXIiOnsiaWQiOiJkaWQ6ZXhhbXBsZTo3NmUxMmVjNzEyZWJjNmYxYzIyMWViZmViMWYiLCJuYW1lIjoiRXhhbXBsZSBVbml2ZXJzaXR5In0sInJlZmVyZW5jZU51bWJlciI6ODMyOTQ4NDcsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJVbml2ZXJzaXR5RGVncmVlQ3JlZGVudGlhbCJdfV19fQ.Rfh63wppLmXFW0nIC1y9aaB9mOJY4D9yQiEcxFVbFjjhjNj6BY9FxzLC67zpl0lwXdIoBeRX_lOhWGOvWo8UAA

func (*Presentation) MarshalJSON

func (vp *Presentation) MarshalJSON() ([]byte, error)

MarshalJSON converts Verifiable Presentation to JSON bytes.

Example
vp := &verifiable.Presentation{
	Context: []string{
		"https://www.w3.org/2018/credentials/v1",
	},
	ID:     "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c",
	Type:   []string{"VerifiablePresentation"},
	Holder: "did:example:ebfeb1f712ebc6f1c276e12ec21",
}

vc := &verifiable.Credential{
	Context: []string{
		"https://www.w3.org/2018/credentials/v1",
		"https://www.w3.org/2018/credentials/examples/v1",
	},
	ID: "http://example.edu/credentials/1872",
	Types: []string{
		"VerifiableCredential",
		"UniversityDegreeCredential",
	},
	Subject: UniversityDegreeSubject{
		ID:     "did:example:ebfeb1f712ebc6f1c276e12ec21",
		Name:   "Jayden Doe",
		Spouse: "did:example:c276e12ec21ebfeb1f712ebc6f1",
		Degree: UniversityDegree{
			Type:       "BachelorDegree",
			University: "MIT",
		},
	},
	Issuer: verifiable.Issuer{
		ID:           "did:example:76e12ec712ebc6f1c221ebfeb1f",
		CustomFields: verifiable.CustomFields{"name": "Example University"},
	},
	Issued:  util.NewTime(issued),
	Expired: util.NewTime(expired),
	Schemas: []verifiable.TypedID{},
	CustomFields: map[string]interface{}{
		"referenceNumber": 83294847,
	},
}

err := vp.SetCredentials(vc)
if err != nil {
	panic(fmt.Errorf("failed to set credentials of VP: %w", err))
}

// json.MarshalIndent() calls Presentation.MarshalJSON()
vpJSON, err := json.MarshalIndent(vp, "", "\t")
if err != nil {
	panic(fmt.Errorf("failed to marshal VP to JSON: %w", err))
}

fmt.Println(string(vpJSON))
Output:

{
	"@context": [
		"https://www.w3.org/2018/credentials/v1"
	],
	"holder": "did:example:ebfeb1f712ebc6f1c276e12ec21",
	"id": "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c",
	"type": "VerifiablePresentation",
	"verifiableCredential": [
		{
			"@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"
			]
		}
	]
}

func (*Presentation) MarshalledCredentials

func (vp *Presentation) MarshalledCredentials() ([]MarshalledCredential, error)

MarshalledCredentials provides marshalled credentials enclosed into Presentation in raw byte array format. They can be used to decode Credentials into struct.

Example
vp := &verifiable.Presentation{
	Context: []string{
		"https://www.w3.org/2018/credentials/v1",
	},
	ID:     "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c",
	Type:   []string{"VerifiablePresentation"},
	Holder: "did:example:ebfeb1f712ebc6f1c276e12ec21",
}

vc := verifiable.Credential{
	Context: []string{
		"https://www.w3.org/2018/credentials/v1",
		"https://www.w3.org/2018/credentials/examples/v1",
	},
	ID: "http://example.edu/credentials/1872",
	Types: []string{
		"VerifiableCredential",
		"UniversityDegreeCredential",
	},
	Subject: UniversityDegreeSubject{
		ID:     "did:example:ebfeb1f712ebc6f1c276e12ec21",
		Name:   "Jayden Doe",
		Spouse: "did:example:c276e12ec21ebfeb1f712ebc6f1",
		Degree: UniversityDegree{
			Type:       "BachelorDegree",
			University: "MIT",
		},
	},
	Issuer: verifiable.Issuer{
		ID:           "did:example:76e12ec712ebc6f1c221ebfeb1f",
		CustomFields: verifiable.CustomFields{"name": "Example University"},
	},
	Issued:  util.NewTime(issued),
	Expired: util.NewTime(expired),
	Schemas: []verifiable.TypedID{},
}

// Put JWS form of VC into VP.
vcJWTClaims, err := vc.JWTClaims(true)
if err != nil {
	panic(fmt.Errorf("failed to set credentials of VP: %w", err))
}

issuerSigner := signature.GetEd25519Signer(issuerPrivKey, issuerPubKey)

vcJWS, err := vcJWTClaims.MarshalJWS(verifiable.EdDSA, issuerSigner, "i-kid")
if err != nil {
	panic(fmt.Errorf("failed to sign VC JWT: %w", err))
}

err = vp.SetCredentials(vcJWS)
if err != nil {
	panic(fmt.Errorf("failed to set credentials of VP: %w", err))
}

// Marshal VP to JWS as well.

vpJWTClaims, err := vp.JWTClaims(nil, true)
if err != nil {
	panic(fmt.Errorf("failed to create JWT claims of VP: %w", err))
}

holderSigner := signature.GetEd25519Signer(holderPrivKey, holderPubKey)

vpJWS, err := vpJWTClaims.MarshalJWS(verifiable.EdDSA, holderSigner, "h-kid")
if err != nil {
	panic(fmt.Errorf("failed to sign VP inside JWT: %w", err))
}

// Decode VP from JWS.
// Note that VC-s inside will be decoded as well. If they are JWS, their signature is verified
// and thus we need to make sure the public key fetcher can retrieve the public key.
vp, err = verifiable.ParsePresentation(
	[]byte(vpJWS),
	verifiable.WithPresPublicKeyFetcher(func(issuerID, keyID string) (*verifier.PublicKey, error) {
		switch issuerID {
		case "did:example:76e12ec712ebc6f1c221ebfeb1f":
			return &verifier.PublicKey{
				Type:  kms.ED25519,
				Value: issuerPubKey,
			}, nil
		case "did:example:ebfeb1f712ebc6f1c276e12ec21":
			return &verifier.PublicKey{
				Type:  kms.ED25519,
				Value: holderPubKey,
			}, nil
		default:
			return nil, fmt.Errorf("unexpected key: %s", keyID)
		}
	}), verifiable.WithPresJSONLDDocumentLoader(getJSONLDDocumentLoader()))
if err != nil {
	panic(fmt.Errorf("failed to decode VP JWS: %w", err))
}

// Get credentials in binary form.
vpCreds, err := vp.MarshalledCredentials()
if err != nil {
	panic(fmt.Errorf("failed to get marshalled credentials from decoded presentation: %w", err))
}

if len(vpCreds) != 1 {
	panic("Expected 1 credential inside presentation")
}

// Decoded credential. Note that no public key fetcher is passed as the VC was already decoded (and proof verified)
// when VP was decoded.
vcDecoded, err := verifiable.ParseCredential(vpCreds[0],
	verifiable.WithJSONLDDocumentLoader(getJSONLDDocumentLoader()))
if err != nil {
	panic(fmt.Errorf("failed to decode VC: %w", err))
}

vcDecodedJSON, err := json.MarshalIndent(vcDecoded, "", "\t")
if err != nil {
	panic(fmt.Errorf("failed to marshal VP to JSON: %w", err))
}

fmt.Println(string(vcDecodedJSON))
Output:

{
	"@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"
	]
}

func (*Presentation) SetCredentials

func (vp *Presentation) SetCredentials(creds ...interface{}) error

SetCredentials defines credentials of presentation. The credential could be string/byte (probably serialized JWT) or Credential structure.

Example
// Holder wants to send 2 credentials to Verifier
vp := &verifiable.Presentation{
	Context: []string{
		"https://www.w3.org/2018/credentials/v1",
	},
	ID:     "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c",
	Type:   []string{"VerifiablePresentation"},
	Holder: "did:example:ebfeb1f712ebc6f1c276e12ec21",
}

// The first VC is created on fly (or just decoded using ParseCredential).
vc := &verifiable.Credential{
	Context: []string{
		"https://www.w3.org/2018/credentials/v1",
		"https://www.w3.org/2018/credentials/examples/v1",
	},
	ID: "http://example.edu/credentials/1872",
	Types: []string{
		"VerifiableCredential",
		"UniversityDegreeCredential",
	},
	Subject: UniversityDegreeSubject{
		ID:     "did:example:ebfeb1f712ebc6f1c276e12ec21",
		Name:   "Jayden Doe",
		Spouse: "did:example:c276e12ec21ebfeb1f712ebc6f1",
		Degree: UniversityDegree{
			Type:       "BachelorDegree",
			University: "MIT",
		},
	},
	Issuer: verifiable.Issuer{
		ID:           "did:example:76e12ec712ebc6f1c221ebfeb1f",
		CustomFields: verifiable.CustomFields{"name": "Example University"},
	},
	Issued:  util.NewTime(issued),
	Expired: util.NewTime(expired),
	Schemas: []verifiable.TypedID{},
	CustomFields: map[string]interface{}{
		"referenceNumber": 83294847,
	},
}

vcStr := `
{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://www.w3.org/2018/credentials/examples/v1"
  ],
  "id": "http://example.edu/credentials/58473",
  "type": ["VerifiableCredential", "AlumniCredential"],
  "issuer": "https://example.edu/issuers/14",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "alumniOf": "Example University"
  },
  "proof": {
    "type": "RsaSignature2018"
  }
}
`

// The second VC is provided in JWS form (e.g. kept in the wallet in that form).
vcJWS := "eyJhbGciOiJFZERTQSIsImtpZCI6IiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1Nzc5MDY2MDQsImlhdCI6MTI2MjM3MzgwNCwiaXNzIjoiZGlkOmV4YW1wbGU6NzZlMTJlYzcxMmViYzZmMWMyMjFlYmZlYjFmIiwianRpIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJuYmYiOjEyNjIzNzM4MDQsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvZXhhbXBsZXMvdjEiXSwiY3JlZGVudGlhbFNjaGVtYSI6W10sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImRlZ3JlZSI6eyJ0eXBlIjoiQmFjaGVsb3JEZWdyZWUiLCJ1bml2ZXJzaXR5IjoiTUlUIn0sImlkIjoiZGlkOmV4YW1wbGU6ZWJmZWIxZjcxMmViYzZmMWMyNzZlMTJlYzIxIiwibmFtZSI6IkpheWRlbiBEb2UiLCJzcG91c2UiOiJkaWQ6ZXhhbXBsZTpjMjc2ZTEyZWMyMWViZmViMWY3MTJlYmM2ZjEifSwiaXNzdWVyIjp7Im5hbWUiOiJFeGFtcGxlIFVuaXZlcnNpdHkifSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIlVuaXZlcnNpdHlEZWdyZWVDcmVkZW50aWFsIl19fQ.AHn2A2q5DL1heX3_izq_2yrsBDhoZ6BGGKhoRvhfMnMUuuOnBOdekdTg-dfUMJgipXRql_6WzBUIj4wTFehXCw" // nolint:lll

err := vp.SetCredentials(vc, vcJWS, vcStr)
if err != nil {
	panic(fmt.Errorf("failed to set credentials of VP: %w", err))
}

vpBytes, err := json.MarshalIndent(vp, "", "\t")
if err != nil {
	panic(err)
}

fmt.Print(string(vpBytes))
Output:

{
	"@context": [
		"https://www.w3.org/2018/credentials/v1"
	],
	"holder": "did:example:ebfeb1f712ebc6f1c276e12ec21",
	"id": "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c",
	"type": "VerifiablePresentation",
	"verifiableCredential": [
		{
			"@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"
			]
		},
		"eyJhbGciOiJFZERTQSIsImtpZCI6IiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1Nzc5MDY2MDQsImlhdCI6MTI2MjM3MzgwNCwiaXNzIjoiZGlkOmV4YW1wbGU6NzZlMTJlYzcxMmViYzZmMWMyMjFlYmZlYjFmIiwianRpIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJuYmYiOjEyNjIzNzM4MDQsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvZXhhbXBsZXMvdjEiXSwiY3JlZGVudGlhbFNjaGVtYSI6W10sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImRlZ3JlZSI6eyJ0eXBlIjoiQmFjaGVsb3JEZWdyZWUiLCJ1bml2ZXJzaXR5IjoiTUlUIn0sImlkIjoiZGlkOmV4YW1wbGU6ZWJmZWIxZjcxMmViYzZmMWMyNzZlMTJlYzIxIiwibmFtZSI6IkpheWRlbiBEb2UiLCJzcG91c2UiOiJkaWQ6ZXhhbXBsZTpjMjc2ZTEyZWMyMWViZmViMWY3MTJlYmM2ZjEifSwiaXNzdWVyIjp7Im5hbWUiOiJFeGFtcGxlIFVuaXZlcnNpdHkifSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIlVuaXZlcnNpdHlEZWdyZWVDcmVkZW50aWFsIl19fQ.AHn2A2q5DL1heX3_izq_2yrsBDhoZ6BGGKhoRvhfMnMUuuOnBOdekdTg-dfUMJgipXRql_6WzBUIj4wTFehXCw",
		{
			"@context": [
				"https://www.w3.org/2018/credentials/v1",
				"https://www.w3.org/2018/credentials/examples/v1"
			],
			"credentialSubject": {
				"alumniOf": "Example University",
				"id": "did:example:ebfeb1f712ebc6f1c276e12ec21"
			},
			"id": "http://example.edu/credentials/58473",
			"issuanceDate": "2010-01-01T19:23:24Z",
			"issuer": "https://example.edu/issuers/14",
			"proof": {
				"type": "RsaSignature2018"
			},
			"type": [
				"VerifiableCredential",
				"AlumniCredential"
			]
		}
	]
}

type PresentationOpt

type PresentationOpt func(opts *presentationOpts)

PresentationOpt is the Verifiable Presentation decoding option.

func WithPresDisabledProofCheck

func WithPresDisabledProofCheck() PresentationOpt

WithPresDisabledProofCheck option for disabling of proof check.

func WithPresEmbeddedSignatureSuites

func WithPresEmbeddedSignatureSuites(suites ...verifier.SignatureSuite) PresentationOpt

WithPresEmbeddedSignatureSuites defines the suites which are used to check embedded linked data proof of VP.

func WithPresJSONLDDocumentLoader

func WithPresJSONLDDocumentLoader(documentLoader ld.DocumentLoader) PresentationOpt

WithPresJSONLDDocumentLoader defines custom JSON-LD document loader. If not defined, when decoding VP a new document loader will be created using CachingJSONLDLoader() if JSON-LD validation is made.

func WithPresPublicKeyFetcher

func WithPresPublicKeyFetcher(fetcher PublicKeyFetcher) PresentationOpt

WithPresPublicKeyFetcher indicates that Verifiable Presentation should be decoded from JWS using the public key fetcher.

func WithPresStrictValidation

func WithPresStrictValidation() PresentationOpt

WithPresStrictValidation enabled strict JSON-LD validation of VP. In case of JSON-LD validation, the comparison of JSON-LD VP document after compaction with original VP one is made. In case of mismatch a validation exception is raised.

type Proof

type Proof map[string]interface{}

Proof defines embedded proof of Verifiable Credential.

type PublicKeyFetcher

type PublicKeyFetcher func(issuerID, keyID string) (*verifier.PublicKey, error)

PublicKeyFetcher fetches public key for JWT signing verification based on Issuer ID (possibly DID) and Key ID. If not defined, JWT encoding is not tested.

func SingleKey

func SingleKey(pubKey []byte, pubKeyType string) PublicKeyFetcher

SingleKey defines the case when only one verification key is used and we don't need to pick the one.

type SchemaCache

type SchemaCache interface {

	// Put element to the cache.
	Put(k string, v []byte)

	// Get element from the cache, returns false at second return value if element is not present.
	Get(k string) ([]byte, bool)
}

SchemaCache defines a cache of credential schemas.

type SignatureRepresentation

type SignatureRepresentation int

SignatureRepresentation is a signature value holder type (e.g. "proofValue" or "jws").

const (
	// SignatureProofValue uses "proofValue" field in a Proof to put/read a digital signature.
	SignatureProofValue SignatureRepresentation = iota

	// SignatureJWS uses "jws" field in a Proof as an element for representation of detached JSON Web Signatures.
	SignatureJWS
)

type Signer

type Signer interface {
	Sign(data []byte) ([]byte, error)
}

Signer defines signer interface which is used to sign VC JWT.

type Subject

type Subject struct {
	ID string `json:"id,omitempty"`

	CustomFields CustomFields `json:"-"`
}

Subject of the Verifiable Credential.

func (*Subject) MarshalJSON

func (s *Subject) MarshalJSON() ([]byte, error)

MarshalJSON marshals Subject to JSON.

func (*Subject) UnmarshalJSON

func (s *Subject) UnmarshalJSON(bytes []byte) error

UnmarshalJSON unmarshals Subject from JSON.

type TypedID

type TypedID struct {
	ID   string `json:"id,omitempty"`
	Type string `json:"type,omitempty"`

	CustomFields `json:"-"`
}

TypedID defines a flexible structure with id and name fields and arbitrary extra fields kept in CustomFields.

func (TypedID) MarshalJSON

func (tid TypedID) MarshalJSON() ([]byte, error)

MarshalJSON defines custom marshalling of TypedID to JSON.

func (*TypedID) UnmarshalJSON

func (tid *TypedID) UnmarshalJSON(data []byte) error

UnmarshalJSON defines custom unmarshalling of TypedID from JSON.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL