====== SSL Certificate Management ======
===== Generate Certificate Request =====
Most CAs will require a person to submit a certificate signing request (CSR)...
With Chrome v58, the developers removed support for Common Name checking so you need to generate certificate request including the SAN (Subject Alternative Name) field to be accepted by Chrome browser.
To generate a request with the SAN field, execute the following:
cat > san.cnf << EOF
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = req_ext
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
organizationName = Organization Name (eg, company)
commonName = Common Name (e.g. server FQDN or YOUR name)
[ req_ext ]
subjectAltName = @alt_names
[alt_names]
DNS.1 = example.com
DNS.2 = www.example.com
EOF
Then execute the following:
openssl req -nodes -days 365 -sha256 -newkey rsa:2048 -keyout cert.key -out cert.csr -config san.cnf
Fill in the information for the request similar to this transcript:
Generating a 2048 bit RSA private key
...............................................+++
........................................+++
writing new private key to 'cert.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:US
State or Province Name (full name) []:New York
Locality Name (eg, city) []:New York
Organization Name (eg, company) []:My Organization, LLC
Common Name (e.g. server FQDN or YOUR name) []:www.example.com
You have to send cert.csr to a certificate signer authority so they can provide you a certificate.
===== Self-Sign Certificate =====
Creating a self-signed test certificate is as easy as executing
openssl req -x509 -nodes -days 365 -sha256 -newkey rsa:2048-keyout cert.key -out cert.pem
===== Certificate Formats =====
There are various formats for certificates and each platform/development framework seem to want to use different formats. Here is a brief and partial list of the various formats that I have ran into.
=== PEM ===
The PEM format is the most common format that Certificate Authorities issue certificates in. They are Base64 encoded ASCII files and usually contain server certificates, intermediate certificates, and private keys. Apache and other similar servers use PEM format certificates. Several PEM certificates, and even the private key, can be included in one PEM file, but Apache expects the certificates and private key to be in separate files.
=== DER ===
The DER format is a binary form of a certificate instead of the ASCII PEM format. It sometimes has a file extension of .der but can also have a file extension of .cer. All types of certificates and private keys can be encoded in DER format. DER is typically used with Java platforms.
=== PKCS#7/P7B ===
The PKCS#7 or P7B format is usually stored in Base64 ASCII format and has a file extention of .p7b or .p7c. A P7B file only contains certificates and chain certificates, not the private key. Several platforms support P7B files including Microsoft Windows and Java Tomcat.
=== PKCS#12/PFX ===
The PKCS#12 or PFX format is a binary format for storing the server certificate, any intermediate certificates, and the private key in one encryptable file. PFX files usually have extensions such as .pfx and .p12. PFX files are typically used on Windows machines to import and export certificates and private keys.
===== Certificate Format Conversions =====
Sometimes I have to convert between formats to use with the various platforms and frameworks that I deal with. I always try to convert to/from a PEM certificate. Some of the conversions require the various components of the certificate. There are two ways to do this:
- Open a text editor and copy each certificate and private key (including the BEGIN/END statements) to its own file such as certificate.cer, ca.cer, and private.key.
- Use OpenSSL to extract the various parts.
Once you have the various components of the certification in individual file, you can use them to convert between some of these formats.
=== PEM to DER ===
openssl x509 -outform der -in cert.pem -out cert.der
=== PEM to P7B ===
openssl crl2pkcs7 -nocrl -certfile cert.pem -out cert.p7b
=== PEM to PFX ===
openssl pkcs12 -export -in cert.pem -inkey cert.key -out cert.pfx
=== DER to PEM ===
openssl x509 -inform der -in cert.der -out cert.pem
=== P7B to PEM ===
openssl pkcs7 -print_certs -in cert.p7b -out cert.pem
=== PFX to PEM ===
openssl pkcs12 -in cert.pfx -out cert.pem -nodes
===== Extract Parts of Certificate =====
=== Extract Key ===
openssl rsa -in cert.pem -out cert.key
=== Extract Certificate ===
openssl x509 -in cert.pem -out cert.cer
OpenSSL assumes that there is only one certificate in a file and will use the first certificate that it finds. It ignores subsequent certificates in the file. Normally, I only have one certificate in each file, but I occasionally have a file where I need to separate the intermediate certificates from the host certificate. I use the following script to extract each certificate into one file per certificate.
#!/usr/bin/perl
my $filename = shift;
open IN, "<$filename" or die("Unable to open file: $!\n");
my $ifile = "";
my $ofile = "";
while() {
$ifile .= $_;
$ofile .= $_;
if($_ =~ /^\-+END(\s\w+)?\sCERTIFICATE\-+$/) {
print "Found certificate: ";
print `echo "$ofile" | openssl x509 -noout -issuer -subject`;
print "\n";
print "FileName? ";
my $fname = <>;
open CERT, ">$fname";
print CERT $ofile;
close CERT;
$ofile = "";
}
}
close INP;
===== Verify that a Private Key Matches a Certificate =====
(Shamelessly stolen from (and expanding upon) [[http://httpd.apache.org/docs/2.0/ssl/ssl_faq.html#verify|The Apache SSL FAQ]])
The private key contains a series of numbers. Two of those numbers form the "public key", the others are part of your "private key". The "public key" bits are also embedded in your Certificate (we get them from your CSR). To check that the public key in your cert matches the public portion of your private key, you need to view the cert and the key and compare the numbers. To view the Certificate and the key run the commands:
openssl x509 -noout -text -in server.crt
openssl rsa -noout -text -in server.key
The `modulus' and the `public exponent' portions in the key and the Certificate must match. But since the public exponent is usually 65537 and it's bothering comparing long modulus you can use the following approach:
openssl x509 -noout -modulus -in server.crt | openssl md5
openssl rsa -noout -modulus -in server.key | openssl md5