Skip to main content

🆔 Creation of an mDoc

After initializing your DocumentStore and related components, you can proceed to create an mDoc (mobile Document) credential. This section guides you through creating a Document and generating a standards-compliant mDoc credential.

Note: The following code should go into the suspend fun init() in AppContainerImpl.kt (in the core module).

Creating an MdocCredential

An MdocCredential represents a mobile credential, such as a Mobile Driving License (mDL), following the ISO/IEC 18013-5:2021 standard.

1. Prepare Timestamps

Set up the credential's validity period and signing time:

val now = Instant.fromEpochSeconds(Clock.System.now().epochSeconds)
val signedAt = now
val validFrom = now
val validUntil = now + 365.days

Refer to this timestamp code for the complete example.

2. Generate IACA Certificate

The IACA (Issuing Authority Certificate Authority) certificate is required for signing the Document Signing (DS) certificate.

val iacaCert =
X509Cert.fromPem(Res.readBytes("files/iaca_certificate.pem").decodeToString())

These certificate files can be downloaded from the following links. They should be placed inside core/src/commonMain/composeResources/files:

We are embedding IACA certificate into the app right now. In a production environment you'll them load from a server.

You can use multipazctl to generate your own certificates & keys. Refer here for the steps.

3. Generate Document Signing (DS) Certificate

The DS certificate signs the mDoc credential.

val dsKey = Crypto.createEcPrivateKey(EcCurve.P256)
val dsCert = MdocUtil.generateDsCertificate(
iacaKey = AsymmetricKey.X509CertifiedExplicit(
certChain = X509CertChain(certificates = listOf(iacaCert)),
privateKey = dsKey,
),
dsKey = dsKey.publicKey,
subject = X500Name.fromName(name = "CN=Test DS Key"),
serial = ASN1Integer.fromRandom(numBits = 128),
validFrom = validFrom,
validUntil = validUntil
)

Refer to this DS certificate code for the complete example.

4. Creating a Document

A Document represents an individual item created and managed by the DocumentStore. Here we only create a new document only if DocumentStore is empty to prevent proliferation.

Method: Use DocumentStore#createDocument to create a new document.

if (documentStore.listDocuments().isEmpty()) {
val document = documentStore.createDocument(
displayName = CredentialDomains.SAMPLE_DOCUMENT_DISPLAY_NAME,
typeDisplayName = CredentialDomains.SAMPLE_DOCUMENT_TYPE_DISPLAY_NAME,
)
}

Refer to this document creation code for the complete example.

5. Create the mDoc Credential

Finally, use the document and generate certificates to create the mDoc credential.

if (documentStore.listDocuments().isEmpty()) {
// create document

val mdocCredential =
DrivingLicense.getDocumentType().createMdocCredentialWithSampleData(
document = document,
secureArea = secureArea,
createKeySettings = CreateKeySettings(
algorithm = Algorithm.ESP256,
nonce = "Challenge".encodeToByteString(),
userAuthenticationRequired = true
),
dsKey = AsymmetricKey.X509CertifiedExplicit(
certChain = X509CertChain(certificates = listOf(dsCert)),
privateKey = dsKey,
),
signedAt = signedAt,
validFrom = validFrom,
validUntil = validUntil,
domain = CredentialDomains.MDOC_USER_AUTH
)
}

By following these steps, you can securely create and provision an mDoc credential, ready to be managed and used within your application.

Refer to this MdocCredential creation code for the complete example.

Looking for a more realistic flow?

The example above uses helpful defaults for quick onboarding. If you're exploring how to construct credentials manually — including MSO creation, issuer namespaces, and authentication — check out this advanced sample created by a core contributor.