Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

TLS Library in python

branch: master

This branch is 0 commits ahead and 0 commits behind master

Fetching latest commit…

Cannot retrieve the latest commit at this time

README
tlslite version 0.3.8a                                            Jan ? 2012
Trevor Perrin <trevp at trevp.net>
http://trevp.net/tlslite/
============================================================================


Table of Contents
==================
1  Introduction
2  License/Acknowledgements
3  Installation
4  Getting Started with the Command-Line Tools
5  Getting Started with the Library
6  Using TLS Lite with httplib
7  Using TLS Lite with xmlrpclib
8  Using TLS Lite with poplib or imaplib
9  Using TLS Lite with smtplib
10 Using TLS Lite with SocketServer
11 Using TLS Lite with asyncore
12 SECURITY CONSIDERATIONS
13 History
14 References


1 Introduction 
=============== 
TLS Lite is an open source python library that implements SSL and TLS. TLS
Lite supports RSA and SRP ciphersuites. TLS Lite is pure python, however it
can use other libraries for faster crypto operations. TLS Lite integrates with
several stdlib neworking libraries.

API documentation is available in the 'docs' directory.

If you have questions or feedback, feel free to contact me.


2 Licenses/Acknowledgements
============================
TLS Lite is written (mostly) by Trevor Perrin. It includes code from Bram
Cohen and Google.

All code in TLS Lite has either been dedicated to the public domain by its
authors, or placed under a BSD-style license. See the LICENSE file for
details.

Thanks to Edward Loper for Epydoc, which generated the API docs.


3 Installation
===============
Requirements:
  Python 2.7 or higher is required. Python 3 is not supported.

Options:
  - If you have the M2Crypto interface to OpenSSL, this will be used for fast
    RSA operations and fast ciphers.

  - If you have pycrypto this will be used for fast RSA operations and fast
    ciphers.

  - If you have the GMPY interface to GMP, this will be used for fast RSA and
    SRP operations.

  - These modules don't need to be present at installation - you can install
    them any time.

Run 'python setup.py install'

Test the Installation:
  - From the distribution's ./tests subdirectory, run:
      ./tlstest.py server localhost:4443 .
  - While the test server is waiting, run:
      ./tlstest.py client localhost:4443 .

  If both say "Test succeeded" at the end, you're ready to go.


4 Getting Started with the Command-Line Tools
==============================================
tlslite installs two command-line scripts: 'tlsdb.py' and 'tls.py'.  They
can be run with no arguments to see a list of commands.

'tls.py' lets you run test clients and servers.  It can be used for testing
other TLS implementations, or as example code for using tlslite.

'tlsdb.py' lets you manage SRP verifier databases. These databases are used by
a TLS server when authenticating clients with SRP.


X.509
------
To run an X.509 server, go to the ./tests directory and do:

  tls.py server -k serverX509Key.pem -c serverX509Cert.pem -t TACK.pem   
    localhost:4443

try connecting to the server with:

  tls.py client localhost:4443

SRP
----
To run an SRP server, try something like:

  tlsdb.py createsrp verifierDB
  tlsdb.py add verifierDB alice abra123cadabra 1024
  tlsdb.py add verifierDB bob swordfish 2048

  tls.py server -v verifierDB localhost:4443

Then you can try connecting to the server with:

  tls.py client localhost:4443 alice abra123cadabra

HTTPS
------
To run a test HTTPS server, go to ./tests and run ./httpsserver.py.


5 Getting Started with the Library
===================================
Using the library is simple.  Whether you're writing a client or server, there
are six steps:
1) Create a socket and connect it to the other party.
2) Construct a TLSConnection instance with the socket.
3) Call a handshake function on TLSConnection to perform the TLS handshake.
4) Check the results to make sure you're talking to the right party.
5) Use the TLSConnection to exchange data.
6) Call close() on the TLSConnection when you're done.

TLS Lite also integrates with several stdlib python libraries. See the
sections following this one for details.

5 Step 1 - create a socket
---------------------------
Below demonstrates a socket connection to Amazon's secure site.

  from socket import *
  sock = socket(AF_INET, SOCK_STREAM)
  sock.connect( ("www.amazon.com", 443) )

5 Step 2 - construct a TLSConnection
-------------------------------------
  from tlslite import TLSConnection
  connection = TLSConnection(sock)

5 Step 3 - call a handshake function (client)
----------------------------------------------
If you're a client, there's several different handshake functions you can
call, depending on how you want to authenticate:

  connection.handshakeClientCert()
  connection.handshakeClientCert(certChain, privateKey)
  connection.handshakeClientSRP("alice", "abra123cadabra")

The ClientCert function without arguments is used when connecting to a site
like Amazon, which doesn't require client authentication.  The server will
authenticate with a certificate chain.

The ClientCert function can also be used to do client authentication with an
X.509 certificate chain as an argument. To use X.509 chains, you'll need some
way of creating these, such as OpenSSL (see http://www.openssl.org/docs/HOWTO/
for details).

Below is an example of loading an X.509 certificate chain:

  #Load X.509 certChain and privateKey.
  s = open("./test/clientX509Cert.pem").read()
  x509 = X509()
  x509.parse(s)
  certChain = X509CertChain([x509])
  s = open("./test/clientX509Key.pem").read()
  privateKey = parsePEMKey(s, private=True)

The SRP function does mutual authentication with a username and password.

If you want more control over the handshake, you can pass in a
HandshakeSettings instance. For example, if you're performing SRP, but you
only want to use SRP parameters of at least 2048 bits, and you only want to
use the AES-256 cipher, and you only want to allow TLS (version 3.1), not SSL
(version 3.0), you can do:

  settings = HandshakeSettings()
  settings.minKeySize = 2048
  settings.cipherNames = ["aes256"]
  settings.minVersion = (3,1)
  connection.handshakeClientSRP("alice", "abra123cadabra", settings=settings)

Finally, every TLSConnection has a session object. You can try to resume a
previous session by passing in the session object from the old session. If the
server remembers this old session and supports resumption, the handshake will
finish more quickly. Otherwise, the full handshake will be done. For example:

  connection.handshakeClientSRP("alice", "abra123cadabra")
  .
  .
  oldSession = connection.session
  connection2.handshakeClientSRP("alice", "abra123cadabra", session=
  oldSession)

5 Step 3 - call a handshake function (server)
----------------------------------------------
If you're a server, there's only one handshake function, but you can pass it
several different parameters, depending on which types of authentication
you're willing to perform.

To perform SRP authentication, you have to pass in a database of password
verifiers.  The VerifierDB class manages an in-memory or on-disk verifier
database.

  #On-disk database (use no-arg constructor if you want an in-memory DB)
  verifierDB = VerifierDB("./test/verifierDB")

  #Open the pre-existing database (can also 'create()' a new one)
  verifierDB.open()

  #Add to the database
  verifier = VerifierDB.makeVerifier("alice", "abra123cadabra", 2048)
  verifierDB["alice"] = verifier

  #Perform a handshake using the database
  connection.handshakeServer(verifierDB=verifierDB)

To perform authentication with a certificate and private key, the server must
load these as described in the previous section, then pass them in.  If the
server sets the reqCert boolean to True, a certificate chain will be requested
from the client.

  connection.handshakeServer(certChain=certChain, privateKey=privateKey,
                             reqCert=True)

You can pass in a verifier database and/or a certificate chain+private key.
The client will use one or both to authenticate the server.

You can also pass in a HandshakeSettings object, as described in the last
section, for finer control over handshaking details.  Finally, the server can
maintain a SessionCache, which will allow clients to use session resumption:

  sessionCache = SessionCache()
  connection.handshakeServer(verifierDB=verifierDB, sessionCache=sessionCache)

It should be noted that the session cache, and the verifier and shared key
databases, are all thread-safe.

5 Step 4 - check the results
-----------------------------
If the handshake completes without raising an exception, authentication
results will be stored in the connection's session object.  The following
variables will be populated if applicable, or else set to None:

  connection.session.srpUsername       #string
  connection.session.clientCertChain   #X509CertChain
  connection.session.serverCertChain   #X509CertChain

X.509 chain objects return the end-entity fingerprint via getFingerprint(),
and ignore the other certificates.

To save yourself the trouble of inspecting fingerprints after the handshake,
you can pass a Checker object into the handshake function. The checker will be
called if the handshake completes successfully. If the other party's
certificate chain isn't approved by the checker, a subclass of
TLSAuthenticationError will be raised. For example, to perform a handshake
with a server based on its X.509 fingerprint, do:

  try:
    checker = Checker(\
              x509Fingerprint='e049ff930af76d43ff4c658b268786f4df1296f2')
    connection.handshakeClientCert(checker=checker)
  except TLSAuthenticationError:
    print "Authentication failure"

If the handshake fails for any reason, an exception will be raised. If the
socket timed out or was unexpectedly closed, a socket.error or
TLSAbruptCloseError will be raised. Otherwise, either a TLSLocalAlert or
TLSRemoteAlert will be raised, depending on whether the local or remote
implementation signalled the error. The exception object has a 'description'
member which identifies the error based on the codes in RFC 2246. A
TLSLocalAlert also has a 'message' string that may have more details.

Example of handling a remote alert:

  try:
      [...]
  except TLSRemoteAlert, alert:
      if alert.description == AlertDescription.unknown_psk_identity:
          print "Unknown user."
  [...]

Figuring out what went wrong based on the alert may require some
interpretation, particularly with remote alerts where you don't have an error
string, and where the remote implementation may not be signalling alerts
properly.  Many alerts signal an implementation error, and so should rarely be
seen in normal operation (unexpected_message, decode_error, illegal_parameter,
internal_error, etc.).

Others alerts are more likely to occur.  Below are some common alerts and
their probable causes, and whether they are signalled by the client or server.

Client handshake failure:
 - SRP parameters are not recognized by client

Client insufficient_security:
 - SRP parameters are too small

Client protocol_version:
 - Client doesn't support the server's protocol version

Server protocol_version:
 - Server doesn't support the client's protocol version

Server bad_record_mac:
 - bad SRP username or password

Server unknown_psk_identity
 - bad SRP username (bad_record_mac could be used for the same thing)

Server handshake_failure:
 - bad shared key username
 - no matching cipher suites

5 Step 5 - exchange data
-------------------------
Now that you have a connection, you can call read() and write() as if it were
a socket.SSL object. You can also call send(), sendall(), recv(), and
makefile() as if it were a socket. These calls may raise TLSLocalAlert,
TLSRemoteAlert, socket.error, or TLSAbruptCloseError, just like the handshake
functions.

Once the TLS connection is closed by the other side, calls to read() or recv()
will return an empty string. If the socket is closed by the other side without
first closing the TLS connection, calls to read() or recv() will return a
TLSAbruptCloseError, and calls to write() or send() will return a
socket.error.

5 Step 6 - close the connection
--------------------------------
When you're finished sending data, you should call close() to close the
connection and socket. When the connection is closed properly, the session
object can be used for session resumption.

If an exception is raised, the connection will be automatically closed; you
don't need to call close().  Furthermore, you will probably not be able to re-
use the socket, the connection object, or the session object, and you
shouldn't even try.

By default, calling close() will close the underlying socket. If you set the
connection's closeSocket flag to False, the socket will remain open after
close, and can be used to send non-secure data, or another handshake function
can be called on the TLSConnection. NOTE: some TLS implementations will
not respond properly to the close_notify alert that close() generates, so the
connection will hang if closeSocket is set to True.


6 Using TLS Lite with httplib
==============================
TLS Lite comes with an HTTPTLSConnection class that extends httplib to work
over SSL/TLS connections.  Depending on how you construct it, it will do
different types of authentication.

  #No authentication whatsoever
  h = HTTPTLSConnection("www.amazon.com", 443)
  h.request("GET", "")
  r = h.getresponse()
  [...]

  #Authenticate server based on its X.509 fingerprint
  h = HTTPTLSConnection("www.amazon.com", 443,
          x509Fingerprint="e049ff930af76d43ff4c658b268786f4df1296f2")
  [...]

  #Mutually authenticate with SRP
  h = HTTPTLSConnection("localhost", 443,
          username="alice", password="abra123cadabra")
  [...]


7 Using TLS Lite with xmlrpclib
================================
TLS Lite comes with an XMLRPCTransport class that extends xmlrpclib to work
over SSL/TLS connections.  This class accepts the same parameters as
HTTPTLSConnection (see previous section), and behaves similarly.  Depending on
how you construct it, it will do different types of authentication.

  from tlslite import XMLRPCTransport
  from xmlrpclib import ServerProxy

  #No authentication whatsoever
  transport = XMLRPCTransport()
  server = ServerProxy("https://localhost", transport)
  server.someFunc(2, 3)
  [...]

  #Authenticate server based on its X.509 fingerprint
  transport = XMLRPCTransport(\
          x509Fingerprint="e049ff930af76d43ff4c658b268786f4df1296f2")  
  [...]


8 Using TLS Lite with poplib or imaplib
========================================
TLS Lite comes with POP3_TLS and IMAP4_TLS classes that extend poplib and
imaplib to work over SSL/TLS connections.  These classes can be constructed
with the same parameters as HTTPTLSConnection (see previous section), and 
behave similarly.

  #To connect to a POP3 server over SSL and display its fingerprint:
  from tlslite import *
  p = POP3_TLS("---------.net", port=995)
  print p.sock.session.serverCertChain.getFingerprint()
  [...]

  #To connect to an IMAP server once you know its fingerprint:
  from tlslite import *
  i = IMAP4_TLS("cyrus.andrew.cmu.edu",
          x509Fingerprint="00c14371227b3b677ddb9c4901e6f2aee18d3e45")
  [...]  
  

9 Using TLS Lite with smtplib
==============================
TLS Lite comes with an SMTP_TLS class that extends smtplib to work
over SSL/TLS connections.  This class accepts the same parameters as
HTTPTLSConnection (see previous section), and behaves similarly.  Depending 
on how you call starttls(), it will do different types of authentication.

  #To connect to an SMTP server once you know its fingerprint:
  from tlslite import *
  s = SMTP_TLS("----------.net", port=587)
  s.ehlo()
  s.starttls(x509Fingerprint="7e39be84a2e3a7ad071752e3001d931bf82c32dc")
  [...]


10 Using TLS Lite with SocketServer
====================================
You can use TLS Lite to implement servers using Python's SocketServer
framework.  TLS Lite comes with a TLSSocketServerMixIn class.  You can combine
this with a TCPServer such as HTTPServer.  To combine them, define a new class
that inherits from both of them (with the mix-in first). Then implement the
handshake() method, doing some sort of server handshake on the connection
argument.  If the handshake method returns True, the RequestHandler will be
triggered.  See the test/httpssserver.py example.


11 Using TLS Lite with asyncore
================================
TLS Lite can be used with subclasses of asyncore.dispatcher.  See the comments
in TLSAsyncDispatcherMixIn.py for details.  This is still experimental, and
may not work with all asyncore.dispatcher subclasses.


12 Security Considerations
===========================
TLS Lite is beta-quality code.  It hasn't received much security analysis.
Use at your own risk.


13 History
===========
0.3.8a - don't call it a comeback
0.3.8 - 2/21/2005
 - Added support for poplib, imaplib, and smtplib
 - Added python 2.4 windows installer
 - Fixed occassional timing problems with test suite
0.3.7 - 10/05/2004
 - Added support for Python 2.2
 - Cleaned up compatibility code, and docs, a bit
0.3.6 - 9/28/2004
 - Fixed script installation on UNIX
 - Give better error message on old Python versions
0.3.5 - 9/16/2004
 - TLS 1.1 support
 - os.urandom() support
 - Fixed win32prng on some systems
0.3.4 - 9/12/2004
 - Updated for TLS/SRP draft 8
 - Bugfix: was setting _versioncheck on SRP 1st hello, causing problems
   with GnuTLS (which was offering TLS 1.1)
 - Removed _versioncheck checking, since it could cause interop problems
 - Minor bugfix: when cryptlib_py and and cryptoIDlib present, cryptlib
   was complaining about being initialized twice
0.3.3 - 6/10/2004
 - Updated for TLS/SRP draft 7
 - Updated test cryptoID cert chains for cryptoIDlib 0.3.1
0.3.2 - 5/21/2004
 - fixed bug when handling multiple handshake messages per record (e.g. IIS)
0.3.1 - 4/21/2004
 - added xmlrpclib integration
 - fixed hanging bug in Twisted integration
 - fixed win32prng to work on a wider range of win32 sytems
 - fixed import problem with cryptoIDlib
 - fixed port allocation problem when test scripts are run on some UNIXes
 - made tolerant of buggy IE sending wrong version in premaster secret
0.3.0 - 3/20/2004
 - added API docs thanks to epydoc
 - added X.509 path validation via cryptlib
 - much cleaning/tweaking/re-factoring/minor fixes
0.2.7 - 3/12/2004
 - changed Twisted error handling to use connectionLost()
 - added ignoreAbruptClose
0.2.6 - 3/11/2004
 - added Twisted errorHandler
 - added TLSAbruptCloseError
 - added 'integration' subdirectory
0.2.5 - 3/10/2004
 - improved asynchronous support a bit
 - added first-draft of Twisted support
0.2.4 - 3/5/2004
 - cleaned up asyncore support
 - added proof-of-concept for Twisted
0.2.3 - 3/4/2004
 - added pycrypto RSA support
 - added asyncore support
0.2.2 - 3/1/2004
 - added GMPY support
 - added pycrypto support
 - added support for PEM-encoded private keys, in pure python
0.2.1 - 2/23/2004
 - improved PRNG use (cryptlib, or /dev/random, or CryptoAPI)
 - added RSA blinding, to avoid timing attacks
 - don't install local copy of M2Crypto, too problematic
0.2.0 - 2/19/2004
 - changed VerifierDB to take per-user parameters
 - renamed tls_lite -> tlslite
0.1.9 - 2/16/2004
 - added post-handshake 'Checker'
 - made compatible with Python 2.2
 - made more forgiving of abrupt closure, since everyone does it:
   if the socket is closed while sending/recv'ing close_notify,
   just ignore it.
0.1.8 - 2/12/2004
 - TLSConnections now emulate sockets, including makefile()
 - HTTPTLSConnection and TLSMixIn simplified as a result
0.1.7 - 2/11/2004
 - fixed httplib.HTTPTLSConnection with multiple requests
 - fixed SocketServer to handle close_notify
 - changed handshakeClientNoAuth() to ignore CertificateRequests
 - changed handshakeClient() to ignore non-resumable session arguments
0.1.6 - 2/10/2004
 - fixed httplib support
0.1.5 - 2/09/2004
 - added support for httplib and SocketServer
 - added support for SSLv3
 - added support for 3DES
 - cleaned up read()/write() behavior
 - improved HMAC speed
0.1.4 - 2/06/2004
 - fixed dumb bug in tls.py
0.1.3 - 2/05/2004
 - change read() to only return requested number of bytes
 - added support for shared-key and in-memory databases
 - added support for PEM-encoded X.509 certificates
 - added support for SSLv2 ClientHello
 - fixed shutdown/re-handshaking behavior
 - cleaned up handling of missing_srp_username
 - renamed readString()/writeString() -> read()/write()
 - added documentation
0.1.2 - 2/04/2004
 - added clienttest/servertest functions
 - improved OpenSSL cipher wrappers speed
 - fixed server when it has a key, but client selects plain SRP
 - fixed server to postpone errors until it has read client's messages
 - fixed ServerHello to only include extension data if necessary
0.1.1 - 2/02/2004
 - fixed close_notify behavior
 - fixed handling of empty application data packets
 - fixed socket reads to not consume extra bytes
 - added testing functions to tls.py
0.1.0 - 2/01/2004
 - first release
Something went wrong with that request. Please try again.