Hide code cell source
import { createWallet } from '@affinidi/wallet-node-sdk'
import { VCV1Type, VPV1 } from '@affinidi/vc-common'
import { uuid } from 'uuidv4';
import { PEX } from '@sphereon/pex'
// @ts-ignore
import platformCryptographyTools from '@affinidi/wallet-node-sdk/dist/PlatformCryptographyTools'
import {W3CVerifiablePresentation} from "@sphereon/ssi-types/src/types/vc";
// @ts-ignore

Presentation Exchange#

We already talk a lot about a Verifiable Presentations and how to share VC with a verifier. Today we descover yet another exchange protocol that actively suported by community nowadays Current Pex v2 introduce a few addinional concepts.

Presentation Definition#

Presentation Definitions are objects that articulate what proofs a Verifier requires. These help the Verifier to decide how or whether to interact with a Holder. Presentation Definitions are composed of inputs, which describe the forms and details of the proofs they require, and optional sets of selection rules, to allow Holders flexibility in cases where many different types of proofs may satisfy an input requirement. If we keep it simple definition is a requirement and query to a user wallet that allow to select VCs needed for verification

Presentation Submission#

Presentation Submissions are objects embedded within VP claim negotiation formats that unify the presentation of proofs to a Verifier in accordance with the requirements a Verifier specified in a Presentation Definition.

We will see in examples and details how presentation definition is corelated with submission part of VP. Submission part contains a id of definition and a descriptors map that help Verifier to navigate to a VC that satisfy concrete input descriptor of presentation definition

Follow a Video#

Hide code cell source
const plantumlEncoder = require('plantuml-encoder')
const tslab = require("tslab");
const encodedTriangle = plantumlEncoder.encode(`
@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml

Boundary(b1,"Presentation exchange") {
Person(holder, "Holder", $sprite="person2")
Person(verifier, "Verifier")
}
Rel(verifier, holder, "1 ask for VCs", "Presentation Definition")
Rel(holder, holder, "2 filter and select VC to share acconding to definition", "VCs", $sprite = "&envelope-closed")
Rel(holder, verifier, "3 issue signed VP", "VP with a submission", $sprite = "&envelope-closed")
Rel(verifier, verifier, "4 verify vp over definition", "VP with submission & definition")


@enduml
`)
 
const urlTriangle = 'http://www.plantuml.com/plantuml/svg/' + encodedTriangle
tslab.display.html(`<img src="${urlTriangle}"/>`)

Flow implementation#

1 Create a Definition#

Definition consist of

  • mandatory unique Id

  • name and purpouse - could be used on UI of wallet to explain expectations and needs

  • list of input descriptors - query and requirements

Input descriptors is most critical part that contains

  • id unique in definition

  • name and purpouse

  • constraints - requirements for a VC fields and values

We could describe a Constraint as a combination of 2 big parts

  • Array of Json pathes that give a flexibility and allow to select fields from a VCs that have different shape. Try to keep json pathes simple and avoid complex queries. JsonPath is a 1:1 mapping of xpath for xml

  • filter - optional but quite poverful way to validate a value of field that was selected by path. is JSONSchema compatible definition pls refer to reference

Lets imagin that we want to get from User VC with his working email. So definition will look like:

const definition = {
            id: uuid(),
            input_descriptors: [
                {
                    id: 'email',
                    name: 'email for login',
                    purpose: 'we want to use you email to login',
                    constraints: {
                        fields: [
                            {
                                path: [
                                    '$.credentialSubject.email',
                                    '$.credentialSubject.data.email',
                                    '$.credentialSubject.workemail',
                                ],
                                purpose: 'auth requirement',
                                filter: {
                                    "type": "string",
                                    "pattern": "^[\\w.%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$"
                                }
                            }
                        ]
                    }
                },
                {
                    id: 'type',
                    name: 'we want to use work email only',
                    purpose: 'authorization of user with work email only',
                    constraints: {
                        fields: [
                            {
                                path: [
                                    '$.credentialSubject.emailType',
                                ],
                                filter: {
                                    type: 'string',
                                    const: 'work'
                                },
                            }
                        ]
                    }
                }
            ]
        }

2 Filtering a VCs in wallet#

Preparation of VCs#

We need a bit of preparation and create our VCs that we could filter. So lets do a simple steps that we do all time in our videos

  • obtain api key via affinidi CLI

  • create a Affinidi Project in VScode extension and define VC schema (optional)

  • create a wallet. I use already predefined seed to speed up a process. it is a test data

  • generate a VCs for user

const API_KEY = '<get your key from affinidi vs code extension or cli>'
const options = {
        env: 'prod' as 'dev' | 'staging' | 'prod',
        accessApiKey : API_KEY
    }
    // @ts-ignore
    const walletFactory = createWallet('AffinityCore')
    const password = 'Test8b60806087f5e7b8eee6607ae8!!'
    const seed = 'a6a6c462b15619273fbf942c99e2b7c1be03ef184f5d1d27a17f29b45c4676dcc5e07ecc835acf1ff1d6f437e95f5cc77ce597d254a7b7db932bbb2698d0804e47cd02c7f02580da2132d008c0e313820964646c7630e01d65925d4b5f8db741'
    const walletHolder  = await walletFactory.openWalletByEncryptedSeed(options, seed, password)
    const createEmailVC = async ({holderId, email, type }: {holderId?: string, email: string, type?: string}) => {

        const jsonSchema = 'https://schema.affinidi.com/VPTestEmailV1-1.json'
        const jsonContext = 'https://schema.affinidi.com/VPTestEmailV1-1.jsonld'
        const unsignedVC = {
            '@context': ['https://www.w3.org/2018/credentials/v1', jsonContext],
            id : `urn:uuid:${uuid()}`,
            type: ['VerifiableCredential', 'VPTestEmail'] as VCV1Type,
            holder: {
            id: holderId || walletHolder.did
            },
            credentialSubject: {
                email,
                emailType: type || 'personal'
            },
            credentialSchema: {
            id:  jsonSchema,
            type: 'JsonSchemaValidator2018',
            },
            issuanceDate: new Date().toISOString(),
        }
        return await walletHolder.signUnsignedCredential(unsignedVC)
    }

    const generateVCs = async () => {
        const emails = [{ email: 'volodymyr.p+dev1@gmail.com', type:'personal'},
            {email: 'randomId', type: 'personal'},
            {email: 'vp@work.com', type: 'work'},
            {email: 'vp2+test@office.com', type: 'work'},
            ]
        return await Promise.all([...emails.map( l =>  createEmailVC(l))])
    }
    const vcs = await generateVCs();
    
vcs[0]
{
  '@context': [
    'https://www.w3.org/2018/credentials/v1',
    'https://schema.affinidi.com/VPTestEmailV1-1.jsonld'
  ],
  id: 'urn:uuid:47bf3837-4e55-4a31-8295-92621273a345',
  type: [ 'VerifiableCredential', 'VPTestEmail' ],
  holder: {
    id: 'did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBek4yTTFaVFV3WTJKaE9HRTNNamRoWkRSbE5XWXdNamc0Tm1VMll6bGxabVk0TWpGaFl6QTJOV1ZtWXpFd1pEZGhPVEkyT1RJME1XTTNZV1kxTUdVek1pSjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TWpNeVpUazVZekl3T1dVd01HSmxOVGM1TldRMFpqUXlNR0psTlRoak1qQm1OREV5Tm1Vd05qZ3hNbVUxTVROalpXWmtOVEprWW1KaU5qazRNekkxTURNaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiRWhKdDlCVEtyV0YyRjdRSGhPNTJuODhtZTdxU3VMOHdJOVdCSGh3UC1BQkVvZzF6R2t3SkJUSkdaNE0wTjZLb1c0U2RGYXRlSnJZTUNhamhNeWtSZlEifQ'
  },
  credentialSubject: { email: 'volodymyr.p+dev1@gmail.com', emailType: 'personal' },
  credentialSchema: {
    id: 'https://schema.affinidi.com/VPTestEmailV1-1.json',
    type: 'JsonSchemaValidator2018'
  },
  issuanceDate: '2023-03-17T10:25:08.237Z',
  issuer: 'did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBek4yTTFaVFV3WTJKaE9HRTNNamRoWkRSbE5XWXdNamc0Tm1VMll6bGxabVk0TWpGaFl6QTJOV1ZtWXpFd1pEZGhPVEkyT1RJME1XTTNZV1kxTUdVek1pSjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TWpNeVpUazVZekl3T1dVd01HSmxOVGM1TldRMFpqUXlNR0psTlRoak1qQm1OREV5Tm1Vd05qZ3hNbVUxTVROalpXWmtOVEprWW1KaU5qazRNekkxTURNaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiRWhKdDlCVEtyV0YyRjdRSGhPNTJuODhtZTdxU3VMOHdJOVdCSGh3UC1BQkVvZzF6R2t3SkJUSkdaNE0wTjZLb1c0U2RGYXRlSnJZTUNhamhNeWtSZlEifQ',
  proof: {
    type: 'EcdsaSecp256k1Signature2019',
    created: '2023-03-17T10:25:08Z',
    verificationMethod: 'did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ#primary',
    proofPurpose: 'assertionMethod',
    jws: 'eyJhbGciOiJFUzI1NksiLCJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdfQ..STVXtzS39fOVF4XnSssDiOn5maeyJp1OM4Qv_dEtkkMhudbNmsTjj7VdUU_ZwvJhkXgkYntO7H41VVjnhdWMlQ'
  }
}

Now on wallet side we a ready to implement filtering and VC selection#

Filtering part

 const pex: PEX = new PEX();
    // Extension VC filter logic
const srMatches = pex.selectFrom(definition, vcs)
JSON.stringify(srMatches, null,1)
{
 "errors": [],
 "matches": [
  {
   "name": "email for login",
   "rule": "all",
   "vc_path": [
    "$.verifiableCredential[0]"
   ]
  },
  {
   "name": "we want to use work email only",
   "rule": "all",
   "vc_path": [
    "$.verifiableCredential[0]"
   ]
  },
  {
   "name": "email for login",
   "rule": "all",
   "vc_path": [
    "$.verifiableCredential[1]"
   ]
  },
  {
   "name": "we want to use work email only",
   "rule": "all",
   "vc_path": [
    "$.verifiableCredential[1]"
   ]
  }
 ],
 "areRequiredCredentialsPresent": "info",
 "verifiableCredential": [
  {
   "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://schema.affinidi.com/VPTestEmailV1-1.jsonld"
   ],
   "id": "urn:uuid:2fcfde66-6a85-4ac8-ba0f-bf0660d10ace",
   "type": [
    "VerifiableCredential",
    "VPTestEmail"
   ],
   "holder": {
    "id": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBek4yTTFaVFV3WTJKaE9HRTNNamRoWkRSbE5XWXdNamc0Tm1VMll6bGxabVk0TWpGaFl6QTJOV1ZtWXpFd1pEZGhPVEkyT1RJME1XTTNZV1kxTUdVek1pSjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TWpNeVpUazVZekl3T1dVd01HSmxOVGM1TldRMFpqUXlNR0psTlRoak1qQm1OREV5Tm1Vd05qZ3hNbVUxTVROalpXWmtOVEprWW1KaU5qazRNekkxTURNaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiRWhKdDlCVEtyV0YyRjdRSGhPNTJuODhtZTdxU3VMOHdJOVdCSGh3UC1BQkVvZzF6R2t3SkJUSkdaNE0wTjZLb1c0U2RGYXRlSnJZTUNhamhNeWtSZlEifQ"
   },
   "credentialSubject": {
    "email": "vp@work.com",
    "emailType": "work"
   },
   "credentialSchema": {
    "id": "https://schema.affinidi.com/VPTestEmailV1-1.json",
    "type": "JsonSchemaValidator2018"
   },
   "issuanceDate": "2023-03-17T10:25:08.294Z",
   "issuer": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBek4yTTFaVFV3WTJKaE9HRTNNamRoWkRSbE5XWXdNamc0Tm1VMll6bGxabVk0TWpGaFl6QTJOV1ZtWXpFd1pEZGhPVEkyT1RJME1XTTNZV1kxTUdVek1pSjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TWpNeVpUazVZekl3T1dVd01HSmxOVGM1TldRMFpqUXlNR0psTlRoak1qQm1OREV5Tm1Vd05qZ3hNbVUxTVROalpXWmtOVEprWW1KaU5qazRNekkxTURNaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiRWhKdDlCVEtyV0YyRjdRSGhPNTJuODhtZTdxU3VMOHdJOVdCSGh3UC1BQkVvZzF6R2t3SkJUSkdaNE0wTjZLb1c0U2RGYXRlSnJZTUNhamhNeWtSZlEifQ",
   "proof": {
    "type": "EcdsaSecp256k1Signature2019",
    "created": "2023-03-17T10:25:08Z",
    "verificationMethod": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ#primary",
    "proofPurpose": "assertionMethod",
    "jws": "eyJhbGciOiJFUzI1NksiLCJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdfQ..ziFqSWNK0oUDrNKAg8eHpSXvQCm7akDBvQ5SYZdB_WltfkiKwsCA7A3yZMEQOtF4XKIDptlhu_Ccp-wu49WBsg"
   }
  },
  {
   "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://schema.affinidi.com/VPTestEmailV1-1.jsonld"
   ],
   "id": "urn:uuid:39a44fe4-2769-480e-9c85-dff79c78770e",
   "type": [
    "VerifiableCredential",
    "VPTestEmail"
   ],
   "holder": {
    "id": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBek4yTTFaVFV3WTJKaE9HRTNNamRoWkRSbE5XWXdNamc0Tm1VMll6bGxabVk0TWpGaFl6QTJOV1ZtWXpFd1pEZGhPVEkyT1RJME1XTTNZV1kxTUdVek1pSjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TWpNeVpUazVZekl3T1dVd01HSmxOVGM1TldRMFpqUXlNR0psTlRoak1qQm1OREV5Tm1Vd05qZ3hNbVUxTVROalpXWmtOVEprWW1KaU5qazRNekkxTURNaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiRWhKdDlCVEtyV0YyRjdRSGhPNTJuODhtZTdxU3VMOHdJOVdCSGh3UC1BQkVvZzF6R2t3SkJUSkdaNE0wTjZLb1c0U2RGYXRlSnJZTUNhamhNeWtSZlEifQ"
   },
   "credentialSubject": {
    "email": "vp2+test@office.com",
    "emailType": "work"
   },
   "credentialSchema": {
    "id": "https://schema.affinidi.com/VPTestEmailV1-1.json",
    "type": "JsonSchemaValidator2018"
   },
   "issuanceDate": "2023-03-17T10:25:08.322Z",
   "issuer": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBek4yTTFaVFV3WTJKaE9HRTNNamRoWkRSbE5XWXdNamc0Tm1VMll6bGxabVk0TWpGaFl6QTJOV1ZtWXpFd1pEZGhPVEkyT1RJME1XTTNZV1kxTUdVek1pSjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TWpNeVpUazVZekl3T1dVd01HSmxOVGM1TldRMFpqUXlNR0psTlRoak1qQm1OREV5Tm1Vd05qZ3hNbVUxTVROalpXWmtOVEprWW1KaU5qazRNekkxTURNaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiRWhKdDlCVEtyV0YyRjdRSGhPNTJuODhtZTdxU3VMOHdJOVdCSGh3UC1BQkVvZzF6R2t3SkJUSkdaNE0wTjZLb1c0U2RGYXRlSnJZTUNhamhNeWtSZlEifQ",
   "proof": {
    "type": "EcdsaSecp256k1Signature2019",
    "created": "2023-03-17T10:25:08Z",
    "verificationMethod": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ#primary",
    "proofPurpose": "assertionMethod",
    "jws": "eyJhbGciOiJFUzI1NksiLCJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdfQ..-H69QkVAVRTeTEBCdBbwabay7I7C2oGtXnkgVCgUDHpcByzC8QZffZa7xWH5ZaDszHSDHmCz5mx0rm-OUaTtgQ"
   }
  }
 ],
 "warnings": []
}

Now Wallet could decide and optionaly show a UI interface that ask user to share all or only selected VCs. Lets share first VC

3 Issue a VP#

Issuence consists of 2 simple steps

  1. preparing a presentation

  2. VPsign

        const presentation  = pex.presentationFrom(definition, [srMatches.verifiableCredential[0]], walletHolder.did);
        presentation.id = `urn:uuid:${uuid()}`

        // Create affinidi signed VP
        const domain = 'affinidi.io'
        const challenge = definition.id
        const affinidiPresentation = JSON.parse(JSON.stringify(presentation))
        affinidiPresentation.holder  = {id: affinidiPresentation.holder }
        const affinidiSignedVP = await walletHolder.signUnsignedPresentation(affinidiPresentation, challenge, domain)
        
JSON.stringify(affinidiSignedVP, null, 1)
{
 "@context": [
  "https://www.w3.org/2018/credentials/v1",
  "https://identity.foundation/presentation-exchange/submission/v1"
 ],
 "type": [
  "VerifiablePresentation",
  "PresentationSubmission"
 ],
 "holder": {
  "id": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBek4yTTFaVFV3WTJKaE9HRTNNamRoWkRSbE5XWXdNamc0Tm1VMll6bGxabVk0TWpGaFl6QTJOV1ZtWXpFd1pEZGhPVEkyT1RJME1XTTNZV1kxTUdVek1pSjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TWpNeVpUazVZekl3T1dVd01HSmxOVGM1TldRMFpqUXlNR0psTlRoak1qQm1OREV5Tm1Vd05qZ3hNbVUxTVROalpXWmtOVEprWW1KaU5qazRNekkxTURNaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiRWhKdDlCVEtyV0YyRjdRSGhPNTJuODhtZTdxU3VMOHdJOVdCSGh3UC1BQkVvZzF6R2t3SkJUSkdaNE0wTjZLb1c0U2RGYXRlSnJZTUNhamhNeWtSZlEifQ"
 },
 "presentation_submission": {
  "id": "pQ4NfGdXr_s_0w-MzZrJJ",
  "definition_id": "93d94bd3-aa6f-49c1-baf0-3870c1571059",
  "descriptor_map": [
   {
    "id": "email",
    "format": "ldp_vc",
    "path": "$.verifiableCredential[0]"
   },
   {
    "id": "type",
    "format": "ldp_vc",
    "path": "$.verifiableCredential[0]"
   }
  ]
 },
 "verifiableCredential": [
  {
   "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://schema.affinidi.com/VPTestEmailV1-1.jsonld"
   ],
   "id": "urn:uuid:2fcfde66-6a85-4ac8-ba0f-bf0660d10ace",
   "type": [
    "VerifiableCredential",
    "VPTestEmail"
   ],
   "holder": {
    "id": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBek4yTTFaVFV3WTJKaE9HRTNNamRoWkRSbE5XWXdNamc0Tm1VMll6bGxabVk0TWpGaFl6QTJOV1ZtWXpFd1pEZGhPVEkyT1RJME1XTTNZV1kxTUdVek1pSjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TWpNeVpUazVZekl3T1dVd01HSmxOVGM1TldRMFpqUXlNR0psTlRoak1qQm1OREV5Tm1Vd05qZ3hNbVUxTVROalpXWmtOVEprWW1KaU5qazRNekkxTURNaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiRWhKdDlCVEtyV0YyRjdRSGhPNTJuODhtZTdxU3VMOHdJOVdCSGh3UC1BQkVvZzF6R2t3SkJUSkdaNE0wTjZLb1c0U2RGYXRlSnJZTUNhamhNeWtSZlEifQ"
   },
   "credentialSubject": {
    "email": "vp@work.com",
    "emailType": "work"
   },
   "credentialSchema": {
    "id": "https://schema.affinidi.com/VPTestEmailV1-1.json",
    "type": "JsonSchemaValidator2018"
   },
   "issuanceDate": "2023-03-17T10:25:08.294Z",
   "issuer": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBek4yTTFaVFV3WTJKaE9HRTNNamRoWkRSbE5XWXdNamc0Tm1VMll6bGxabVk0TWpGaFl6QTJOV1ZtWXpFd1pEZGhPVEkyT1RJME1XTTNZV1kxTUdVek1pSjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TWpNeVpUazVZekl3T1dVd01HSmxOVGM1TldRMFpqUXlNR0psTlRoak1qQm1OREV5Tm1Vd05qZ3hNbVUxTVROalpXWmtOVEprWW1KaU5qazRNekkxTURNaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiRWhKdDlCVEtyV0YyRjdRSGhPNTJuODhtZTdxU3VMOHdJOVdCSGh3UC1BQkVvZzF6R2t3SkJUSkdaNE0wTjZLb1c0U2RGYXRlSnJZTUNhamhNeWtSZlEifQ",
   "proof": {
    "type": "EcdsaSecp256k1Signature2019",
    "created": "2023-03-17T10:25:08Z",
    "verificationMethod": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ#primary",
    "proofPurpose": "assertionMethod",
    "jws": "eyJhbGciOiJFUzI1NksiLCJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdfQ..ziFqSWNK0oUDrNKAg8eHpSXvQCm7akDBvQ5SYZdB_WltfkiKwsCA7A3yZMEQOtF4XKIDptlhu_Ccp-wu49WBsg"
   }
  }
 ],
 "id": "urn:uuid:6d6b6345-8293-408f-a939-399930114f88",
 "proof": {
  "type": "EcdsaSecp256k1Signature2019",
  "created": "2023-03-17T10:25:18Z",
  "verificationMethod": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ#primary",
  "proofPurpose": "authentication",
  "challenge": "93d94bd3-aa6f-49c1-baf0-3870c1571059",
  "domain": "affinidi.io",
  "jws": "eyJhbGciOiJFUzI1NksiLCJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdfQ..6WZAkVAa2J8vPq3bcK-g3i09yrUTdAU9HczvJC4MeCIf6nZPzqszNM1QALpPvRif728QBXgZqe4b2-gb0pdiUQ"
 }
}

4 Verify a VP#

Now we gets back to a verifier and Validate a VP. VP validation is a complex tasks that include few steps

  • check a VP integrity and signature

  • check the challenge part

  • evaluate a VP over presentation definition

  • check the validity and integrity of every VC

For simplisity we will focus on 2 key point that matter for PEX

Evaluate a VP#

const sphereonVP = JSON.parse(JSON.stringify(affinidiSignedVP))
sphereonVP.holder = sphereonVP.holder.id
const result = pex.evaluatePresentation(definition, sphereonVP)
JSON.stringify(result, null,1)
{
 "areRequiredCredentialsPresent": "info",
 "verifiableCredential": [
  {
   "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://schema.affinidi.com/VPTestEmailV1-1.jsonld"
   ],
   "id": "urn:uuid:2fcfde66-6a85-4ac8-ba0f-bf0660d10ace",
   "type": [
    "VerifiableCredential",
    "VPTestEmail"
   ],
   "holder": {
    "id": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBek4yTTFaVFV3WTJKaE9HRTNNamRoWkRSbE5XWXdNamc0Tm1VMll6bGxabVk0TWpGaFl6QTJOV1ZtWXpFd1pEZGhPVEkyT1RJME1XTTNZV1kxTUdVek1pSjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TWpNeVpUazVZekl3T1dVd01HSmxOVGM1TldRMFpqUXlNR0psTlRoak1qQm1OREV5Tm1Vd05qZ3hNbVUxTVROalpXWmtOVEprWW1KaU5qazRNekkxTURNaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiRWhKdDlCVEtyV0YyRjdRSGhPNTJuODhtZTdxU3VMOHdJOVdCSGh3UC1BQkVvZzF6R2t3SkJUSkdaNE0wTjZLb1c0U2RGYXRlSnJZTUNhamhNeWtSZlEifQ"
   },
   "credentialSubject": {
    "email": "vp@work.com",
    "emailType": "work"
   },
   "credentialSchema": {
    "id": "https://schema.affinidi.com/VPTestEmailV1-1.json",
    "type": "JsonSchemaValidator2018"
   },
   "issuanceDate": "2023-03-17T10:25:08.294Z",
   "issuer": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBek4yTTFaVFV3WTJKaE9HRTNNamRoWkRSbE5XWXdNamc0Tm1VMll6bGxabVk0TWpGaFl6QTJOV1ZtWXpFd1pEZGhPVEkyT1RJME1XTTNZV1kxTUdVek1pSjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TWpNeVpUazVZekl3T1dVd01HSmxOVGM1TldRMFpqUXlNR0psTlRoak1qQm1OREV5Tm1Vd05qZ3hNbVUxTVROalpXWmtOVEprWW1KaU5qazRNekkxTURNaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiRWhKdDlCVEtyV0YyRjdRSGhPNTJuODhtZTdxU3VMOHdJOVdCSGh3UC1BQkVvZzF6R2t3SkJUSkdaNE0wTjZLb1c0U2RGYXRlSnJZTUNhamhNeWtSZlEifQ",
   "proof": {
    "type": "EcdsaSecp256k1Signature2019",
    "created": "2023-03-17T10:25:08Z",
    "verificationMethod": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ#primary",
    "proofPurpose": "assertionMethod",
    "jws": "eyJhbGciOiJFUzI1NksiLCJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdfQ..ziFqSWNK0oUDrNKAg8eHpSXvQCm7akDBvQ5SYZdB_WltfkiKwsCA7A3yZMEQOtF4XKIDptlhu_Ccp-wu49WBsg"
   }
  }
 ],
 "warnings": [],
 "errors": [],
 "value": {
  "id": "w2rpt--45agft3AUbaPRn",
  "definition_id": "93d94bd3-aa6f-49c1-baf0-3870c1571059",
  "descriptor_map": [
   {
    "id": "email",
    "format": "ldp_vc",
    "path": "$.verifiableCredential[0]"
   },
   {
    "id": "email",
    "format": "ldp_vc",
    "path": "$.verifiableCredential[2]"
   },
   {
    "id": "email",
    "format": "ldp_vc",
    "path": "$.verifiableCredential[3]"
   },
   {
    "id": "type",
    "format": "ldp_vc",
    "path": "$.verifiableCredential[2]"
   },
   {
    "id": "type",
    "format": "ldp_vc",
    "path": "$.verifiableCredential[3]"
   },
   {
    "id": "email",
    "format": "ldp_vc",
    "path": "$.verifiableCredential[0]"
   },
   {
    "id": "email",
    "format": "ldp_vc",
    "path": "$.verifiableCredential[2]"
   },
   {
    "id": "type",
    "format": "ldp_vc",
    "path": "$.verifiableCredential[2]"
   },
   {
    "id": "email",
    "format": "ldp_vc",
    "path": "$.verifiableCredential[3]"
   },
   {
    "id": "type",
    "format": "ldp_vc",
    "path": "$.verifiableCredential[3]"
   },
   {
    "id": "email",
    "format": "ldp_vc",
    "path": "$.verifiableCredential[0]"
   },
   {
    "id": "email",
    "format": "ldp_vc",
    "path": "$.verifiableCredential[2]"
   },
   {
    "id": "email",
    "format": "ldp_vc",
    "path": "$.verifiableCredential[3]"
   },
   {
    "id": "type",
    "format": "ldp_vc",
    "path": "$.verifiableCredential[2]"
   },
   {
    "id": "type",
    "format": "ldp_vc",
    "path": "$.verifiableCredential[3]"
   },
   {
    "id": "email",
    "path": "$.verifiableCredential[0]"
   },
   {
    "id": "email",
    "path": "$.verifiableCredential[0]"
   },
   {
    "id": "email",
    "path": "$.verifiableCredential[3]"
   },
   {
    "id": "type",
    "path": "$.verifiableCredential[3]"
   },
   {
    "id": "email",
    "format": "ldp_vc",
    "path": "$.verifiableCredential[0]"
   }
  ]
 }
}
const {errors , warnings } = result 
const isEvaluated = errors.length === 0 && warnings.length === 0 
isEvaluated
true

Integrity Check#

const validationResult = await walletHolder.verifyPresentation(affinidiSignedVP as VPV1)
JSON.stringify(validationResult, null,1)
{
 "isValid": true,
 "did": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBek4yTTFaVFV3WTJKaE9HRTNNamRoWkRSbE5XWXdNamc0Tm1VMll6bGxabVk0TWpGaFl6QTJOV1ZtWXpFd1pEZGhPVEkyT1RJME1XTTNZV1kxTUdVek1pSjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TWpNeVpUazVZekl3T1dVd01HSmxOVGM1TldRMFpqUXlNR0psTlRoak1qQm1OREV5Tm1Vd05qZ3hNbVUxTVROalpXWmtOVEprWW1KaU5qazRNekkxTURNaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiRWhKdDlCVEtyV0YyRjdRSGhPNTJuODhtZTdxU3VMOHdJOVdCSGh3UC1BQkVvZzF6R2t3SkJUSkdaNE0wTjZLb1c0U2RGYXRlSnJZTUNhamhNeWtSZlEifQ",
 "challenge": "93d94bd3-aa6f-49c1-baf0-3870c1571059",
 "suppliedPresentation": {
  "@context": [
   "https://www.w3.org/2018/credentials/v1",
   "https://identity.foundation/presentation-exchange/submission/v1"
  ],
  "type": [
   "VerifiablePresentation",
   "PresentationSubmission"
  ],
  "holder": {
   "id": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBek4yTTFaVFV3WTJKaE9HRTNNamRoWkRSbE5XWXdNamc0Tm1VMll6bGxabVk0TWpGaFl6QTJOV1ZtWXpFd1pEZGhPVEkyT1RJME1XTTNZV1kxTUdVek1pSjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TWpNeVpUazVZekl3T1dVd01HSmxOVGM1TldRMFpqUXlNR0psTlRoak1qQm1OREV5Tm1Vd05qZ3hNbVUxTVROalpXWmtOVEprWW1KaU5qazRNekkxTURNaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiRWhKdDlCVEtyV0YyRjdRSGhPNTJuODhtZTdxU3VMOHdJOVdCSGh3UC1BQkVvZzF6R2t3SkJUSkdaNE0wTjZLb1c0U2RGYXRlSnJZTUNhamhNeWtSZlEifQ"
  },
  "presentation_submission": {
   "id": "pQ4NfGdXr_s_0w-MzZrJJ",
   "definition_id": "93d94bd3-aa6f-49c1-baf0-3870c1571059",
   "descriptor_map": [
    {
     "id": "email",
     "format": "ldp_vc",
     "path": "$.verifiableCredential[0]"
    },
    {
     "id": "type",
     "format": "ldp_vc",
     "path": "$.verifiableCredential[0]"
    }
   ]
  },
  "verifiableCredential": [
   {
    "@context": [
     "https://www.w3.org/2018/credentials/v1",
     "https://schema.affinidi.com/VPTestEmailV1-1.jsonld"
    ],
    "id": "urn:uuid:2fcfde66-6a85-4ac8-ba0f-bf0660d10ace",
    "type": [
     "VerifiableCredential",
     "VPTestEmail"
    ],
    "holder": {
     "id": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBek4yTTFaVFV3WTJKaE9HRTNNamRoWkRSbE5XWXdNamc0Tm1VMll6bGxabVk0TWpGaFl6QTJOV1ZtWXpFd1pEZGhPVEkyT1RJME1XTTNZV1kxTUdVek1pSjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TWpNeVpUazVZekl3T1dVd01HSmxOVGM1TldRMFpqUXlNR0psTlRoak1qQm1OREV5Tm1Vd05qZ3hNbVUxTVROalpXWmtOVEprWW1KaU5qazRNekkxTURNaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiRWhKdDlCVEtyV0YyRjdRSGhPNTJuODhtZTdxU3VMOHdJOVdCSGh3UC1BQkVvZzF6R2t3SkJUSkdaNE0wTjZLb1c0U2RGYXRlSnJZTUNhamhNeWtSZlEifQ"
    },
    "credentialSubject": {
     "email": "vp@work.com",
     "emailType": "work"
    },
    "credentialSchema": {
     "id": "https://schema.affinidi.com/VPTestEmailV1-1.json",
     "type": "JsonSchemaValidator2018"
    },
    "issuanceDate": "2023-03-17T10:25:08.294Z",
    "issuer": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBek4yTTFaVFV3WTJKaE9HRTNNamRoWkRSbE5XWXdNamc0Tm1VMll6bGxabVk0TWpGaFl6QTJOV1ZtWXpFd1pEZGhPVEkyT1RJME1XTTNZV1kxTUdVek1pSjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TWpNeVpUazVZekl3T1dVd01HSmxOVGM1TldRMFpqUXlNR0psTlRoak1qQm1OREV5Tm1Vd05qZ3hNbVUxTVROalpXWmtOVEprWW1KaU5qazRNekkxTURNaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiRWhKdDlCVEtyV0YyRjdRSGhPNTJuODhtZTdxU3VMOHdJOVdCSGh3UC1BQkVvZzF6R2t3SkJUSkdaNE0wTjZLb1c0U2RGYXRlSnJZTUNhamhNeWtSZlEifQ",
    "proof": {
     "type": "EcdsaSecp256k1Signature2019",
     "created": "2023-03-17T10:25:08Z",
     "verificationMethod": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ#primary",
     "proofPurpose": "assertionMethod",
     "jws": "eyJhbGciOiJFUzI1NksiLCJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdfQ..ziFqSWNK0oUDrNKAg8eHpSXvQCm7akDBvQ5SYZdB_WltfkiKwsCA7A3yZMEQOtF4XKIDptlhu_Ccp-wu49WBsg"
    }
   }
  ],
  "id": "urn:uuid:6d6b6345-8293-408f-a939-399930114f88",
  "proof": {
   "type": "EcdsaSecp256k1Signature2019",
   "created": "2023-03-17T10:25:18Z",
   "verificationMethod": "did:elem:EiBi2nJp4p8x6dVz8zW635_ccJFn3Y_tIQDIvdxUUmtMgQ#primary",
   "proofPurpose": "authentication",
   "challenge": "93d94bd3-aa6f-49c1-baf0-3870c1571059",
   "domain": "affinidi.io",
   "jws": "eyJhbGciOiJFUzI1NksiLCJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdfQ..6WZAkVAa2J8vPq3bcK-g3i09yrUTdAU9HczvJC4MeCIf6nZPzqszNM1QALpPvRif728QBXgZqe4b2-gb0pdiUQ"
  }
 }
}
isEvaluated && validationResult.isValid
true