ServiceEncryptionWithSSL
From HerzbubeWiki
Contents |
References
Provides a good overview over SSL/TLS, and also gives some details how to create your own SSL certificates:
http://httpd.apache.org/docs-2.0/ssl/ssl_faq.html
Another interesting article/FAQ that is OpenLDAP-centric:
http://www.openldap.org/faq/data/cache/185.html
And, of course, the helpful Wikipedia article:
http://en.wikipedia.org/wiki/Transport_Layer_Security
A Debian article that describes how to become your own root CA and sign your own certificates:
http://www.debian-administration.org/articles/284
Basics on SSL/TLS
Q: What is SSL/TLS?
A: A protocol to encrypt communication over a computer network. The protocol runs on top of the TCP and UDP protocols, but below any application protocols such as HTTP or FTP. In other words, it runs between the transport and the application network layers.
Q: What is the difference between SSL and TLS?
A: TLS is the successor to SSL. The SSL 3.0 specification was the last version of SSL to be published in 1996 by Netscape. The first version of TLS was TLS 1.0, it was published in 1999 in RFC 2246. The latest version of TLS as of writing this document is TLS 1.1, published in 2006 in RFC4346.
Q: Implementations?
A: Probably most popular is the OpenSSL library, which is basically free but has a license that is not compatible with the GPL. An alternative was therefore created by the GNU project in the form of the GnuTLS, which uses the LGPL.
Basics on certificates
Network communication occurs between 2 hosts. Throughout this document one of these hosts will always be called "the client", the other host will be called "the server".
SSL/TLS relies on the concept of public key cryptography. The server has the public/private key pair. Communication between server and client is encrypted using the server's public key. The server hands out its public key in the form of a certificate, which may contain additional information that the client uses to make sure that the server really is whom it claims to be.
Overview of certificates involved in client/server communication:
- client side
- a public server certificate that the client uses to encrypt messages it sends to the server
- the client gets this public certificate from the server
- the public certificate provided by the server is, in itself, not trustworthy; to make it trustworthy for the client, the public certificate must be signed by a third party, a so-called Certificate Authority (CA) that the client knows and trusts
- an example for a commercial CA is VeriSign
- an example for a community CA is cacert.org
- the client needs the public certificate of the CA in order to be able to check the public server certificate's signature and therefore its authenticity
- server side
- a private RSA key that the server uses to decrypt messages from the client
- a public certificate that the server hands out to the client so that the client can encrypt its messages
- if the public certificate is signed by a CA, that CA's public certificate is also required
Generic procedure for signing a certificate
- the private RSA key is generated by the operator of the server
- the public unsigned certificate is generated by the operator of the server
- to let the CA sign the certificate, the server operator must contact the CA
- first the operator creates a Certificate Signing Request (CSR)
- the CSR contains various information about the person or organisation
- if the signed certificate should be used by a server process (e.g. HTTP server, LDAP server), it is vital that the attribute "common name" is set to the FQDN under which the server is going to operate
- the operator sends his or her CSR to the CA
- first the operator creates a Certificate Signing Request (CSR)
- the CA signs the CSR with its private key; the result is the public signed certificate which the CA sends back to the server operator for usage
System installation
The following Debian packages need to be installed:
openssl
The Certificate Authority (CA)
CAcert.org
Get root certificates
The public root certificates of CAcert.org can be obtained from this page (use the PEM variants):
https://www.cacert.org/index.php?id=3
At the time of writing there are 2 root certificates available:
- a class 1 root certificate
- a class 3 root certificate; this one is signed by the class 1 root certificate
At the time of writing, the Debian package ca-certificates provides those two certificates in /etc/ssl/certs so it should not be necessary to manually store them there. These are the package-provided files:
lrwxrwxrwx 1 root root 48 Sep 25 19:32 class3.pem -> /usr/share/ca-certificates/cacert.org/class3.crt lrwxrwxrwx 1 root root 46 Sep 25 19:32 root.pem -> /usr/share/ca-certificates/cacert.org/root.crt
Certificate chain file
Create a so-called certificate chain file in the following way:
cd /etc/ssl/certs rm cacert.org.certchain cat class3.crt >>cacert.org.certchain cat root.crt >>cacert.org.certchain
The Apache web server is one of the applications that requires this chain file (it is specified by the directive SSLCertificateChainFile): When a client requests a server certificate such as for www.herzbube.ch (which is signed by the class 3 CAcert.org root certificate), the server not only hands out the server certificate, but also provides the root certificates in the chain file. If the client trusts one of the CAcert.org root certificates, it will thereby automatically trust the server certificate, too.
Note: The certificates in the chain file should appear in the order of the certificate chain order, i.e. the root certificate that was used to sign the server certificate should appear first. I have not tested what happens if this is not the case, but it may affect browsers on the client side.
Manually add root certificates to browser
As per Wikipedia:
- class 1 root certificate is for email
- class 3 root certificate is for server certificates and software signing
If the browser supports it (e.g. Firefox does), also add the CRLs (certificate revocation list) for both root certificates.
Manually add root certificates to system (Mac OS X)
The following procedure works for me on Mac OS X 10.5.4:
- Download the class 1 and class 3 certificates to the desktop (use the files in the DER format)
- Import the class 1 certificate into the system keychain
- Double-click on root.crt; this will open "Keychain Access.app" ("Schlüsselbundverwaltung" in German)
- Select the keychain "System" (refers to /Library/Keychains/System.keychain)
- Authenticate by specifying your administrator user's name and password
- Confirm that you want to trust the certificate
- Repeat the procedure by double-clicking on class3.crt (the class 3 certificate)
- The certificate is automatically trusted because the root cert was already imported
Creating your own Certificate Authority (CA)
In order to act as your own CA, two things are needed
- a private key
- a certificate
In theory, the certificate can be obtained in 2 ways:
- either create a self-signed public certificate
- or create a CSR and convince a third party to issue the certificate for you
In practice, you will only use a self-signed certificate, because no other CA will issue a certificate to you that is capable of doing CA things. The reason is obvious: The other CA would lose control over the certificate issuing process, which is exactly what must never happen to a CA.
Private key
The following command creates a new private key with the following attributes:
- the key is an RSA key
- the key is protected by a passphrase that you must specify; the encryption algorithm/cipher used is Triple-DES
- the key is formatted for PEM
openssl genrsa -des3 -out ca.herzbube.ch.key 1024
Example key file content:
osgiliath:~/ssltest# cat ca.herzbube.ch.key -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,D238054F2ED5C62B hRy60/LS02UiWCtxJ5exSCX4nc1/bjSTfkR02PQhyrieAZjWK05YC5cYl17nobho 2evuG8QXCfEn4u6F/ckG9KcVD4LSpEPNOFijd/7lZjE7g07aP7Z11Bhqed03Orzh UTUwCPUXm9lxE+zypUmfY4F5r0MVSS3v5ULA4ckZMfkuCX4Ed0WNZjmqfyjLbwOr FA8TMDj7pb/HLiUt74TQyw58nENdNRG2NP/IAapMZvrj0+izxPD9LSmdFAAexAbY IcACNR4Ou5FypJE5d05PUVAPtBKYJQWdWW3lbOGovpQOdgLW7M13q/7doHYS0IHl sETcibGidhA6Nt4BI3XQ/LJgGV8v7ravmi7wj7ZvQ0l8INR5208E8rBQ6+QtoBsf A2nzZrd3L9k3GE05Tll8xp+vjkTkr38Kn31AGDz/W47bQfErYlbUutq4TvGIyFHl o6+MwqnsLHw88u9CneGprd6UNo49dLbcOrEX7CCnWSfRJR6oTb17yBbtCi2+yfBi 1Q+an7t3jTwDews3OAraSqCt/W5I8IHT4VLsDd+4T7TDXMWXYkqGv8rs+HlsMvGV YjOpwhFMk0ITJy8CkqP72TrsqRDBlhI7Rif2nT3kPOfJKwK6uc6F0S/Y0EuamhQu BqzPym4Nn35NmnWp7kI0C8ro9eu2i3shDUyW1GJdNvbzgiO3NVkvwq55LZA7YRQT tD0UIlEYmG8rD6BpQX3rwmU7utaE3jMuuW/G8BLHsRwo4F1IhbFQ0rmfXNKGBy+l NNx2zhpA44Hh+KR5RYcyl13nKsgmkevdt365XvGeQNrvrS8xHlGzLA== -----END RSA PRIVATE KEY-----
Self-signed certificate
The following command creates a new self-signed certificate with the following attributes:
- the certificate has the X.509 structure
- the certificate is signed with the CA's private RSA key
- the certificate is formatted for PEM
- the certificate is valid 30 years (= 10'950 days)
- the certificate is capable of issuing other certificates (i.e. it is a CA certificate)
openssl req -new -x509 -days 10950 -key ca.herzbube.ch.key -out ca.herzbube.ch.crt
Note: You must specify the passphrase in order to access the private RSA key.
OpenSSL will also ask for some information that will be incorporated into the certificate. The information is also called a "distinguished name" (DN) and consists of multiple fields or attributes. Attributes that you want to leave blank must be entered with a value "." It is advisable to enter at least the "common name" attribute:
Example DN:
- Country Name (2 letter code) = CH
- State or Province Name (full name) = .
- Locality Name (eg, city) = .
- Organization Name (eg, company) = herzbube.ch Certificate Authority
- Organizational Unit Name (eg, section) = .
- Common Name (eg, YOUR name) = ca.herzbube.ch
- Email Address = ca@herzbube.ch
Example certificate file content:
osgiliath:~/ssltest# cat ca.herzbube.ch.crt -----BEGIN CERTIFICATE----- MIICsDCCAhmgAwIBAgIJAJS709dIawALMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQwHhcNMDcwMzI3MTkzMzIxWhcNMzcwMzE5MTkzMzIxWjBF MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50 ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB gQC8TmwotmWgM4mXoBqUOD/BYgwfPQ3Z31uMZnpAE1mvmYuE//pzy2dzTX4Y8wFH 2j6VzNFnqXy0Y5dULLc5kURswCIUSiMVUYWqSc5b+ybv1d0P5CSrypgk4tC0uYAz L43RAaAp+CJsBjKkesIKzQKfNODD5DoFf2z6SS6pwe52EwIDAQABo4GnMIGkMB0G A1UdDgQWBBSpWd567nU+3gOlS6b9wquTl3hBljB1BgNVHSMEbjBsgBSpWd567nU+ 3gOlS6b9wquTl3hBlqFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUt U3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAJS709dI awALMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAWy/SVVDw1YvorgU3 6yRtqjXBxSDEqTZRfGfGOxGiYhhJ6QyMHjy4b+MHoJRBYKaaq/ZmJbvob4bYskat X7vqrXO9/71JXSU10ZRRr7kczXNz0bZqeMtvtKi8ook0bdN/JwELp4pKHqWbI5od 7FuhwUSF17elipH/RuLLpalLfhk= -----END CERTIFICATE-----
Storage
The private key and the certificate (either self-signed or signed by a third party) should be stored in a permanent location. For instance:
Store the private key in:
/etc/ssl/private
Store the certificate in
/etc/ssl/certs
To follow the guidelines of the ca-certificates package (see section below), we also need to create a hash symlink:
cd /etc/ssl/certs ln -s ca.herzbube.ch.crt "$(openssl x509 -subject_hash -in ca.herzbube.ch.crt | head -1).0"
Last but not least, for those applications that are not able to follow a certificate chain (e.g. Apache, OpenLDAP), a single file with such a chain should be created:
cd /etc/ssl/certs rm ca.herzbube.ch.certchain cat ca.herzbube.ch.crt >>ca.herzbube.ch.certchain cat class3.crt >>ca.herzbube.ch.certchain cat root.crt >>ca.herzbube.ch.certchain
The server
Create a server key
The following command creates a new private key. It has the same attributes as the key that was created for the CA (see further up).
openssl genrsa -des3 -out foobar.herzbube.ch.key 1024
Create a Certificate Signing Request (CSR)
The following command creates a CSR with the following attributes:
- the CSR is formatted for PEM
openssl req -new -key foobar.herzbube.ch.key -out foobar.herzbube.ch.csr
Example DN:
- Country Name (2 letter code) = CH
- State or Province Name (full name) = .
- Locality Name (eg, city) = .
- Organization Name (eg, company) = .
- Organizational Unit Name (eg, section) = .
- Common Name (eg, YOUR name) = foobar.herzbube.ch
- Email Address = herzbube@herzbube.ch
- Challenge password: .
- Optional company name: .
Note 1: It is important to set the "common name" attribute = the FQDN (fully qualified domain name) under which the server will operate, otherwise the information in the certificate will not match the information that the server announces to its clients. If a client is picky about this, the client may even refuse to cooperate with the server!!!
Note 2: Specifying the common name *.herzbube.ch will create a wildcard certificate that is valid for all sub-domains of herzbube.ch.
Storage
Store the private key in:
/etc/ssl/private
Store the CSR in:
/etc/ssl/csr
Note: You may wish to store an un-encrypted version of the private key in /etc/ssl/private so that a server process can read the key without user interaction (i.e. the user entering the passphrase) during a system reboot. See the "Useful commands" chapter for an example of how to do this.
The certificate
Sign the CSR through CAcert.org
The form to sign CSRs can be found here
https://www.cacert.org/account.php?id=10
Paste the CSR into the form, then sign it (by the class 3 root certificate, which is selected by default in the Web form) and thereby generate the certificate. The certificate can be copied and pasted into a certificate file. That file should be stored in
/etc/ssl/certs
Sign the CSR through your own CA
Note: I recently discovered /usr/lib/ssl/misc/CA.sh which is provided by the openssl Debian package. Maybe it would be worth to have a look at that.
The first CSR
If this is the first CSR to be signed, I recommend creating a working directory that can be used to sign other CSRs in the future:
mkdir /usr/local/ssl cd /usr/local/ssl cp /usr/share/doc/libapache-mod-ssl/examples/sign.sh . ln -s /etc/ssl/certs/ca.herzbube.ch.crt ln -s /etc/ssl/private/ca.herzbube.ch.key
Make the following modifications to the script sign.sh:
- set CA_PREFIX to use ca.herzbube.ch
- set default_days to a value that you find suitable; the attribute determines how long the signed certificate remains valid
Sign the CSR
The following command uses the script sign.sh discussed in the above chapter to sign the CSR:
cd /usr/local/ssl ./sign.sh foobar.herzbube.ch.csr
Store the file that contains the signed certificate in
/etc/ssl/certs
Other useful commands
Generate an un-encrypted, PEM formatted version of a private RSA key. This is useful if a server process needs to read the key without user interaction (i.e. the user entering the passphrase) during a system reboot. Note: The passphrase is removed because there is no cipher option such as -des3 after the rsa command.
openssl rsa -in foobar.key -out foobar.key.unsecure
Display details about an RSA key:
openssl rsa -noout -text -in foobar.key
Display details about a CSR:
openssl req -noout -text -in foobar.csr
Display details about a certificate:
openssl x509 -noout -text -in foobar.crt
Change the passphrase (requires that you enter the old and the new passphrase). This can also be used to encrypt an unprotected, unencrypted key.
openssl rsa -des3 -in foobar.key -out foobar.key.new
Certificate verification:
openssl verify -CAfile ca.herzbube.ch.crt foobar.crt
Managing certificates with Debian
The package ca-certificates
Overview
From the blurb of the package ca-certificates:
This package includes PEM files of CA certificates to allow SSL-based applications to check for the authenticity of SSL connections. It includes, among others, certificate authorities used by the Debian infrastructure and those shipped with Mozilla's browsers. Please note that certificate authorities whose certificates are included in this package are not in any way audited for trustworthiness and RFC 3647 compliance, and that full responsibility to assess them belongs to the local system administrator.
How certificates are installed
The CA certificates provided by the package are located in
/usr/share/ca-certificates
The following configuration file defines whether a CA certificate in the above directory should be used, or not (in this case the certificate must be listed with a prefix "!"):
/etc/ca-certificates.conf
The configuratin file is read and evaluated by the update program
update-ca-certificates
The update program is invoked when a new version of the package is installed on the system. It installs the certificate files in
/etc/ssl/certs
The update program also generates a single file (bundle) that contains all the certificates
/etc/ssl/certs/ca-certificates.crt
Content of /etc/ssl/certs
When update-ca-certificates is executed, it organizes the content of the directory /etc/ssl/certs in the following way:
- Creates a symlink for each active certificate that points to the certificate file in /usr/share/ca-certificates
- Creates another symlink for each active certificate whose name is based on the certificates "subject hash"; see "man c_rehash"; an individual hash can be generated with the command openssl x509 -subject_hash -in foo.pem (see "man x509")
- Updates the bundle file ca-certificates.crt
- Symlinks for certificates that have vanished from the Debian package are left and dangling and should be cleaned out periodically
An example:
lrwxrwxrwx 1 root root 48 Sep 25 19:12 class3.pem -> /usr/share/ca-certificates/cacert.org/class3.crt lrwxrwxrwx 1 root root 10 Sep 25 19:07 e5662767.0 -> class3.pem
Presumably the whole scheme is required so that applications can be provided with a single directory that contains all of the system's trusted certificates. The hash symlinks exist because they make lookup for a specific certificate fast and easy (e.g. for an application that wants to follow a certificate chain). One example that I have found that requires this setup is courier-imap-ssl.
Non-CA certificates
Naturally I have various certificates in /etc/ssl/certs that are not CA certificates (e.g. the one for imap.herzbube.ch). Presumably, these certificates do not require a hash symlink because they are specified with their real names in whatever configuration file requires them, and they never need to be looked up in order to follow a certificate chain.
When the ca-certificates package is upgraded and the upgrade contains new certificates, or some certificates have been deactivated, then update-ca-certificates will cause c_rehash to be run over the /etc/ssl/certs directory, which will lead to hash symlinks being generated even for my non-CA certificates. These symlinks can be removed if detected, but otherwise they do no harm.
Local CA certificates
A CA certificate that is locally installed (i.e. is not part of the ca-certificates package) and that is used in a certificate chain should be symlinked. The following command should (hopefully) work:
ln -s ca.herzbube.ch.crt "$(openssl x509 -subject_hash -in ca.herzbube.ch.crt | head -1).0"
The package ssl-cert
Overview
From the blurb of the package ssl-cert:
This package enables unattended installs of packages that need to create SSL certificates. It is a simple wrapper for OpenSSL's certificate request utility that feeds it with the correct user variables.
Besides this, I have found ssl-cert to be useful because it demonstrates how the different parts of the certificate management process can be protected on the file system level with a sensible user rights concept.
User rights concept
The user rights concept is this:
- There is a system group ssl-cert
- This group has some limited rights to the directory /etc/ssl/private
osgiliath:~# ls -ld /etc/ssl/private drwx--x--- 2 root ssl-cert 4096 Nov 29 03:16 /etc/ssl/private
- This allows users that belong to the group to read files inside the directory
- Daemons that do not start and/or run as root should have the ssl-cert group assigned as a secondary group
- Key files within /etc/ssl/private can be "given" to ssl-cert; the read permission needs to be changed accordingly:
osgiliath:~# ls -ld /etc/ssl/private/ldap.herzbube.ch.key.unsecure -r--r----- 1 root ssl-cert 887 Jan 10 2004 /etc/ssl/private/ldap.herzbube.ch.key.unsecure
- Unfortunately all daemons that belong to ssl-cert can now read the key file; it is therefore sensible to further restrict the key file's group:
osgiliath:~# ls -ld /etc/ssl/private/ldap.herzbube.ch.key.unsecure -r--r----- 1 root openldap 887 Jan 10 2004 ldap.herzbube.ch.key.unsecure
OpenSSL vulnerability in Debian
A brief check using the SSL certificate checker on the Heise web site
http://www.heise.de/netze/tools/chksslkey
reveals that all the certificates I created on my system are vulnerable to the infamous weakness in the Debian OpenSSL package. This is bad news, but since I cannot ignore the problem I will try to make the best of it and improve my security infrastructure in the following way:
- Revoke all certificates signed so far by CAcert
- Issue a new certificate for ca.herzbube.ch through CAcert, just in case I want to do my own certification business
- Re-issue all the other server certificates through CAcert
- Using CAcert to issue certificates has the benefit that certificates are not valid such a long time (i.e. 30 years) and can be managed through a CRL
- Check out how to manage my own CRL
