Skip to content

Instantly share code, notes, and snippets.

@HelioCampos
Forked from gabrielfalcao/create-a-ca.md
Created June 1, 2016 17:52
Show Gist options
  • Save HelioCampos/6c6a56909a3d721663a730f31b65c7a8 to your computer and use it in GitHub Desktop.
Save HelioCampos/6c6a56909a3d721663a730f31b65c7a8 to your computer and use it in GitHub Desktop.
How to create a CA to emit SSL certificates (transcription to markdown from https://www.phildev.net/ssl/creating_ca.html)

Creating a CA

Creating a Certificate Authority is easy. There are many scripts out there to do it for you. However, creating a CA that is easy to manage can be tricky. This should walk you through creating a CA and explain all the pieces.

Note: This page takes an extra step to make a fairly PKIX-compliant Certificate Authority. In pariticular, it ensures that the email address associated with your CA is in the SubjectAltName extension rather than in the DN. The former is the PKIX and X509v3 standard way of presenting an email address while the later is the old X509v1 way.

Initial Preparation

1. Create the directory your CA will live in

mkdir -p CA/{certsdb,certreqs,crl,private}

Here's what each of those directories do:

  • certsdb: This is where signed certs will be stored

  • certreqs: This is where copies of the original CSRs will be stored

  • crl: This is where your CRL will be stored

  • private: This is where the private key for the CA will live

2. Protect your private directory

chmod 700 CA/private

3. Create the flat-file DB for your certificates

This is where a list of all signed certs will go. Openssl will use this to keep track of what's happened.

touch CA/index.txt

Configuration

1. Copy over openssl conf

You'll want to make a configuration file for the CA separate from the system openssl configuration file. So move into the CA directory, and make a copy:

cd CA
cp /etc/openssl.cnf .

Your system openssl.cnf may be in some place other than /etc/openssl.cnf. If it's not there, try /usr/lib/ssl/openssl.cnf or /usr/share/ssl/openssl.cnf. If all else fails, run locate openssl.cnf.

2. Make changes in the conf file

More details about the options in the openssl docs

Now, in order to make sure the CA itself has the email in SubjectAltName instead of the Subject (for PKIX compliance), ensure that your [ v3_req ] section has subjectAltName = email:move.

If you'd prefer the old v1-style way of email in the Subject, simply remove this line.

Next, unfortunately since openssl doesn't always handle things nicely, we need to make a copy of both the v3_ca and usr_cert sections. Then to the original's, we'll add the line SubjectAltName = email:move.

Again, this is necessary for a PKIX compliant CA. Skip this step if you prefer the old way.

This will look like:

####################################################################
# Extensions for when we sign normal certs (specified as default)
[ usr_cert ]
basicConstraints = CA:false
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
subjectAltName = email:move

####################################################################
# Same as above, but cert req already has SubjectAltName
[ usr_cert_has_san ]
basicConstraints = CA:false
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer

####################################################################
# Extensions to use when signing a CA
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = CA:true
subjectAltName=email:move

####################################################################
# Same as above, but CA req already has SubjectAltName
[ v3_ca_has_san ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = CA:true

The reason we have to do this is that if you have subjectAltName = email:move set when signing a certificate that doesn't have an email in the subject (i.e. is already PKIX compliant), openssl will 'move' the email from the subject (since it's not there, that's null) to the SubjectAltName extension thus deleting the original.

Remember, you use a section with the -extensions argument.

Decide on a CRL distribution method. In order to revoke certificates, you need to make a CRL publically available. This is usually done via a web server. For this example, we'll say you're going to put your CRL at http://www.example.com/example_ca.crl.

Then you'll need to add this information to all 4 extension sections: the v3_ca, v3_ca_has_san, usr_cert, and usr_cert_has_san sections.

To do that, add a line to each section as follows:

crlDistributionPoints = URI:http://www.example.com/example_ca.crl

Again, be sure to put this all 4 extension sections.

Create the CA!

1.Create the keypair (private key and CSR)

openssl req -new -newkey rsa:2048 -keyout private/cakey.pem -out careq.pem -config ./openssl.cnf
What is what:
  • -new denotes a new keypair
  • -newkey rsa:2048 specifies the size and type of your private key: RSA 2048-bit
  • -keyout dictates where they new private key will go
  • -out determines where the request will go
  • -config tells openssl to use our config rather than the default config.

2. Self-sign the CSR to make your CA CRT

openssl ca -create_serial \
    -out cacert.pem \
    -days 365 -keyfile private/cakey.pem \
    -selfsign \
    -extensions v3_ca_has_san \
    -config ./openssl.cnf \
    -infiles careq.pem

Note the choice of v3_ca_has_san here. If you prefer the old-style, simply use v3_ca here instead.

  • -create_serial is especially important. Many HOW-TOs will have you echo "01" into the serial file thus starting the serial number at 1, and using 8-bit serial numbers instead of 128-bit serial numbers. This will generate a random 128-bit serial number to start with. The randomness helps to ensure that if you make a mistake and start over, you won't overwrite existing serial numbers out there.

  • -out determines where the self-signed certificate will go.

  • -days determines how long the certificate will be valid for.

  • -keyfile specifies the private key to use for signing (this was created in the last step).

  • -selfsign tells openssl to use the data from the CSR when signing instead of expecting a CA CRT.

  • -extensions tells openssl to use the v3_root_ca section of the config we added above to determine what extensions to use.

  • -config again specifies our config.

  • -infiles specifies what to sign, which in this case is the CSR for our new CA.

Note that while you can use req to create a self-signed certificate all in one step, req does not support the '-create_serial' option, and does not leave the intermediate CSR for you (though you can generate later), and thus is not the best option.

You now have a functional Certificate Authority. See Managing your CA for information on signing certificates, creating CRLs, and other management tasks. If you need to change an existing CA, see Modifying your CA.

original source

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment