decentralized-identity / did-jwt-vc

Create and verify W3C Verifiable Credentials and Presentations in JWT format

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Question about the Verifiable Presentation

vollit opened this issue · comments

In the example the Issuer signs the Verifiable Presentation, but the Verifiable Credential which is already inside the Verifiable Presentation is already signed by the Issuer. According the W3 Schema, the Verifiable Presentation needs to be signed with the Holder's Private key instead of Issuer.

link: https://www.w3.org/TR/vc-data-model/#concrete-lifecycle-example

What we want to achieve:

  1. We Issue some credentials to a holder named Pat, with the signature from the Issuer.
  2. Pat stores the Verifiable Credentials into his wallet.
  3. Pat want to login into website, makes a Verifiable Presentation from the Verifiable Credentials, with the signature from Pat.
  4. Website verify's the Presentation from Pat, and the Credential from the Issuer.

Is this possible with this package? And if so what are the right steps?

Can we just do this:

import { JwtPresentationPayload, createVerifiablePresentationJwt } from 'did-jwt-vc'
import { JwtCredentialPayload, createVerifiableCredentialJwt } from 'did-jwt-vc'
import { EthrDID } from 'ethr-did'
import { Issuer } from 'did-jwt-vc'

const issuer = new EthrDID({
  identifier: '0xf1232f840f3ad7d23fcdaa84d6c66dac24efb198',
  privateKey: 'd8b595680851765f38ea5405129244ba3cbad84467d190859f4c8b20c1ff6c75'
}) as Issuer

const holder = new EthrDID({
  identifier: '0xf1232f840f3ad7d23fcdaa84d6c66dac24efb198',
  privateKey: 'd8b595680851765f38ea5405129244ba3cbad84467d190859f4c8b20c1ff6c75'
}) as Issuer

const vcPayload: JwtCredentialPayload = {
  sub: 'did:ethr:0x435df3eda57154cf8cf7926079881f2912f54db4',
  nbf: 1562950282,
  vc: {
    '@context': ['https://www.w3.org/2018/credentials/v1'],
    type: ['VerifiableCredential'],
    credentialSubject: {
      degree: {
        type: 'BachelorDegree',
        name: 'Baccalauréat en musiques numériques'
      }
    }
  }
}

const vcJwt = await createVerifiableCredentialJwt(vcPayload, issuer)


const vpPayload: JwtPresentationPayload = {
  vp: {
    '@context': ['https://www.w3.org/2018/credentials/v1'],
    type: ['VerifiablePresentation'],
    verifiableCredential: [vcJwt]
  }
}

const vpJwt = await createVerifiablePresentationJwt(vpPayload, holder)




Yes, the steps you listed are correct. I realize how the example can be confusing, but using different keys for issuer and holder is perfectly fine and can definitely be done with this library.

To verify that you have the proper holder and issuer, you can do something like this:

let vpResult: VerifiedPresentation
try {
  vpResult = await verifyPresentation(vpJwt, resolver)
} catch (e) {
  console.error('could not verify presentation', e)
}

// check that the presentation was signed by the holder DID
console.assert(vpResult.issuer === 'DID of the holder')

// extract the credential from the presentation
const credentialJwt = vpResult?.payload?.vp?.verifiableCredential?.[0]

try {
  vcResult = await verifyCredential(credentialJwt, resolver)
} catch (e) {
  console.error('could not verify credential', e)
}

// check that the credential was signed by the expected issuer DID
console.assert(vcResult.issuer === 'DID of the issuer')

I hope this helps.
Please close this issue if this works for you.


P.S. If you think the readme or other documentation could be improved (we certainly think they could), feel free to contribute a PR ;)

@mirceanis Thanks for your fast reply. Nice this is exactly what I thought. I wil look into the documentation to improve it.