How to create and administer X.509 Certificate chains, Part I

X.509 certificates are widely used for data transport security and integrity assertion. The first part describes the creation of a private Certificate Authority (CA) and host certificates, while the second part deals with administration of certificates. The third part will enable you to build your own administration tools based on Bash and Perl. The following examples are based on OpenSSL. In this part we describe steps to generate

  • a root signing key,
  • a private Certificate Authority
  • a host key and private signed certificate
  • a user key and private signed certificate

If you do have access to a trusted publicly available Certificate Authority you may omit the steps on how to create your own CA and proceed with how to generate a host or user certificate.

Create a Certificate Authority

In order to sign certificates, a Root Signing Key has to be created.

Important

This root key should be kept secured

As a first step a password file is prepared:

$ touch myPassfile
$ chmod 0600 myPassfile
$ echo 'secret'> myPassfile

As a second step a private Root Signing Key is generated:

$ openssl genrsa \
  -des3 \
  -passout file:myPassfile \
  -out privateRoot.key \
  2048

This will create a password secured signing key named privateRoot.key with a size of 2048 bit. The manual page genrsa(1) provides further information on available parameters.

Prior to the generation of a Certificate Authority and a certificate chain, preliminary steps have to be taken, which will ease further procedures.

  • A configuration file with parameters to initiate the CA, myCA.conf
  • A configuration file with parameters to initiate a host certificate, host.conf
  • A configuration file with X.509 extension parameters to initiate the CA, myCA.ext
  • A configuration file with X.509 extension parameters to initiate a host cert, host.ext
  • A serial file for administration purposes, myCA.serial

To create a serial file, just do

$ touch myCA.serial
$ chmod 0644 myCA.serial
$ echo '00' > myCA.serial

Now we prepare the necessary configuration files to initiate a Certificate Authority.

myCA.conf
  [ req ]
default_bits               = 2048
distinguished_name         = req_DN
string_mask                = nombstr

 [req_DN ]
countryName                = "1. Country Name      (2 letter code)"
countryName_default        = DE
countryName_min            = 2
countryName_max            = 2
stateOrProvinceName        = "2. State or Province Name (full Name)"
#stateOrProvinceName_default =
localityName               = "3. Locality Name (eg. City)"
localityName_default       = Hamburg
0.organizationName         = "4. Organization Name (eg. Company)"
0.organizationName_default = My Organization
organizationalUnitName     = "5. Organizational Unit Name (eg. section)"
organizationalUnitName_default  = Certificate Authority
commonName                 = "6. Common Name (eg. CA Name)"
commonName_max             = 64
commonName_default         = My Private CA
emailAddress               = "7. Email Address (eg. name@FQDN)"
emailAddress_max           = 40
emailAddress_default       = admin@example.com

myCA.ext

extensions = x509v3

  [ x509v3 ]
basicConstraints        = CA:true,pathlen:0
crlDistributionPoints   = URI:http://example.com/ca/myca.crl
nsCertType              = sslCA,emailCA,objCA
nsCaPolicyUrl           = "http://example.com/ca/policy.html"
nsCaRevocationUrl       = "http://example.com/ca/myca.crl"
nsComment               = "My Private CA"

For ease of administration, information on distribution points, policy URL and revocation lists URL should be provided with any CA.

In order to create a certificate request, some information on the Certificate Authority has to be provided, for this we created myCA.conf. In this configuration file a default value is set, this enables us to modify a value according to requirements. We now create a Certificate Signing Request, based on the provided information:

$ openssl req \
  -config myCA.conf \
  -new \
  -key privateRoot.key \
  -passin file:myPassfile \
  -out myPrivateCA.csr

Prior to signing this CSR, a configuration file for Certificate Authority Extensions has to be prepared, myCA.ext, as described above.

$ openssl x509 \
  -days 3650 \
  -extfile myCA.ext \
  -signkey privateRoot.key \
  -CAserial myCA.serial \
  -passin file:myPassfile \
  -in myPrivateCA.csr \
  -req \
  -out myPrivateCA.crt

Now we have a Certificate Authority in PEM format, which can be used to sign host and user certificates.

Create a Host Certificate

Web server, SMTP server, IMAP server, LDAP server and many more require Transport Layer Security and integrity of client applications and service hosts. In order to enable this requirement, a host certificate as well as the signing Certificate Authority are necessary. Thus in this chapter we describe the generation of

  • a private host key
  • a host certificate
  • a configuration file host.conf
  • a configuration file host.ext

As a first step , a file``host.conf`` is prepared:

host.conf
  [ req ]
default_bits               = 2048
distinguished_name         = req_DN
string_mask                = nombstr

  [req_DN ]
countryName                = "1. Country Name      (2 letter code)"
countryName_default        = DE
countryName_min            = 2
countryName_max            = 2
stateOrProvinceName        = "2. State or Province Name (full Name)"
#stateOrProvinceName_default =
localityName               = "3. Locality Name (eg. City)"
localityName_default       = Hamburg
0.organizationName         = "4. Organization Name (eg. Company)"
0.organizationName_default = My Organization
organizationalUnitName     = "5. Organizational Unit Name (eg. section)"
organizationalUnitName_default  = My Server
commonName                 = "6. Common Name (eg. CA Name)"
commonName_max             = 64
commonName_default         = host.example.com
emailAddress               = "7. Email Address (eg. name@FQDN)"
emailAddress_max           = 40
emailAddress_default       = admin@example.com

host.ext

extensions = x509v3

  [ x509v3 ]
nsCertType              = server
keyUsage                = digitalSignature,nonRepudiation,keyEncipherment
extendedKeyUsage        = msSGC,nsSGC,serverAuth
subjectAltName          = DNS:ldap.example.com

The attribute type commonName takes the FQHN as value, the subjectAltName attribute type allows to specify multiple host name aliases, separated by comma.

First, a private host key is created:

$ touch hostPassfile
$ chmod 0600 hostPassfile
$ echo 'secret' > hostPassfile
$ openssl genrsa \
  -des3 \
  -passout file:hostPassfile \
  -out myHost.key \
  2048

Tip

If you don't want a password secured host key, just call:

$ openssl genrsa -out myHost.key 2048

Next a certificate signing request is initiated:

$ openssl req \
  -config host.conf \
  -new \
  -key myHost.key \
  -passin file:hostPassfile \
  -out MyHost.csr

And finally a host certificate can be signed:

$ openssl x509 \
  -days 1825 \
  -extfile host.ext \
  -CA myPrivateCA.crt \
  -CAkey privateRoot.key
  -passin file:myPassfile \
  -CAserial myCA.serial \
  -in MyHost.csr \
  -req \
  -out myHost.crt

Now a host certificate, a host certificate key, and a certificate authority are available. Next we will prepare a user certificate

Create a User Certificate

User certificates generally are used for authentication purposes and email signing. The same steps as used before are necessary to create a user key and a user certificate. In addition the full certificate chain may be archived in a pkcs12 file. As with host certificates, a few preliminaries are required:

  • a user.conf file
  • a user.ext file
  • a user.key
  • a user certificate

First a user.conf file is created:

user.conf

     [ req ]
default_bits       = 2048
distinguished_name = req_DN
string_mask        = nombstr

     [ req_DN ]
countryName                        = "1. Country Name             (2 letter code)"
countryName_default             = DE
countryName_min                 = 2
countryName_max                 = 2r
stateOrProvinceName             = "2. State or Province Name   (full name)    "
#stateOrProvinceName_default     =
localityName                    = "3. Locality Name            (eg, city)     "
localityName_default            = Hamburg
0.organizationName              = "4. Organization Name        (eg, company)  "
0.organizationName_default      = My Organization
organizationalUnitName          = "5. Organizational Unit Name (eg, section)  "
organizationalUnitName_default  =  People
commonName                      = "6. Common Name              (eg, CA name)  "
commonName_max                  = 64
commonName_default              = Paul Smith
emailAddress                    = "7. Email Address            (eg, name@FQDN)"
emailAddress_max                = 40
emailAddress_default            = paul@example.com

This data set will generate the certificate distinguished name:

dn: cn=Paul Smith,ou=People,o=My Organization,c=DE

user.ext

  extensions = x509v3

  [ x509v3 ]
nsCertType = client,email,objsign
keyUsage   = digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment

First a private password file and a private key is generated:

$ touch userPassfile
$ chmod 0600 userPassfile
$ echo 'secret' > userPassfile
$ openssl genrsa \
  -des3 \
  -passout file:userPassfile \
  -out myUser.key \
  2048

Next a user certificate signing request is created:

$ openssl req \
  -config user.conf \
  -new \
  -key myUser.key \
  -passin file:userPassfile \
  -out MyUser.csr

And finally the user certificate is signed:

$ openssl x509 \
 -days 1825 \
 -extfile user.ext \
 -CA myPrivateCA.crt \
 -CAkey privateRoot.key
 -passin file:myPassfile \
 -CAserial myCA.serial \
 -in MyUser.csr \
 -req \
 -out myUser.crt

Now we have a valid certificate chain, which will enable us to create a pkcs12 archiv.

$ openssl pkcs12 \
  -export \
  -in myUser.crt \
  -inkey myUser.key \
  -passin file:userPassfile \
  -CAfile myPrivateCA.crt \
  -name MyUsercertificate \
  -out myUser.pkcs12

In Part II we will discuss the administration of certificates, maintain the serial file and index file.


Comments

  1. Brett Nelson

    Brett Nelson (2 years, 3 months) # Reply

    Am wondering for it to be a chain wouldn't the User cert be signed by the intermediate host key instead of the root key? This appears to put both the host and user key at the same level.

  2. Pablo Cosio

    Pablo Cosio (2 years, 2 months) # Reply

    Sorry, where is the part II that talks about serial file?

  3. Ben Solaj

    Ben Solaj (1 year, 11 months) # Reply

    Just a security reminder to be conscient of third command, it will reappear at a lot of places, be it in process list, in .bashrc which often is found to be readable by ordinary users... Use "cat >myPassfile" instead. And if you haven't done so before, check your .psql_history and .viminfo and ... as well, you'll be surprised.

Comments are closed.