Generating Your Own Self-Signed CA and HTTPS Certificates with OpenSSL

Last Updated: May 17, 2025

In this post, I’ll guide you through the process of creating your own Certificate Authority (CA) and using it to sign server certificates for HTTPS. This is particularly useful for development environments, internal services, or any situation where you need SSL/TLS encryption without purchasing certificates from a commercial CA. We’ll be using OpenSSL, a powerful and versatile command-line tool.

Prerequisites:

  • OpenSSL installed on your system.

Let’s dive into the steps.

Step 1: Generate the CA Private Key (SelfSignedCA.key)

The first step is to create a private key for your self-signed CA. This key is the foundation of your CA’s trustworthiness; keep it secure and private. If this key is compromised, any certificates signed by it could be forged.

openssl genpkey -algorithm RSA -out SelfSignedCA.key -aes256 -pkeyopt rsa_keygen_bits:4096

Let’s break down this command:

  • openssl genpkey: Command to generate a private key.
  • -algorithm RSA: Specifies the RSA algorithm for the key.
  • -out SelfSignedCA.key: The output filename for your CA private key.
  • -aes256: Encrypts the outputted private key with AES 256-bit encryption. You will be prompted for a passphrase to protect this key.
  • -pkeyopt rsa_keygen_bits:4096: Sets the key length to 4096 bits, which is generally considered strong.

Step 2: Prepare the CA Configuration File (openssl_ca.cnf)

Before generating the CA root certificate, you need to create an OpenSSL configuration file. This file defines crucial properties and extensions for your CA certificate. Create a file named openssl_ca.cnf in your working directory with the following content:

# openssl_ca.cnf
[ req ]
distinguished_name = req_distinguished_name
x509_extensions = v3_ca # The extensions to add to the self-signed cert

[ req_distinguished_name ]
# No specific entries needed here if providing subject via -subj command line argument
# You could define default values or prompts here if not using -subj

[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:TRUE
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

Explanation of openssl_ca.cnf:

  • [ req ]: Basic request settings.
    • x509_extensions = v3_ca: Specifies the section (v3_ca) containing extensions for the self-signed CA certificate.
  • [ v3_ca ]: Defines the X.509 v3 extensions for the CA certificate.
    • subjectKeyIdentifier = hash: An identifier for the public key of this certificate.
    • authorityKeyIdentifier = keyid:always,issuer: An identifier for the public key of the certificate that signed this one. For a self-signed root, this refers to itself.
    • basicConstraints = critical, CA:TRUE: Crucial for a CA certificate. It marks the certificate as a CA, meaning it can be used to sign other certificates. critical means this extension must be understood by the application.
    • keyUsage = critical, digitalSignature, cRLSign, keyCertSign: Specifies the allowed uses for the CA’s key (signing other certificates, signing Certificate Revocation Lists).

Step 3: Generate the CA Root Certificate (SelfSignedCA.pem)

With the CA private key (SelfSignedCA.key) and the openssl_ca.cnf configuration file prepared, you can now generate the CA’s root certificate. This certificate is what you will install in browsers or systems to make them trust the certificates signed by your CA.

openssl req -x509 -new -nodes -key SelfSignedCA.key -sha256 -days 7300 \
    -out SelfSignedCA.pem \
    -subj "/C=XX/ST=YourState/L=YourCity/O=Your Organization/OU=Your Unit/CN=Your Custom Root CA" \
    -config openssl_ca.cnf

Command explanation:

  • openssl req -x509: Command for X.509 certificate signing request (CSR) management and certificate generation. The -x509 flag means we are creating a self-signed certificate.
  • -new: Indicates a new certificate request.
  • -nodes: If your CA private key (SelfSignedCA.key) is encrypted, this option allows you to proceed without encrypting the certificate itself (you’ll be prompted for the private key’s passphrase).
  • -key SelfSignedCA.key: Specifies the private key to use for signing the certificate.
  • -sha256: Uses the SHA-256 hash algorithm for the signature.
  • -days 7300: Sets the validity period of the certificate (7300 days is approximately 20 years).
  • -out SelfSignedCA.pem: The output filename for your CA root certificate.
  • -subj "/C=XX/ST=YourState/L=YourCity/O=Your Organization/OU=Your Unit/CN=Your Custom Root CA": Sets the subject information for the CA certificate.
    • C: Country Code (e.g., US)
    • ST: State or Province
    • L: Locality (City)
    • O: Organization Name
    • OU: Organizational Unit (e.g., IT Department)
    • CN: Common Name (The name of your CA, e.g., “My Company Internal Root CA”)
  • -config openssl_ca.cnf: Specifies the configuration file created in Step 2.

Step 4: Generate a Server Private Key (server.key)

Now, let’s create a private key for the server/application for which you want to enable HTTPS. This key is distinct from the CA’s private key.

openssl genpkey -algorithm RSA -out server.key -pkeyopt rsa_keygen_bits:2048

Command explanation:

  • openssl genpkey: Same command as before to generate a private key.
  • -algorithm RSA: Using RSA algorithm.
  • -out server.key: The output filename for the server’s private key. You might want to name this more descriptively, like your-service.com.key.
  • -pkeyopt rsa_keygen_bits:2048: A 2048-bit key is generally sufficient for server keys.

Note: For better organization, you might place server-specific files in a subdirectory, e.g., mkdir my-service && openssl genpkey -algorithm RSA -out my-service/server.key ...

Step 5: Prepare the Server Configuration File (openssl_server.cnf)

Before generating the server’s Certificate Signing Request (CSR), you need another OpenSSL configuration file. This file will define extensions for the CSR and the final server certificate, such as Subject Alternative Names (SANs). Create a file named openssl_server.cnf in your working directory with the following content. Remember to customize the [alt_names] section for your specific server.

# openssl_server.cnf
[ req ]
distinguished_name = req_distinguished_name
req_extensions = v3_req # Extensions for the CSR

[ req_distinguished_name ]
# No specific entries needed here if providing subject via -subj command line argument

[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names # Crucial: Used by modern browsers to validate hostnames

[ alt_names ]
DNS.1 = your.domain.com       # Your server's primary domain name (should match CN)
DNS.2 = www.your.domain.com   # Optional: Another DNS name
DNS.3 = *.your.internal.lan # Optional: Wildcard domain for internal use
IP.1 = 192.168.1.10           # Optional: Server's IP address, if accessed directly via IP
# You can have more DNS.x and IP.x entries as needed.
# Replace the above DNS and IP values with your actual server details.

Explanation of openssl_server.cnf:

  • [ req ]:
    • req_extensions = v3_req: Specifies the section (v3_req) containing extensions to be included in the Certificate Signing Request and subsequently in the certificate.
  • [ v3_req ]: Defines X.509 v3 extensions for the server certificate.
    • basicConstraints = CA:FALSE: Specifies that this certificate is not a CA and cannot be used to sign other certificates.
    • keyUsage = digitalSignature, keyEncipherment: Defines how the certificate’s public key can be used (e.g., for digital signatures and key encryption).
    • extendedKeyUsage = serverAuth: Indicates the key can be used for server authentication (i.e., for HTTPS).
    • subjectAltName = @alt_names: Extremely important. This directive points to another section (alt_names) that lists all Subject Alternative Names. Modern browsers and applications rely on SANs rather than just the Common Name (CN) for validating hostnames.
  • [ alt_names ]:
    • Customize this section carefully.
    • DNS.1 = your.domain.com: Replace your.domain.com with the actual domain name of your server. This should usually match the CN.
    • DNS.2 = www.your.domain.com: Add any other DNS names your server uses.
    • DNS.3 = *.your.internal.lan: Example of a wildcard for an internal domain.
    • IP.1 = 192.168.1.10: Replace with your server’s actual IP address if needed. Include IP addresses if the server will be accessed directly via IP.
    • You can add more DNS.x and IP.x entries as required.

Step 6: Generate a Server Certificate Signing Request (server.csr)

With the server private key (server.key) and openssl_server.cnf ready, create a Certificate Signing Request (CSR) for the server. The CSR contains information about the server, including its public key, and will be sent to your CA for signing.

openssl req -new -key server.key -out server.csr \
    -subj "/C=XX/ST=YourState/L=YourCity/O=Your Organization/CN=your.domain.com" \
    -config openssl_server.cnf

Command explanation:

  • openssl req -new: Indicates a new CSR.
  • -key server.key: Specifies the server’s private key generated in Step 4.
  • -out server.csr: The output filename for the CSR.
  • -subj "/C=XX/ST=YourState/L=YourCity/O=Your Organization/CN=your.domain.com": Sets the subject information for the server certificate.
    • The CN (Common Name) is very important: it must match the primary domain name specified as DNS.1 in your openssl_server.cnf [alt_names] section.
  • -config openssl_server.cnf: Specifies the server-specific OpenSSL configuration file created in Step 5.

Step 7: Sign the Server Certificate using Your CA (server.crt)

Finally, use your CA’s private key (SelfSignedCA.key) and root certificate (SelfSignedCA.pem) to sign the server’s CSR (server.csr), thereby creating the server’s SSL/TLS certificate. This step also uses the openssl_server.cnf file for applying the necessary extensions.

openssl x509 -req -in server.csr \
    -CA SelfSignedCA.pem -CAkey SelfSignedCA.key -CAcreateserial \
    -out server.crt -days 3650 -sha256 \
    -extfile openssl_server.cnf -extensions v3_req

Command explanation:

  • openssl x509 -req: Command for X.509 certificate data management. The -req flag indicates that we are processing a CSR.
  • -in server.csr: Specifies the input CSR file from Step 6.
  • -CA SelfSignedCA.pem: Specifies the CA’s root certificate from Step 3.
  • -CAkey SelfSignedCA.key: Specifies the CA’s private key from Step 1. You will be prompted for the passphrase of this key if it’s encrypted.
  • -CAcreateserial: Creates and manages a serial number file (e.g., SelfSignedCA.srl). This file is necessary for the CA to keep track of issued certificates and ensure each has a unique serial number. If the file doesn’t exist, it will be created.
  • -out server.crt: The output filename for the signed server certificate.
  • -days 3650: Sets the validity period of the server certificate (e.g., 10 years). This should typically be shorter than or equal to the CA’s validity.
  • -sha256: Uses SHA-256 for the certificate signature.
  • -extfile openssl_server.cnf: Points to the OpenSSL configuration file (created in Step 5) containing certificate extensions for the server certificate.
  • -extensions v3_req: Specifies the section (v3_req) in the openssl_server.cnf configuration file that contains the X.509 v3 extensions to add to the certificate. This is where SANs, key usage, etc., are defined.

Using Your Certificates

  1. Server Configuration: Configure your web server (e.g., Apache, Nginx) or application to use the generated server.crt (your server’s certificate) and server.key (your server’s private key) files for HTTPS.
  2. Client Trust: For clients (browsers, other applications) to trust your new server certificate without warnings, they must trust your CA. You will need to import the SelfSignedCA.pem (your CA’s root certificate) into the trust store of any system or browser that needs to connect to your server. The steps for this vary depending on the operating system and browser.

You now have the foundation to create and manage your own certificates for internal or development use! Remember to keep your CA private key (SelfSignedCA.key) extremely secure.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *