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.
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
chmod 700 CA/private
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
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
.
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.
openssl req -new -newkey rsa:2048 -keyout private/cakey.pem -out careq.pem -config ./openssl.cnf
-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.
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.