Skip to main content

๐Ÿค Verification

In this section, you play the role of a Verifier that does the following:

  1. Take a Presentation object supplied by a Claimer
  2. Verify that its data is correct
  3. Verify that the attestation is valid, i.e., its hash exists on-chain and the attestation has not been revoked
  4. Verify that the Claimer sending the Credential owns it
Presentation object

The Claimer uses a Credential to create the Presentation object. Unlike the credential, a Presentation can hide some attributes that are not required by the Verifier and can contain a claimer-signed challenge. A Presentation also contains a proof that the Claimer owns the credential.

Create Presentationโ€‹

A Claimer needs to send more than a credential, as they also need to prove ownership of the credential. A Claimer does this by creating a presentation and signing the Verifier's challenge.

claimer/createPresentation.ts
import * as Kilt from '@kiltprotocol/sdk-js'

export async function createPresentation(
credential: Kilt.ICredential,
signCallback: Kilt.SignCallback,
challenge?: string
): Promise<Kilt.ICredentialPresentation> {
// Create the presentation from credential, DID and challenge.
return Kilt.Credential.createPresentation({
credential,
signCallback,
challenge
})
}

The createPresentation method returns a presentation, taking the credential, a callback to sign data, and the Verifier's challenge as input.

Verifyโ€‹

The verification code exposes the getChallenge method which returns a random and unique challenge for the Claimer to sign. This unique challenge is used to prove ownership.

verify.ts
import { config as envConfig } from 'dotenv'

import * as Kilt from '@kiltprotocol/sdk-js'

import { createPresentation } from './claimer/createPresentation'
import { generateKeypairs } from './claimer/generateKeypairs'
import { generateLightDid } from './claimer/generateLightDid'

function getChallenge(): string {
return Kilt.Utils.UUID.generate()
}

// Verifies validity, ownership & attestation.
async function verifyPresentation(
presentation: Kilt.ICredentialPresentation,
challenge: string,
trustedAttesterUris: Kilt.DidUri[]
): Promise<boolean> {
Kilt.ConfigService.get('api')

try {
const { revoked, attester } = await Kilt.Credential.verifyPresentation(
presentation,
{ challenge }
)

if (revoked) {
return false
}
// Returns true if no trusted attester URI is provided or, if it is, if it matches the one that issued the presented credential.
return trustedAttesterUris.includes(attester)
} catch {
return false
}
}

export async function verificationFlow(
credential: Kilt.ICredential,
signCallback: Kilt.SignCallback,
trustedAttesterUris: Kilt.DidUri[] = []
) {
// Verifier sends a unique challenge to the claimer ๐Ÿ•Š
const challenge = getChallenge()

// Create a presentation and send it to the verifier ๐Ÿ•Š
const presentation = await createPresentation(
credential,
signCallback,
challenge
)

// The verifier checks the presentation.
const isValid = await verifyPresentation(
presentation,
challenge,
trustedAttesterUris
)

if (isValid) {
console.log('Verification successful! You are allowed to enter the club ๐ŸŽ‰')
} else {
console.log('Verification failed! ๐Ÿšซ')
}
}

// Don't execute if this is imported by another file.
if (require.main === module) {
;(async () => {
envConfig()

try {
await Kilt.connect(process.env.WSS_ADDRESS as string)
const claimerDidMnemonic = process.env.CLAIMER_DID_MNEMONIC as string
const { authentication } = generateKeypairs(claimerDidMnemonic)
const claimerDid = generateLightDid(claimerDidMnemonic)
const attesterDid = process.env.ATTESTER_DID_URI as Kilt.DidUri
// Load credential and claimer DID
const credential = JSON.parse(process.env.CLAIMER_CREDENTIAL as string)
await verificationFlow(
credential,
async ({ data }) => ({
signature: authentication.sign(data),
keyType: authentication.type,
keyUri: `${claimerDid.uri}${claimerDid.authentication[0].id}`
}),
[attesterDid]
)
} catch (e) {
console.log('Error in the verification flow')
throw e
}
})()
}

The verifyPresentation method performs the actual verification, taking a presentation and the Claimer's challenge as input.

Runโ€‹

Run the code from the command line:

yarn ts-node verify.ts

That's it! All done :-)