SSL Private Key, Signing Request, Certificate Generation and Apache Configuration
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 & 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