This module covers the creation of a CNSA 2.0 compliant Root Certificate Authority with a 10-year validity period using quantum-resistant algorithms. Type each command directly to understand the process. Try to only copy the larger blocks that denote line breaks with \ .
Switch to the CA admin user and navigate to the root CA directory:
sudo su - caadmin
cd /opt/sassycorp-ca/root-caCreate the required subdirectories:
mkdir -p private certs crl newcerts csrSet restrictive permissions on the private key directory:
chmod 700 privateSet appropriate permissions on other directories:
chmod 755 certs crl newcerts csrCreate the database files:
touch index.txt
echo 1000 > serial
echo 1000 > crlnumberSet file permissions:
chmod 644 index.txt serial crlnumberVerify your directory structure:
ls -laCreate the OpenSSL configuration file for the Root CA. Use your preferred text editor:
vim /opt/sassycorp-ca/root-ca/openssl.cnfCopy the following configuration into the file:
# OpenSSL Root CA Configuration - CNSA 2.0 Compliant
# Organization: SassyCorp
# Enable OQS Provider for quantum-resistant algorithms
openssl_conf = openssl_init
[openssl_init]
providers = provider_sect
[provider_sect]
default = default_sect
oqsprovider = oqsprovider_sect
[default_sect]
activate = 1
[oqsprovider_sect]
activate = 1
####################################################################
[ ca ]
default_ca = CA_default
[ CA_default ]
# Directory and file locations
dir = /opt/sassycorp-ca/root-ca
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand
# Root CA certificate and key
private_key = $dir/private/root-ca.key
certificate = $dir/certs/root-ca.crt
# Certificate revocation list
crlnumber = $dir/crlnumber
crl = $dir/crl/root-ca.crl
crl_extensions = crl_ext
default_crl_days = 30
# SHA-512 for CNSA 2.0 compliance
default_md = sha512
name_opt = ca_default
cert_opt = ca_default
default_days = 3650
preserve = no
policy = policy_strict
[ policy_strict ]
# Root CA should only sign intermediate CA certificates
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_loose ]
# Allow intermediate CA to sign a wider range of certificates
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
####################################################################
[ req ]
# Options for certificate requests
default_bits = 4096
distinguished_name = req_distinguished_name
string_mask = utf8only
default_md = sha512
# Extension to add when the -x509 option is used
x509_extensions = v3_ca
# Quantum-resistant signature algorithm
# Using ML-DSA-87 (mldsa87) for CNSA 2.0 compliance
default_sigalg = mldsa87
[ req_distinguished_name ]
# Prompts for distinguished name
countryName = Country Name (2 letter code)
countryName_default = US
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name
stateOrProvinceName_default = Washington
localityName = Locality Name
localityName_default = Glacier
0.organizationName = Organization Name
0.organizationName_default = SassyCorp
organizationalUnitName = Organizational Unit Name
organizationalUnitName_default = IT Security Division
commonName = Common Name
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
emailAddress_default = ca-admin@sassycorp.internal
[ v3_ca ]
# Extensions for a typical CA
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:TRUE
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
subjectAltName = @alt_names_ca
issuerAltName = @alt_names_ca
[ alt_names_ca ]
DNS.1 = ca.sassycorp.lab
DNS.2 = root-ca.sassycorp.lab
email = ca-admin@sassycorp.internal
URI = https://ca.sassycorp.lab
[ v3_intermediate_ca ]
# Extensions for intermediate CA certificates
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:TRUE, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
crlDistributionPoints = @crl_section
authorityInfoAccess = @ocsp_section
subjectAltName = @alt_names_intermediate
[ alt_names_intermediate ]
DNS.1 = intermediate-ca.sassycorp.lab
DNS.2 = ca.sassycorp.lab
email = intermediate-ca@sassycorp.internal
URI = https://intermediate-ca.sassycorp.lab
[ crl_section ]
URI.0 = http://crl.sassycorp.lab/root-ca.crl
URI.1 = http://ca.sassycorp.lab/crl/root-ca.crl
[ ocsp_section ]
caIssuers;URI.0 = http://ca.sassycorp.lab/certs/root-ca.crt
OCSP;URI.0 = http://ocsp.sassycorp.lab/
[ crl_ext ]
# Extension for CRLs
authorityKeyIdentifier=keyid:always
[ ocsp ]
# Extension for OCSP signing certificates
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigningSave the file and set appropriate permissions:
chmod 644 /opt/sassycorp-ca/root-ca/openssl.cnfNavigate to the Root CA directory:
cd /opt/sassycorp-ca/root-caGenerate an ML-DSA-87 (mldsa87) private key for highest CNSA 2.0 security level:
openssl genpkey \
-provider oqsprovider \
-provider default \
-algorithm mldsa87 \
-out private/root-ca.keyNote: We use ML-DSA-87 (mldsa87) for the Root CA as it provides the highest security level in CNSA 2.0.
Set restrictive permissions on the private key:
chmod 400 private/root-ca.keyVerify the key was created:
ls -la private/root-ca.keyCreate the Root CA certificate with 10-year validity (3650 days):
openssl req -config openssl.cnf \
-provider oqsprovider \
-provider default \
-key private/root-ca.key \
-new -x509 \
-sha512 \
-extensions v3_ca \
-days 3650 \
-out certs/root-ca.crt \
-subj "/C=US/ST=Washington/L=Glacier/O=SassyCorp/OU=IT Security Division/CN=SassyCorp Root CA/emailAddress=ca-admin@sassycorp.internal"Set appropriate permissions:
chmod 444 certs/root-ca.crtVerify the Root CA certificate:
openssl x509 -provider oqsprovider -provider default -noout -text -in certs/root-ca.crtCheck the signature algorithm (should show mldsa87 for ML-DSA-87):
openssl x509 -in certs/root-ca.crt -provider oqsprovider -provider default -noout -text | grep "Signature Algorithm"Expected Output: You should see mldsa87 which is ML-DSA-87 in CNSA 2.0.
Check certificate validity (should be 10 years):
openssl x509 -in certs/root-ca.crt -noout -datesCheck key usage:
openssl x509 -in certs/root-ca.crt -noout -text | grep -A1 "Key Usage"Check Subject Alternative Names:
openssl x509 -in certs/root-ca.crt -provider oqsprovider -provider default -noout -text | grep -A5 "Subject Alternative Name"Verify certificate hash with SHA-512:
openssl x509 -in certs/root-ca.crt -noout -fingerprint -sha512Generate an initial empty CRL:
openssl ca -config openssl.cnf \
-provider oqsprovider \
-provider default \
-gencrl \
-out crl/root-ca.crlSet appropriate permissions:
chmod 644 crl/root-ca.crlVerify the CRL:
openssl crl -in crl/root-ca.crl -provider oqsprovider -provider default -noout -textCreate a PEM bundle for distribution:
cat certs/root-ca.crt > certs/root-ca-bundle.pem
chmod 444 certs/root-ca-bundle.pemCreate DER format for Windows compatibility:
openssl x509 -in certs/root-ca.crt -outform DER -out certs/root-ca.der
chmod 444 certs/root-ca.derCreate a certificate fingerprints file:
echo "Root CA Certificate Fingerprints" > certs/root-ca-fingerprints.txt
echo "=================================" >> certs/root-ca-fingerprints.txt
echo "" >> certs/root-ca-fingerprints.txt
echo "SHA256:" >> certs/root-ca-fingerprints.txt
openssl x509 -in certs/root-ca.crt -noout -fingerprint -sha256 >> certs/root-ca-fingerprints.txt
echo "" >> certs/root-ca-fingerprints.txt
echo "SHA512:" >> certs/root-ca-fingerprints.txt
openssl x509 -in certs/root-ca.crt -noout -fingerprint -sha512 >> certs/root-ca-fingerprints.txt
chmod 444 certs/root-ca-fingerprints.txtDisplay the fingerprints:
cat certs/root-ca-fingerprints.txtCreate backup directory:
mkdir -p /opt/sassycorp-ca/backups/root-ca-$(date +%Y%m%d)Create a backup archive:
tar -czf /opt/sassycorp-ca/backups/root-ca-$(date +%Y%m%d)/root-ca-backup.tar.gz \
--exclude='newcerts/*' \
-C /opt/sassycorp-ca/root-ca \
private certs crl index.txt serial crlnumber openssl.cnfSet restrictive permissions on the backup:
chmod 600 /opt/sassycorp-ca/backups/root-ca-$(date +%Y%m%d)/root-ca-backup.tar.gzGenerate backup verification hash:
sha512sum /opt/sassycorp-ca/backups/root-ca-$(date +%Y%m%d)/root-ca-backup.tar.gz > \
/opt/sassycorp-ca/backups/root-ca-$(date +%Y%m%d)/root-ca-backup.sha512Verify the backup was created:
ls -la /opt/sassycorp-ca/backups/root-ca-$(date +%Y%m%d)/Run these commands to perform a complete verification of your Root CA:
Display certificate details:
openssl x509 -in /opt/sassycorp-ca/root-ca/certs/root-ca.crt -provider oqsprovider -provider default -noout -subject -issuer -datesVerify signature algorithm is ML-DSA-87 (mldsa87) for CNSA 2.0:
openssl x509 -in /opt/sassycorp-ca/root-ca/certs/root-ca.crt -provider oqsprovider -provider default -noout -text | grep "Signature Algorithm" | head -1Expected Output: Should show mldsa87 confirming ML-DSA-87 CNSA 2.0 compliance.
Display key usage:
openssl x509 -in /opt/sassycorp-ca/root-ca/certs/root-ca.crt -provider oqsprovider -provider default -noout -text | grep -A2 "Key Usage"Display Subject Alternative Names:
openssl x509 -in /opt/sassycorp-ca/root-ca/certs/root-ca.crt -provider oqsprovider -provider default -noout -text | grep -A5 "Subject Alternative Name"Check file permissions:
ls -la /opt/sassycorp-ca/root-ca/private/root-ca.key
ls -la /opt/sassycorp-ca/root-ca/certs/root-ca.crtVerify certificate chain (should show OK):
openssl verify -provider oqsprovider -provider default -CAfile /opt/sassycorp-ca/root-ca/certs/root-ca.crt \
/opt/sassycorp-ca/root-ca/certs/root-ca.crtIf you get an error about the OQS provider, verify installation:
openssl list -providers -provider oqsproviderYou should see something similar to:
Providers:
oqsprovider
name: OpenSSL OQS Provider
version: 0.10.1-dev
status: activeEnsure you're running as the caadmin user:
whoami # Should show 'caadmin'List available quantum-resistant algorithms:
openssl list -signature-algorithms -provider oqsprovider | grep -i mldsaIf you see dilithium5 instead of mldsa87, you may be using an older version of the OQS provider. Why?
You have successfully created a CNSA 2.0 compliant quantum-resistant Root CA that is:
- CNSA 2.0 compliant using ML-DSA-87 (mldsa87)
- Valid for 10 years as recommended for Root CAs
- Using SHA-512 for hashing (CNSA 2.0 requirement)
- Protected with appropriate Unix file permissions
- Ready to sign intermediate CA certificates