Monday, March 18, 2013

SSL essentials for system administrators

X.509 standard specifies format for public key certificates.

Structure of a public key certificate is expressed in a formal language: ASN.1.

Creating self-signed certificate:

1) create private key & public key (without passphrase)
$ openssl genrsa -out server.key 2048

2) only private key was generated, but public key can be always extracted from it:
$ openssl rsa -in server.key -pubout

3) create certificate-signing request (CSR). It will contain public key of the entity requesting the certificate and information about the entity.
$ openssl req -new -key server.key -out server.csr

4) sign your own certificate using CSR and your private key (for real certs it would be private key of Certificate Authority)
$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

5) examine the contents of your certificate
$ openssl x509 -text -in server.crt

Adding SSL support in Apache2:
<IfModule mod_ssl.c>
Listen 443
NameVirtualHost *:443
<VirtualHost *:443>
SSLEngine On
SSLOptions +StrictRequire
SSLCertificateFile /etc/httpd/conf/ssl/server.crt
SSLCertificateKeyFile /etc/httpd/conf/ssl/server.key
</VirtualHost>
</IfModule>

SSL deployment best practices can be found here.

Example certificate in text format:
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
aa:c9:e7:2b:f7:fe:38:e2
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=PL, ST=xxx, L=xxx, O=xxx, OU=xxx, CN=www.mysecuresite.com/emailAddress=xxx
Validity
Not Before: Feb 7 13:28:40 2013 GMT
Not After : Feb 7 13:28:40 2014 GMT
Subject: C=PL, ST=xxx, L=xxx, O=xxx, OU=xxx, CN=www.mysecuresite.com/emailAddress=xxx
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:df:02:92:d7:f4:0d:08:a0:78:14:f3:d4:a6:ff:
d7:36:ce:1d:75:90:92:af:c6:79:b1:e9:7a:60:2e:
b3:8a:77:94:79:c0:4f:a2:07:50:c0:9b:9e:38:9d:
a2:80:a9:c6:97:24:3d:80:da:13:15:63:f0:46:aa:
98:4d:3a:0b:37:94:4b:d9:bf:fd:8e:b6:7e:b7:46:
a1:58:05:20:9c:e0:6f:85:21:35:8a:14:04:7c:11:
0b:ed:1e:d5:24:98:0d:60:48:3f:40:51:38:17:05:
46:5a:2f:78:0d:64:f7:83:0a:e2:86:63:e0:23:18:
9a:ca:29:32:70:43:4e:41:ca:c9:57:5a:c8:9a:a7:
3d:50:63:96:b5:99:5a:c5:21:29:39:a5:6e:37:fb:
60:14:a4:a4:c7:4d:98:dc:1e:fa:c5:3e:b7:e1:ad:
2e:e5:c2:83:30:af:81:5d:0b:b2:19:26:6a:04:0b:
0b:e1:a6:70:75:ee:a2:fa:32:8d:b6:89:c8:ad:9f:
f0:25:66:29:27:e9:16:bf:1e:2f:ab:d4:29:af:33:
46:a1:c8:84:36:9a:f9:67:1a:e7:0e:e3:ac:bf:a4:
54:e6:e4:8d:dc:e2:1b:ad:3f:b9:3f:8c:af:7e:72:
27:ea:6b:6f:c7:cd:54:5a:4b:b0:e8:0a:2b:b4:dc:
aa:b1
Exponent: 65537 (0x10001)
Signature Algorithm: sha1WithRSAEncryption
57:96:60:2f:97:92:a7:b4:23:9d:0d:17:62:33:e2:bb:df:34:
c1:5c:43:df:63:c1:78:53:8c:a7:e5:ad:25:3a:5f:1d:f7:70:
2b:0b:28:33:61:f9:94:6f:4f:19:e0:2d:fc:fd:40:ad:8b:5c:
cc:b3:7d:0c:ed:85:05:ad:d5:ec:9f:61:61:d7:e4:89:12:5d:
f4:97:c4:a5:b2:37:4f:15:5b:da:f2:80:a0:5d:a7:91:5f:77:
1b:ee:2e:03:3f:10:3e:2c:bf:7e:f9:c0:5b:21:04:97:bb:42:
c9:f9:b6:30:99:8d:1a:35:7c:8e:6e:2a:91:c1:c0:2c:06:53:
eb:f5:72:a1:44:f5:b5:e0:b8:b8:3f:cd:34:2c:10:0b:69:ea:
11:a8:98:00:28:f8:36:64:18:53:73:fd:7f:35:81:cd:5a:7e:
a4:34:2f:8b:b9:54:46:94:6d:d4:13:13:e2:16:df:73:9b:0d:
fe:ce:1f:53:5c:ff:cd:91:d6:60:7d:bf:65:35:67:f6:57:a9:
8a:f8:ff:d3:23:4e:a0:83:41:5f:22:dc:4c:39:06:02:84:0f:
82:21:72:21:e7:d9:14:5d:9a:66:36:38:ba:15:af:97:45:06:
dc:da:9a:e3:6d:e4:61:36:42:ba:82:39:44:a4:35:cb:75:56:
2d:36:b0:9a

most important fields:
1) Issuer: #certificate authority, Verisign for example (Issuer == Subject in case of self-signed certificates)
2) Subject: CN: #common name, it's the part that must match the host being authenticated (it should be domain name of your server)

Certificates are commonly stored in two formats:
1) DER binary with extensions: .cer, .crt, .der
2) PEM (Privacy Enhanced Mail), base64 encoded DER certificate, enclosed between "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----" with extension .pem

Getting certificate in PEM format from remote server:
$ openssl s_client -connect <ip:port> < /dev/null 2> /dev/null | openssl x509

Showing remote certificate in text format:
$ openssl s_client -connect <ip:port> < /dev/null 2> /dev/null | \
openssl x509 -noout -text

Creating fingerprints (sha1):
$ openssl s_client -connect <ip:port> < /dev/null 2> /dev/null | \
openssl x509 -noout -fingerprint

Simple debugging technique:
$ openssl s_client -connect <ip:port> -state -debug

Google maintains database of SSL certificates that were found by it's web crawlers. To check whether given certificate is available in Google's database (Google Certificate Catalog) do this:
calculate sha1 fingerprint of chosen certificate:
$ openssl s_client -connect <ip:port> < /dev/null | \ 
openssl x509 -outform DER | openssl sha1

look up a TXT record with calculated fingerprint as a name in the certs.googlednstest.com domain:
$ dig +short 405062e5befde4af97e9382af16cc87c8fb7c4e2.certs.googlednstest.com TXT

You will get three numbers: the first number is the day that Google's crawlers first saw that certificate, the second is the most recent day, and the third is the number of days we saw it in between.
Only Certificates that satisfy following criteria will appear in Google's catalog: it must by correctly signed (either by a CA or self-signed); it must have correct domain name, that is, one that matches the one we used to retrieve the certificate.