Overview

The walt.id verifiable credentials lib offers the use of data functions when creating and issuing W3C Verifiable Credentials.

These functions offer a way to update data present in the credential data structure after it has been build using the CredentialBuilder and before it is signed as JWT or SD-JWT. This is probably not required for most use-cases, however, can be extremely helpful when, for example, building an API. As it is the case with the walt.id issuer API.

Below you find an example of how you can use data functions.

Using Data Functions

First we create a credential using the CredentialBuilder and then we apply the data functions and sign the resulting Verifiable Credential as JWT. A full list of available Data functions can be found here.

import id.walt.credentials.CredentialBuilder
import id.walt.credentials.CredentialBuilderType
import id.walt.crypto.keys.KeyType
import id.walt.crypto.keys.LocalKey
import id.walt.crypto.utils.JsonUtils.toJsonObject
import id.walt.did.dids.DidService
import kotlinx.serialization.json.JsonPrimitive
import kotlin.time.Duration.Companion.days

suspend fun main() {
    DidService.minimalInit() // initialising the local DID registry and resolver

    val myIssuerKey = LocalKey.generate(KeyType.Ed25519)
    val myIssuerDid = DidService.registerByKey("key", myIssuerKey).did

    val mySubjectKey = LocalKey.generate(KeyType.Ed25519)
    val mySubjectDid = DidService.registerByKey("key", mySubjectKey).did


    // Defining the credential
    val credentialBuilder = CredentialBuilder(CredentialBuilderType.W3CV11Creden tialBuilder).apply {
        // Adds context next to default "https://www.w3.org/2018/credentials/v1"
        addContext("https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.2.json")

        // Adds type next to default "VerifiableCredential"
        addType("OpenBadgeCredential")

        credentialId = "urn:uuid:4177e048-9a4a-474e-9dc6-aed4e61a6439"

        issuerDid = myIssuerDid

        // Sets issuance date to current time - 1.5 min
        validFromNow()

        // Adds expiration date
        validFor(2.days)

        subjectDid = mySubjectDid

        // Used to add any custom data
        useData("name", JsonPrimitive("JFF x vc-edu PlugFest 3 Interoperability"))
        useData("test", JsonPrimitive(""))

        // Used to insert credential subject data
        useCredentialSubject(
                mapOf(
                        "type" to listOf("AchievementSubject"),
                        "achievement" to mapOf(
                                "id" to "urn:uuid:ac254bd5-8fad-4bb1-9d29-efd938536926",
                                "type" to listOf("Achievement"),
                                "name" to "JFF x vc-edu PlugFest 3 Interoperability",
                                "description" to "This wallet supports the use of W3C Verifiable Credentials and has demonstrated interoperability during the presentation request workflow during JFF x VC-EDU PlugFest 3.",
                                "criteria" to mapOf(
                                        "type" to "Criteria",
                                        "narrative" to "Wallet solutions providers earned this badge by demonstrating interoperability during the presentation request workflow. This includes successfully receiving a presentation request, allowing the holder to select at least two types of verifiable credentials to create a verifiable presentation, returning the presentation to the requestor, and passing verification of the presentation and the included credentials."
                                ),
                                "image" to mapOf(
                                        "id" to "https://w3c-ccg.github.io/vc-ed/plugfest-3-2023/images/JFF-VC-EDU-PLUGFEST3-badge-image.png",
                                        "type" to "Image"
                                )
                        )
                ).toJsonObject()
        )
    }

    // building the credential
    val credential = credentialBuilder.buildW3C()

    // DATA FUNCTIONS PART

    // using data functions to replace values in the defined credential structure above
    // and signing it as JWT
    val jwt = credential.mergingJwtIssue(
            myIssuerKey, myIssuerDid, mySubjectDid, JsonObject(
            mapOf(
                    "test" to JsonPrimitive("<timestamp-in:2d>") // here the value
                    // of test in the defined credential above
                    // will be replaced with the return 
                    // value of the timestamp-in data function
            )
    ), emptyMap(), emptyMap()
    )

    println(jwt)
}