Overview
System administrators frequently need TLS certificates for systems that are not publicly accessible (and can leverage OpenSSL CA.pl as a solution), including:
- internal web applications;
- monitoring dashboards;
- development servers;
- network appliances;
- test environments;
- configuration-management servers;
- lab systems;
- temporary proof-of-concept deployments.
A public certificate authority may not be appropriate for these systems, especially when their hostnames are only resolvable on an internal network.
For a small lab or test environment, OpenSSL includes a Perl script named CA.pl. It provides a simplified interface to several OpenSSL certificate commands and can create a basic certificate authority directory, generate certificate requests, sign certificates, revoke certificates, verify certificates, and generate certificate revocation lists.
The OpenSSL documentation describes CA.pl as a beginner-friendly front end that supplies arguments to underlying commands such as openssl req, openssl ca, openssl verify, and openssl pkcs12. It also warns that the script does not provide the control required for every use case.
This tutorial uses CA.pl to create a small internal certificate authority and issue a TLS certificate for an internal monitoring server named:
monitoring.example.internal
This guide follows the official OpenSSL 3.5 CA.pl documentation and includes compatibility notes for OpenSSL 3.0 and OpenSSL 4.0.
OpenSSL version compatibility
This article applies to:
- OpenSSL 3.0;
- OpenSSL 3.1;
- OpenSSL 3.2;
- OpenSSL 3.3;
- OpenSSL 3.4;
- OpenSSL 3.5 LTS;
- OpenSSL 4.0.
The workflow and principal CA.pl options covered here are available across OpenSSL 3.0, OpenSSL 3.5, and OpenSSL 4.0. The command remains listed in the official command indexes for all three versions.
The examples use the OpenSSL 3.5 documentation as the primary reference.
Check your installed version before continuing:
openssl version -a
Example:
OpenSSL 3.5.5 27 January 2026
This series supports OpenSSL 3.0 and later. OpenSSL 1.0 and 1.1 are outside its scope.
When should a system administrator use CA.pl?
CA.pl is appropriate for:
- learning how a certificate authority works;
- creating certificates for a personal lab;
- testing TLS configurations;
- generating temporary certificates for development;
- demonstrating certificate issuance and revocation;
- building a disposable CA for automation testing.
It is generally not the best choice for:
- a large enterprise PKI;
- a highly available certificate service;
- automated certificate enrollment at scale;
- Internet-facing public trust;
- environments requiring formal certificate profiles;
- environments requiring approval workflows;
- a production root CA that must remain offline and carefully audited.
The underlying openssl ca command is itself documented as a sample minimal CA application, and OpenSSL advises reviewing its warnings before using it productively. It maintains a text database of issued certificates and their status rather than providing a transactional or multi-user CA database.
For a real enterprise deployment, administrators will usually want a dedicated CA platform or a more carefully designed OpenSSL configuration and operating procedure.
What CA.pl does
The CA.pl script wraps several common certificate operations.
| CA.pl option | Purpose |
|---|---|
-newca | Creates a new CA directory and root certificate |
-newreq | Creates an encrypted private key and CSR |
-newreq-nodes | Creates an unencrypted private key and CSR |
-sign | Signs the CSR in newreq.pem |
-signCA | Signs a CSR as an intermediate CA certificate |
-signcert | Signs an existing self-signed certificate |
-verify | Verifies a certificate against the CA |
-revoke | Revokes an issued certificate |
-crl | Generates a certificate revocation list |
-pkcs12 | Exports the certificate and key as a PKCS#12 file |
-newcert | Creates a new self-signed certificate |
The script uses predictable filenames such as:
newkey.pem
newreq.pem
newcert.pem
newcert.p12
It creates its certificate authority files under a directory named:
demoCA
These fixed names make the script easy to learn, but they also make it less flexible than using the underlying OpenSSL commands directly.
Prerequisites
You need:
- OpenSSL 3.0 or later;
- Perl;
- access to the
CA.plscript; - a Linux, Unix-like, WSL, or compatible Windows environment;
- a dedicated working directory;
- permission to protect the generated CA private key.
Verify OpenSSL:
openssl version
Verify Perl:
perl --version
Locate CA.pl
Depending on the operating system and installation method, CA.pl may not be in the normal executable path.
Try:
command -v CA.pl
If that returns no result, search common OpenSSL directories:
find /usr/lib /usr/local/lib /opt -name CA.pl 2>/dev/null
You may also be able to locate it through the OpenSSL installation directory:
openssl version -d
A Linux distribution may place the script in an OpenSSL miscellaneous-tools directory rather than /usr/bin.
For the remainder of this article, replace CA.pl with its complete path when necessary.
For example:
/usr/lib/ssl/misc/CA.pl
You can make the examples easier to follow by assigning the path to a shell variable:
CAPL=/usr/lib/ssl/misc/CA.pl
Then run commands using:
"$CAPL" -help
If the script cannot be executed directly, run it through Perl:
perl -S CA.pl -help
The OpenSSL documentation specifically notes that invoking the script through Perl may be necessary in some environments, including Windows.
Real-world scenario
Assume that you administer a monitoring server with the following internal DNS name:
monitoring.example.internal
The server hosts Grafana, Prometheus, or another administrative dashboard over HTTPS.
Because the hostname is internal, you cannot obtain a normal publicly trusted certificate for it. Instead, you will:
- create a private root CA;
- create a server private key;
- generate a certificate signing request;
- sign the request with the private CA;
- verify the resulting certificate;
- install the CA certificate on administrator workstations;
- deploy the certificate and key to the monitoring server;
- test revocation and CRL generation.
Step 1: Create a secure working directory
Do not create your CA in a shared home directory or a directory accessible to other users.
Create a dedicated directory:
mkdir -p ~/openssl-ca-lab
cd ~/openssl-ca-lab
Restrict access:
chmod 700 ~/openssl-ca-lab
Confirm the current directory:
pwd
CA.pl creates its demoCA hierarchy in the current working directory, so the directory from which you run the command matters.
Step 2: Set a secure file-creation mask
Set a restrictive umask before generating private keys:
umask 077
Files created during the current shell session will not be readable by other users by default.
You can confirm it with:
umask
Expected output:
0077
Step 3: Create the private certificate authority
Run:
"$CAPL" -newca
Or, when calling the script through Perl:
perl "$CAPL" -newca
The script will ask whether you already have a CA certificate and private key.
For a new lab CA, press Enter when prompted for an existing CA certificate. The script will then generate a new private key and self-signed CA certificate.
You will be asked to create a passphrase for the CA private key.
Use a strong, unique passphrase. This private key can issue certificates trusted by any machine on which you install the CA certificate.
You will also be prompted for certificate subject fields, which may include:
Country Name
State or Province Name
Locality Name
Organization Name
Organizational Unit Name
Common Name
Email Address
A reasonable example is:
Country Name: US
State or Province Name: Virginia
Locality Name: Reston
Organization Name: Example Internal IT
Organizational Unit Name: Infrastructure
Common Name: Example Internal Root CA
Email Address: pki@example.com
The most important value is the common name. Use a name that clearly identifies the certificate as a CA rather than as a server certificate.
For example:
Example Internal Root CA
The -newca operation creates the demoCA hierarchy and uses the underlying openssl req and openssl ca functionality. If demoCA already exists, the script will not overwrite it.
Step 4: Examine the CA directory
List the generated files:
find demoCA -maxdepth 2 -type f -print
You should see files similar to:
demoCA/cacert.pem
demoCA/private/cakey.pem
demoCA/index.txt
demoCA/serial
Depending on the script and configuration, additional files or directories may also exist.
Important files include:
| File | Purpose |
|---|---|
demoCA/cacert.pem | Root CA certificate |
demoCA/private/cakey.pem | Root CA private key |
demoCA/index.txt | Database of issued and revoked certificates |
demoCA/serial | Next certificate serial number |
demoCA/newcerts/ | Copies of certificates issued by the CA |
The underlying openssl ca application requires a CA certificate, private key, new-certificates directory, serial file, policy configuration, and certificate database.
Step 5: Protect the CA private key
Check the permissions:
ls -l demoCA/private/cakey.pem
The key should not be accessible to other users.
Set restrictive permissions explicitly:
chmod 600 demoCA/private/cakey.pem
chmod 700 demoCA/private
For a disposable lab, keeping the CA on the same host may be acceptable.
For anything more important, the root CA key should be:
- stored offline when not in use;
- backed up securely;
- encrypted with a strong passphrase;
- accessible only to authorized administrators;
- separated from ordinary application servers.
Never copy the CA private key to the server receiving the TLS certificate.
The monitoring server should receive only:
its own private key
its signed server certificate
the CA certificate or chain when required
Step 6: Inspect the root CA certificate
Display the root certificate:
openssl x509 \
-in demoCA/cacert.pem \
-noout \
-subject \
-issuer \
-serial \
-dates
Because this is a self-signed root certificate, the subject and issuer should match.
Inspect its extensions:
openssl x509 \
-in demoCA/cacert.pem \
-noout \
-text
Look for values similar to:
X509v3 Basic Constraints:
CA:TRUE
You can also confirm the certificate’s purpose with:
openssl x509 \
-in demoCA/cacert.pem \
-noout \
-purpose
Step 7: Back up the CA before issuing certificates
Before proceeding, create an encrypted or otherwise securely protected backup of:
demoCA/cacert.pem
demoCA/private/cakey.pem
demoCA/index.txt
demoCA/serial
The CA database and serial files matter because they track certificate issuance and revocation.
A CA is not just a certificate and key. Losing the database can make ongoing certificate management and revocation more difficult.
Do not store an unencrypted backup of cakey.pem in a general shared folder.
Step 8: Create a server certificate request
The simplest CA.pl workflow is:
"$CAPL" -newreq
This creates:
newkey.pem
newreq.pem
The private key in newkey.pem is encrypted, and newreq.pem contains the certificate signing request.
The OpenSSL documentation confirms that -newreq generates the private key and request using the underlying openssl req command.
When prompted for the certificate subject, use a common name matching the server:
monitoring.example.internal
Example subject information:
Country Name: US
State or Province Name: Virginia
Locality Name: Reston
Organization Name: Example Internal IT
Organizational Unit Name: Infrastructure
Common Name: monitoring.example.internal
Email Address:
However, the common name alone is not sufficient for modern TLS hostname validation. The certificate should also contain a Subject Alternative Name.
Step 9: Add a Subject Alternative Name
Modern clients validate server names against the Subject Alternative Name extension.
For this server, the desired extension is:
DNS:monitoring.example.internal
You may also need aliases:
DNS:monitoring.example.internal
DNS:grafana.example.internal
Because CA.pl is only a wrapper, SAN handling depends on the OpenSSL configuration and parameters passed to the underlying req and ca commands.
Create a small extension file:
cat > monitoring-ext.cnf <<'EOF'[server_cert]
basicConstraints = critical, CA:FALSE keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth subjectAltName = @server_names
[server_names]
DNS.1 = monitoring.example.internal EOF
This extension file defines the certificate as an end-entity server certificate rather than a CA certificate.
The OpenSSL CA documentation warns against blindly copying extensions from a request, particularly because an unreviewed request could attempt to include CA:TRUE. It recommends explicitly enforcing values such as basicConstraints = CA:FALSE and appropriate key usage.
Step 10: Inspect the CSR before signing
Display the request:
openssl req \
-in newreq.pem \
-noout \
-subject \
-verify
Inspect the complete CSR:
openssl req \
-in newreq.pem \
-noout \
-text
Verify that the public key, subject, and requested extensions are appropriate.
A CA administrator should never sign an unreviewed CSR.
At a minimum, verify:
- the common name;
- all DNS names;
- the organization;
- the key algorithm;
- the key length;
- whether the request asks for CA capabilities;
- whether the request contains unexpected extensions.
Step 11: Sign the server certificate
The basic CA.pl signing command is:
"$CAPL" -sign
This expects the CSR to be named:
newreq.pem
It writes the issued certificate to:
newcert.pem
The command prompts for the CA private-key passphrase and asks you to confirm certificate issuance.
The -sign operation invokes the underlying openssl ca command.
For a certificate that requires explicit TLS server extensions, pass the extension file and section to the underlying ca command:
"$CAPL" \
-sign \
-extra-ca "-extfile monitoring-ext.cnf" \
-extra-ca "-extensions server_cert"
Depending on the shell and CA.pl build, the arguments may also be supplied separately:
"$CAPL" \
-sign \
-extra-ca -extfile \
-extra-ca monitoring-ext.cnf \
-extra-ca -extensions \
-extra-ca server_cert
The -extra-cmd mechanism passes additional parameters to the corresponding OpenSSL subcommand. In this example, -extra-ca passes arguments to openssl ca. Multiword parameters may be quoted or supplied through repeated options.
If your distribution’s CA.pl wrapper handles quoted arguments differently, use the underlying command directly:
openssl ca \
-in newreq.pem \
-out newcert.pem \
-extfile monitoring-ext.cnf \
-extensions server_cert
That is often preferable when building a repeatable production procedure.
Step 12: Inspect the issued certificate
Display the certificate summary:
openssl x509 \
-in newcert.pem \
-noout \
-subject \
-issuer \
-serial \
-dates
Inspect the Subject Alternative Name:
openssl x509 \
-in newcert.pem \
-noout \
-ext subjectAltName
Expected output:
X509v3 Subject Alternative Name:
DNS:monitoring.example.internal
Check basic constraints:
openssl x509 \
-in newcert.pem \
-noout \
-ext basicConstraints
Expected:
CA:FALSE
Check extended key usage:
openssl x509 \
-in newcert.pem \
-noout \
-ext extendedKeyUsage
Expected:
TLS Web Server Authentication
Review the complete certificate:
openssl x509 \
-in newcert.pem \
-noout \
-text
Step 13: Verify the certificate with CA.pl
Run:
"$CAPL" -verify newcert.pem
The script verifies the certificate against:
demoCA/cacert.pem
A successful result should resemble:
newcert.pem: OK
If no filename is supplied, CA.pl -verify attempts to verify newcert.pem.
You can perform the same test directly:
openssl verify \
-CAfile demoCA/cacert.pem \
newcert.pem
Step 14: Verify the server hostname
Certificate-chain validation and hostname validation are related but distinct checks.
Use:
openssl verify \
-CAfile demoCA/cacert.pem \
-verify_hostname monitoring.example.internal \
newcert.pem
Expected output:
newcert.pem: OK
Test an incorrect name:
openssl verify \
-CAfile demoCA/cacert.pem \
-verify_hostname wrong.example.internal \
newcert.pem
This should fail with a hostname mismatch.
This test confirms why the Subject Alternative Name is essential.
Step 15: Rename the certificate and key
The default filenames are useful for learning but poor for long-term administration.
Create a deployment directory:
mkdir -p issued/monitoring.example.internal
Copy the files:
cp newcert.pem \
issued/monitoring.example.internal/monitoring.example.internal.crt
cp newkey.pem \
issued/monitoring.example.internal/monitoring.example.internal.key
cp demoCA/cacert.pem \
issued/monitoring.example.internal/example-internal-root-ca.crt
Protect the key:
chmod 600 \
issued/monitoring.example.internal/monitoring.example.internal.key
After copying the files, avoid confusing them with the fixed newcert.pem and newkey.pem names that CA.pl will reuse during the next issuance.
Step 16: Decide whether the server key should remain encrypted
The -newreq option creates an encrypted private key.
An encrypted key is safer at rest, but a web service normally needs a way to unlock the key whenever it starts.
For an unattended service, administrators commonly use an unencrypted service key protected by:
- restrictive filesystem permissions;
- root ownership;
- disk encryption;
- host-access controls;
- configuration-management controls;
- secrets management where supported.
CA.pl provides:
"$CAPL" -newreq-nodes
This creates a request like -newreq, but leaves the private key unencrypted.
Despite the option name, -newreq-nodes does not mean that no certificate nodes are created. Historically, “nodes” refers to “no DES,” meaning no private-key encryption.
For a server certificate, you may use:
"$CAPL" -newreq-nodes
Then protect the resulting key immediately:
chmod 600 newkey.pem
Do not use unencrypted keys casually on administrator laptops, shared servers, or untrusted filesystems.
Step 17: Deploy the certificate
A typical web server needs:
monitoring.example.internal.crt
monitoring.example.internal.key
It may also need the CA certificate or a chain file, depending on the application.
For an internal root CA that directly issued the server certificate, the client trust store normally receives:
example-internal-root-ca.crt
The root CA certificate is not secret. The root CA private key is secret.
Never deploy this file to the monitoring server:
demoCA/private/cakey.pem
Step 18: Trust the private CA on client systems
Browsers and operating systems will not automatically trust your private CA.
You must install:
demoCA/cacert.pem
into the appropriate trust store on each authorized client.
Examples include:
- Linux system trust stores;
- Windows Trusted Root Certification Authorities;
- browser-specific trust stores;
- Java trust stores;
- application-specific certificate bundles.
Only install the CA certificate on systems that should trust certificates issued by this private CA.
Once a root CA is trusted, any certificate validly issued by that CA may be trusted for the names and purposes permitted by the certificate.
Step 19: Test the deployed TLS service
After configuring the monitoring server, test it with:
openssl s_client \
-connect monitoring.example.internal:443 \
-servername monitoring.example.internal \
-CAfile demoCA/cacert.pem \
-verify_return_error
Review:
- the certificate chain;
- the subject;
- the issuer;
- the verification result;
- the negotiated TLS protocol;
- the negotiated cipher suite.
Look for:
Verify return code: 0 (ok)
The -servername option sends the intended hostname through Server Name Indication, which is necessary when multiple TLS virtual hosts share an IP address.
Step 20: Export a PKCS#12 file
Some Windows applications, browsers, appliances, and administrative tools expect a PKCS#12 file containing:
- the private key;
- the issued certificate;
- the CA certificate.
CA.pl can create one with:
"$CAPL" -pkcs12 "Monitoring Server"
This expects:
newcert.pem
newkey.pem
demoCA/cacert.pem
It creates:
newcert.p12
The optional text becomes the certificate’s friendly name.
Rename the file:
mv newcert.p12 monitoring.example.internal.p12
Inspect it without displaying private-key material:
openssl pkcs12 \
-in monitoring.example.internal.p12 \
-info \
-noout
Protect the file carefully. A PKCS#12 bundle may contain the server’s private key.
Step 21: Issue another certificate
CA.pl reuses generic filenames.
Before generating the next certificate, move or remove:
newkey.pem
newreq.pem
newcert.pem
A safer workflow is to create a separate working directory for each request while keeping the CA database in a controlled location.
For example:
openssl-ca-lab/
├── demoCA/
├── requests/
│ ├── monitoring.example.internal/
│ └── grafana.example.internal/
└── issued/
However, because CA.pl expects demoCA in the current directory, more advanced layouts may require:
- symbolic links;
- script modifications;
- a custom OpenSSL configuration;
- direct use of
openssl ca.
This is one of the points where administrators often outgrow CA.pl.
Step 22: View the issued-certificate database
Display the CA database:
cat demoCA/index.txt
A valid certificate entry usually begins with:
V
A revoked certificate usually begins with:
R
The database records information such as:
- certificate status;
- expiration date;
- revocation date;
- serial number;
- certificate subject.
Do not edit this file casually.
Back it up with the CA key, certificate, and serial file.
Step 23: Revoke the server certificate
Assume the monitoring server was compromised and its private key may have been exposed.
Revoke its certificate:
"$CAPL" \
-revoke newcert.pem \
keyCompromise
The supported reasons include:
unspecified
keyCompromise
CACompromise
affiliationChanged
superseded
cessationOfOperation
certificateHold
removeFromCRL
The script passes the operation to the underlying openssl ca command.
Confirm the database entry:
grep monitoring.example.internal demoCA/index.txt
The line should now begin with:
R
Revoking the certificate updates the CA database, but it does not automatically inform clients.
Clients need access to a CRL or another revocation-status mechanism and must be configured to check it.
Step 24: Generate a certificate revocation list
Generate a CRL:
"$CAPL" -crl
Depending on the CA.pl implementation and configuration, the output may be written to a default CRL filename or standard output.
To generate a clearly named CRL directly, use:
openssl ca \
-gencrl \
-out demoCA/crl.pem
Inspect the CRL:
openssl crl \
-in demoCA/crl.pem \
-noout \
-issuer \
-lastupdate \
-nextupdate
Display revoked entries:
openssl crl \
-in demoCA/crl.pem \
-noout \
-text
The underlying OpenSSL CA command generates a CRL from the status information maintained in its index database.
Step 25: Verify a certificate against the CRL
Verify the certificate and check the CRL:
openssl verify \
-CAfile demoCA/cacert.pem \
-CRLfile demoCA/crl.pem \
-crl_check \
newcert.pem
A revoked certificate should fail verification with an error similar to:
certificate revoked
This illustrates an important operational requirement: creating a CRL is not enough. It must be:
- published at a stable location;
- refreshed before expiration;
- reachable by clients;
- referenced by certificates when appropriate;
- checked by the consuming software.
CA.pl can demonstrate revocation mechanics, but it does not build a complete CRL publishing service.
Creating an intermediate CA with CA.pl
CA.pl also provides:
"$CAPL" -signCA
This signs the request in newreq.pem using the v3_ca configuration section, producing a certificate capable of acting as a CA. The documented purpose is creating an intermediate CA signed by a root CA.
A better PKI design generally keeps the root CA offline and uses an intermediate CA for routine certificate issuance.
However, a secure intermediate-CA design requires careful control over:
basicConstraints;- path-length constraints;
- key usage;
- certificate policies;
- name constraints where required;
- validity periods;
- CRL distribution points;
- authority information access;
- private-key storage;
- signing procedures.
Do not rely solely on the default -signCA workflow for an important production hierarchy.
For a serious root-and-intermediate design, use a reviewed OpenSSL configuration and direct openssl req and openssl ca commands.
Using a custom OpenSSL configuration
CA.pl can pass a custom configuration location to the commands it invokes.
The documented environment variable is:
OPENSSL_CONFIG
Its value should contain a configuration option and path, such as:
export OPENSSL_CONFIG="-config /path/to/openssl-ca.cnf"
CA.pl also supports setting the OPENSSL environment variable to specify the OpenSSL executable it should call.
For example:
export OPENSSL=/usr/local/openssl-3.5/bin/openssl
This is useful when multiple OpenSSL versions are installed:
/usr/bin/openssl
/usr/local/openssl-3.5/bin/openssl
/opt/openssl-4.0/bin/openssl
Confirm the selected binary:
"$OPENSSL" version -a
Some CA.pl versions or platform notes may also reference OPENSSL_CONF, which is the broader OpenSSL environment variable used to identify the default configuration file. When troubleshooting configuration selection, inspect both:
env | grep '^OPENSSL'
OpenSSL 3.0, 3.5, and 4.0 differences
The basic CA.pl workflow is largely unchanged across these versions:
CA.pl -newca
CA.pl -newreq
CA.pl -sign
CA.pl -verify
CA.pl -revoke
CA.pl -crl
CA.pl -pkcs12
However, the underlying OpenSSL behavior can differ.
OpenSSL 3.0
OpenSSL 3.0 introduced the provider architecture and deprecated the older ENGINE framework.
When using algorithms that are no longer available through the default provider, an administrator may need to load another provider, such as the legacy provider.
CA.pl can pass extra provider-related parameters to an underlying command through options such as:
-extra-req
-extra-ca
-extra-pkcs12
For modern certificates, avoid legacy algorithms unless compatibility explicitly requires them.
OpenSSL 3.2 and later
The official openssl ca history notes that beginning with OpenSSL 3.2, generated certificates are X.509 version 3 and key identifier extensions are included by default unless otherwise configured.
You should still define critical certificate extensions explicitly rather than relying solely on defaults.
OpenSSL 3.5 LTS
OpenSSL 3.5 is the primary version used by this article series.
The CA.pl interface remains consistent with the OpenSSL 3.0 workflow, including:
-newca;-newreq;-newreq-nodes;-sign;-signCA;-verify;-revoke;-crl;-pkcs12;-extra-cmd.
OpenSSL 3.5 is the recommended documentation target for new MisterPKI articles, while OpenSSL 3.0 remains the compatibility baseline.
OpenSSL 4.0
CA.pl is still included in the OpenSSL 4.0 command documentation.
The principal CA.pl workflow remains available, but OpenSSL 4.0 removes additional legacy ENGINE support from the underlying commands. For example, the OpenSSL 4.0 openssl ca syntax no longer lists the deprecated -engine option that appeared in OpenSSL 3.5.
Provider-based configuration should therefore be preferred for procedures intended to work on both OpenSSL 3 and OpenSSL 4.
For normal RSA or elliptic-curve internal certificates using the default provider, the workflow in this article should remain substantially the same.
Windows considerations
Windows does not normally include a native system-wide CA.pl command.
A Windows administrator may use CA.pl through:
- a third-party OpenSSL installation;
- a manually built OpenSSL installation;
- Git Bash or another Unix-like environment;
- Strawberry Perl or another Perl distribution;
- Windows Subsystem for Linux.
Check the OpenSSL executable:
Get-Command openssl | Format-List Source
Check Perl:
Get-Command perl | Format-List Source
Locate CA.pl:
Get-ChildItem C:\ -Filter CA.pl -Recurse -ErrorAction SilentlyContinue
Run the script through Perl:
perl C:\OpenSSL\bin\CA.pl -help
Because CA.pl assumes Unix-like paths and a particular configuration location, WSL is often the least troublesome Windows method.
Inside WSL, follow the Linux instructions and use the OpenSSL version supplied by the installed WSL distribution.
Common CA.pl errors
CA.pl: command not found
The script is not in your PATH.
Locate it:
find /usr /usr/local /opt -name CA.pl 2>/dev/null
Then run it by full path.
Cannot open configuration file
Find the OpenSSL configuration directory:
openssl version -d
Find possible configuration files:
find /etc /usr/lib/ssl /usr/local/ssl -name openssl.cnf 2>/dev/null
Then specify the configuration through the appropriate environment variable or direct OpenSSL command.
demoCA already exists
CA.pl -newca will not overwrite an existing demoCA directory.
Inspect it before deleting anything:
find demoCA -maxdepth 2 -type f -ls
If it is an incomplete disposable test CA, remove it:
rm -rf demoCA
Then rerun:
"$CAPL" -newca
Never delete an active CA directory merely to clear an error.
Unable to load CA private key
Confirm that the key exists:
ls -l demoCA/private/cakey.pem
Check whether it is readable:
openssl pkey \
-in demoCA/private/cakey.pem \
-noout \
-check
You will be prompted for the passphrase.
TXT_DB error number 2
This commonly indicates that the CA database believes a valid certificate with the same subject already exists.
Inspect:
cat demoCA/index.txt
For server certificates, repeated subjects may be expected during renewal. A custom CA configuration can set:
unique_subject = no
Do not manually delete entries from index.txt without understanding the effect on CA state.
The certificate has no Subject Alternative Name
The CSR or signing configuration did not supply a SAN.
Check the CSR:
openssl req \
-in newreq.pem \
-noout \
-text
Check the certificate:
openssl x509 \
-in newcert.pem \
-noout \
-ext subjectAltName
Use an explicit extension file during signing.
The browser still reports an untrusted certificate
Verify that:
- the root CA certificate was installed in the correct trust store;
- the browser uses that trust store;
- the server sent the correct certificate;
- the certificate has the correct SAN;
- the certificate is within its validity period;
- the server was restarted after certificate deployment.
Test from the command line:
openssl s_client \
-connect monitoring.example.internal:443 \
-servername monitoring.example.internal \
-CAfile demoCA/cacert.pem \
-verify_return_error
The certificate verifies but the hostname fails
Check the SAN:
openssl x509 \
-in newcert.pem \
-noout \
-ext subjectAltName
Then test:
openssl verify \
-CAfile demoCA/cacert.pem \
-verify_hostname monitoring.example.internal \
newcert.pem
The DNS name must match an entry in the SAN extension.
Security recommendations
When using CA.pl, follow these minimum safeguards:
- Protect the CA private key with a strong passphrase.
- Restrict permissions on the CA directory.
- Back up the CA certificate, key, database, and serial state.
- Do not place the root private key on application servers.
- Review every CSR before signing it.
- Explicitly set
CA:FALSEon server and client certificates. - Explicitly define key usage and extended key usage.
- Avoid blindly copying CSR extensions.
- Use SANs for DNS names.
- Use an intermediate CA for anything beyond a disposable lab.
- Keep the root CA offline when practical.
- Document certificate owners, purposes, and expiration dates.
- Establish a renewal process before certificates expire.
- Establish a CRL publishing process before relying on revocation.
- Migrate away from CA.pl when the environment requires automation, scale, auditing, or multiple administrators.
CA.pl versus openssl ca
CA.pl is easier to learn:
CA.pl -newca
CA.pl -newreq
CA.pl -sign
Direct OpenSSL commands provide more control:
openssl req ...
openssl ca ...
openssl verify ...
openssl pkcs12 ...
Use CA.pl when:
- teaching OpenSSL certificate concepts;
- running a small lab;
- testing basic certificate workflows;
- creating a disposable internal CA.
Use direct OpenSSL commands or dedicated PKI software when:
- certificate profiles must be tightly controlled;
- SANs and extensions vary;
- certificates are issued automatically;
- multiple operators manage the CA;
- audit records are required;
- hardware-protected keys are used;
- the CA serves production systems;
- revocation information must be reliably published;
- high availability is required.
The OpenSSL documentation itself states that CA.pl may not behave exactly as desired and recommends calling the underlying OpenSSL commands directly when more control is needed.
Complete CA.pl command summary
Create a new private CA:
CA.pl -newca
Create an encrypted private key and CSR:
CA.pl -newreq
Create an unencrypted private key and CSR:
CA.pl -newreq-nodes
Sign the CSR:
CA.pl -sign
Sign an intermediate CA CSR:
CA.pl -signCA
Verify the issued certificate:
CA.pl -verify newcert.pem
Export a PKCS#12 file:
CA.pl -pkcs12 "Certificate Friendly Name"
Revoke a certificate:
CA.pl -revoke newcert.pem keyCompromise
Generate a CRL:
CA.pl -crl
Display help:
CA.pl -help
Conclusion
The OpenSSL CA.pl script provides a convenient way to learn and demonstrate the certificate-authority lifecycle:
Create CA
Create private key
Generate CSR
Review CSR
Sign certificate
Verify certificate
Deploy certificate
Revoke certificate
Generate CRL
For a system administrator managing a small internal lab, it can quickly produce certificates for internal dashboards, test servers, development systems, and administrative tools.
Its simplicity is also its limitation. It relies on fixed filenames, a demoCA directory, a text certificate database, and defaults that may not match a production PKI design.
Use CA.pl to understand the workflow and handle limited lab use. Once you need repeatability, carefully controlled extensions, automated issuance, intermediate CAs, hardware-backed keys, multiple administrators, or reliable revocation services, move to direct OpenSSL commands or a dedicated certificate-authority platform.
Leave a Reply