SSL Private Key, Signing Request, Certificate Generation and Apache Configuration

Posted on Oct 13, 2016

Preparation

Versions prior to Apache v2.2.12 and OpenSSL v0.9.8j required a dedicated IP address for each certificate. With Server Name Indication (SNI) there is no need to request a new IP every time a certificate needs to be installed for a domain.

SNI can secure:

  • Multiple Apache sites with a single certificate
  • Multiple subdomains of a domains with multiple certificates
  • Multiple domains from a single IP address

With that said, you don’t have to request a dedicated IP address for sites that use SSL certificates.

In order to create certificates or certificate signing requests (CSR) and use them, openssl, apache, and mod_ssl must be installed on the system.

If you are purchasing an SSL certificate from a company such as DigiCert or GoDaddy you need to generate a Certificate Signing Request (CSR):



openssl req -out CSR.csr -new -newkey rsa:2048 -nodes -keyout privateKey.key
openssl req -out CSR.csr -key privateKey.key -new
openssl x509 -x509toreq -in certificate.crt -out CSR.csr -signkey privateKey.key

The first command creates a new CSR and private key. If you don’t need a new private key, then you can create a new CSR based on your existing key by using the second command. A third way to create a CSR is to use an existing certificate, but you need the private key in order to do so. The req sub-command creates and processes certificate requests by taking various commandline options. When the --out option is used in conjunction with the req sub-command, it takes a parameter that specifies where the CSR will be placed.

The --new option specifies that we want to create a new private key causing OpenSSL to ask the user for values for relevant fields.--newkey takes the form of algorithm:bits. In the above example, we are creating a private key using the RSA algorithm with a length of 2048 bits. Other algorithms support the format of algorithm:file where file contains the parameters for the algorithm specified. This file is generated by using the genpkey sub-command. 
--nodes specify that the key is not to be password protected.
--keyout specifies the name of the file to write the private key to.

The x509 sub-command is used to view information about, convert, and sign certificates specified by the -in option. The -x509toreq specifies that a CSR is to be generated from the certificate. The -signkey is used to pass the private key that’s required when generating the CSR.

If you can get away with a self-signed certificate:



openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout privateKey.key -out certificate.crt

Most of the command-line options used in creating a self-signed certificate are used in creating a CSR from a new or existing private key. The -x509 outputs the self-signed certificate rather a CSR, which is valid for the number of days specified by -days option.

Verifying



openssl req -text -noout -verify -in request.csr

The above retrieves the containing in the signing request by displaying the text (-text, -noout). The -verify command-line option indicates that the user wants to verify the file specified by -in.

To ensure that private key is valid, run the following command.



$ openssl rsa -in private.key -check

To print the certificate:



openssl x509 -in certificate.crt -noout -text
Certificate:
  Data:
  Version: 3 (0x2)
  Serial Number:
  a2:42:e1:14:66:96:5c:8f
  Signature Algorithm: sha256WithRSAEncryption
  Issuer: C=US, ST=Texas, L=Dallas, O=Paulus World, OU=IT, CN=paulusworld.com/emailAddress=webmaster@paulusworld.com
  Validity
  Not Before: Oct 12 07:46:50 2016 GMT
  Not After : Oct 12 07:46:50 2017 GMT
  Subject: C=US, ST=Texas, L=Dallas, O=Paulus World, OU=IT, CN=paulusworld.com/emailAddress=webmaster@paulusworld.com
  Subject Public Key Info:
  Public Key Algorithm: rsaEncryption
  Public-Key: (2048 bit)
  Modulus:
  00:f4:5f:d8:67:ea:dd:bd:c4:ad:75:4a:40:42:2e:
  a6:0a:6f:af:7d:e4:1d:c9:c8:04:ec:ae:8e:07:58:
  4a:1d:49:3b:a7:0a:4f:02:79:cc:4d:5e:11:c8:24:
  47:77:be:ff:b6:f2:55:1f:8a:f3:61:18:5f:96:08:
  27:7e:2b:50:fb:97:45:69:82:c2:ff:71:bb:89:6e:
  63:35:d6:5e:4b:df:87:9a:81:b0:73:c4:fb:69:d4:
  e7:40:3e:7d:65:7a:a0:86:69:ea:09:a0:ee:c1:e1:
  4f:54:b4:e7:f2:3c:25:b8:ad:c4:5b:25:af:25:37:
  b8:bb:e5:31:09:b7:47:4d:94:48:ee:b8:bd:1c:1f:
  95:88:04:eb:e6:73:22:3b:0a:39:a6:c1:d3:65:0e:
  28:0d:6b:5d:17:9d:20:71:21:2b:d9:5e:65:0f:cf:
  87:d0:cd:90:4e:a9:65:4f:81:15:f9:1a:8a:3c:23:
  aa:0e:e7:c8:32:51:ce:f9:f3:63:da:12:6a:6d:65:
  6a:dd:0f:02:6e:1b:26:d3:59:de:aa:c7:8b:37:d7:
  ed:31:ad:a8:5d:f8:2d:b7:e6:fa:70:29:96:cd:e3:
  94:e3:18:fa:ed:29:16:11:c4:e3:34:fc:73:a7:ce:
  9d:83:f6:ff:c5:fa:a1:85:7d:27:40:3e:71:71:c3:
  94:fd
  Exponent: 65537 (0x10001)
  X509v3 extensions:
  X509v3 Subject Key Identifier:
  9D:99:53:68:2E:77:28:48:34:4B:44:53:85:6C:CB:24:9F:B7:F0:7A
  X509v3 Authority Key Identifier:
  keyid:9D:99:53:68:2E:77:28:48:34:4B:44:53:85:6C:CB:24:9F:B7:F0:7A
  X509v3 Basic Constraints:
  CA:TRUE
  Signature Algorithm: sha256WithRSAEncryption
  86:e6:80:9f:d8:9e:e1:2a:7a:1b:bd:fa:a5:1a:60:30:dd:ee:
  cb:d7:8a:17:4e:90:35:2c:d3:24:ba:29:b5:c9:64:a2:1d:f2:
  9c:77:46:fd:d8:d5:5e:91:af:b6:37:42:b2:4f:72:e4:99:7d:
  57:be:a5:25:41:9a:9e:19:b7:be:09:7e:84:2f:87:b0:54:a7:
  b2:82:1c:4c:9d:54:09:e7:86:97:b6:f2:c9:94:4b:59:e2:ed:
  55:e7:46:f8:17:75:19:12:bc:70:f9:81:c8:f3:d7:c3:b4:9b:
  c9:66:e5:f3:80:46:08:ab:44:84:27:ca:c5:8c:b6:c1:79:93:
  9f:75:e4:d5:9a:77:70:95:5c:85:d7:38:87:ad:96:f1:21:f0:
  8a:42:b6:6c:46:cd:6e:95:35:f2:57:4e:ef:48:47:29:22:20:
  cc:56:86:08:fb:96:4b:c0:0d:1b:93:c6:6c:02:98:9d:25:21:
  ed:3d:8a:ff:e0:09:c7:bb:de:78:2b:87:14:72:ba:22:2b:8d:
  ed:5d:f9:1f:36:5e:d0:8e:db:c1:82:72:75:bd:45:72:a9:61:
  50:99:25:b8:58:7f:4f:70:a4:76:36:1a:15:c8:c6:95:4f:e1:
  4d:b0:5b:a0:04:2a:5f:e8:4f:97:ec:b4:7b:cc:06:fb:37:90:
  d4:aa:84:3a

To check a PKCS#12 file:



openssl pkcs12 -info -in keyStore.p12

Configuration

The minimal configuration lines that are needed are to enable SSL:

<VirtualHost *:443>
     ServerName www.example.com
     SSLEngine On
     SSLCertificateFile "/path/to/file.crt"
     SSLCertificateKeyFile "/parth/to/file.key"
</VirtualHost>

The default and global SSL configuration settings are stored in a separate file located either in the /etc/httpd, /etc/apache or a subdirectory within the aforementioned directories.

When setting up a domain on a server that isn’t managed by a control panel such as Plesk or cPanel, I break up the configuration for each virtual host based on domain. Each HTTP and HTTPS virtual host configuration lives in their own file located in either vhosts or ssl_vhosts, respectively.

/etc/httpd/conf/vhosts/example_com.conf

<VirtualHost *:80>
     ServerName example.com
     ServerAlias www.example.com
     ServerAdmin webmaster@example.com
     ErrorLog "/path/to/logs/error_log"
     CustomLog "/path/to/logs/access_log" combined
     DocumentRoot "/path/to/web/root"
     <Directory "/path/to/web/root">
          Options -Indexes -FollowSymLinks
          AllowOverride None
          # Redirects &amp; Rewrites
          Include example.inc
          Require all granted
     </Directory>
</VirtualHost>

/etc/httpd/conf/ssl_vhosts/example_com.conf

<VirtualHost *:443>
     ServerName example.com
     ServerAlias www.example.com
     ServerAdmin webmaster@example.com
     ErrorLog "/path/to/logs/ssl-error_log"
     CustomLog "/path/to/logs/ssl-access_log" combined
     SSLEngine On
     # Specify Protocol
     SSLProtocol -All +TLSv1.2
     SSLHonorCypherOrder On
     SSLCipherSuite SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5
     SSLCertificateFile "/path/to/file.crt"
     SSLCertificateKeyFile "/path/to/file.key"
     SSLCertificateChainFile "/path/to/bundle.ctr"
     DocumentRoot "/path/to/we/root"
     <Directory "/path/to/web/root">
          Include example_com.inc
     </Directory>
</VirtualHost>

Troubleshooting

To verify a certificate using the commandline:



openssl s_client -showcerts -connect example.com:443

Converting Certificates

Convert a DER file (.crt .cer .der) to PEM



openssl x509 -inform der -in certificate.cer -out certificate.pem

Convert a PEM file to DER



openssl x509 -outform der -in certificate.pem -out certificate.der

Convert a PKCS#12 file (.pfx .p12) containing a private key and certificates to PEM



openssl pkcs12 -in keyStore.pfx -out keyStore.pem -nodes

You can add -nocerts to only output the private key or add -nokeys to only output the certificates.

Convert a PEM certificate file and a private key to PKCS#12 (.pfx .p12)



openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile CACert.crt