How to become your own certificate authority (CA)


My notes (that I never remember) on creating a self-signed root CA.


  • 20151105 — migrated to medium
  • 20170321 — migrated from sha1 to sha2 (sha512)

Create the CA

First, setup the standard directory structure

# mkdir ca
# cd ca
# mkdir certs newcerts crl requests
# mkdir -m 0700 private

N.B. the rest of this document presumes your working directory is ca

Copy openssl.cnf

while not necessary since the openssl.cnf has the CA sections separate from the user sections, i like to get my ca setup self contained in a directory

  • Cygwin
$ cp /usr/ssl/openssl.cnf ./
  • RedHat (CentOS)
# cp /etc/pki/tls/openssl.cnf ./
  • Debian (Ubuntu)
# cp /etc/ssl/openssl.cnf ./
  • MacOSX (El Capitan)
$ cp /System/Library/OpenSSL/openssl.cnf ./

Set openssl.cnf permissions

# chmod 0600 openssl.cnf

Edit openssl.cnf

dir = .
certificate = $dir/certs/
private_key = $dir/private/
countryName_default = US
stateOrProvinceName_default = california
localityName_default = los angeles
0.organizationName_default =
organizationalUnitName_default = information assurance directorate
commonName_default = certificate authority
emailAddress_default =
default_md = sha512 # which message digest to use.
keyUsage = cRLSign, keyCertSign
nsCertType = sslCA,emailCA,objCA

Setup db and serial files

# touch index.txt
# echo 01 > serial

Generate the CA keypair

# openssl req -config openssl.cnf -newkey rsa:4096 -sha512 -x509 -extensions v3_ca -keyout private/ -out certs/ -days 1825

N.B. the common name (CN) here is the name of the certificate that will display in the certificate manager.

Signing a request

When a request is received place the .csr file in the requests directory then execute:

# openssl ca -config openssl.cnf -policy policy_anything -infiles requests/server.csr

There are two default policies defined in a default openssl.cnf: 1. policy_match (default) — which requires that the country, state, and organizational unit all matches and common name is supplied 2. policy_anything — common name is supplied

all other fields are optional

N.B. to specify a policy on the commandline use -policy policy_name

what this does:

  • shows you the request and asks if you would like to sign it
  • backup database index file (index.txt) to *.old
  • stores signing in database index file
  • creates database index attributes file (index.txt.attr)
  • asks for commit
  • backup serial to serial.old
  • increments the serial
  • stores signed certificate in newcert/NN.pem (this is the filethat should be sent back to the requester)

N.B. using -out certs/server.crt, above, can optionally be used to pick the output path/filename

Signing an intermediate CA request

While the CSR portion is the same as a regular request, signing is a little different. you must sign a CA as a CA (of course); for example:

# openssl ca -extensions v3_ca -policy policy_anything -config openssl.cnf -infiles requests/


  • sha-1 (default)
$ openssl x509 -noout -in certs/cryp7ca.crt -fingerprint
  • md5
$ openssl x509 -noout -in certs/cryp7ca.crt -fingerprint -md5
  • sha256
$ openssl x509 -noout -in certs/cryp7ca.crt -fingerprint -sha256
  • sha512
$ openssl x509 -noout -in certs/cryp7ca.crt -fingerprint -sha512

Generating Diffie-Hellman pairs (e.g. for use with an OpenVPN server)

# openssl dhparam -out private/dh-1024.key 1024

N.B. In the previous example the integer ‘’’1024'’’ is the key size and may be modified. See dhparam(1).

N.B. performing this step is equivalent to running ‘’’./build-dh’’’ in section “Generate Diffie Hellman parameters” of Setting up your own Certificate Authority (CA) and generating certificates and keys for an OpenVPN server and multiple clients.

File extension definitions

  • key — private key
  • csr — certificate signing request
  • crt — certificate
  • crl — certificate revocation list
  • pem — Base64-encoded x.509 certificate

See Also