Skip to main content

Certificates

Overview

X.509 certificates are used to bind a public key to an entity through the signature of a trusted Certificate Authority (CA). This enables wallet holders to know with whom they interact, and lets verifiers know that presented credentials are signed by trusted issuers.

Procivis One supports two certificate-based identifier types: certificate identifiers for credential issuance and verification, and CA identifiers for signing certificates for other entities.

There are four workflows depending on your setup.

GoalWorkflow
Issue or verify credentials with a certificate signed by an external CAImport a certificate
Issur or verify credentials with a certificate signed by a CA internal to the systemCreate a certificate using an internal CA
Use an externally-signed CA to issue certificates to other entitiesImport a CA certificate chain
Create your own root CA without external signingCreate a self-signed root CA

Configuration

See the X.509 Signing Configuration guide.

Check if you can use certificates

Retrieve the configuration through the API and check two things:

  1. Whether certificates are enabled in your system. The identifier object determines the types of identifier available to you:

"identifier": {
"CERTIFICATE": {
"display": "identifier.certificate",
"enabled": true,
"order": 1
},
"CA": {
"display": "identifier.ca",
"enabled": true,
"order": 2
}
},
  1. Whether the credential format you want to work with is compatible with certificates. Formats have capabilities that specify which identifier types are compatible:

"format": {
"EXAMPLE_FORMAT": {
"capabilities": {
"issuanceIdentifierTypes": [
"DID",
"CERTIFICATE" // You can use certificates to issue credentials of this format
],
"verificationIdentifierTypes": [
"DID",
"CERTIFICATE" // You can use certificates to verify credentials of this format
],
},
"display": "format.example",
"type": "EXAMPLE_FORMAT"
}
}

Import a certificate

Certificate identifiers are used for issuing and verifying credentials. This workflow involves creating a key pair, obtaining a signed certificate from an external CA, then importing it as an identifier.

1. Create a key pair

Generate an ECDSA or EDDSA key pair.

Related guide: Create a key pair

2. Create a CSR

CSR operations

Generate a Certificate Signing Request using your key. If you plan on issuing ISO mDL (DocType: org.iso.18013.5.1.mDL), set the profile to MDL to add the necessary extensions. Otherwise, set to GENERIC.

3. Get the CSR signed

Submit your CSR to a Certificate Authority that offers SHA256 signatures. This can be an external CA or a CA identifier you've created in the system. When your request is completed, download the signed certificate in PEM format.

4. Import the signed certificate

Identifier operations

Create a new identifier with type CERTIFICATE. Provide the certificate chain in PEM format and reference the key ID used to create the CSR. If your certificate has no common name (CN), you must provide a name during identifier creation.

Example request body:

{
"name": "My Certificate Identifier",
"organisationId": "{{ORG-UUID}}",
"certificates": [
{
"chain": "-----BEGIN CERTIFICATE-----\nMIIDo.....\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIC6j....\n-----END CERTIFICATE-----\n",
"keyId": "{{KEY-UUID}}",
"name": "Optional certificate name"
}
]
}

The chain field must include the leaf certificate and can optionally include intermediate and root certificates up the chain. The system validates that the certificate is currently valid, that the referenced key matches the certificate's public key, and that the chain is properly signed.

5. Use the certificate identifier

Once imported, use your certificate identifier for credential operations:

  • Issuance: Reference the identifier UUID as the issuer when creating a credential
  • Verification: Reference the identifier UUID as the verifier when creating a proof request

Create a certificate using an internal CA

This workflow uses a CA identifier already in the system to sign your certificate, removing the need for external signing.

1. Create a key pair

Generate an ECDSA or EDDSA key pair.

Related guide: Create a key pair

2. Create a certificate identifier

Identifier operations

Create a new identifier, providing certificate subject details and referencing both the key ID and the CA identifier to sign the certificate.

Example request body:

{
"name": "My Certificate Identifier",
"organisationId": "{{ORG-UUID}}",
"certificates": [
{
"keyId": "{{KEY-UUID}}",
"name": "Optional certificate name",
"content": {
"profile": "GENERIC",
"subject": {
"commonName": "Acme Issuer",
"organization": "Acme Corporation",
"country": "CH"
},
"certificateAuthority": {
"identifierId": "{{CA-IDENTIFIER-UUID}}"
},
"signer": "X509_CERTIFICATE", // Reference a configured instance
"validityStart": "2025-01-01T00:00:00Z",
"validityEnd": "2027-01-01T00:00:00Z"
}
}
]
}

3. Use the certificate identifier

Use your certificate identifier for credential operations:

  • Issuance: Reference the identifier UUID as the issuer when creating a credential
  • Verification: Reference the identifier UUID as the verifier when creating a proof request

Import a CA certificate chain

If you have a CA certificate signed by an external authority, you can import it as a CA identifier.

1. Create a key pair

Generate an ECDSA or EDDSA key pair.

Related guide: Create a key pair

2. Create a CSR

CSR operations

Generate a Certificate Signing Request using the CA profile to include appropriate CA extensions.

3. Get the CSR signed externally

Submit your CSR to an external Certificate Authority. When completed, download the full certificate chain in PEM format.

4. Import the CA chain

Identifier operations

Create a new identifier, providing the full certificate chain where the leaf certificate is your CA certificate.

Example request body:

{
"name": "My CA Identifier",
"organisationId": "{{ORG-UUID}}",
"certificateAuthorities": [
{
"chain": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n",
"keyId": "{{KEY-UUID}}",
"name": "Optional CA name"
}
]
}

The system validates that the leaf certificate is a CA certificate (with CA:TRUE in basic constraints), that it's signed by the specified key, and that the chain is properly signed.

Create a self-signed root CA

To create your own root CA without external signing, you can generate a self-signed CA certificate directly.

1. Create a key pair

Generate an ECDSA or EDDSA key pair.

Related guide: Create a key pair

2. Create the self-signed CA identifier

Identifier operations

Create a new identifier, providing certificate subject details and validity period. The system generates and self-signs the CA certificate.

Example request body:

{
"name": "My Root CA",
"organisationId": "{{ORG-UUID}}",
"certificateAuthorities": [
{
"keyId": "{{KEY-UUID}}",
"name": "Optional CA name",
"selfSigned": {
"content": {
"commonName": "Acme Root CA",
"organization": "Acme Corporation",
"country": "CH"
},
"signer": "X509_CERTIFICATE",
"validityStart": "2025-01-01T00:00:00Z",
"validityEnd": "2035-01-01T00:00:00Z"
}
}
]
}

The system creates a self-signed CA certificate with the specified subject information and validity period.

mdoc CAs

mdoc CAs require an issuer alternative name in the certificate content. Add the issuerAlternativeName object to content with a type of EMAIL or URI and a corresponding name value:

"content": {
"commonName": "Acme mdoc Root CA",
"organization": "Acme Corporation",
"country": "CH",
"issuerAlternativeName": {
"type": "URI",
"name": "https://acme.example.com"
}
}

Ensure the signer value references an X509_CERTIFICATE instance configured for mdoc CA issuance.

Certificate and CA status

Identifier detail

Retrieve the identifier detail and check the state field for status: ACTIVE or DEACTIVATED. Certificates and CAs are active unless none of the certificates are currently valid.

You can run a task (typically a cronjob) using the Core API with the following request body to update certificate status:

{
"name": "CERTIFICATE_CHECK"
}