../_images/thumbnail-ssl.png

8. Topic 5 - SSL

For at least this semester, we are just going to introduce SSL in this course. The programming of SSL is a little bit harder than the other programming we have done; and, we have limited time. So there is a short online quiz covering this topic, but no programming assignment.

See also

8.1. Data Encryption using SSL

  • The newer name for Secure Sockets Layer (SSL) is actually Transport Layer Security (TLS), but it is more commonly known as SSL.
  • Based on public certificates and private keys
  • Certificates may be either self signed or verified by one of a few trusted Certificate Authorities (CA)
  • Often used with HTTP (i.e., https://www...). It can be used with SMTP, ssh, scp, or any client / server communication.
  • Python has basic SSL client capability.  The OpenSSL module provides more functionality.   SSL was re-worked in Python 3 (available in Python 2.6) to include support for programming an SSL server in Python. The existing SSL support in the socket module hasn’t been removed and continues to work, though it will be removed in Python 3.

8.1.1. How it works

  1. The client and server establish a socket connection.
  2. The server sends its public certificate to the client.
  3. To verify the authenticity of the server, the client may validate the certificate with one a few trusted certificate authorities.
  4. The client encrypts the message using the server’s public key and sends it to the server.
  5. The server receives the message and decrypts it using its private key.

8.1.2. Public / Private Keys

  • The keys are a matched pair

    • Messages encrypted with the public key can only be decrypted with the private key.
    • Having the public key will not help decrypt a message. Thus, as long as the client is certain that the public key came from the intended server, then it is safe to assume that only the intended server will be able to decrypt the message.
  • In many cases, especially with HTTP, the message is only encrypted when data is sent from the client to the server.  This is one reason why the credit card number is ‘X’ed out in the receipt – can’t send the credit card number from server to client.

  • Keys may be self signed for private activities.

  • Public servers usually have purchased certificates from a certificate authority.

Note

A certificate authority is an entity (company) that can verify the authenticity of a public key. For example, when you are about to make an on-line purchase from the likes of Amazon.com, your web browser will send a message to the certificate authority asking if the supplied public key truly belongs to Amazon.com. If the answer is yes, then it is safe to send the credit card number.

8.1.3. Self Signing a certificate

Here is an example how a self signed certificate can be generated. It is done from Linux just because it was easy to find the program and instructions for how to do it in Unix/Linux.

$ openssl req -new -out certfile.pem -keyout keyfile.pem
Generating a 1024 bit RSA private key
........++++++
................................................++++++
writing new private key to 'keyfile.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
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) [GB]:US
State or Province Name (full name) [Berkshire]:Kansas
Locality Name (eg, city) [Newbury]:Salina
Organization Name (eg, company) [My Company Ltd]:Kansas State University
Organizational Unit Name (eg, section) []:Engineering Technology
Common Name (eg, your name or your server's hostname) []:timber.sal.ksu.edu
Email Address []:tim@ksu.edu
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:.
An optional company name []:.

What do the Public Certificate and Private Key look like?:

$ cat keyfile.pem
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,F7FFBD69A863B27B
oq2s6YBa+6XVk+sfhFwYQixYQnP1wDDPVFpf+gdFTQUZ7qkG+qeR23z9LqEiTm1H
E5ZB8TW3m1PC8Bhz8EansTV9/Q2AqpgWduytuKX9mo1nEwjTQPx7vZpnb+JrcGB2
Ew2qp4NfU1sYVpXV+KO66TunsTdhvNyV1fH8r6Dgk9xruNfvoUB0WRRKDGZ17iaP
1GeGPnQWWDC7WWE2LYugz/LW5BSoZtwdYf2U/48F/SvAgf1MyPUExwBqYRinzjdo
PP9MXMGPHJQJ9PLeGnIRqUAAU2p0NJB8tb8ZrwFWpK4Aa1B3I9cNiMa42L0mfcax
Y10+0MMq4UcAIHkfdIOBbRN8m9lpM3haeAs9ppAewyG3MKII2DC+FsEsdYIBWRhL
Mfi3WcUOwqrVHLL2Qf1d4QZS9MkYZahvKsz3iYGZkw2Le/BXy+0/esLFnCjDhEOA
NLLrVRcpo+82bKjjeQf4yTxL6w++HmfWsWSSGgD+BLWx6geVDZsUS65XaNsUsHQ7
PPi2taqaTu+rHKbYBoTdZUi3gUHhzH5NlWBvOe3tyWMVtid+GgmI418ib5uOikYL
c//IjhwrVzUL4+9raSVcHqFn+kOX/bGxbDzr5vJSJSDFfff2dwYAFvsPYK2ka5gZ
rYdq2tGjrEQycNXksOqsVGv4JEsuEacXeQRpVqh6AOVEWbC0eTUA1bjo9wM6aywi
FIqgr0lLIE7lvL9rW8mkPQ9Tl9lwrLZfqB3vcfmstDXfQqH/A9VEgjhbNHnJkZ3n
MihuBRizFEbK/kZRbk0yVMiFU6HltIJUgJ5b06bLEpcz6wlHSBBxhA==
-----END RSA PRIVATE KEY-----

$ cat certfile.pem
-----BEGIN CERTIFICATE REQUEST-----
MIIB7DCCAVUCAQAwgasxCzAJBgNVBAYTAlVTMQ8wDQYDVQQIEwZLYW5zYXMxDzAN
BgNVBAcTBlNhbGluYTEgMB4GA1UEChMXS2Fuc2FzIFN0YXRlIFVuaXZlcnNpdHkx
HzAdBgNVBAsTFkVuZ2luZWVyaW5nIFRlY2hub2xvZ3kxGzAZBgNVBAMTEnRpbWJl
ci5zYWwua3N1LmVkdTEaMBgGCSqGSIb3DQEJARYLdGltQGtzdS5lZHUwgZ8wDQYJ
KoZIhvcNAQEBBQADgY0AMIGJAoGBAOTRJmntlJy7cf3N3yW0/1jSUoWROlVkaZfg
Aojz59gKlEDMLtVn2DKYDexWe0AUV9gBEpHTguX5Vi322IpPjOvO/3n1kHrdgD5L
Nnc9tYYe5fF0RKzisRz7HKu6aXXY6dNFJMVRj7cTg4uSh7IS5lJvDCjohEnPJYzF
2g8mSoSBAgMBAAGgADANBgkqhkiG9w0BAQQFAAOBgQC1BjorEY98HkW7ceyH9s3d
EcFy6uFKXP2hFjCEesrW+N8lMdyrXYbyxffdE6ZpMEcNoYS9S0wxuwg1f7WjI/3S
y+fA2yviU+7c7blBd7r/r8uaviJB3uMWTgWKdnKBsnqBRvUQcytSrflzANV0MHIq
tVhFOv/lfqxQIha0m6BFQw==
-----END CERTIFICATE REQUEST-----

8.2. Programming SSL

8.2.1. Client Side

  • Limited support in pre-Python 2.6 built-in socket module
  • ssl = socket.ssl(socket)
  • Two methods: read(), write()
  • Create a wrapper to it make easier to use (see below).

8.2.2. Buffered reading from a socket

The basic-wrap.py program on page 328-329 is a good example of using a buffer to read from a socket. The buffer is implemented mainly to provide readline() functionality, which is already available for non-SSL socket connections. The implementation is not the easiest code to follow, but does give some interesting insights on how buffers are implemented.

Note

The guiding principle of buffers is to read as much data as possible at one time while providing a framework to the application, which does not have performance penalties for frequent requests for small amounts of data. Thus, buffers attempt to improve performance by limiting the number of reads relative to the number of read requests from the application.

sslwrapper.readline([newlinestring])

This is the primary public method of the class and it returns one line from the SSL encrypted socket connection. It calls self.read(1024) (described below) to get data in blocks. It uses the string.find() function to look for the new line character. If it finds the new line character, it returns the data for one line and puts the remainder of the data back in the buffer.

sslwrapper.read(n)

An argument could perhaps be made that this function is not needed and its code should be split between self._read() and self.readline(). Regardless, its function is to manage the buffer. If data remains in the buffer, then as much of the buffer that was requested or is available is returned. It calls self._read() when the buffer is empty.

sslwrapper._read(n)

This where the data is actually read from the socket. The socket.ssl.read() function works differently than the socket.recv() function that we have used before. The read() function can raise an exception of socket.SSL_ERROR_WANT_READ or socket.SSL_ERROR_WANT_WRITE rather than blocking until it is able to complete the read operation. Thus, this function loops trying to read from the socket until it either gets the data or it receives an indicator that the full message has already been received.

8.2.3. Server Side

  • SSL was re-worked for Python 3 (available in Python 2.6). The improvements add a new module, ssl, that’s built atop the OpenSSL library. This new module provides more control over the protocol negotiated, the X.509 certificates used, and has better support for writing SSL servers (as opposed to just clients).

    To use the new module, you must first create a TCP connection in the usual way and then pass it to the ssl.wrap_socket() function. It is possible to specify whether a certificate is required, and to obtain certificate info by calling the getpeercert() method.

  • See following example

8.2.4. Python 3 SSL Module Server Side Example

while True:
    newsocket, fromaddr = listening_socket.accept()
    connstream = ssl.wrap_socket(newsocket,
                            server_side = True,
                            certfile = "mycertfile",
                            keyfile = "mykeyfile",
                            ssl_version = ssl.PROTOCOL_TLSv1)
    deal_with_client(connstream)