Home / Alt manpages / ca.pl(1ssl)

  • ca.pl(1ssl)
  • OpenSSL command
  • linux

Build a Throwaway CA and Certificate Bundle with CA.pl

CA.pl turns the handful of OpenSSL subcommands you would otherwise chain by hand into one script for standing up a disposable certificate authority. You will build the CA, generate a request, sign it, verify the result and package it as a PKCS#12 file, all useful for a lab, a browser test or a development service, but none of it a recipe for a production public CA. Allow about 20 minutes, most of it answering prompts for names and passwords.

The examples use the CA.pl installed with the Ubuntu openssl package, version 3.0.13-0ubuntu3.15. On this machine the script lives at /usr/lib/ssl/misc/CA.pl, off the normal shell PATH. The wrapper follows whichever OpenSSL version the openssl command on your path reports, unless you set OPENSSL.

Security boundary

Keep this work in a disposable directory. If you import the CA certificate anywhere, its private key can sign certificates that clients will trust. Never reuse it for a real service, and never let it leave the test environment.

1. Choose an empty working directory

CA.pl writes fixed names, demoCA, newkey.pem, newreq.pem, into whatever directory you run it from. Use a fresh one so an old request or CA database cannot get mixed into the run:

$ workdir=$(mktemp -d /tmp/ca-pl-demo.XXXXXX)
$ cd "$workdir"
$ command -v openssl
/home/linuxbrew/.linuxbrew/bin/openssl
$ test ! -e demoCA && echo 'empty CA workspace'
empty CA workspace

The workdir variable only lasts for this shell. Prefer a named directory instead? Give it permissions that shut out other users and confirm it holds no leftover CA files first.

2. Confirm the wrapper and its options

Run the script by its installed path. This is read-only and needs no sudo:

$ /usr/lib/ssl/misc/CA.pl -help
Usage:
    CA.pl -newcert | -newreq | -newreq-nodes | -xsign | -sign | -signCA | -signcert | -crl | -newca [-extra-cmd parameter]
    CA.pl -pkcs12 [certname]
    CA.pl -verify certfile ...
    CA.pl -revoke certfile [reason]

It is deliberately a thin front end over OpenSSL's req, ca, pkcs12, x509 and verify subcommands. Need a different policy, extension or file name? Use the relevant OpenSSL command directly rather than assuming CA.pl hides a switch for it.

3. Create the CA hierarchy

Start the interactive setup:

$ /usr/lib/ssl/misc/CA.pl -newca

Press ENTER at the first prompt to create a new CA, answer the distinguished-name questions, then set a strong passphrase when OpenSSL asks for the CA private key. This creates demoCA/ in the current directory: demoCA/private/cakey.pem, demoCA/cacert.pem, a certificate database and the directories for issued certificates.

Checkpoint

Stop if the output says demoCA/index.txt or demoCA/serial already exists. CA.pl will not overwrite an existing hierarchy, and you should not delete one casually either: that database is the record of every certificate issued and revoked. If this really was a failed disposable attempt, leave it alone and start fresh in a new temporary directory.

$ test -s demoCA/cacert.pem && test -s demoCA/private/cakey.pem && echo 'CA created'
CA created

4. Generate an encrypted certificate request

Create the user key and request:

$ /usr/lib/ssl/misc/CA.pl -newreq

OpenSSL asks for a passphrase to protect newkey.pem and for the request's subject fields. The key comes out encrypted; the request lands in newreq.pem. You can hand extra arguments to the underlying req command, for example to set a subject without giving up key encryption:

$ /usr/lib/ssl/misc/CA.pl -newreq -extra-req '-subj /C=GB/ST=Test/L=Test/O=Example/OU=Lab/CN=example.invalid'

Pick one, not both: the first form is fully interactive, the second still prompts for the encrypted key's passphrase but takes the subject from -subj. Check the files before moving on:

$ test -s newkey.pem && test -s newreq.pem && echo 'request and private key created'
request and private key created
$ openssl req -in newreq.pem -noout -subject
subject=...

5. Sign the request with the test CA

Issue the certificate against the CA database:

$ /usr/lib/ssl/misc/CA.pl -sign

OpenSSL asks for the CA's private-key passphrase and shows you the request. Only confirm if the subject is the one you meant to sign. The signed certificate lands in newcert.pem, and the CA database records the issuance:

$ test -s newcert.pem && echo 'certificate created'
certificate created
$ openssl x509 -in newcert.pem -noout -subject -issuer
subject=...
issuer=...

The issuer field should name the CA you just created, not the request's own subject. A certificate file existing on disk proves nothing by itself, check that relationship before you import anything into a browser or service.

6. Verify the certificate against the CA

-verify checks a certificate against demoCA/cacert.pem. Name the issued certificate explicitly:

$ /usr/lib/ssl/misc/CA.pl -verify newcert.pem
newcert.pem: OK

Some OpenSSL builds print extra diagnostic lines, but a genuine pass ends with OK and a zero exit status. If verification fails, check you are still sitting in the directory that holds the matching demoCA hierarchy. Do not copy a CA certificate over from another test directory just to make the check pass.

7. Export a PKCS#12 bundle

Package the user certificate, its private key and the CA certificate together:

$ /usr/lib/ssl/misc/CA.pl -pkcs12 'Example Lab Certificate'
PKCS #12 file is in newcert.p12
$ test -s newcert.p12 && echo 'PKCS#12 bundle created'
PKCS#12 bundle created

CA.pl expects newcert.pem, newkey.pem and demoCA/cacert.pem at exactly these relative paths. It prompts for the encrypted key's passphrase and a fresh export passphrase. Treat newcert.p12 as sensitive, it holds the private key. The name you pass is just the friendly label shown in most browser import dialogs.

Common traps

  • -newcert is not -newreq. It creates a self-signed certificate instead of a request for your CA, writing newkey.pem and newcert.pem directly. Skip it if you actually want to exercise the CA database.
  • -newreq-nodes skips key encryption. It behaves like -newreq but leaves the private key unencrypted. Fine for a disposable test protected some other way, a poor default for a key you intend to keep.
  • Fixed file names bite you on reruns. Shell redirection and CA.pl's fixed output names can overwrite useful files. Check pwd and find . -maxdepth 2 -type f before rerunning a command.
  • The CA database cannot be half-undone. Signing or revoking a certificate is not reversed by deleting newcert.pem alone. For a full disposable reset, abandon the directory and start a fresh one under /tmp rather than deleting a hierarchy that might still be needed to validate existing certificates.

Done means

  • CA created. demoCA/cacert.pem and its private key exist in a dedicated test directory.
  • Request generated. newreq.pem exists with an encrypted newkey.pem, unless you deliberately chose -newreq-nodes for a disposable test.
  • Certificate signed and verified. newcert.pem was issued by the test CA and passed CA.pl -verify.
  • Bundle exported. newcert.p12 exists, has an export passphrase and is treated as a private-key container.
  • CA kept. The directory and its database remain available for later verification.