Build and Configure Your Own Certificate Authority with OpenSSL
Building your own Certificate Authority (CA) can be incredibly useful for a variety of purposes, including internal development, testing, managing server certificates within a private network, and understanding the fundamentals of PKI (Public Key Infrastructure). While not suitable for issuing publicly trusted certificates, a private CA allows you to issue certificates that are trusted within your controlled environment. This article provides a detailed guide to building and configuring a CA using OpenSSL, the ubiquitous open-source cryptographic toolkit.
Why Build Your Own CA?
- Cost Savings: Avoids the cost of purchasing certificates from commercial CAs for internal use.
- Control: You have complete control over the certificate issuance process, validity periods, and extensions.
- Learning: Provides hands-on experience with PKI concepts and best practices.
- Testing: Allows testing of secure communication setups (e.g., HTTPS, VPN) without exposing your system to the public internet.
- Internal Services: Enables secure communication for internal applications and services.
Prerequisites:
- OpenSSL: Ensure you have OpenSSL installed on your system. Most Linux distributions include it by default. On Windows, you can download it from https://www.openssl.org/ (or better, use a package manager like Chocolatey).
- Basic Terminal/Command Prompt Knowledge: You’ll be working primarily from the command line.
- Understanding of PKI Concepts (helpful): While we’ll explain the steps, a basic understanding of public/private keys, certificates, and the certificate chain of trust is beneficial.
Step 1: Create the CA Directory Structure
A well-organized directory structure is crucial for managing your CA. We’ll create a dedicated directory to store all CA-related files. The following structure is a common and recommended approach:
bash
mkdir -p myCA/{certs,crl,newcerts,private}
chmod 700 myCA/private
touch myCA/index.txt
echo 1000 > myCA/serial
myCA
: The root directory for your CA.certs
: Stores copies of issued certificates.crl
: Stores the Certificate Revocation List (CRL).newcerts
: OpenSSL will store newly issued certificates here (by serial number).private
: Stores the CA’s private key. Crucially, this directory is protected withchmod 700
to restrict access to only the owner. Compromise of this key compromises the entire CA.index.txt
: A text database OpenSSL uses to track issued certificates.serial
: A file containing the next serial number to be used for new certificates. We start with1000
as a common practice.
Step 2: Configure openssl.cnf
(OpenSSL Configuration File)
The openssl.cnf
file controls OpenSSL’s behavior. You can use command-line flags for everything, but creating a custom configuration file is much more manageable and less error-prone.
Copy the default OpenSSL configuration file (location varies by system, often in /etc/ssl/
, /usr/lib/ssl/
, or within the OpenSSL installation directory). Let’s assume it’s /etc/ssl/openssl.cnf
. Make a copy for our CA:
bash
cp /etc/ssl/openssl.cnf myCA/openssl.cnf
Now, edit myCA/openssl.cnf
and make the following changes (explanations follow):
“`
[ CA_default ]
dir = ./myCA # Where everything is kept (our root directory)
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
new_certs_dir = $dir/newcerts # default place for new certs.
certificate = $dir/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/cakey.pem # The private key
RANDFILE = $dir/private/.rand # private random number file
default_days = 365 # How long to certify for
default_crl_days= 30 # How long before next CRL
default_md = sha256 # Use public key default MD
policy = policy_match
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
distinguished_name = req_distinguished_name
req_extensions = v3_req # The extensions to add to the request
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = California
localityName = Locality Name (eg, city)
localityName_default = San Francisco
0.organizationName = Organization Name (eg, company)
0.organizationName_default = My Company
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default =
commonName = Common Name (eg, your domain name, OR the server’s FQDN)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical,CA:true
keyUsage = cRLSign, keyCertSign
“`
Explanation of Configuration Options:
[ CA_default ]
: Defines defaults for the CA. The key here isdir = ./myCA
, which points to our CA root directory. All other paths are relative to this.default_days
: Sets the default validity period for issued certificates (365 days).default_crl_days
: Sets how often the CRL is updated (30 days).default_md
: Specifies the default hashing algorithm (SHA-256).policy
: Defines the certificate request policy.policy_match
requires thecountryName
,stateOrProvinceName
, andorganizationName
in the certificate request to match those of the CA.commonName
must be supplied, andemailAddress
andorganizationalUnitName
are optional.[ req ]
: Configuration for generating certificate signing requests (CSRs).distinguished_name
: Specifies the section containing the Distinguished Name (DN) fields.req_extensions
: Specifies the section containing extensions to add to the CSR.[ req_distinguished_name ]
: Defines the DN fields. You can set defaults here (e.g.,countryName_default
,stateOrProvinceName_default
). These defaults will be pre-populated when generating a CSR.[ v3_req ]
: Extensions for a regular (non-CA) certificate.basicConstraints = CA:FALSE
is important; this prevents the certificate from being used as a CA.keyUsage
defines allowed key usages.[ v3_ca ]
: Extensions for the CA certificate.basicConstraints = critical,CA:true
is essential – it designates this certificate as a CA certificate.keyUsage
specifies the allowed key usages for the CA (signing CRLs and certificates).subjectKeyIdentifier
andauthorityKeyIdentifier
adds identifier to help openssl verify the certificate chain.
Step 3: Create the CA Certificate and Key
This is the core of your CA. The private key is the most sensitive part, and the certificate is what you’ll distribute to clients to trust your CA.
bash
openssl req -new -x509 -days 3650 -keyout myCA/private/cakey.pem -out myCA/cacert.pem -config myCA/openssl.cnf -extensions v3_ca
openssl req
: The OpenSSL command for certificate requests and self-signed certificates.-new
: Creates a new request.-x509
: Creates a self-signed certificate (instead of just a CSR).-days 3650
: Sets the validity period of the CA certificate (10 years in this case – you should choose a long validity period for your root CA).-keyout myCA/private/cakey.pem
: Specifies the output file for the private key.-out myCA/cacert.pem
: Specifies the output file for the CA certificate.-config myCA/openssl.cnf
: Uses our custom configuration file.-extensions v3_ca
: use the v3_ca section of the configuration file.- You’ll be prompted to enter the DN information for your CA (Country, State, Organization, Common Name, etc.). The Common Name (CN) for your CA should be a descriptive name for your CA (e.g., “My Company Internal CA”). It does not need to be a resolvable hostname.
- You will be prompted for a password, choose a strong and safe password.
Step 4: Issue a Server Certificate
Now that you have a CA, you can issue certificates. Here’s how to issue a certificate for a server (e.g., for HTTPS).
-
Generate a Private Key and CSR for the Server:
bash
openssl req -new -nodes -out server.csr -keyout server.key -config myCA/openssl.cnf-nodes
: Creates the private key without a passphrase (for automated use cases like web servers). Be extremely careful with unencrypted private keys – store them securely! If you need a passphrase, omit-nodes
.-out server.csr
: Output file for the Certificate Signing Request (CSR).-keyout server.key
: Output file for the server’s private key.- You’ll be prompted for the DN information. Crucially, the Common Name (CN) must match the server’s Fully Qualified Domain Name (FQDN) or hostname that clients will use to connect. (e.g.,
www.example.com
,server.internal.local
).
-
Sign the CSR with the CA:
bash
openssl ca -in server.csr -out server.crt -config myCA/openssl.cnf -extensions v3_reqopenssl ca
: Uses the CA functions of OpenSSL.-in server.csr
: The CSR to sign.-out server.crt
: The output certificate file.-config myCA/openssl.cnf
: Our configuration file.-extensions v3_req
: Use the v3_req section of the configuration file.- You’ll be prompted to confirm the signing. Type
y
and enter the CA’s private key password.
Step 5: Verify the Certificate
Verify the signed certificate:
bash
openssl verify -CAfile myCA/cacert.pem server.crt
It should output server.crt: OK
.
Step 6: Install the CA Certificate on Clients
To trust certificates issued by your CA, you need to install the CA certificate (myCA/cacert.pem
) on client machines. The process varies depending on the operating system and application:
- Linux: Copy
cacert.pem
to/usr/local/share/ca-certificates/
(or a similar directory), rename it with a.crt
extension (e.g.,myCA.crt
), and runsudo update-ca-certificates
. - Windows: Double-click the
cacert.pem
file and follow the prompts to import it into the “Trusted Root Certification Authorities” store. - macOS: Double-click the
cacert.pem
file and add it to the Keychain Access. You’ll need to explicitly trust the certificate. - Browsers: Most browsers use the system’s certificate store, but some (like Firefox) have their own. You may need to import the CA certificate into the browser’s settings.
- Specific Applications: Some applications have their own way of configuring trusted CAs. Consult the application’s documentation.
Step 7: (Optional) Create a Certificate Revocation List (CRL)
A CRL is a list of certificates that have been revoked (e.g., due to key compromise). It’s good practice to maintain a CRL, even for a private CA.
-
Generate the CRL:
bash
openssl ca -gencrl -out myCA/crl.pem -config myCA/openssl.cnf -
Revoke a Certificate (if needed):
bash
openssl ca -revoke myCA/newcerts/SERIAL.pem -config myCA/openssl.cnfReplace
SERIAL.pem
with the actual filename of the certificate you want to revoke (found inmyCA/newcerts
). This updatesindex.txt
to mark the certificate as revoked. Then, regenerate the CRL using the-gencrl
command above. -
Verify the CRL:
bash
openssl crl -in myCA/crl.pem -text -noout -
Distribute the CRL: The CRL should be made available to clients (e.g., via a web server). You can configure your web server to serve the CRL. You can also specify the CRL distribution point in the certificates using openssl configuration.
Important Considerations:
- Security: The CA’s private key (
myCA/private/cakey.pem
) is extremely sensitive. Protect it with a strong passphrase and store it securely, ideally on a dedicated, offline machine. - Key Length: For strong security, use at least a 2048-bit RSA key (the default). You can specify the key size with the
-newkey
option when creating the CA key and CSRs (e.g.,-newkey rsa:4096
). - Hashing Algorithm: Use SHA-256 (the default) or a stronger algorithm.
- Validity Periods: Choose appropriate validity periods for your CA and issued certificates. A shorter validity period is generally more secure (requiring more frequent renewals), but a longer period is more convenient.
- Renewal: Certificates expire. Establish a process for renewing both your CA certificate and issued certificates before they expire.
- Backups: Regularly back up your entire CA directory, especially the
private
directory. - Intermediate CA: For large or complex deployments, consider creating an intermediate CA. The root CA signs the intermediate CA, and the intermediate CA issues end-entity certificates. This helps protect the root CA.
- Offline Root CA: Best practice dictates that the root CA should be kept offline in a physically secure location. This mitigates the risk of the root CA’s private key being compromised.
This comprehensive guide provides a solid foundation for building and managing your own CA with OpenSSL. Remember to adapt the steps and configurations to your specific needs and security requirements. By following these instructions and taking the necessary precautions, you can create a secure and controlled PKI environment.