Self Signed Ca Certificate Openssl

Create a Self Signed Certificate using openssl commands Now you can take CSR (cyberithub.csr) and private key (testserver.key) to create a self signed certificate with a validity of 365 days using below openssl commands. You can create a self signed code signing certificate using OpenSSL. Or, for Windows 10 users, you can use PowerShell’s New-SelfSignedCertificate, an automated script that makes the job of creating such certificates easier for you.

A self-signed certificate is one that is obtained without going through any third-party certificate authority. TLS/SSL is a combination of a public certificate and a private key. The private key is stored securely on the server or on the load balancer, whereas the certificate is publicly accessible.

🚨 This page covers approaches for self-signed certs; these are useful for local dev work, testing, and special use-cases. For actual production websites, you should not be using self-signed certificates - if you want a free alternative to paid SSL certs, I cannot recommend Let's Encrypt enough!

  1. Create Root Certificate Authority and self-signed certificate for your Home Assistant. Compatible with Chrome browser version 58, including the macOS Catalina 10.15 / iOS 13 (and above) new requirements. Create Root Key. Attention: this is the key used to sign the certificate requests, anyone holding this can sign certificates on your behalf.
  2. This article was written for version 1.0.1f of openssl, it could work on both lower and higher version if nothing else is stated. This is a short instruction on how you can create your own CA certificate & then generate a client certificate based on this CA.

Table of Contents

Self-Signed SSL Certificates: Basic Requirements

The basic requirements for local SSL hosting, and setting up self-signed SSL in general, are:

  • A private key (.pem)
  • A CSR (Certificate Signing Request)
  • A public certificate (usually .crt, sometimes .pem too)

The CSR is kind of intermediate step between the key and the cert (the CSR is signed by the key to become the cert, so in many cases it is temporarily created via a prompt). You can think of the cert as being derived from the key, via the CSR.

πŸ’‘ SSL cert pairs are often referred to with the X.509 identifier; this is essentially the standard that is used for TLS/SSL, but it is used for other purposes as well.

However, how you generate these is a little more complicated than how you might normally generate key-pairs with OpenSSL, since it is best practice to provide more configuration inputs to create the certificate, such as DNS entries that can use the certificate. There are also different approaches, based on how you want to use the cert you are generating.

πŸ’‘ If you are on Windows, there is a handy built-in Powershell Cmdlet that simplifies generating a local dev certificate a lot! - the New-SelfSignedCertificate command.

πŸ’‘ Also, don't forget that if you want to use a custom local domain (like using mydomain.test instead of localhost) you need to edit your local HOSTS file to add an entry resolving localhost (or 127.0.0.1) to that custom local domain.

Using OpenSSL to Generate Self-Signed Certs

Before you get started with any of the above approaches, you are going to need the actual OpenSSL binary. There are pretty good chances you might already have it installed (especially if you do a fair amount of dev work) - try running where openssl (Windows), or which openssl (Unix).

If you need a new copy, you can either build from source, or grab a pre-built binary.

You can check the version of local binary with openssl version.

Now, on to how to actually use OpenSSL to generate your own cert! πŸ‘‡

OpenSSL - Temporary CSR - Prompt Based

With this method, you don't need to create a CSR as a separate step; instead OpenSSL will prompt you (via the CLI) for the minimum information it needs to temporarily create a CSR, then use that temporary CSR with your private key to generate cert.

This method is commonly recommended, because it involves the least steps.

Explanation of command parts:

  • req: This is the main command we are passing to OpenSSL - it asks OpenSSL to generate a CSR for us. (Docs).

    • The rest of the arguments we provide can be found on the doc for this command
  • -newkey: Says that we want both a new CSR and a new private key

    • rsa:4096: algorithm and number of bits to use when creating the private key. Many versions of OpenSSL now use 2048 as the default bit size
    • -nodes: Tells OpenSSL not to encrypt the private key with a password / passphrase. Normally, this is a bad idea, but since this is a throwaway local self-signed cert for development purposes, adding a password adds unnecessary steps to our setup.
    • -keyout domain.key: Save the generated private key to domain.key file. We can use any filname we want
  • -x509: Important: This tells OpenSSL that the output of our command should be a Self-Signed Certificate, not the CSR used to generate it.

    • -sha256: Explicitly specifies the algorithm, for the message digest, used to sign the CSR and generate the final certificate. The default is now sha256, but it is worth explicitly declaring, since older versions default to insecure MD5.
    • -days 365: How long the cert should be valid for, before it expires.

      • If you are going to add a permanent exception to your browser to trust the local cert, you should probably put this to a shorter value to avoid adding too much extra risk
    • out domain.crt: Tells OpenSSL where to save our generated cert file. You can use any filename.

OpenSSL - Generating Self-Signed Cert Without Prompts

This is very similar to the above approach, but instead of filling out the CLI Q&A prompt that OpenSSL gives us, we can pass in pre-configured values to use with the CSR. This is useful if we want to be able to share a configuration that other devs can use to generate their own local certs, create a base template config, etc.

Openssl self signed certificate own ca

You can pass configuration values either entirely through the CLI, as arguments, or by giving OpenSSL the filename of a plain-text file where you have saved the values (in a specific config file format).

OpenSSL - Self-Signed Cert Without Prompt - Using Arguments

πŸ“„ Here is a doc page specifically for x509 (cert) arguments

Argument Based:

If the above command failed for you (perhaps with req: Unknown digest addext), check your version of OpenSSL (with openssl version). If it is below v1.1.1, you either need to use a config file to pass in extension values (see below), or use some tricky bash sub-shell stuff.

OpenSSL - Self-Signed Cert Without Prompt - Using Config File

These files are usually called __.conf (e.g. mydomain.conf), and they follow a specific INI-like format. The syntax can be a little confusing (here is an unofficial doc page that is helpful).

One really important thing to note about the config file syntax is that often values are passed by section lookup, rather than directly. So, for example, if we wanted to pass custom alternative names (DNS entries), we would pass a pointer to the section of the config where we have entered those values.
In this scenario, we can use any header name we want, but assuming we went with alternate_names, we would need a key-pair under our extensions with subjectAltName = @alternate_names, and then a section with the header [alternate_names ], under which our DNS entries are stored (e.g. DNS.1 = localhost).

πŸ“„ For config keys that go with req, see the bottom of the req man page

πŸ“„ Here is a doc page specifically for x509 (cert) config sections

To actually load the config values, use the -config argument, and pass your filename. For example, here is the typical command to generate a private key and self-signed cert, with input from a config.

Generate

Example Config File, with comments:

Above Example Config, Without Comments

OpenSSL - Saving a Generated CSR

If you want to save the generated CSR, instead of having OpenSSL just temporarily use and throw away the one it uses to create a cert, you just need to change a few arguments.

  • Remove -x509 (this targets Cert as output, not CSR, so don't want it)
  • Change -out domain.crt to -out domain.csr (or whatever filename you prefer)

You can export the CSR while:

  • also generating a new private key

    • keep -newkey and -keyout
  • or with an existing private key

    • Remove -newkey and -keyout, add -key mykeyfile.key
Self Signed Ca Certificate Openssl

Since the Cert is created by signing CSR values with your key, you can also reverse the process, and actually generate a CSR from an existing public certificate, assuming you have the private key:

Self Signed Ca Certificate Openssl

OpenSSL - Using an Existing Saved CSR File to Generate a New Certificate

If you already have a saved CSR and private key, you skip providing all the information needed to generate the CSR:

  • Remove -newkey and -keyout, remove `-out

    OpenSSL - Verifying and Viewing SSL Info

  • CSR

    • openssl req -text -noout -verify -in domain.csr
  • Certificate

    • openssl x509 -text -noout -in domain.crt

Generating Certificates: Scripts and Generator Tools

🚨 Be very careful about tools (and try to avoid them) that work by installing a global / root level CA / certificate; this opens a large security hole in your dev environment. See this post for an explanation.

πŸ“„ If you find it easier to read code, rather than bash commands, you might find it helpful to look at how mockttp handles TLS.

These are tools that can make creating local certs a little less painful than a bunch of hard to remember commands. Most of these are just wrappers around OpenSSL.

  • mkcert (🚨 = Uses root CA)
  • Windows Built-in Tools:

    • New-SelfSignedCertificate (Powershell Cmdlet)
    • MakeCert.exe (Deprecated)

Local Hosting - Trusting a Self-Signed Cert

Once you have your certificate generated, that's not actually the end of the work necessary to use SSL locally. Because browsers (generally) don't trust self-signed certificates, you need to an exception to allow your specific certificate to be trusted.

As a best practice, trusting a local self-signed certificate should be done temporary, and on a per-site basis (not with a root / global / shared CA).

Temporary certificate trusting:

  1. Get the fingerprint of the cert

    • openssl x509 -pubkey -noout -in {CERT_PATH} openssl pkey -pubin -outform der openssl dgst -sha256 -binary openssl enc -base64 (credit)

      • Or
    • openssl x509 -pubkey < {CERT_PATH} openssl pkey -pubin -outform der openssl dgst -sha256 -binary base64 (Credit)
  2. Launch Chrome, temporarily, with the fingerprint of the cert to trust:

    • chrome --ignore-certificate-errors-spki-list={FINGERPRINT}

      • OR
    • chrome --ignore-certificate-errors-spki-list=$(cat fingerprints.txt)
    • Also, you can pass your domain as the last argument to have it automatically open to that page

πŸ’‘ For Chrome, you probably also want / need to have it force opened in a new instance, rather than your normal browser. You can do this with either chrome --user-data-dir=tmp, or, on Windows, chrome --user-data-dir=%TEMP%

Other Resources

Generate Ssl Certificate

Other guidesOpenssl

Openssl Create Self Signed Ca

  • DigitalOcean: 'OpenSSL Essentials'
  • StackOverflow: 'How to create a self-signed certificate with OpenSSL