Home | History | Annotate | Download | only in tlslite
      1 
      2 tlslite version 0.3.8                                      February 21, 2005
      3 Trevor Perrin <trevp at trevp.net>
      4 http://trevp.net/tlslite/
      5 ============================================================================
      6 
      7 
      8 Table of Contents
      9 ==================
     10 1  Introduction
     11 2  License/Acknowledgements
     12 3  Installation
     13 4  Getting Started with the Command-Line Tools
     14 5  Getting Started with the Library
     15 6  Using TLS Lite with httplib
     16 7  Using TLS Lite with xmlrpclib
     17 8  Using TLS Lite with poplib or imaplib
     18 9  Using TLS Lite with smtplib
     19 10 Using TLS Lite with SocketServer
     20 11 Using TLS Lite with asyncore
     21 12 Using TLS Lite with Twisted
     22 13 SECURITY CONSIDERATIONS
     23 14 History
     24 15 References
     25 
     26 
     27 1 Introduction
     28 ===============
     29 TLS Lite is a free python library that implements SSL v3, TLS v1, and 
     30 TLS v1.1 [0]. TLS Lite supports non-traditional authentication methods 
     31 such as SRP [1], shared keys [2], and cryptoIDs [3], in addition to X.509
     32 certificates.  TLS Lite is pure python, however it can access OpenSSL [4], 
     33 cryptlib [5], pycrypto [9], and GMPY [10] for faster crypto operations.  TLS 
     34 Lite integrates with httplib, xmlrpclib, poplib, imaplib, smtplib,
     35 SocketServer, asyncore, and Twisted.
     36 
     37 API documentation is available in the 'docs' directory.
     38 
     39 If you have questions or feedback, feel free to contact me.
     40 
     41 
     42 2 Licenses/Acknowledgements
     43 ============================
     44 All code here is public domain.
     45 
     46 Thanks to Bram Cohen for his public domain Rijndael implementation.
     47 
     48 Thanks to Edward Loper for Epydoc, which generated the API docs.
     49 
     50 
     51 3 Installation
     52 ===============
     53 Requirements:
     54   Python 2.2 or greater is required.
     55 
     56 Options:
     57   - If you have cryptoIDlib [8], you can use cryptoID certificate chains for
     58   authentication.  CryptoIDlib is the sister library to TLS Lite; it was
     59   written by the same author, and has a similar interface.
     60 
     61   - If you have the M2Crypto [6] interface to OpenSSL, this will be used for
     62   fast RSA operations and fast ciphers.
     63 
     64   - If you have the cryptlib_py [7] interface to cryptlib, this will be used
     65   for random number generation and fast ciphers.  If TLS Lite can't find an
     66   OS-level random-number generator (i.e. /dev/urandom on UNIX or CryptoAPI on
     67   Windows), then you must MUST install cryptlib.
     68 
     69   - If you have pycrypto [9], this will be used for fast ciphers and fast RSA
     70   operations.
     71 
     72   - If you have the GMPY [10] interface to GMP, this will be used for fast RSA
     73   and SRP operations.
     74 
     75   - These modules don't need to be present at installation - you can install
     76   them any time.
     77 
     78 On Windows:
     79   Run the installer in the 'installers' directory.
     80   *OR*
     81   Run 'setup.py install' (this only works if your system has a compiler
     82   available).
     83 
     84 Anywhere else:
     85   - Run 'python setup.py install'
     86 
     87 Test the Installation:
     88   - The 'tls.py' script should have been copied onto your path.  If not,
     89     you may have to copy it there manually.
     90   - From the distribution's ./test subdirectory, run:
     91       tls.py servertest localhost:4443 .
     92   - While the test server is waiting, run:
     93       tls.py clienttest localhost:4443 .
     94 
     95   If both say "Test succeeded" at the end, you're ready to go.
     96 
     97   (WARNING: Be careful running these (or any) scripts from the distribution's
     98   root directory.  Depending on your path, the scripts may load the local copy
     99   of the library instead of the installed version, with unpredictable
    100   results).
    101 
    102 
    103 4 Getting Started with the Command-Line Tools
    104 ==============================================
    105 tlslite comes with two command-line scripts: 'tlsdb.py' and 'tls.py'.  They
    106 can be run with no arguments to see a list of commands.
    107 
    108 'tlsdb.py' lets you manage shared key or verifier databases.  These databases
    109 store usernames associated with either shared keys, or SRP password verifiers.
    110 These databases are used by a TLS server when authenticating clients with
    111 shared keys or SRP.
    112 
    113 'tls.py' lets you run test clients and servers.  It can be used for testing
    114 other TLS implementations, or as example code for using tlslite.  To run an
    115 SRP server, try something like:
    116 
    117   tlsdb.py createsrp verifierDB
    118   tlsdb.py add verifierDB alice abra123cadabra 1024
    119   tlsdb.py add verifierDB bob swordfish 2048
    120 
    121   tls.py serversrp localhost:443 verifierDB
    122 
    123 Then you can try connecting to the server with:
    124 
    125   tls.py clientsrp localhost:443 alice abra123cadabra
    126 
    127 
    128 5 Getting Started with the Library
    129 ===================================
    130 Using the library is simple.  Whether you're writing a client or server, there
    131 are six steps:
    132 1) Create a socket and connect it to the other party.
    133 2) Construct a TLSConnection instance with the socket.
    134 3) Call a handshake function on TLSConnection to perform the TLS handshake.
    135 4) Check the results to make sure you're talking to the right party.
    136 5) Use the TLSConnection to exchange data.
    137 6) Call close() on the TLSConnection when you're done.
    138 
    139 TLS Lite also integrates with httplib, xmlrpclib, poplib, imaplib, smtplib, 
    140 SocketServer, asyncore, and Twisted.  When used with these, some of the steps 
    141 are performed for you.  See the sections following this one for details.
    142 
    143 5 Step 1 - create a socket
    144 ---------------------------
    145 Below demonstrates a socket connection to Amazon's secure site.  It's a good
    146 idea to set the timeout value, so if the other side fails to respond you won't
    147 end up waiting forever.
    148 
    149   from socket import *
    150   sock = socket(AF_INET, SOCK_STREAM)
    151   sock.connect( ("www.amazon.com", 443) )
    152   sock.settimeout(10)  #Only on python 2.3 or greater
    153 
    154 5 Step 2 - construct a TLSConnection
    155 -------------------------------------
    156   from tlslite.api import *
    157   connection = TLSConnection(sock)
    158 
    159 5 Step 3 - call a handshake function (client)
    160 ----------------------------------------------
    161 If you're a client, there's several different handshake functions you can
    162 call, depending on how you want to authenticate:
    163 
    164   connection.handshakeClientCert()
    165   connection.handshakeClientCert(certChain, privateKey)
    166   connection.handshakeClientSRP("alice", "abra123cadabra")
    167   connection.handshakeClientSharedKey("alice", "PaVBVZkYqAjCQCu6UBL2xgsnZhw")
    168   connection.handshakeClientUnknown(srpCallback, certCallback)
    169 
    170 The ClientCert function without arguments is used when connecting to a site
    171 like Amazon, which doesn't require client authentication.  The server will
    172 authenticate with a certificate chain.
    173 
    174 The ClientCert function can also be used to do client authentication with an
    175 X.509 or cryptoID certificate chain.  To use cryptoID chains, you'll need the
    176 cryptoIDlib library [8].  To use X.509 chains, you'll need some way of
    177 creating these, such as OpenSSL (see http://www.openssl.org/docs/HOWTO/ for
    178 details).
    179 
    180 Below are examples of loading cryptoID and X.509 certificate chains:
    181 
    182   #Load cryptoID certChain and privateKey.  Requires cryptoIDlib.
    183   from cryptoIDlib.CertChain import CertChain
    184   s = open("./test/clientCryptoIDChain.xml").read()
    185   certChain = CertChain()
    186   certChain.parse(s)
    187   s = open("./test/clientCryptoIDKey.xml").read()
    188   privateKey = parseXMLKey(s, private=True)
    189 
    190   #Load X.509 certChain and privateKey.
    191   s = open("./test/clientX509Cert.pem").read()
    192   x509 = X509()
    193   x509.parse(s)
    194   certChain = X509CertChain([x509])
    195   s = open("./test/clientX509Key.pem").read()
    196   privateKey = parsePEMKey(s, private=True)
    197 
    198 The SRP and SharedKey functions both do mutual authentication with a username
    199 and password.  The difference is this: SRP is slow but safer when using low-
    200 entropy passwords, since the SRP protocol is not vulnerable to offline
    201 dictionary attacks.  Using shared keys is faster, but it's only safe when
    202 used with high-entropy secrets.  In general, you should prefer SRP for human-
    203 memorable passwords, and use shared keys only when your performance needs
    204 outweigh the inconvenience of handling large random strings.
    205 
    206 [WARNING: shared keys and SRP are internet-drafts; these protocols may change,
    207 which means future versions of tlslite may not be compatible with this one.
    208 This is less likely with SRP, more likely with shared-keys.]
    209 
    210 The Unknown function is used when you're not sure if the server requires
    211 client authentication.	 If the server requests SRP or certificate-based
    212 authentication, the appropriate callback will be triggered, and you should
    213 return a tuple containing either a (username, password) or (certChain,
    214 privateKey), as appropriate.  Alternatively, you can return None, which will
    215 cancel the handshake from an SRP callback, or cause it to continue without
    216 client authentication (if the server is willing) from a certificate callback.
    217 
    218 If you want more control over the handshake, you can pass in a
    219 HandshakeSettings instance.  For example, if you're performing SRP, but you
    220 only want to use SRP parameters of at least 2048 bits, and you only want to use
    221 the AES-256 cipher, and you only want to allow TLS (version 3.1), not SSL
    222 (version 3.0), you can do:
    223 
    224   settings = HandshakeSettings()
    225   settings.minKeySize = 2048
    226   settings.cipherNames = ["aes256"]
    227   settings.minVersion = (3,1)
    228   connection.handshakeClientSRP("alice", "abra123cadabra", settings=settings)
    229 
    230 Finally, every TLSConnection has a session object.  You can try to resume a
    231 previous session by passing in the session object from the old session.  If
    232 the server remembers this old session and supports resumption, the handshake
    233 will finish more quickly.  Otherwise, the full handshake will be done.  For
    234 example:
    235 
    236   connection.handshakeClientSRP("alice", "abra123cadabra")
    237   .
    238   .
    239   oldSession = connection.session
    240   connection2.handshakeClientSRP("alice", "abra123cadabra", session=
    241   oldSession)
    242 
    243 5 Step 3 - call a handshake function (server)
    244 ----------------------------------------------
    245 If you're a server, there's only one handshake function, but you can pass it
    246 several different parameters, depending on which types of authentication
    247 you're willing to perform.
    248 
    249 To perform SRP authentication, you have to pass in a database of password
    250 verifiers.  The VerifierDB class manages an in-memory or on-disk verifier
    251 database.
    252 
    253   #On-disk database (use no-arg constructor if you want an in-memory DB)
    254   verifierDB = VerifierDB("./test/verifierDB")
    255 
    256   #Open the pre-existing database (can also 'create()' a new one)
    257   verifierDB.open()
    258 
    259   #Add to the database
    260   verifier = VerifierDB.makeVerifier("alice", "abra123cadabra", 2048)
    261   verifierDB["alice"] = verifier
    262 
    263   #Perform a handshake using the database
    264   connection.handshakeServer(verifierDB=verifierDB)
    265 
    266 To perform shared key authentication, you have to pass in a database of shared
    267 keys.  The SharedKeyDB class manages an in-memory or on-disk shared key
    268 database.
    269 
    270   sharedKeyDB = SharedKeyDB("./test/sharedkeyDB")
    271   sharedKeyDB.open()
    272   sharedKeyDB["alice"] = "PaVBVZkYqAjCQCu6UBL2xgsnZhw"
    273   connection.handshakeServer(sharedKeyDB=sharedKeyDB)
    274 
    275 To perform authentication with a certificate and private key, the server must
    276 load these as described in the previous section, then pass them in.  If the
    277 server sets the reqCert boolean to True, a certificate chain will be requested
    278 from the client.
    279 
    280   connection.handshakeServer(certChain=certChain, privateKey=privateKey,
    281                              reqCert=True)
    282 
    283 You can pass in any combination of a verifier database, a shared key database,
    284 and a certificate chain/private key.  The client will use one of them to
    285 authenticate.  In the case of SRP and a certificate chain/private key, they
    286 both may be used.
    287 
    288 You can also pass in a HandshakeSettings object, as described in the last
    289 section, for finer control over handshaking details.  Finally, the server can
    290 maintain a SessionCache, which will allow clients to use session resumption:
    291 
    292   sessionCache = SessionCache()
    293   connection.handshakeServer(verifierDB=verifierDB, sessionCache=sessionCache)
    294 
    295 It should be noted that the session cache, and the verifier and shared key
    296 databases, are all thread-safe.
    297 
    298 5 Step 4 - check the results
    299 -----------------------------
    300 If the handshake completes without raising an exception, authentication
    301 results will be stored in the connection's session object.  The following
    302 variables will be populated if applicable, or else set to None:
    303 
    304   connection.session.srpUsername       #string
    305   connection.session.sharedKeyUsername #string
    306   connection.session.clientCertChain   #X509CertChain or
    307                                        #cryptoIDlib.CertChain.CertChain
    308   connection.session.serverCertChain   #X509CertChain or
    309                                        #cryptoIDlib.CertChain.CertChain
    310 
    311 Both types of certificate chain object support the getFingerprint() function,
    312 but with a difference.  X.509 objects return the end-entity fingerprint, and
    313 ignore the other certificates.  CryptoID fingerprints (aka "cryptoIDs") are
    314 based on the root cryptoID certificate, so you have to call validate() on the
    315 CertChain to be sure you're really talking to the cryptoID.
    316 
    317 X.509 certificate chain objects may also be validated against a list of
    318 trusted root certificates.  See the API documentation for details.
    319 
    320 To save yourself the trouble of inspecting fingerprints after the handshake,
    321 you can pass a Checker object into the handshake function.  The checker will be
    322 called if the handshake completes successfully.  If the other party's
    323 certificate chain isn't approved by the checker, a subclass of
    324 TLSAuthenticationError will be raised.  For example, to perform a handshake
    325 with a server based on its X.509 fingerprint, do:
    326 
    327   try:
    328     checker = Checker(\
    329               x509Fingerprint='e049ff930af76d43ff4c658b268786f4df1296f2')
    330     connection.handshakeClientCert(checker=checker)
    331   except TLSAuthenticationError:
    332     print "Authentication failure"
    333 
    334 If the handshake fails for any reason, an exception will be raised.  If the
    335 socket timed out or was unexpectedly closed, a socket.error or
    336 TLSAbruptCloseError will be raised.  Otherwise, either a TLSLocalAlert or
    337 TLSRemoteAlert will be raised, depending on whether the local or remote
    338 implementation signalled the error.  The exception object has a 'description'
    339 member which identifies the error based on the codes in RFC 2246.  A
    340 TLSLocalAlert also has a 'message' string that may have more details.
    341 
    342 Example of handling a remote alert:
    343 
    344   try:
    345       [...]
    346   except TLSRemoteAlert, alert:
    347       if alert.description == AlertDescription.unknown_srp_username:
    348           print "Unknown user."
    349   [...]
    350 
    351 Figuring out what went wrong based on the alert may require some
    352 interpretation, particularly with remote alerts where you don't have an error
    353 string, and where the remote implementation may not be signalling alerts
    354 properly.  Many alerts signal an implementation error, and so should rarely be
    355 seen in normal operation (unexpected_message, decode_error, illegal_parameter,
    356 internal_error, etc.).
    357 
    358 Others alerts are more likely to occur.  Below are some common alerts and
    359 their probable causes, and whether they are signalled by the client or server.
    360 
    361 Client bad_record_mac:
    362  - bad shared key password
    363 
    364 Client handshake failure:
    365  - SRP parameters are not recognized by client
    366 
    367 Client user_canceled:
    368  - The client might have returned None from an SRP callback.
    369 
    370 Client insufficient_security:
    371  - SRP parameters are too small
    372 
    373 Client protocol_version:
    374  - Client doesn't support the server's protocol version
    375 
    376 Server protocol_version:
    377  - Server doesn't support the client's protocol version
    378 
    379 Server bad_record_mac:
    380  - bad SRP username or password
    381 
    382 Server unknown_srp_username
    383  - bad SRP username (bad_record_mac could be used for the same thing)
    384 
    385 Server handshake_failure:
    386  - bad shared key username
    387  - no matching cipher suites
    388 
    389 5 Step 5 - exchange data
    390 -------------------------
    391 Now that you have a connection, you can call read() and write() as if it were
    392 a socket.SSL object.  You can also call send(), sendall(), recv(), and
    393 makefile() as if it were a socket.  These calls may raise TLSLocalAlert,
    394 TLSRemoteAlert, socket.error, or TLSAbruptCloseError, just like the handshake
    395 functions.
    396 
    397 Once the TLS connection is closed by the other side, calls to read() or recv()
    398 will return an empty string.  If the socket is closed by the other side
    399 without first closing the TLS connection, calls to read() or recv() will return
    400 a TLSAbruptCloseError, and calls to write() or send() will return a
    401 socket.error.
    402 
    403 5 Step 6 - close the connection
    404 --------------------------------
    405 When you're finished sending data, you should call close() to close the
    406 connection down.  When the connection is closed properly, the socket stays
    407 open and can be used for exchanging non-secure data, the session object can be
    408 used for session resumption, and the connection object can be re-used by
    409 calling another handshake function.
    410 
    411 If an exception is raised, the connection will be automatically closed; you
    412 don't need to call close().  Furthermore, you will probably not be able to re-
    413 use the socket, the connection object, or the session object, and you
    414 shouldn't even try.
    415 
    416 By default, calling close() will leave the socket open.  If you set the
    417 connection's closeSocket flag to True, the connection will take ownership of
    418 the socket, and close it when the connection is closed.
    419 
    420 
    421 6 Using TLS Lite with httplib
    422 ==============================
    423 TLS Lite comes with an HTTPTLSConnection class that extends httplib to work
    424 over SSL/TLS connections.  Depending on how you construct it, it will do
    425 different types of authentication.
    426 
    427   #No authentication whatsoever
    428   h = HTTPTLSConnection("www.amazon.com", 443)
    429   h.request("GET", "")
    430   r = h.getresponse()
    431   [...]
    432 
    433   #Authenticate server based on its X.509 fingerprint
    434   h = HTTPTLSConnection("www.amazon.com", 443,
    435           x509Fingerprint="e049ff930af76d43ff4c658b268786f4df1296f2")
    436   [...]
    437 
    438   #Authenticate server based on its X.509 chain (requires cryptlib_py [7])
    439   h = HTTPTLSConnection("www.amazon.com", 443,
    440           x509TrustList=[verisignCert],
    441           x509CommonName="www.amazon.com")
    442   [...]
    443 
    444   #Authenticate server based on its cryptoID
    445   h = HTTPTLSConnection("localhost", 443,
    446           cryptoID="dmqb6.fq345.cxk6g.5fha3")
    447   [...]
    448 
    449   #Mutually authenticate with SRP
    450   h = HTTPTLSConnection("localhost", 443,
    451           username="alice", password="abra123cadabra")
    452   [...]
    453 
    454   #Mutually authenticate with a shared key
    455   h = HTTPTLSConnection("localhost", 443,
    456           username="alice", sharedKey="PaVBVZkYqAjCQCu6UBL2xgsnZhw")
    457   [...]
    458 
    459   #Mutually authenticate with SRP, *AND* authenticate the server based
    460   #on its cryptoID
    461   h = HTTPTLSConnection("localhost", 443,
    462           username="alice", password="abra123cadabra",
    463           cryptoID="dmqb6.fq345.cxk6g.5fha3")
    464   [...]
    465 
    466 
    467 7 Using TLS Lite with xmlrpclib
    468 ================================
    469 TLS Lite comes with an XMLRPCTransport class that extends xmlrpclib to work
    470 over SSL/TLS connections.  This class accepts the same parameters as
    471 HTTPTLSConnection (see previous section), and behaves similarly.  Depending on
    472 how you construct it, it will do different types of authentication.
    473 
    474   from tlslite.api import XMLRPCTransport
    475   from xmlrpclib import ServerProxy
    476 
    477   #No authentication whatsoever
    478   transport = XMLRPCTransport()
    479   server = ServerProxy("https://localhost", transport)
    480   server.someFunc(2, 3)
    481   [...]
    482 
    483   #Authenticate server based on its X.509 fingerprint
    484   transport = XMLRPCTransport(\
    485           x509Fingerprint="e049ff930af76d43ff4c658b268786f4df1296f2")  
    486   [...]
    487 
    488 
    489 8 Using TLS Lite with poplib or imaplib
    490 ========================================
    491 TLS Lite comes with POP3_TLS and IMAP4_TLS classes that extend poplib and
    492 imaplib to work over SSL/TLS connections.  These classes can be constructed
    493 with the same parameters as HTTPTLSConnection (see previous section), and 
    494 behave similarly.
    495 
    496   #To connect to a POP3 server over SSL and display its fingerprint:
    497   from tlslite.api import *
    498   p = POP3_TLS("---------.net")
    499   print p.sock.session.serverCertChain.getFingerprint()
    500   [...]
    501 
    502   #To connect to an IMAP server once you know its fingerprint:
    503   from tlslite.api import *
    504   i = IMAP4_TLS("cyrus.andrew.cmu.edu",
    505           x509Fingerprint="00c14371227b3b677ddb9c4901e6f2aee18d3e45")
    506   [...]  
    507   
    508 
    509 9 Using TLS Lite with smtplib
    510 ==============================
    511 TLS Lite comes with an SMTP_TLS class that extends smtplib to work
    512 over SSL/TLS connections.  This class accepts the same parameters as
    513 HTTPTLSConnection (see previous section), and behaves similarly.  Depending 
    514 on how you call starttls(), it will do different types of authentication.
    515 
    516   #To connect to an SMTP server once you know its fingerprint:
    517   from tlslite.api import *
    518   s = SMTP_TLS("----------.net")
    519   s.starttls(x509Fingerprint="7e39be84a2e3a7ad071752e3001d931bf82c32dc")
    520   [...]
    521 
    522 
    523 10 Using TLS Lite with SocketServer
    524 ====================================
    525 You can use TLS Lite to implement servers using Python's SocketServer
    526 framework.  TLS Lite comes with a TLSSocketServerMixIn class.  You can combine
    527 this with a TCPServer such as HTTPServer.  To combine them, define a new class
    528 that inherits from both of them (with the mix-in first). Then implement the
    529 handshake() method, doing some sort of server handshake on the connection
    530 argument.  If the handshake method returns True, the RequestHandler will be
    531 triggered.  Below is a complete example of a threaded HTTPS server.
    532 
    533   from SocketServer import *
    534   from BaseHTTPServer import *
    535   from SimpleHTTPServer import *
    536   from tlslite.api import *
    537 
    538   s = open("./serverX509Cert.pem").read()
    539   x509 = X509()
    540   x509.parse(s)
    541   certChain = X509CertChain([x509])
    542 
    543   s = open("./serverX509Key.pem").read()
    544   privateKey = parsePEMKey(s, private=True)
    545 
    546   sessionCache = SessionCache()
    547 
    548   class MyHTTPServer(ThreadingMixIn, TLSSocketServerMixIn, HTTPServer):
    549       def handshake(self, tlsConnection):
    550           try:
    551               tlsConnection.handshakeServer(certChain=certChain,
    552                                             privateKey=privateKey,
    553                                             sessionCache=sessionCache)
    554               tlsConnection.ignoreAbruptClose = True
    555               return True
    556           except TLSError, error:
    557               print "Handshake failure:", str(error)
    558               return False
    559 
    560   httpd = MyHTTPServer(('localhost', 443), SimpleHTTPRequestHandler)
    561   httpd.serve_forever()
    562 
    563 
    564 11 Using TLS Lite with asyncore
    565 ================================
    566 TLS Lite can be used with subclasses of asyncore.dispatcher.  See the comments
    567 in TLSAsyncDispatcherMixIn.py for details.  This is still experimental, and
    568 may not work with all asyncore.dispatcher subclasses.
    569 
    570 Below is an example of combining Medusa's http_channel with
    571 TLSAsyncDispatcherMixIn:
    572 
    573   class http_tls_channel(TLSAsyncDispatcherMixIn,
    574                          http_server.http_channel):
    575       ac_in_buffer_size = 16384
    576 
    577       def __init__ (self, server, conn, addr):
    578           http_server.http_channel.__init__(self, server, conn, addr)
    579           TLSAsyncDispatcherMixIn.__init__(self, conn)
    580           self.tlsConnection.ignoreAbruptClose = True
    581           self.setServerHandshakeOp(certChain=certChain,
    582                                     privateKey=privateKey)
    583 
    584 
    585 12 Using TLS Lite with Twisted
    586 ===============================
    587 TLS Lite can be used with Twisted protocols.  Below is a complete example of
    588 using TLS Lite with a Twisted echo server.
    589 
    590 There are two server implementations below.  Echo is the original protocol,
    591 which is oblivious to TLS.  Echo1 subclasses Echo and negotiates TLS when the
    592 client connects.  Echo2 subclasses Echo and negotiates TLS when the client
    593 sends "STARTTLS".
    594 
    595   from twisted.internet.protocol import Protocol, Factory
    596   from twisted.internet import reactor
    597   from twisted.protocols.policies import WrappingFactory
    598   from twisted.protocols.basic import LineReceiver
    599   from twisted.python import log
    600   from twisted.python.failure import Failure
    601   import sys
    602   from tlslite.api import *
    603 
    604   s = open("./serverX509Cert.pem").read()
    605   x509 = X509()
    606   x509.parse(s)
    607   certChain = X509CertChain([x509])
    608 
    609   s = open("./serverX509Key.pem").read()
    610   privateKey = parsePEMKey(s, private=True)
    611 
    612   verifierDB = VerifierDB("verifierDB")
    613   verifierDB.open()
    614 
    615   class Echo(LineReceiver):
    616       def connectionMade(self):
    617           self.transport.write("Welcome to the echo server!\r\n")
    618 
    619       def lineReceived(self, line):
    620           self.transport.write(line + "\r\n")
    621 
    622   class Echo1(Echo):
    623       def connectionMade(self):
    624           if not self.transport.tlsStarted:
    625               self.transport.setServerHandshakeOp(certChain=certChain,
    626                                                   privateKey=privateKey,
    627                                                   verifierDB=verifierDB)
    628           else:
    629               Echo.connectionMade(self)
    630 
    631       def connectionLost(self, reason):
    632           pass #Handle any TLS exceptions here
    633 
    634   class Echo2(Echo):
    635       def lineReceived(self, data):
    636           if data == "STARTTLS":
    637               self.transport.setServerHandshakeOp(certChain=certChain,
    638                                                   privateKey=privateKey,
    639                                                   verifierDB=verifierDB)
    640           else:
    641               Echo.lineReceived(self, data)
    642 
    643       def connectionLost(self, reason):
    644           pass #Handle any TLS exceptions here
    645 
    646   factory = Factory()
    647   factory.protocol = Echo1
    648   #factory.protocol = Echo2
    649 
    650   wrappingFactory = WrappingFactory(factory)
    651   wrappingFactory.protocol = TLSTwistedProtocolWrapper
    652 
    653   log.startLogging(sys.stdout)
    654   reactor.listenTCP(1079, wrappingFactory)
    655   reactor.run()
    656 
    657 
    658 13 Security Considerations
    659 ===========================
    660 TLS Lite is beta-quality code.  It hasn't received much security analysis.
    661 Use at your own risk.
    662 
    663 
    664 14 History
    665 ===========
    666 0.3.8 - 2/21/2005
    667  - Added support for poplib, imaplib, and smtplib
    668  - Added python 2.4 windows installer
    669  - Fixed occassional timing problems with test suite
    670 0.3.7 - 10/05/2004
    671  - Added support for Python 2.2
    672  - Cleaned up compatibility code, and docs, a bit
    673 0.3.6 - 9/28/2004
    674  - Fixed script installation on UNIX
    675  - Give better error message on old Python versions
    676 0.3.5 - 9/16/2004
    677  - TLS 1.1 support
    678  - os.urandom() support
    679  - Fixed win32prng on some systems
    680 0.3.4 - 9/12/2004
    681  - Updated for TLS/SRP draft 8
    682  - Bugfix: was setting _versioncheck on SRP 1st hello, causing problems
    683    with GnuTLS (which was offering TLS 1.1)
    684  - Removed _versioncheck checking, since it could cause interop problems
    685  - Minor bugfix: when cryptlib_py and and cryptoIDlib present, cryptlib
    686    was complaining about being initialized twice
    687 0.3.3 - 6/10/2004
    688  - Updated for TLS/SRP draft 7
    689  - Updated test cryptoID cert chains for cryptoIDlib 0.3.1
    690 0.3.2 - 5/21/2004
    691  - fixed bug when handling multiple handshake messages per record (e.g. IIS)
    692 0.3.1 - 4/21/2004
    693  - added xmlrpclib integration
    694  - fixed hanging bug in Twisted integration
    695  - fixed win32prng to work on a wider range of win32 sytems
    696  - fixed import problem with cryptoIDlib
    697  - fixed port allocation problem when test scripts are run on some UNIXes
    698  - made tolerant of buggy IE sending wrong version in premaster secret
    699 0.3.0 - 3/20/2004
    700  - added API docs thanks to epydoc
    701  - added X.509 path validation via cryptlib
    702  - much cleaning/tweaking/re-factoring/minor fixes
    703 0.2.7 - 3/12/2004
    704  - changed Twisted error handling to use connectionLost()
    705  - added ignoreAbruptClose
    706 0.2.6 - 3/11/2004
    707  - added Twisted errorHandler
    708  - added TLSAbruptCloseError
    709  - added 'integration' subdirectory
    710 0.2.5 - 3/10/2004
    711  - improved asynchronous support a bit
    712  - added first-draft of Twisted support
    713 0.2.4 - 3/5/2004
    714  - cleaned up asyncore support
    715  - added proof-of-concept for Twisted
    716 0.2.3 - 3/4/2004
    717  - added pycrypto RSA support
    718  - added asyncore support
    719 0.2.2 - 3/1/2004
    720  - added GMPY support
    721  - added pycrypto support
    722  - added support for PEM-encoded private keys, in pure python
    723 0.2.1 - 2/23/2004
    724  - improved PRNG use (cryptlib, or /dev/random, or CryptoAPI)
    725  - added RSA blinding, to avoid timing attacks
    726  - don't install local copy of M2Crypto, too problematic
    727 0.2.0 - 2/19/2004
    728  - changed VerifierDB to take per-user parameters
    729  - renamed tls_lite -> tlslite
    730 0.1.9 - 2/16/2004
    731  - added post-handshake 'Checker'
    732  - made compatible with Python 2.2
    733  - made more forgiving of abrupt closure, since everyone does it:
    734    if the socket is closed while sending/recv'ing close_notify,
    735    just ignore it.
    736 0.1.8 - 2/12/2004
    737  - TLSConnections now emulate sockets, including makefile()
    738  - HTTPTLSConnection and TLSMixIn simplified as a result
    739 0.1.7 - 2/11/2004
    740  - fixed httplib.HTTPTLSConnection with multiple requests
    741  - fixed SocketServer to handle close_notify
    742  - changed handshakeClientNoAuth() to ignore CertificateRequests
    743  - changed handshakeClient() to ignore non-resumable session arguments
    744 0.1.6 - 2/10/2004
    745  - fixed httplib support
    746 0.1.5 - 2/09/2004
    747  - added support for httplib and SocketServer
    748  - added support for SSLv3
    749  - added support for 3DES
    750  - cleaned up read()/write() behavior
    751  - improved HMAC speed
    752 0.1.4 - 2/06/2004
    753  - fixed dumb bug in tls.py
    754 0.1.3 - 2/05/2004
    755  - change read() to only return requested number of bytes
    756  - added support for shared-key and in-memory databases
    757  - added support for PEM-encoded X.509 certificates
    758  - added support for SSLv2 ClientHello
    759  - fixed shutdown/re-handshaking behavior
    760  - cleaned up handling of missing_srp_username
    761  - renamed readString()/writeString() -> read()/write()
    762  - added documentation
    763 0.1.2 - 2/04/2004
    764  - added clienttest/servertest functions
    765  - improved OpenSSL cipher wrappers speed
    766  - fixed server when it has a key, but client selects plain SRP
    767  - fixed server to postpone errors until it has read client's messages
    768  - fixed ServerHello to only include extension data if necessary
    769 0.1.1 - 2/02/2004
    770  - fixed close_notify behavior
    771  - fixed handling of empty application data packets
    772  - fixed socket reads to not consume extra bytes
    773  - added testing functions to tls.py
    774 0.1.0 - 2/01/2004
    775  - first release
    776 
    777 
    778 15 References
    779 ==============
    780 [0] http://www.ietf.org/html.charters/tls-charter.html
    781 [1] http://www.trevp.net/tls_srp/draft-ietf-tls-srp-07.html
    782 [2] http://www.ietf.org/internet-drafts/draft-ietf-tls-sharedkeys-02.txt
    783 [3] http://www.trevp.net/cryptoID/
    784 [4] http://www.openssl.org/
    785 [5] http://www.cs.auckland.ac.nz/~pgut001/cryptlib/
    786 [6] http://sandbox.rulemaker.net/ngps/m2/
    787 [7] http://trevp.net/cryptlibConverter/
    788 [8] http://www.trevp.net/cryptoID/
    789 [9] http://www.amk.ca/python/code/crypto.html
    790 [10] http://gmpy.sourceforge.net/
    791 
    792 
    793 
    794 
    795 
    796 
    797 
    798 
    799 
    800 
    801 
    802 
    803 
    804 
    805 
    806 
    807 
    808 
    809 
    810 
    811 
    812 
    813 
    814 
    815 
    816