Category: PKI Infrastructure
Complexity: ⭐⭐⭐⭐ (High)
Prerequisites: None (Entry Point)
Estimated Time: 15-30 Minutes
This scenario describes the creation of a self-signed Root CA with Post-Quantum keys. The Root CA forms the Trust Anchor for the entire PKI hierarchy and is the most security-critical element of the infrastructure.
What is created:
Use cases:
┌─────────────────────────────────────────────────────────────────┐
│ ROOT CA CREATION │
└─────────────────────────────────────────────────────────────────┘
┌──────────────┐
│ 1. Init │
│ Library │
└──────┬───────┘
│
▼
┌──────────────┐
│ 2. KeyPair │ ──────► ML-DSA-65 (FIPS 204)
│ generate │ ~4KB Public Key
└──────┬───────┘ ~2KB Private Key
│
▼
┌──────────────┐
│ 3. DN │ ──────► CN=WvdS Root CA
│ create │ O=DATECpro GmbH
└──────┬───────┘ C=DE
│
▼
┌──────────────┐
│ 4. Serial │ ──────► 20 Bytes random (160 bit)
│ generate │
└──────┬───────┘
│
▼
┌──────────────┐
│ 5. Validity │ ──────► notBefore: now
│ set │ notAfter: +20 years
└──────┬───────┘
│
▼
┌──────────────┐
│ 6. Extensions│ ──────► BasicConstraints: CA=true, pathLen=1
│ set │ KeyUsage: keyCertSign, cRLSign
└──────┬───────┘ SKI: SHA-256(publicKey)
│
▼
┌──────────────┐
│ 7. Certificate│ ──────► Subject = Issuer (self-signed)
│ create │ Signature with ML-DSA-65
└──────┬───────┘
│
▼
┌──────────────┐
│ 8. Export │ ──────► root-ca.crt.pem (certificate)
│ PEM │ root-ca.key.pem (encrypted)
└──────┬───────┘
│
▼
┌──────────────┐
│ 9. Cleanup │ ──────► Release handles
│ │ Zeroize secrets
└──────────────┘
| Step | FFI Function | Rust Crate | Description |
|---|---|---|---|
| 1 | wvds_sec_crypto_x509_init() | std::sync | Initialize library |
| 2 | wvds_sec_crypto_x509_keypair_generate_mldsa(65) | ml-dsa | ML-DSA-65 key pair |
| 2a | wvds_sec_crypto_x509_keypair_self_test() | ml-dsa | Self-test (sign/verify) |
| 3a | wvds_sec_crypto_x509_dn_create() | x509-cert | Create DN handle |
| 3b | wvds_sec_crypto_x509_dn_add_component() | x509-cert, der | Add CN, O, C |
| 4 | wvds_sec_crypto_x509_serial_generate() | rand | 160-bit serial number |
| 5 | wvds_sec_crypto_x509_validity_create() | x509-cert | Validity period |
| 6a | wvds_sec_crypto_x509_ext_set_basic_constraints() | x509-cert, der | CA=true, pathLen |
| 6b | wvds_sec_crypto_x509_ext_set_key_usage() | x509-cert, der | keyCertSign, cRLSign |
| 6c | wvds_sec_crypto_x509_ext_set_ski_from_keypair() | sha2 | Subject Key Identifier |
| 7 | wvds_sec_crypto_x509_cert_create_root() | x509-cert, ml-dsa | Create root certificate |
| 8a | wvds_sec_crypto_x509_cert_to_pem() | pem-rfc7468 | Certificate as PEM |
| 8b | wvds_sec_crypto_x509_keypair_to_pem_encrypted() | argon2, aes-gcm | Key encrypted |
| 9a | wvds_sec_crypto_x509_free_*() | std::alloc | Release handles |
| 9b | wvds_sec_crypto_x509_zeroize_keypair() | zeroize | Delete secrets |
wvds_sec_crypto_x509_init()
│
├── wvds_sec_crypto_x509_keypair_generate_mldsa(level: u8) → *mut KeyPairHandle
│ │
│ ├── // Parameter selection
│ │ ├── [ML_DSA_44] → ml_dsa::ml_dsa_44::KeyPair::generate(&mut OsRng)
│ │ ├── [ML_DSA_65] → ml_dsa::ml_dsa_65::KeyPair::generate(&mut OsRng) ✓
│ │ └── [ML_DSA_87] → ml_dsa::ml_dsa_87::KeyPair::generate(&mut OsRng)
│ │
│ ├── // Self-test (FIPS requirement)
│ │ ├── test_msg = [0x00..0x20] // 32 bytes test data
│ │ ├── signature = signing_key.sign(&test_msg)
│ │ └── assert!(verifying_key.verify(&test_msg, &signature).is_ok())
│ │
│ └── // Create handle
│ └── Box::into_raw(Box::new(KeyPairHandle {
│ algorithm: ML_DSA_65,
│ signing_key,
│ verifying_key
│ }))
│
├── wvds_sec_crypto_x509_dn_create() → *mut DnHandle
│ └── x509_cert::name::Name::default()
│
├── wvds_sec_crypto_x509_dn_add_component(dn, oid, value) → i32
│ │
│ ├── [OID_CN = "2.5.4.3"]
│ │ └── dn.0.push(RelativeDistinguishedName::from(
│ │ AttributeTypeAndValue { oid: OID_CN, value: "WvdS Root CA" }
│ │ ))
│ │
│ ├── [OID_O = "2.5.4.10"]
│ │ └── dn.0.push(..., value: "DATECpro GmbH")
│ │
│ └── [OID_C = "2.5.4.6"]
│ └── dn.0.push(..., value: "DE")
│
├── wvds_sec_crypto_x509_serial_generate(out: *mut u8, len: usize) → i32
│ │
│ ├── // RFC 5280: max 20 bytes, positive
│ │ └── rand::rngs::OsRng.fill_bytes(&mut serial[0..len])
│ │
│ └── // Set highest bit to 0 (positive)
│ └── serial[0] &= 0x7F
│
├── wvds_sec_crypto_x509_validity_create(not_before, not_after) → *mut ValidityHandle
│ │
│ ├── not_before = x509_cert::time::Time::UtcTime(now)
│ │
│ └── not_after = x509_cert::time::Time::GeneralizedTime(now + 20 years)
│ │
│ └── // GeneralizedTime for dates >= 2050
│
├── wvds_sec_crypto_x509_ext_set_basic_constraints(ext, ca: bool, path_len: i32) → i32
│ │
│ ├── bc = x509_cert::ext::pkix::BasicConstraints {
│ │ ca: true,
│ │ path_len_constraint: Some(1) // only 1 intermediate level
│ │ }
│ │
│ └── ext.add(Extension {
│ extn_id: OID_BASIC_CONSTRAINTS,
│ critical: true, // MUST be critical for CA
│ extn_value: der::Encode::to_der(&bc)
│ })
│
├── wvds_sec_crypto_x509_ext_set_key_usage(ext, flags: u16) → i32
│ │
│ ├── // For Root CA: keyCertSign (5) + cRLSign (6)
│ │ └── flags = 0x0006 // Bit 5 + Bit 6
│ │
│ ├── ku = x509_cert::ext::pkix::KeyUsage(flags)
│ │
│ └── ext.add(Extension {
│ extn_id: OID_KEY_USAGE,
│ critical: true, // SHOULD be critical
│ extn_value: der::Encode::to_der(&ku)
│ })
│
├── wvds_sec_crypto_x509_ext_set_ski_from_keypair(ext, keypair) → i32
│ │
│ ├── // Subject Key Identifier = SHA-256(SubjectPublicKeyInfo.subjectPublicKey)
│ │ ├── public_key_bytes = keypair.verifying_key.to_bytes()
│ │ └── ski = sha2::Sha256::digest(&public_key_bytes)[0..20]
│ │
│ └── ext.add(Extension {
│ extn_id: OID_SUBJECT_KEY_ID,
│ critical: false,
│ extn_value: der::Encode::to_der(&OctetString::new(ski))
│ })
│
├── wvds_sec_crypto_x509_cert_create_root(
│ keypair: *const KeyPairHandle,
│ subject: *const DnHandle,
│ serial: *const u8,
│ serial_len: usize,
│ validity: *const ValidityHandle,
│ extensions: *const ExtHandle
│ ) → *mut CertHandle
│ │
│ ├── // Build TBSCertificate
│ │ └── tbs = x509_cert::TbsCertificate {
│ │ version: Version::V3,
│ │ serial_number: SerialNumber::new(&serial[..serial_len]),
│ │ signature: AlgorithmIdentifier { oid: OID_ML_DSA_65, parameters: None },
│ │ issuer: subject.clone(), // self-signed: issuer = subject
│ │ validity: validity.clone(),
│ │ subject: subject.clone(),
│ │ subject_public_key_info: keypair.to_spki(),
│ │ extensions: Some(extensions.clone())
│ │ }
│ │
│ ├── // DER-encode TBS certificate
│ │ └── tbs_der = der::Encode::to_der(&tbs)
│ │
│ ├── // Sign with ML-DSA-65
│ │ └── signature = ml_dsa::ml_dsa_65::SigningKey::sign(&tbs_der)
│ │ │
│ │ └── // Deterministic signature (FIPS 204)
│ │ // Signature length: 3293 bytes
│ │
│ └── // Assemble certificate
│ └── cert = x509_cert::Certificate {
│ tbs_certificate: tbs,
│ signature_algorithm: AlgorithmIdentifier { oid: OID_ML_DSA_65 },
│ signature: BitString::from_bytes(&signature)
│ }
│
├── wvds_sec_crypto_x509_cert_to_pem(cert, out, out_len) → i32
│ │
│ ├── cert_der = der::Encode::to_der(&cert)
│ │
│ └── pem_rfc7468::encode_string("CERTIFICATE", &cert_der)
│ │
│ └── // Example output:
│ // -----BEGIN CERTIFICATE-----
│ // MIIxxxxxx...
│ // -----END CERTIFICATE-----
│
├── wvds_sec_crypto_x509_keypair_to_pem_encrypted(
│ keypair, password, kdf_algorithm, out, out_len
│ ) → i32
│ │
│ ├── // Private key as PKCS#8 DER
│ │ └── private_key_der = keypair.signing_key.to_pkcs8_der()
│ │
│ ├── // Generate salt and nonce
│ │ ├── salt = rand::OsRng.gen::<[u8; 16]>()
│ │ └── nonce = rand::OsRng.gen::<[u8; 12]>()
│ │
│ ├── // Derive Key Encryption Key
│ │ └── [ARGON2ID]
│ │ └── argon2::Argon2::new(
│ │ Algorithm::Argon2id,
│ │ Version::V0x13,
│ │ Params::new(65536, 3, 4, Some(32)) // 64MB, 3 iter, 4 lanes
│ │ ).hash_password_into(password.as_bytes(), &salt, &mut kek)
│ │
│ ├── // Encrypt private key
│ │ └── encrypted = aes_gcm::Aes256Gcm::new(&kek)
│ │ .encrypt(&nonce, private_key_der.as_ref())
│ │
│ ├── // Create EncryptedPrivateKeyInfo (PKCS#8)
│ │ └── epki = pkcs8::EncryptedPrivateKeyInfo {
│ │ encryption_algorithm: ...,
│ │ encrypted_data: encrypted
│ │ }
│ │
│ ├── // Encode as PEM
│ │ └── pem_rfc7468::encode_string("ENCRYPTED PRIVATE KEY", &epki_der)
│ │
│ └── // Zeroize KEK
│ └── zeroize::Zeroize::zeroize(&mut kek)
│
└── // Cleanup
│
├── wvds_sec_crypto_x509_free_cert(cert)
├── wvds_sec_crypto_x509_free_keypair(keypair)
│ └── // Automatic zeroize via Drop
├── wvds_sec_crypto_x509_free_dn(dn)
├── wvds_sec_crypto_x509_free_validity(validity)
├── wvds_sec_crypto_x509_free_ext(ext)
└── wvds_sec_crypto_x509_shutdown()
using System; using System.IO; using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ; namespace RootCaExample { class Program { static void Main(string[] args) { // Password for private key (in production: enter securely!) string keyPassword = "MyStr0ng!RootCA#Password2024"; // 1. Initialize context using var context = PqCryptoContext.Initialize(); // 2. Generate ML-DSA-65 key pair Console.WriteLine("Generating ML-DSA-65 key pair..."); using var keyPair = context.GenerateKeyPair(PqAlgorithm.MlDsa65); // Perform self-test if (!keyPair.SelfTest()) throw new CryptographicException("KeyPair self-test failed!"); Console.WriteLine($" Public Key: {keyPair.PublicKeySize} Bytes"); Console.WriteLine($" Private Key: {keyPair.PrivateKeySize} Bytes"); // 3. Create Distinguished Name var subjectDn = new DistinguishedNameBuilder() .AddCommonName("WvdS Root CA") .AddOrganization("DATECpro GmbH") .AddOrganizationalUnit("PQ-Security") .AddCountry("DE") .AddLocality("Munich") .Build(); Console.WriteLine($"Subject DN: {subjectDn}"); // 4. Validity period (20 years for Root CA) var validity = new CertificateValidity( notBefore: DateTime.UtcNow, notAfter: DateTime.UtcNow.AddYears(20) ); // 5. Extensions for Root CA var extensions = new X509ExtensionsBuilder() // BasicConstraints: CA=true, max 1 intermediate level .AddBasicConstraints(isCa: true, pathLengthConstraint: 1, critical: true) // KeyUsage: only certificate and CRL signing .AddKeyUsage( KeyUsageFlags.KeyCertSign | KeyUsageFlags.CrlSign, critical: true ) // Subject Key Identifier for later AKI reference .AddSubjectKeyIdentifier(keyPair) .Build(); // 6. Create root certificate (self-signed) Console.WriteLine("Creating self-signed root certificate..."); using var rootCert = context.CreateRootCertificate( keyPair: keyPair, subject: subjectDn, validity: validity, extensions: extensions ); // 7. Output certificate information Console.WriteLine("\n=== ROOT CA CERTIFICATE ==="); Console.WriteLine($"Subject: {rootCert.Subject}"); Console.WriteLine($"Issuer: {rootCert.Issuer}"); Console.WriteLine($"Serial: {rootCert.SerialNumber}"); Console.WriteLine($"Not Before: {rootCert.NotBefore:yyyy-MM-dd HH:mm:ss} UTC"); Console.WriteLine($"Not After: {rootCert.NotAfter:yyyy-MM-dd HH:mm:ss} UTC"); Console.WriteLine($"Algorithm: {rootCert.SignatureAlgorithm}"); Console.WriteLine($"Thumbprint: {rootCert.Thumbprint}"); Console.WriteLine($"Is CA: {rootCert.IsCertificateAuthority}"); Console.WriteLine($"Path Length: {rootCert.PathLengthConstraint}"); // 8. Save as PEM files string certPath = "root-ca.crt.pem"; string keyPath = "root-ca.key.pem"; // Certificate (public) File.WriteAllText(certPath, rootCert.ExportToPem()); Console.WriteLine($"\nCertificate saved: {certPath}"); // Private key (encrypted with Argon2id) File.WriteAllText(keyPath, keyPair.ExportToEncryptedPem( password: keyPassword, kdfAlgorithm: KeyDerivationAlgorithm.Argon2id )); Console.WriteLine($"Private key saved: {keyPath} (encrypted)"); // 9. Validation: reload certificate and verify Console.WriteLine("\n=== VALIDATION ==="); using var loadedCert = context.LoadCertificateFromPem(File.ReadAllText(certPath)); using var loadedKey = context.LoadKeyPairFromEncryptedPem( File.ReadAllText(keyPath), keyPassword ); // Verify self-signature bool signatureValid = loadedCert.VerifySignature(loadedCert); // self-signed Console.WriteLine($"Self-signature valid: {signatureValid}"); // Verify key pair match bool keyMatch = loadedCert.PublicKeyMatches(loadedKey); Console.WriteLine($"Public key match: {keyMatch}"); Console.WriteLine("\n✓ Root CA successfully created!"); } } }
program CreateRootCA; {$APPTYPE CONSOLE} uses SysUtils, DateUtils, WvdS.PqCrypto.FFI; // FFI unit with declarations const KEY_PASSWORD = 'MyStr0ng!RootCA#Password2024'; var res: Integer; keypair: Pointer; dn: Pointer; validity: Pointer; ext: Pointer; cert: Pointer; serial: array[0..19] of Byte; pem_buf: array[0..65535] of AnsiChar; pem_len: NativeUInt; begin WriteLn('=== WvdS Root CA Creation ==='); WriteLn; // 1. Initialize library res := wvds_sec_crypto_x509_init(); if res <> WVDS_OK then begin WriteLn('ERROR: Init failed (', res, ')'); Exit; end; try // 2. Generate ML-DSA-65 key pair WriteLn('Generating ML-DSA-65 key pair...'); keypair := wvds_sec_crypto_x509_keypair_generate_mldsa(65); if keypair = nil then raise Exception.Create('KeyPair generation failed'); // Self-test res := wvds_sec_crypto_x509_keypair_self_test(keypair); if res <> WVDS_OK then raise Exception.Create('KeyPair self-test failed'); WriteLn(' Self-test: OK'); // 3. Create Distinguished Name WriteLn('Creating Distinguished Name...'); dn := wvds_sec_crypto_x509_dn_create(); if dn = nil then raise Exception.Create('DN creation failed'); wvds_sec_crypto_x509_dn_add_component(dn, PAnsiChar('2.5.4.3'), PAnsiChar('WvdS Root CA')); // CN wvds_sec_crypto_x509_dn_add_component(dn, PAnsiChar('2.5.4.10'), PAnsiChar('DATECpro GmbH')); // O wvds_sec_crypto_x509_dn_add_component(dn, PAnsiChar('2.5.4.11'), PAnsiChar('PQ-Security')); // OU wvds_sec_crypto_x509_dn_add_component(dn, PAnsiChar('2.5.4.6'), PAnsiChar('DE')); // C // 4. Generate serial number (20 bytes = 160 bit) WriteLn('Generating serial number...'); res := wvds_sec_crypto_x509_serial_generate(@serial[0], 20); if res <> WVDS_OK then raise Exception.Create('Serial generation failed'); // 5. Validity: 20 years WriteLn('Setting validity period (20 years)...'); validity := wvds_sec_crypto_x509_validity_create( DateTimeToUnix(Now, False), // not_before: now DateTimeToUnix(IncYear(Now, 20), False) // not_after: +20 years ); if validity = nil then raise Exception.Create('Validity creation failed'); // 6. Create extensions WriteLn('Setting extensions...'); ext := wvds_sec_crypto_x509_ext_create(); if ext = nil then raise Exception.Create('Extension creation failed'); // BasicConstraints: CA=true, pathLen=1 res := wvds_sec_crypto_x509_ext_set_basic_constraints(ext, True, 1); if res <> WVDS_OK then raise Exception.Create('BasicConstraints failed'); // KeyUsage: keyCertSign (Bit 5) + cRLSign (Bit 6) = 0x0006 res := wvds_sec_crypto_x509_ext_set_key_usage(ext, $0006); if res <> WVDS_OK then raise Exception.Create('KeyUsage failed'); // Subject Key Identifier res := wvds_sec_crypto_x509_ext_set_ski_from_keypair(ext, keypair); if res <> WVDS_OK then raise Exception.Create('SKI failed'); // 7. Create root certificate (self-signed) WriteLn('Creating self-signed root certificate...'); cert := wvds_sec_crypto_x509_cert_create_root( keypair, // Key pair dn, // Subject (= Issuer for Root) @serial[0], 20, // Serial number validity, // Validity ext // Extensions ); if cert = nil then raise Exception.Create('Certificate creation failed'); // 8. Save as PEM WriteLn; WriteLn('Saving files...'); // Certificate pem_len := SizeOf(pem_buf); res := wvds_sec_crypto_x509_cert_to_pem(cert, @pem_buf[0], @pem_len); if res <> WVDS_OK then raise Exception.Create('Certificate export failed'); with TFileStream.Create('root-ca.crt.pem', fmCreate) do try Write(pem_buf[0], pem_len); finally Free; end; WriteLn(' root-ca.crt.pem saved'); // Private key (encrypted) pem_len := SizeOf(pem_buf); res := wvds_sec_crypto_x509_keypair_to_pem_encrypted( keypair, PAnsiChar(KEY_PASSWORD), WVDS_KDF_ARGON2ID, @pem_buf[0], @pem_len ); if res <> WVDS_OK then raise Exception.Create('Key export failed'); with TFileStream.Create('root-ca.key.pem', fmCreate) do try Write(pem_buf[0], pem_len); finally Free; end; WriteLn(' root-ca.key.pem saved (encrypted)'); WriteLn; WriteLn('=== Root CA successfully created! ==='); finally // 9. Cleanup if cert <> nil then wvds_sec_crypto_x509_free_cert(cert); if keypair <> nil then wvds_sec_crypto_x509_free_keypair(keypair); if dn <> nil then wvds_sec_crypto_x509_free_dn(dn); if validity <> nil then wvds_sec_crypto_x509_free_validity(validity); if ext <> nil then wvds_sec_crypto_x509_free_ext(ext); wvds_sec_crypto_x509_shutdown(); end; end.
| Parameter | Type | Description | Valid Values |
|---|---|---|---|
level | u8 | ML-DSA Security Level | 44, 65, 87 |
| Level | NIST Security | Public Key | Private Key | Signature |
|---|---|---|---|---|
| 44 | Level 2 (~128-bit) | 1,312 Bytes | 2,560 Bytes | 2,420 Bytes |
| 65 | Level 3 (~192-bit) | 1,952 Bytes | 4,032 Bytes | 3,293 Bytes |
| 87 | Level 5 (~256-bit) | 2,592 Bytes | 4,896 Bytes | 4,595 Bytes |
| Parameter | Type | Description | Example |
|---|---|---|---|
dn | *mut DnHandle | DN handle | – |
oid | *const c_char | OID as string | „2.5.4.3“ |
value | *const c_char | UTF-8 value | „WvdS Root CA“ |
| OID | Constant | Description | Example Value |
|---|---|---|---|
| 2.5.4.3 | OID_CN | Common Name | WvdS Root CA |
| 2.5.4.10 | OID_O | Organization | DATECpro GmbH |
| 2.5.4.11 | OID_OU | Organizational Unit | PQ-Security |
| 2.5.4.6 | OID_C | Country (2 characters) | DE |
| 2.5.4.8 | OID_ST | State/Province | Bavaria |
| 2.5.4.7 | OID_L | Locality | Munich |
| Parameter | Type | Description | Root CA Value |
|---|---|---|---|
ext | *mut ExtHandle | Extension handle | – |
ca | bool | Is CA certificate | true |
path_len | i32 | Max path length (-1 = unlimited) | 1 or 2 |
| Flag | Bit | Value | Description |
|---|---|---|---|
| digitalSignature | 0 | 0x0080 | Digital signatures |
| nonRepudiation | 1 | 0x0040 | Non-repudiation |
| keyEncipherment | 2 | 0x0020 | Key encipherment |
| dataEncipherment | 3 | 0x0010 | Data encipherment |
| keyAgreement | 4 | 0x0008 | Key agreement |
| keyCertSign | 5 | 0x0004 | Certificate signing ✓ |
| cRLSign | 6 | 0x0002 | CRL signing ✓ |
| encipherOnly | 7 | 0x0001 | Encipher only |
For Root CA: flags = 0x0006 (keyCertSign + cRLSign)
| Code | Constant | Meaning |
|---|---|---|
| 0 | WVDS_OK | Success |
| 1 | WVDS_ERROR_INVALID_PARAMETER | Invalid parameter (e.g., level ≠ 44/65/87) |
| 2 | WVDS_ERROR_OUT_OF_MEMORY | Memory allocation failed |
| 3 | WVDS_ERROR_NOT_INITIALIZED | init() not called |
| 200 | WVDS_ERROR_KEY_GENERATION_FAILED | Key generation failed |
| 201 | WVDS_ERROR_SIGNATURE_FAILED | Signing failed |
| 210 | WVDS_ERROR_KEYPAIR_SELF_TEST_FAILED | Self-test failed |
→ Complete list: Error Codes
-----BEGIN CERTIFICATE----- MIIHxjCCBiagAwIBAgIUP7J2kM9x... (Base64-encoded DER) ... -----END CERTIFICATE-----
| Field | Value |
|---|---|
| Version | 3 (0x02) |
| Serial | 20 bytes random |
| Signature Algorithm | ML-DSA-65 (OID: 2.16.840.1.101.3.4.3.18) |
| Issuer | CN=WvdS Root CA, O=DATECpro GmbH, C=DE |
| Subject | CN=WvdS Root CA, O=DATECpro GmbH, C=DE |
| Validity | 20 years |
| Public Key | ML-DSA-65 (~1,952 bytes) |
| Extensions | BasicConstraints, KeyUsage, SKI |
| Signature | ML-DSA-65 (~3,293 bytes) |
-----BEGIN ENCRYPTED PRIVATE KEY----- MIIHbTBXBgkqhkiG9w0BBQ0w... (PKCS#8 EncryptedPrivateKeyInfo) ... -----END ENCRYPTED PRIVATE KEY-----
| Field | Value |
|---|---|
| Format | PKCS#8 EncryptedPrivateKeyInfo |
| KDF | Argon2id (64MB, 3 iterations, 4 lanes) |
| Cipher | AES-256-GCM |
| Key Size | ~4,032 bytes (ML-DSA-65 private key) |
CRITICAL – Root CA Private Key:
The Root CA private key is the most security-critical element of the entire PKI. Compromise means complete loss of trust!
Recommended Protection Measures:
Best Practices:
| Problem | Cause | Solution |
|---|---|---|
KEY_GENERATION_FAILED | Not enough entropy | Check OS random source, /dev/urandom available? |
KEYPAIR_SELF_TEST_FAILED | Defective implementation | Check library version, recompile |
| Certificate invalid | DN empty | Set at least CN |
| Key not readable | Wrong password | Check password, encoding (UTF-8) |
| pathLength error | Value < -1 | -1 for unlimited, 0, 1, 2, … for limit |
NOT_INITIALIZED | init() forgotten | Call wvds_sec_crypto_x509_init() first |
| Memory leak | Handles not released | Call all free_*() functions |
| PEM too large | Buffer too small | Query size first (out_len = 0) |
| Relationship | Scenario | Description |
|---|---|---|
| Next Step | 1.2 Intermediate CA | Sign subordinate CA from Root |
| Then | 1.4 Trust Store | Distribute root certificate |
| Then | 1.6 CRL/OCSP | Set up revocation services |
| Alternative | 11.1 Generate Keys | Keys only, no certificate |
| Related | 11.2 Store Keys | More storage options |
« ← PKI Infrastructure | ▲ Scenarios | 1.2 Intermediate CA → »
Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional