Create a CA (new)

Create the initial directory structure

mkdir -p ~/ca/root_ca/{certs,crl,newcerts,private}
mkdir -p ~/ca/intermediate_ca/{certs,crl,csr,newcerts,private}
mkdir -p ~/ca/server/{certs,crl,csr,newcerts,private}
chmod 700 root_ca/private intermediate_ca/private
echo 1000 > root_ca/serial; echo 1000 > intermediate_ca/serial
echo 1000 > root_ca/crlnumber; echo 1000 > intermediate_ca/crlnumber
:>root_ca/index.txt; :>intermediate_ca/index.txt

Create config files

Create the Root CA config file

Paste the following into ~/ca/root_ca.cnf

# vim: sts=4 sw=4 ts=4 et
# OpenSSL configuration file for Root CA

[ ca ]
default_ca = CA_default

[ CA_default ]
dir                     = ./root_ca
certs                   = $dir/certs
crl_dir                 = $dir/crl
database                = $dir/index.txt
new_certs_dir           = $dir/newcerts
certificate             = $dir/certs/root_ca.crt
serial                  = $dir/serial
crlnumber               = $dir/crlnumber
private_key             = $dir/private/root_ca.key
RANDFILE                = $dir/private/.rand
x509_extensions         = v3_ca
copy_extensions         = copy
default_days            = 14600
default_crl_days        = 30
default_md              = sha512
preserve                = no
policy                  = policy_strict

[ policy_strict ]
countryName             = optional
stateOrProvinceName     = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req ]
default_bits            = 4096
default_md              = sha512
distinguished_name      = req_distinguished_name
x509_extensions         = v3_ca
string_mask             = utf8only
prompt                  = yes

[ req_distinguished_name ]
countryName             = Country Name (2 letter code)
stateOrProvinceName     = State or Province Name
localityName            = Locality Name
organizationName        = Organization Name
commonName              = Common Name

countryName_default             =
stateOrProvinceName_default     =
localityName_default            =
0.organizationName_default      =
organizationalUnitName_default  =
emailAddress_default            =
commonName_default              = Pwned Global Root CA

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

[ v3_intermediate_ca ]
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always,issuer
basicConstraints        = critical, CA:true, pathlen:0
keyUsage                = critical, cRLSign, keyCertSign

[ crl_ext ]
authorityKeyIdentifier  = keyid:always,issuer

Create the Intermediate CA config file

Paste the following into ~/ca/intermediate_ca.cnf

# vim: sts=4 sw=4 ts=4 et
# OpenSSL configuration file for Intermediate CA

[ ca ]
default_ca              = CA_default

[ CA_default ]
dir                     = ./intermediate_ca
certs                   = $dir/certs
crl_dir                 = $dir/crl
database                = $dir/index.txt
new_certs_dir           = $dir/newcerts
certificate             = $dir/certs/intermediate_ca.crt
serial                  = $dir/serial
crlnumber               = $dir/crlnumber
private_key             = $dir/private/intermediate_ca.key
RANDFILE                = $dir/private/.rand
x509_extensions         = v3_intermediate_ca
copy_extensions         = copy
default_days            = 3650
default_crl_days        = 30
default_md              = sha512
preserve                = no
policy                  = policy_loose

[ policy_loose ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req ]
default_bits            = 4096
default_md              = sha512
distinguished_name      = req_distinguished_name
x509_extensions         = v3_intermediate_ca
string_mask             = utf8only
prompt                  = yes

[ req_distinguished_name ]
countryName             = Country Name (2 letter code)
stateOrProvinceName     = State or Province Name
localityName            = Locality Name
organizationName        = Organization Name
commonName              = Common Name

countryName_default             =
stateOrProvinceName_default     =
localityName_default            =
0.organizationName_default      =
organizationalUnitName_default  =
emailAddress_default            =
commonName_default              = Pwned Global Intermediate CA

[ v3_intermediate_ca ]
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always,issuer
basicConstraints        = critical, CA:true, pathlen:0
keyUsage                = critical, cRLSign, keyCertSign

[ v3_req ]
basicConstraints        = CA:FALSE
keyUsage                = critical, digitalSignature, keyEncipherment
extendedKeyUsage        = serverAuth

[ crl_ext ]
authorityKeyIdentifier  = keyid:always,issuer

Create The Server Certificate config file

Paste the following into ~/ca/server.cnf

# vim: sts=4 sw=4 ts=4 et
# OpenSSL configuration file for Server Certificates

[ req ]
default_bits                = 2048
default_md                  = sha256
distinguished_name          = req_distinguished_name
req_extensions              = v3_req
string_mask                 = utf8only
prompt                      = yes

[ req_distinguished_name ]
countryName                 = Country Name (2 letter code)
stateOrProvinceName         = State or Province Name
localityName                = Locality Name
organizationName            = Organization Name
commonName                  = Common Name

countryName_default         = US
stateOrProvinceName_default = California
localityName_default        = Venice Beach
organizationName_default    =
commonName_default          = www.example.com

[ v3_req ]
basicConstraints            = CA:FALSE
keyUsage                    = critical, digitalSignature, keyEncipherment
extendedKeyUsage            = serverAuth
subjectAltName              = @alt_names

[ alt_names ]
DNS.1                       = www.example.com
DNS.2                       = example.com

Create all the certs

Create the Root CA

Create the Root Key

openssl genpkey -aes256 -algorithm EC -pkeyopt ec_paramgen_curve:P-384 -out root_ca/private/root_ca.key

Create the Root Certificate

openssl req -config root_ca.cnf -x509 -new -nodes -key root_ca/private/root_ca.key -sha512 -days 14600 -out root_ca/certs/root_ca.crt

Verify the Root Certificate looks good

cat root_ca/certs/root_ca.crt | openssl x509 -text -noout

Create the Intermediate CA

Create the Intermediate Key

openssl genpkey -aes256 -algorithm EC -pkeyopt ec_paramgen_curve:P-384 -out intermediate_ca/private/intermediate_ca.key

Create the Intermediate Certificate Sign Request

openssl req -config intermediate_ca.cnf -new -key intermediate_ca/private/intermediate_ca.key -out intermediate_ca/csr/intermediate_ca.csr

Sign the Intermediate CSR with the Root CA

openssl ca -config root_ca.cnf -extensions v3_intermediate_ca -days 3650 -notext -md sha512 -in intermediate_ca/csr/intermediate_ca.csr -out intermediate_ca/certs/intermediate_ca.crt

Verify the Intermediate CA Certificate looks good

cat intermediate_ca/certs/intermediate_ca.crt | openssl x509 -text -noout

Create a Certificate Chain

cat intermediate_ca/certs/intermediate_ca.crt root_ca/certs/root_ca.crt > intermediate_ca/certs/ca_chain.crt

Verify the Certificate Chain looks good

cat intermediate_ca/certs/ca_chain.crt | openssl x509 -text -noout

Create a server (leaf) certificate

Warning

You will need to modify server.cnf to fit your needs

Note

Unlike the Root and Intermediate certs, we don’t encrypt the server key with a password (Notice the missing -aes256 option) because all your applications will require you to enter the password every time you start or restart them

Create a key for your new Server Certificate

openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-384 -out server/private/server.key

Create a Certificate Signing Request using your new key

openssl req -config server.cnf -new -key server/private/server.key -out server/csr/server.csr

Sign the Server Certificate with the Intermediate CA

openssl ca -config intermediate_ca.cnf -extensions v3_req -days 365 -notext -in server/csr/server.csr -out server/certs/server.crt

Verify the Server Certificate

cat server/certs/server.crt | openssl x509 -text -noout

Verify the Chain of Trust

openssl verify -CAfile intermediate_ca/certs/ca_chain.crt server/certs/server.crt

Create a Full Chain Bundle

cat server/certs/server.crt intermediate_ca/certs/ca_chain.crt > server/certs/server.pem

Verify the Full Chain Bundle

cat server/certs/server.pem | openssl x509 -text -noout