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.
| Goal | Workflow |
|---|---|
| Issue or verify credentials with a certificate signed by an external CA | Import a certificate |
| Issur or verify credentials with a certificate signed by a CA internal to the system | Create a certificate using an internal CA |
| Use an externally-signed CA to issue certificates to other entities | Import a CA certificate chain |
| Create your own root CA without external signing | Create 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:
Whether certificates are enabled in your system. The
identifierobject 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
}
},
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
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
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
issuerwhen creating a credential - Verification: Reference the identifier UUID as the
verifierwhen 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
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
issuerwhen creating a credential - Verification: Reference the identifier UUID as the
verifierwhen 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
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
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
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 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
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"
}