Python SSL socket echo test with self-signed certificate

For testing purposes it is convenient to use a self-signed certificate. Follow these instructions. You will be prompted for a password a few times:

openssl genrsa -des3 -out server.orig.key 2048
openssl rsa -in server.orig.key -out server.key
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Here is client.py, slightly modified from the Python 2.7.3 docs:

import socket, ssl, pprint

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Require a certificate from the server. We used a self-signed certificate
# so here ca_certs must be the server certificate itself.
ssl_sock = ssl.wrap_socket(s,
                           ca_certs="server.crt",
                           cert_reqs=ssl.CERT_REQUIRED)

ssl_sock.connect(('localhost', 10023))

print repr(ssl_sock.getpeername())
print ssl_sock.cipher()
print pprint.pformat(ssl_sock.getpeercert())

ssl_sock.write("boo!")

if False: # from the Python 2.7.3 docs
    # Set a simple HTTP request -- use httplib in actual code.
    ssl_sock.write("""GET / HTTP/1.0r
    Host: www.verisign.comnn""")

    # Read a chunk of data.  Will not necessarily
    # read all the data returned by the server.
    data = ssl_sock.read()

    # note that closing the SSLSocket will also close the underlying socket
    ssl_sock.close()

And here is server.py:

import socket, ssl

bindsocket = socket.socket()
bindsocket.bind(('', 10023))
bindsocket.listen(5)

def do_something(connstream, data):
    print "do_something:", data
    return False

def deal_with_client(connstream):
    data = connstream.read()
    while data:
        if not do_something(connstream, data):
            break
        data = connstream.read()

while True:
    newsocket, fromaddr = bindsocket.accept()
    connstream = ssl.wrap_socket(newsocket,
                                 server_side=True,
                                 certfile="server.crt",
                                 keyfile="server.key")
    try:
        deal_with_client(connstream)
    finally:
        connstream.shutdown(socket.SHUT_RDWR)
        connstream.close()

Note: if you try to use the standard system ca certificates, e.g. on Debian:

ssl_sock = ssl.wrap_socket(s,
                           ca_certs="/etc/ssl/certs/ca-certificates.crt",
                           cert_reqs=ssl.CERT_REQUIRED)

then server.py explodes with:

Traceback (most recent call last):
  File "server.py", line 24, in 
    ssl_version=ssl.PROTOCOL_TLSv1)
  File "/usr/lib/python2.6/ssl.py", line 338, in wrap_socket
    suppress_ragged_eofs=suppress_ragged_eofs)
  File "/usr/lib/python2.6/ssl.py", line 120, in __init__
    self.do_handshake()
  File "/usr/lib/python2.6/ssl.py", line 279, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [Errno 1] _ssl.c:490: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number

If you specify the SSL version, e.g.

    connstream = ssl.wrap_socket(newsocket,
                                 server_side=True,
                                 certfile="server.crt",
                                 keyfile="server.key",
                                 ssl_version=ssl.PROTOCOL_TLSv1)

then you can run into other problems, e.g.

Traceback (most recent call last):
  File "server.py", line 27, in 
    ssl_version=ssl.PROTOCOL_TLSv1)
  File "/usr/lib64/python2.6/ssl.py", line 338, in wrap_socket
    suppress_ragged_eofs=suppress_ragged_eofs)
  File "/usr/lib64/python2.6/ssl.py", line 120, in __init__
    self.do_handshake()
  File "/usr/lib64/python2.6/ssl.py", line 279, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [Errno 1] _ssl.c:490: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number

Archived Comments

Date: 2014-08-13 19:11:58.59444 UTC

Author: David

Thanks very much. This was extremely helpful.

I would like to offer one odd caveat here. When I create my certificate and key files on Linux, I am unable to connect to the server from a client running on OS X.

Details:

I tested on 3 computers in July and August, 2014:

Windows 7, Python 2.7.6. OpenSSL 1.0.1i
OS X 10.7.5, Python 2.7.8, OpenSSL 0.9.8y
Ubuntu 14.04, Python 2.7.6, OpenSSL 1.0.1f

I created a set of certificate and key files on each of the computers. I then ran the client on Windows and OS X and server on all three of the computers using each of the 3 sets of certificate files.

If the certificate files were created on Linux, I could not connect the OS X client to the server, regardless of the server platform. If the certificate files were created on Windows or OS X, all combinations of client and server worked. The Windows client worked against all 3 servers with all three certificate files. The OS X client worked on all three servers if the OS X or Windows certificates were used. But the OS X client failed against all three servers when those servers used the Linux certificate files.

I can offer no explanation of why.

Date: 2015-09-14 07:22:50.526278 UTC

Author: Limey

In order to get this to work with python V3 I had to change:

ssl_sock.write(“boo!”)

to:

ssl_sock.write(“boo!”.encode())

No idea if this is the best solution, but it made it work. =)

Date: 2015-11-06 06:06:35.515219 UTC

Author: Ketan Kothari

Thank’s for describing with example. Good to use and easy to understand.

Installation notes: wxHaskell on Debian Squeeze

As of January 2013 I was not able to find Debian packages for wxWidgets 2.9, which is required by 0.90.0.1, so we’ll install directly from source. First grab some dependencies:

sudo apt-get install build-essential libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev

Download 2.9.4 from http://www.wxwidgets.org/downloads/. Then:

tar jxf wxWidgets-2.9.4.tar.bz2
cd wxWidgets-2.9.4
./configure --open-gl
make -j 10
sudo make install

This installs to /usr/local. Make sure that wx-config reports the correct libs, e.g.

$ wx-config  --libs
-L/usr/local/lib -pthread   -lwx_gtk2u_xrc-2.9 -lwx_gtk2u_html-2.9 -lwx_gtk2u_qa-2.9 -lwx_gtk2u_adv-2.9 -lwx_gtk2u_core-2.9 -lwx_baseu_xml-2.9 -lwx_baseu_net-2.9 -lwx_baseu-2.9

Now try to install using cabal:

cabal update
cabal install wx

If the build fails with

    /usr/local/include/wx-2.9/wx/gtk/bitmap.h:64:24: error:   initializing argument 1 of ‘wxBitmap& wxBitmap::operator=(const wxBitmap&)’

then we need to patch a C++ file in wxc (credit for this is due to Mads Lindstrøm on comp.lang.haskell.wxhaskell.general).

cd ~/.cabal/packages/hackage.haskell.org/wxc/0.90.0.4
tar jxf wxc-0.90.0.4.tar.gz

Now edit wxc-0.90.0.4/src/cpp/eljpen.cpp and change line 159 from

* _ref = NULL;

to

_ref = NULL;

Then repackage:

tar zcvf wxc-0.90.0.4.tar.gz wxc-0.90.0.4
rm -fr wxc-0.90.0.4

Beware that the patch to wxc is under cabal’s control, so it could be lost if wxc is upgraded, etc. Finally, try to install again using:

cabal install wx

Finally, make sure that the hello world example works:

module Main where
import Graphics.UI.WX

main :: IO ()
main = start hello

hello :: IO ()
hello = do
    f    <- frame    [text := "Hello!"]
    quit <- button f [text := "Quit", on command := close f]
    set f [layout := widget quit]

Note: if cabal install wx fails with

src/cpp/glcanvas.cpp:43:60: error: ‘wxGLContext’ has not been declared
src/cpp/glcanvas.cpp:102:1: error: ‘wxGLContext’ does not name a type
src/cpp/glcanvas.cpp:109:1: error: ‘wxGLContext’ does not name a type
src/cpp/glcanvas.cpp:116:1: error: ‘wxGLContext’ was not declared in this scope
src/cpp/glcanvas.cpp:116:1: error: ‘self’ was not declared in this scope
src/cpp/glcanvas.cpp:116:1: error: expected primary-expression before ‘void’
src/cpp/glcanvas.cpp:116:1: error: expression list treated as compound expression in initializer [-fpermissive]
src/cpp/glcanvas.cpp:117:1: error: expected ‘,’ or ‘;’ before ‘{’ token
cabal: Error: some packages failed to install:

then your system is missing OpenGL libraries (this is not a bug in wx). Double-check the configure output of wxWidgets.

Archived Comments

Date: 2013-03-19 09:24:45 UTC

Author: babalone

Very helpful. I tried installing wx a few times and failed until now.

Date: 2013-03-27 02:30:14 UTC

Author: Hermit

Thanks, however, I’m still unable to build wxcore. It’s spurting a lot of compiler errors: http://dpaste.com/1035609

When running wx-config –libs, -lwx_gtk2u_html-2.9 is there so…

I’ve been banging my head against a wall with this. I’m not very into C/C++ stack (that’s why I use haskell!!). I couldn’t build it for OSX either…

I ended up switching toolkits, moved to HTk, but it’s orphan so I wonder if it’s worth it for the long run.

Date: 2014-10-25 01:05:27.99669 UTC

Author: david diggles

Having similar issues on openSUSE. I wish cabal was better with package management.