Authentication

Authentication Using Qualified Certificates (QCerts)

Liccium supports the use of Qualified Electronic Seals (QCerts for eSeal) issued by Qualified Trust Service Providers (QTSPs) as a secure and legally valid method of authenticating content declarations. This authentication model aligns with the eIDAS Regulation and ensures a high level of trust, traceability, and legal integrity.

Overview

When using QCerts:

  • The declaring party authenticates declarations using a qualified RSA key pair.
  • The corresponding X.509 certificate chain (x5c) is embedded in the declaration metadata.
  • The declaration is signed using the QCert private key with the RS256 algorithm (RSA + SHA-256).
  • Optionally, the public key may be published via did to enable decentralized validation.

This method is primarily used by legal entities, public institutions, or regulated organisations.

Requirements

To use QCert-based authentication, you must have:

  • A Qualified Certificate for eSeal (issued by a QTSP)
  • Access to the private key for signing declarations
  • The full X.509 certificate chain in PEM or DER format
  • (Optional) A did identifier with a .well-known/did.json for decentralized public key discovery

Signing a Declaration

  1. Generate the ISCC and declaration metadata.
  2. Convert your X.509 certificate into DER format.
  3. Base64-encode the DER data and prepare the x5c header.
  4. Sign the metadata using your QCert private key.
  5. Include the x5c array in the JWT header.

Step-by-Step: Convert Certificate to DER Format

If your certificate is in .cer or .pem format, convert it to .der format:

Code(bash)
openssl x509 -in certificate.cer -outform der -out certificate.der

This converts your certificate to binary DER format, suitable for embedding in JWT headers.

Step-by-Step: Create the x5c Header in Code (Node.js)

Code(javascript)
const fs = require('fs'); const jwt = require('jsonwebtoken'); const certFilePath = './certificate.der'; const derBuffer = fs.readFileSync(certFilePath); const base64Data = derBuffer.toString('base64'); const signature = jwt.sign(metadata, certPrivateKey, { algorithm: 'RS256', header: { x5c: [base64Data] } });
  • metadata is your declaration payload
  • certPrivateKey is your private signing key
  • The base64-encoded DER certificate is embedded in the JWT x5c header

Make sure that the first certificate in the x5c array corresponds to the signing key.

Example JWT Header

Code(json)
{ "x5c": [ "MIID...base64-encoded-cert...", "MIIE...intermediate-cert...", "MIIC...root-cert..." ] }

The certificate at position [0] in the x5c array must match the public key used to sign the declaration.

Public Key Discovery via did (Optional)

Although QCerts can be validated against QTSP trust lists, you may also publish the associated public key in a .well-known/did.json file on your domain.

This is useful when:

  • You want verifiers to validate your declarations without resolving external trust lists.
  • You want to align with the DID ecosystem for self-describing identity.

For QCerts, the .did.json file must use RSA keys that match the QCert public key.

See Setup of .well-known/did.json for a complete guide.

  • The use of QCerts provides legal certainty under eIDAS Article 35.
  • Liccium treats such declarations as high-trust events, and they may be prioritized in registry validation pipelines.
  • The QCert must remain valid at the time of signing. Expired or revoked certificates will result in rejection.
Last modified on