Day: February 1, 2026

cyber-posts

CVC example

Example CVC from BSI TR-03110 (Public/Test Patterns)

BSI TR-03110 defines the CVC format precisely for use in ePassports (EAC) and eID systems, but BSI does not publish raw CVC test files directly on their site (they focus on test CSCA X.509 roots and interoperability guidelines). Instead, public test CVCs are widely available in open-source implementations and interoperability test suites that follow TR-03110 exactly.

These test certificates typically use the fictional country code "UT" (Utopia) or "DETEST" to avoid conflicting with production keys. They form short chains: CVCA → DV → Terminal (IS).

Libraries like EJBCA (with CVC plugin), OpenPACE, pycvc (Python), and JMRTD (Java) generate or include compliant test CVCs for developers.

Typical Parsed Test CVCA Example (Self-Signed Root)

Here is a realistic parsed example of a test CVCA CVC (based on common public test patterns from open-source TR-03110 implementations):

  • Profile Identifier (tag 0x5F29): 00 (initial profile)
  • Certificate Authority Reference (CAR) (tag 0x42): UTCVCA00001 (ASCII, identifies the issuer)
  • Public Key (tag 0x7F49): Nested TLV
  • OID: id-TA-ECDSA-SHA-256 (1.0.36.3.3.2.8.1.1.7 for brainpoolP256r1)
  • Domain parameters: BrainpoolP256r1 reference
  • Uncompressed point: 04 || X (32 bytes) || Y (32 bytes) – e.g., a test key point like 04 6B17D1F2... (full hex varies by generated key)
  • Certificate Holder Reference (CHR) (tag 0x5F20): UTCVCA00001 (same as CAR for root/self-signed)
  • Effective Date (tag 0x5F25): 100101 (YYMMDD → 2010-01-01)
  • Expiration Date (tag 0x5F24): 251231 (2025-12-31)
  • Signature (tag 0x5F37): ECDSA-SHA-256 signature (r || s, ~64 bytes)

No CHAT (0x7F4C) or extensions (0x65) in a basic CVCA.

The signed body is the raw concatenation of all TLV objects from 0x5F29 to 0x5F24. This keeps parsing simple on cards (no full ASN.1 parser needed).

Quick Comparison to X.509 (Connecting Dots)

Field/AspectX.509 (ASN.1 DER)CVC (BER-TLV)
Issuer/SubjectFull DN in complex ASN.1Short printable strings (CAR/CHR)
Public KeySubjectPublicKeyInfo with OID0x7F49 with nested OIDs and point
ValidityUTCTime fields in TBSCertificateSimple YYMMDD strings
AuthorizationExtensions (EKU, SAN)Dedicated CHAT (bitmask for roles)
Signed PortionOnly TBSCertificateAll TLVs except signature
SizeOften 500–1000+ bytesTypically 200–400 bytes (card-optimized)

CVC trades flexibility for size and parsing speed – perfect for offline verification on the chip.

Practical Part: Get and Inspect a Real Test CVC

  1. Install a library to generate/view one (10-minute task):
  • Python: pip install pycvc (implements TR-03110 fully).
  • Or clone https://github.com/frankmorgner/openpace and build cvc-print.
  1. Example with pycvc (run this to create a real test CVCA):
   from pycvc.cvc import CVCertificateBuilder, ECCurve
   from ecdsa import SigningKey, NIST256p  # Or Brainpool

   # Simple test self-signed CVCA
   sk = SigningKey.generate(curve=NIST256p)  # Use Brainpool for full TR-03110 compliance
   vk = sk.verifying_key

   builder = CVCertificateBuilder()
   builder.set_car("UTCVCA00001")
   builder.set_chr("UTCVCA00001")
   builder.set_public_key(vk)
   builder.set_effective_date("100101")
   builder.set_expiration_date("251231")

   cvc = builder.build(sk)  # Signs it
   print(cvc.to_der().hex())  # Outputs full hex of the CVC

This gives you a real DER-encoded CVC in hex. Dump it to file: with open('test_cvca.cvc', 'wb') as f: f.write(cvc.to_der())

  1. Simple TLV parser to inspect any CVC hex (extend for nested public key):
   def parse_simple_tlv(data: bytes):
       pos = 0
       fields = {}
       while pos < len(data):
           tag = data[pos]
           pos += 1
           len_byte = data[pos]
           pos += 1
           if len_byte & 0x80:  # Long form (rare in CVC)
               continue  # Skip for simplicity
           length = len_byte
           value = data[pos:pos + length]
           pos += length
           if tag == 0x42:
               fields['CAR'] = value.decode('ascii')
           elif tag == 0x5F20:
               fields['CHR'] = value.decode('ascii')
           elif tag == 0x5F25:
               fields['Effective'] = value.decode('ascii')
           elif tag == 0x5F24:
               fields['Expiration'] = value.decode('ascii')
           # Add 0x7F49 handling recursively for pubkey
       return fields

   # Use with your generated hex
   hex_cvc = "your_hex_here_without_spaces"
   print(parse_simple_tlv(bytes.fromhex(hex_cvc)))

Run the builder → get real hex → parse it. You'll see the exact fields match the example above.

This connects directly to signature verification: next time, we can add ECDSA verify on the body bytes using the public point from 0x7F49.

Spend your 10 minutes generating one with pycvc – it's the fastest way to have a real TR-03110-compliant CVC on your machine.

cyber-posts

Signatures Certificates

Digital Signatures in Certificates and Credentials: X.509 vs. CVC

Digital signatures are the core mechanism that makes certificates trustworthy in identity and credential systems. They ensure authenticity (the certificate really comes from the claimed issuer), integrity (the content hasn’t been tampered with), and non-repudiation (the issuer can’t deny having issued it).

How a Digital Signature Works (General Principle)

  1. The issuer creates the certificate data (subject identity, public key, validity dates, authorizations, etc.).
  2. This data (or a specific “to-be-signed” portion) is hashed using a cryptographic hash function (e.g., SHA-256 or SHA-3).
  3. The hash is encrypted with the issuer’s private key → this encrypted hash is the signature.
  4. The signature is attached to the certificate.
  5. To verify:
  • Compute the hash of the received certificate data.
  • Decrypt the signature using the issuer’s public key.
  • Compare the two hashes. If they match → valid signature.

This is the same fundamental process for both X.509 and CVC, but the structure, encoding, and use cases differ.

X.509 Certificates

  • Standard: ITU-T X.509 (most widely used public key certificate format).
  • Use cases in your domain: TLS/SSL server certificates, client certificates, code signing, S/MIME email, enterprise PKI for user authentication, many verifiable credential systems (when using traditional PKI).
  • Structure relevant to signatures:
  • Three main parts:
    1. TBSCertificate (To Be Signed Certificate) – contains version, serial number, issuer, subject, public key, validity, extensions, etc.
    2. signatureAlgorithm – identifies the algorithm (e.g., sha256WithRSAEncryption, ecdsa-with-SHA256).
    3. signatureValue – the actual signature bits (the encrypted hash of the TBSCertificate).
  • Encoding: ASN.1 DER (strict binary encoding).
  • Signature process:
  • Hash only the TBSCertificate (not the signature fields).
  • Sign with issuer’s private key.
  • Common algorithms: RSA-PKCS#1 v1.5, RSA-PSS, ECDSA (with NIST or Brainpool curves).
  • Libraries you’ll use: OpenSSL, Bouncy Castle, Java’s java.security.cert, Python’s cryptography or pyOpenSSL.

Card Verifiable Certificates (CVC)

  • Standard: Defined in ISO/IEC 7816-8 and BSI TR-03110 (German Federal Office for Information Security).
  • Use cases in your domain: Smart card-based identity systems, especially European eID cards, ePassports (EAC – Extended Access Control), government-issued credentials where the card itself performs verification (offline, constrained environment).
  • Key differences from X.509:
  • Designed for resource-constrained devices (smart cards).
  • Focus on role-based authorization rather than general identity.
  • Shorter chain length, often self-described references (CAR = Certificate Authority Reference, CHR = Certificate Holder Reference).
  • Structure relevant to signatures:
  • TLV (Tag-Length-Value) encoding (BER-TLV, more flexible than DER).
  • Profile Identifier, CAR, Public Key, CHR, Certificate Holder Authorization Template (CHAT – defines roles/permissions), validity dates, optional extensions, and outer signature.
  • No separate TBSCertificate block – the signature is over the entire certificate body (all fields except the signature itself).
  • Signature process:
  • Concatenate the body fields in defined order.
  • Hash and sign with issuer’s private key (almost always ECDSA for performance on cards).
  • Common curves: BrainpoolP256r1, BrainpoolP384r1, or NIST P-256.
  • Chain: Starts from a root CVCA (often linked to an X.509 CSCA), then DV (Document Verifier) certificates, then terminal/IS certificates – all in CVC format after the root.
  • Libraries/tools: Less common than X.509. Often BSI libraries, OpenSC, or custom implementations in JavaCard/GlobalPlatform environments.

Quick Comparison Table

AspectX.509CVC (Card Verifiable Certificate)
Primary UseGeneral PKI, web, enterpriseSmart cards, eID, ePassport EAC
EncodingASN.1 DER (strict)BER-TLV (flexible)
Signed DataTBSCertificate onlyEntire body except signature
Typical AlgorithmsRSA or ECDSAAlmost always ECDSA (card-friendly)
Authorization ModelExtensions (e.g., SAN, EKU)CHAT field (role-based, bitmask)
Chain LengthCan be longUsually very short (1–3 levels)
Verification LocationAnywhere (online/offline)Often on the card itself (offline)
Standard BodiesITU-T, IETF (RFC 5280)ISO/IEC 7816, BSI TR-03110

Why This Matters for Your Job

  • In identity/credential systems, you’ll often need to issue, verify, or chain both types.
  • Modern systems sometimes bridge them: an X.509 CSCA root signs a CVC chain for ePassport access control.
  • When implementing verification services, remember that CVC requires stricter parsing of TLV structures and specific OID handling.
  • Performance tip: ECDSA verification is much faster than RSA on constrained devices → prefer ECDSA when designing new credential formats.

Spend your 10 minutes today mentally walking through a verification flow: take a real client certificate (X.509) in your browser, view it, and trace the signature fields. Then look up a BSI TR-03110 example CVC (public test data exists) and compare the structure.

Next time you ask about a related topic (e.g., specific algorithms, revocation, or verifiable credentials with JSON-LD signatures), I’ll connect it back to this foundation.