Commits

Anonymous committed 773bc03

Version 0.2.1:
- RSA blinding
- good PRNG use
- removed M2Crypto

  • Participants
  • Parent commits 948ee7e

Comments (0)

Files changed (8)

 
-tlslite version 0.2.0                                        February 19, 2004
+tlslite version 0.2.1                                         February 23, 2004
 Trevor Perrin <trevp at trevp.net>
-http://trevp.net/tlslite
+http://trevp.net/tlslite/
 ===============================================================================
 
 
-Introduction
-=============
+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 and SocketServer
+7 SECURITY CONSIDERATIONS
+8 History
+9 References
+
+
+1 Introduction
+===============
 TLS Lite is a free python library that implements SSL v3 and TLS v1 [0].  TLS
 Lite supports non-traditional authentication methods such as SRP [1], shared
 keys[2], and cryptoIDs [3], in addition to X.509 certificates.  TLS Lite is pure
 If you have questions or feedback, feel free to contact me.
 
 
-License/Copyrights
-===================
-On Windows, DLLs containing M2Crypto [6] and OpenSSL routines may be
-installed.  Copyright notices, licenses, and acknowledgements for these
-libraries are at the bottom of this file.
+2 Licenses/Acknowledgements
+============================
+All code here is public domain.
 
-All other code here is public domain.
+Thanks to Bram Cohen for his public domain Rijndael implementation.
 
 
-Installation
-=============
+3 Installation
+===============
 Requirements:
   Python 2.3.2 or greater is recommended.  Python versions 2.2.1 or greater
-  should work, but haven't been tested much.  The initial Python 2.3 release had
-  a memory leak bug, and SHOULD NOT be used.
+  should work, but haven't been tested much.
 
 Options:
-  - If you have the M2Crypto interface to OpenSSL, this will be used for fast
-  RSA operations, fast ciphers, and accessing OpenSSL's PEM-encoded keys.  The
-  windows installer installs a DLL for M2Crypto / OpenSSL side-by-side with
-  tlslite (so it doesn't interfere with anything else).
+  - If you have the M2Crypto [6] interface to OpenSSL, this will be used for
+  fast RSA operations, fast ciphers, and accessing OpenSSL's PEM-encoded keys.
 
   - If you have the cryptlib_py [7] interface to cryptlib, this will be used
-  for good randomness generation and fast ciphers.
+  for random number generation and fast ciphers.  If TLS Lite can't find an OS-
+  level random-number generator (i.e. /dev/urandom on UNIX or CryptoAPI on
+  Windows), then you must MUST install cryptlib.
 
   - If you have cryptoIDlib [8], you can use cryptoID certificate chains for
   authentication.
   them any time.
 
 On Windows:
-  - Run the installer in the 'installers' directory.
+  Run the installer in the 'installers' directory.
   *OR*
-  - Run 'python setup.py install' (this only works if your system has a compiler
+  Run 'python setup.py install' (this only works if your system has a compiler
   available).
 
 Anywhere else:
   If both say "Test succeeded" at the end, you're ready to go.
 
 
-Getting Started with the Command-Line Tools
-============================================
+4 Getting Started with the Command-Line Tools
+==============================================
 tlslite comes with two command-line scripts: 'tlsdb.py' and 'tls.py'.  They can
 be run with no arguments to see a list of commands.
 
   tls.py clientsrp localhost:443 alice abra123cadabra
 
 
-Getting Started with the Library
-=================================
+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.
 framework.  When used with these, some of the steps are performed for you.  See
 the next section for details.
 
-Step 1 - create a socket
--------------------------
+5 Step 1 - create a socket
+---------------------------
 Below demonstrates a socket connection to Amazon's secure site.  It's a good
 idea to set the timeout value, so if the other side fails to respond you won't
 end up waiting forever.
   sock.connect( ("www.amazon.com", 443) )
   sock.settimeout(10)  #Only on python 2.3
 
-Step 2 - construct a TLSConnection
------------------------------------
+5 Step 2 - construct a TLSConnection
+-------------------------------------
   import tlslite
   connection = tlslite.TLSConnection(sock)
 
-Step 3 - call a handshake function (client)
---------------------------------------------
+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:
 
   oldSession = connection.session
   connection2.handshakeClientSRP("alice", "abra123cadabra", session=oldSession)
 
-Step 3 - call a handshake function (server)
---------------------------------------------
+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.
 It should be noted that the session cache, and the verifier and shared key
 databases, are all thread-safe.
 
-Step 4 - check the results
----------------------------
+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:
  - bad shared key username
  - no matching cipher suites
 
-Step 5 - exchange data
------------------------
+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, or
 closing the TLS connection, a call to read() or write() will return a
 socket.error.
 
-Step 6 - close the connection
-------------------------------
+5 Step 6 - close the connection
+--------------------------------
 When you're finished sending data, you should call close() to shut the
 connection down and signal the other side you're done.  When the connection is
 closed properly, the socket stays open and can be used for exchanging non-secure
 socket, and close it when the connection is closed.
 
 
-Using TLS Lite with httplib and SocketServer
-=============================================
+6 Using TLS Lite with httplib and SocketServer
+===============================================
 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.  For example:
   httpd.serve_forever()
 
 
-History
-========
+7 Security Considerations
+==========================
+TLS Lite is alpha-quality code.  Don't use it for anything important.
+
+
+8 History
+==========
+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 tlslite -> tlslite
+ - renamed tls_lite -> tlslite
 0.1.9 - 2/16/2004
  - added post-handshake 'Checker'
  - made compatible with Python 2.2
  - first release
 
 
-References
-===========
+9 References
+=============
 [0] http://www.ietf.org/rfc/rfc2246.txt
 [1] http://www.trevp.net/tls_srp/draft-ietf-tls-srp-06.html
 [2] http://www.ietf.org/internet-drafts/draft-ietf-tls-sharedkeys-02.txt
 [8] http://www.trevp.net/cryptoID/
 
 
-Copyright Notice and License for M2Crypto
-==========================================
-Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.
 
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation.
 
 
-Copyright Notices and Licenses for OpenSSL
-===========================================
-The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
-the OpenSSL License and the original SSLeay license apply to the toolkit.
-See below for the actual license texts. Actually both licenses are BSD-style
-Open Source licenses. In case of any license issues related to OpenSSL
-please contact openssl-core@openssl.org.
 
-OpenSSL License
-----------------
-Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. Redistribution
-and use in source and binary forms, with or without modification, are permitted
-provided that the following conditions are met:
 
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
 
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-All advertising materials mentioning features or use of this software must
-display the following acknowledgment: This product includes software developed
-by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org)
 
-The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or
-promote products derived from this software without prior written permission.
-For written permission, please contact openssl-core@openssl.org
 
-Products derived from this software may not be called "OpenSSL" nor may
-"OpenSSL" appear in their names without prior written permission of the OpenSSL
-Project.
 
-Redistributions of any form whatsoever must retain the following acknowledgment:
-"This product includes software developed by the OpenSSL Project for use in the
-OpenSSL Toolkit (http://www.openssl.org)"
 
 
-THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This product includes cryptographic
-software written by Eric Young (eay@cryptsoft.com). This product includes
-software written by Tim Hudson (tjh@cryptsoft.com).
-
-Original SSLeay License
-------------------------
-Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
-All rights reserved.
-
-This package is an SSL implementation written
-by Eric Young (eay@cryptsoft.com).
-The implementation was written so as to conform with Netscapes SSL.
-
-This library is free for commercial and non-commercial use as long as
-the following conditions are aheared to.  The following conditions
-apply to all code found in this distribution, be it the RC4, RSA,
-lhash, DES, etc., code; not just the SSL code.  The SSL documentation
-included with this distribution is covered by the same copyright terms
-except that the holder is Tim Hudson (tjh@cryptsoft.com).
-
-Copyright remains Eric Young's, and as such any Copyright notices in
-the code are not to be removed.
-If this package is used in a product, Eric Young should be given attribution
-as the author of the parts of the library used.
-This can be in the form of a textual message at program startup or
-in documentation (online or textual) provided with the package.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the copyright
-   notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-   "This product includes cryptographic software written by
-    Eric Young (eay@cryptsoft.com)"
-   The word 'cryptographic' can be left out if the rouines from the library
-   being used are not cryptographic related :-).
-4. If you include any Windows specific code (or a derivative thereof) from
-   the apps directory (application code) you must include an acknowledgement:
-   "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
-
-THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-
-The licence and distribution terms for any publically available version or
-derivative of this code cannot be changed.  i.e. this code cannot simply be
-copied and put under another distribution licence
-[including the GNU Public Licence.]
-
-
-
-
-#! python
-
-import sys
-import os
-import os.path
-import socket
-import thread
-import time
-import httplib
-import BaseHTTPServer
-import SimpleHTTPServer
-
-
-try:
-    import cryptoIDlib
-    cryptoIDlibLoaded = True
-except:
-    cryptoIDlibLoaded = False
-
-if __name__ != "__main__":
-    raise "This must be run as a command, not used as a module!"
-
-
-import tlslite
-from tlslite.utils.jython_compat import formatExceptionTrace
-
-
-def parsePrivateKey(s):
-    try:
-        return tlslite.parsePEMKey(s, private=True)
-    except:
-        return tlslite.parseXMLKey(s, private=True)
-
-
-def clientTest(address, dir):
-
-    #Split address into hostname/port tuple
-    address = address.split(":")
-    if len(address)==1:
-        address.append("443")
-    address = ( address[0], int(address[1]) )    
-        
-    def connect():
-        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        if hasattr(sock, 'settimeout'): #It's a python 2.3 feature
-            sock.settimeout(5)
-        sock.connect(address)
-        c = tlslite.TLSConnection(sock)
-        return c
-
-    test = 0
-    
-    badFault = False
-    
-    print "Test 1 - good shared key"
-    connection = connect()
-    connection.handshakeClientSharedKey("shared", "key")
-    connection.close()
-    connection.sock.close()
-    
-    print "Test 2 - shared key faults"
-    for fault in tlslite.ClientSharedKeyFault.faults + tlslite.GenericFault.faults:
-        connection = connect()
-        connection.fault = fault
-        try:
-            connection.handshakeClientSharedKey("shared", "key")
-            print "  Good Fault %s" % (tlslite.faultNames[fault])
-        except tlslite.FaultError, e:
-            print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
-            badFault = True
-        connection.sock.close()    
-    
-    print "Test 3 - good SRP"
-    connection = connect()
-    connection.handshakeClientSRP("test", "password")
-    connection.close()
-
-    print "Test 4 - SRP faults"
-    for fault in tlslite.ClientSRPFault.faults + tlslite.GenericFault.faults:
-        connection = connect()
-        connection.fault = fault
-        try:
-            connection.handshakeClientSRP("test", "password")
-            print "  Good Fault %s" % (tlslite.faultNames[fault])
-        except tlslite.FaultError, e:
-            print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
-            badFault = True
-        connection.sock.close()
-    
-    print "Test 5 - good SRP: unknown_srp_username idiom"
-    def srpCallback():
-        return ("test", "password")
-    connection = connect()
-    connection.handshakeClientUnknown(srpCallback=srpCallback)
-    connection.close()
-    connection.sock.close()
-        
-    if tlslite.m2cryptoLoaded:    
-        print "Test 6 - good SRP: with X.509 certificate"
-        connection = connect()
-        connection.handshakeClientSRP("test", "password")
-        assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
-        connection.close()
-        connection.sock.close()
-
-        print "Test 7 - X.509 with SRP faults"
-        for fault in tlslite.ClientSRPFault.faults + tlslite.GenericFault.faults:
-            connection = connect()
-            connection.fault = fault
-            try:
-                connection.handshakeClientSRP("test", "password")
-                print "  Good Fault %s" % (tlslite.faultNames[fault])
-            except tlslite.FaultError, e:
-                print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
-                badFault = True
-            connection.sock.close()
-            
-    
-    if cryptoIDlibLoaded:
-        print "Test 8 - good SRP: with cryptoID certificate chain"
-        connection = connect()
-        connection.handshakeClientSRP("test", "password")
-        assert(isinstance(connection.session.serverCertChain, cryptoIDlib.CertChain))
-        if not (connection.session.serverCertChain.validate()):
-            print connection.session.serverCertChain.validate(listProblems=True)
-            
-        connection.close()
-        connection.sock.close()
-
-        print "Test 9 - CryptoID with SRP faults"
-        for fault in tlslite.ClientSRPFault.faults + tlslite.GenericFault.faults:
-            connection = connect()
-            connection.fault = fault
-            try:
-                connection.handshakeClientSRP("test", "password")
-                print "  Good Fault %s" % (tlslite.faultNames[fault])
-            except tlslite.FaultError, e:
-                print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
-                badFault = True
-            connection.sock.close()
-        
-    if tlslite.m2cryptoLoaded:
-        print "Test 10 - good X509"
-        connection = connect()
-        connection.handshakeClientNoAuth()
-        assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
-        connection.close()
-        connection.sock.close()
-
-        print "Test 10.a - good X509, SSLv3"
-        connection = connect()
-        settings = tlslite.HandshakeSettings()
-        settings.minVersion = (3,0)
-        settings.maxVersion = (3,0)
-        connection.handshakeClientNoAuth(settings=settings)
-        assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
-        connection.close()
-        connection.sock.close()
-        
-        print "Test 11 - X.509 faults"
-        for fault in tlslite.ClientNoAuthFault.faults + tlslite.GenericFault.faults:
-            connection = connect()
-            connection.fault = fault
-            try:
-                connection.handshakeClientNoAuth()
-                print "  Good Fault %s" % (tlslite.faultNames[fault])
-            except tlslite.FaultError, e:
-                print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
-                badFault = True
-            connection.sock.close()
-                
-    if cryptoIDlibLoaded:        
-        print "Test 12 - good cryptoID"
-        connection = connect()
-        connection.handshakeClientNoAuth()
-        assert(isinstance(connection.session.serverCertChain, cryptoIDlib.CertChain))
-        assert(connection.session.serverCertChain.validate())
-        connection.close()
-        connection.sock.close()
-        
-        print "Test 13 - cryptoID faults"
-        for fault in tlslite.ClientNoAuthFault.faults + tlslite.GenericFault.faults:
-            connection = connect()
-            connection.fault = fault
-            try:
-                connection.handshakeClientNoAuth()
-                print "  Good Fault %s" % (tlslite.faultNames[fault])
-            except tlslite.FaultError, e:
-                print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
-                badFault = True
-            connection.sock.close()        
-        
-    if tlslite.m2cryptoLoaded:
-        print "Test 14 - good mutual X509"
-        x509Cert = tlslite.X509().parse(open(os.path.join(dir, "clientX509Cert.pem")).read())
-        x509Chain = tlslite.X509CertChain([x509Cert])        
-        s = open(os.path.join(dir, "clientX509Key.pem")).read()
-        x509Key = tlslite.parsePEMKey(s, private=True)
-        
-        connection = connect()
-        connection.handshakeClientCert(x509Chain, x509Key)
-        assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
-        connection.close()
-        connection.sock.close()
-        
-        print "Test 14.a - good mutual X509, SSLv3"
-        connection = connect()
-        settings = tlslite.HandshakeSettings()
-        settings.minVersion = (3,0)
-        settings.maxVersion = (3,0)
-        connection.handshakeClientCert(x509Chain, x509Key, settings=settings)
-        assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
-        connection.close()
-        connection.sock.close()
-
-        print "Test 15 - mutual X.509 faults"
-        for fault in tlslite.ClientCertFault.faults + tlslite.GenericFault.faults:
-            connection = connect()
-            connection.fault = fault
-            try:
-                connection.handshakeClientCert(x509Chain, x509Key)
-                print "  Good Fault %s" % (tlslite.faultNames[fault])
-            except tlslite.FaultError, e:
-                print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
-                badFault = True
-            connection.sock.close()        
-        
-    if cryptoIDlibLoaded:        
-        print "Test 16 - good mutual cryptoID"
-        cryptoIDChain = cryptoIDlib.CertChain().parse(open(os.path.join(dir, "serverCryptoIDChain.xml"), "r").read())
-        cryptoIDKey = tlslite.parseXMLKey(open(os.path.join(dir, "serverCryptoIDKey.xml"), "r").read(), private=True)
-        
-        connection = connect()
-        connection.handshakeClientCert(cryptoIDChain, cryptoIDKey)
-        assert(isinstance(connection.session.serverCertChain, cryptoIDlib.CertChain))
-        assert(connection.session.serverCertChain.validate())
-        connection.close()
-        connection.sock.close()
-        
-        print "Test 17 - mutual cryptoID faults"
-        for fault in tlslite.ClientCertFault.faults + tlslite.GenericFault.faults:
-            connection = connect()
-            connection.fault = fault
-            try:
-                connection.handshakeClientCert(cryptoIDChain, cryptoIDKey)
-                print "  Good Fault %s" % (tlslite.faultNames[fault])
-            except tlslite.FaultError, e:
-                print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
-                badFault = True
-            connection.sock.close()                
-
-    print "Test 18 - good SRP, prepare to resume..."
-    connection = connect()
-    connection.handshakeClientSRP("test", "password")
-    connection.close()
-    connection.sock.close()
-    session = connection.session
-
-    print "Test 19 - resumption"
-    connection = connect()    
-    connection.handshakeClientSRP("test", "garbage", session=session)
-    #Don't close! -- see below
-    
-    print "Test 20 - invalidated resumption"   
-    connection.sock.close() #Close the socket without a close_notify!
-    connection = connect()    
-    try:
-        connection.handshakeClientSRP("test", "garbage", session=session)    
-        assert()
-    except tlslite.TLSRemoteAlert, alert:
-        if alert.description != tlslite.AlertDescription.bad_record_mac:
-            raise
-    connection.sock.close()
-        
-    if tlslite.m2cryptoLoaded:
-        print "Test 21 - HTTPS test X.509"
-        time.sleep(2)
-        htmlBody = open(os.path.join(dir, "index.html")).read()
-        fingerprint = None
-        for y in range(2):
-            h = tlslite.HTTPTLSConnection(address[0], address[1], x509Fingerprint=fingerprint)
-            for x in range(3):
-                h.request("GET", "/index.html")
-                r = h.getresponse()
-                assert(r.status == 200)
-                s = r.read()
-                assert(s == htmlBody)
-            fingerprint = h.tlsSession.serverCertChain.getFingerprint()
-            assert(fingerprint)
-        time.sleep(2)
-    
-    if cryptoIDlibLoaded:
-        print "Test 21a - HTTPS test SRP+cryptoID"
-        time.sleep(2) #Time to generate key and cryptoID
-        htmlBody = open(os.path.join(dir, "index.html")).read()
-        fingerprint = None
-        protocol = None
-        for y in range(2):
-            h = tlslite.HTTPTLSConnection(address[0], address[1], 
-                         username="test", password="password",
-                         cryptoID=fingerprint, protocol=protocol)
-            for x in range(3):
-                h.request("GET", "/index.html")
-                r = h.getresponse()
-                assert(r.status == 200)
-                s = r.read()
-                assert(s == htmlBody)
-            fingerprint = h.tlsSession.serverCertChain.cryptoID
-            assert(fingerprint)
-            protocol = "urn:whatever"
-        time.sleep(2)
-    
-    implementations = []
-    if tlslite.cryptlibpyLoaded:
-        implementations.append("cryptlib")
-    if tlslite.m2cryptoLoaded:
-        implementations.append("openssl")
-    implementations.append("python")
-
-    print "Test 22 - different ciphers"
-    for implementation in implementations:
-        for cipher in ["aes128", "aes256", "rc4"]:
-        
-            print "Test 22:",
-            connection = connect()      
-            
-            settings = tlslite.HandshakeSettings()
-            settings.cipherNames = [cipher]
-            settings.cipherImplementations = [implementation, "python"]
-            connection.handshakeClientSharedKey("shared", "key", settings=settings)
-            print ("%s %s" % (connection.getCipherName(), connection.getCipherImplementation()))
-            
-            connection.write("hello")
-            h = connection.read(min=5, max=5)
-            assert(h == "hello")
-            connection.close()
-            connection.sock.close()
-
-    print "Test 23 - throughput test"
-    for implementation in implementations:
-        for cipher in ["aes128", "aes256", "3des", "rc4"]:
-            if cipher == "3des" and implementation not in ("openssl", "cryptlib"):
-                continue
-
-            print "Test 23:",
-            connection = connect()      
-            
-            settings = tlslite.HandshakeSettings()
-            settings.cipherNames = [cipher]
-            settings.cipherImplementations = [implementation, "python"]
-            connection.handshakeClientSharedKey("shared", "key", settings=settings)
-            print ("%s %s:" % (connection.getCipherName(), connection.getCipherImplementation())),
-            
-            startTime = time.clock()
-            connection.write("hello"*10000)
-            h = connection.read(min=50000, max=50000)
-            stopTime = time.clock()
-            print "100K exchanged at rate of %d bytes/sec" % int(100000/(stopTime-startTime))
-            
-            assert(h == "hello"*10000)
-            connection.close()
-            connection.sock.close()
-
-    if not badFault:
-        print "Test succeeded"
-    else:
-        print "Test failed"
-
-
-
-
-
-def serverTest(address, dir):
-    #Split address into hostname/port tuple
-    address = address.split(":")
-    if len(address)==1:
-        address.append("443")
-    address = ( address[0], int(address[1]) )    
-
-    #Connect to server
-    lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-    lsock.bind(address)
-    lsock.listen(5)
-    
-    def connect():
-        return tlslite.TLSConnection(lsock.accept()[0])
-        
-    print "Test 1 - good shared key"
-    sharedKeyDB = tlslite.SharedKeyDB()
-    sharedKeyDB["shared"] = "key"
-    sharedKeyDB["shared2"] = "key2"
-    connection = connect()
-    connection.handshakeServer(sharedKeyDB=sharedKeyDB)
-    connection.close()
-    connection.sock.close()
-
-    print "Test 2 - shared key faults"
-    for fault in tlslite.ClientSharedKeyFault.faults + tlslite.GenericFault.faults:
-        connection = connect()
-        connection.fault = fault
-        try:
-            connection.handshakeServer(sharedKeyDB=sharedKeyDB)
-            assert()
-        except:
-            pass
-        connection.sock.close()            
-
-    print "Test 3 - good SRP"
-    #verifierDB = tlslite.VerifierDB(os.path.join(dir, "verifierDB"))
-    #verifierDB.open()
-    verifierDB = tlslite.VerifierDB()
-    verifierDB.create()
-    entry = tlslite.makeVerifier("test", "password", 1536)
-    verifierDB["test"] = entry
-    
-    connection = connect()
-    connection.handshakeServer(verifierDB=verifierDB)
-    connection.close()
-    connection.sock.close()
-
-    print "Test 4 - SRP faults"
-    for fault in tlslite.ClientSRPFault.faults + tlslite.GenericFault.faults:
-        connection = connect()
-        connection.fault = fault
-        try:            
-            connection.handshakeServer(verifierDB=verifierDB)
-            assert()
-        except:
-            pass
-        connection.sock.close()
-        
-    print "Test 5 - good SRP: unknown_srp_username idiom"
-    connection = connect()
-    connection.handshakeServer(verifierDB=verifierDB)
-    connection.close()
-    connection.sock.close()
-
-
-    if tlslite.m2cryptoLoaded:
-        print "Test 6 - good SRP: with X.509 cert"
-        x509Cert = tlslite.X509().parse(open(os.path.join(dir, "serverX509Cert.pem")).read())
-        x509Chain = tlslite.X509CertChain([x509Cert])        
-        s = open(os.path.join(dir, "serverX509Key.pem")).read()
-        x509Key = tlslite.parsePEMKey(s, private=True)
-        
-        connection = connect()
-        connection.handshakeServer(verifierDB=verifierDB, \
-                                   certChain=x509Chain, privateKey=x509Key)
-        connection.close()
-        connection.sock.close()
-        
-        print "Test 7 - X.509 with SRP faults"
-        for fault in tlslite.ClientSRPFault.faults + tlslite.GenericFault.faults:
-            connection = connect()
-            connection.fault = fault
-            try:            
-                connection.handshakeServer(verifierDB=verifierDB, \
-                                           certChain=x509Chain, privateKey=x509Key)
-                assert()
-            except:
-                pass
-            connection.sock.close()
-    
-    if cryptoIDlibLoaded:
-        print "Test 8 - good SRP: with cryptoID certs"
-        cryptoIDChain = cryptoIDlib.CertChain().parse(open(os.path.join(dir, "serverCryptoIDChain.xml"), "r").read())
-        cryptoIDKey = tlslite.parseXMLKey(open(os.path.join(dir, "serverCryptoIDKey.xml"), "r").read(), private=True)
-        connection = connect()
-        connection.handshakeServer(verifierDB=verifierDB, \
-                                   certChain=cryptoIDChain, privateKey=cryptoIDKey)
-        connection.close()
-        connection.sock.close()
-
-        print "Test 9 - cryptoID with SRP faults"
-        for fault in tlslite.ClientSRPFault.faults + tlslite.GenericFault.faults:
-            connection = connect()
-            connection.fault = fault
-            try:            
-                connection.handshakeServer(verifierDB=verifierDB, \
-                                           certChain=cryptoIDChain, privateKey=cryptoIDKey)
-                assert()
-            except:
-                pass
-            connection.sock.close()
-
-
-
-    if tlslite.m2cryptoLoaded:
-        print "Test 10 - good X.509"
-        connection = connect()
-        connection.handshakeServer(certChain=x509Chain, privateKey=x509Key)
-        connection.close()
-        connection.sock.close()
-
-        print "Test 10.a - good X.509, SSL v3"
-        connection = connect()
-        settings = tlslite.HandshakeSettings()
-        settings.minVersion = (3,0)
-        settings.maxVersion = (3,0)        
-        connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, settings=settings)
-        connection.close()
-        connection.sock.close()
-
-        print "Test 11 - X.509 faults"
-        for fault in tlslite.ClientNoAuthFault.faults + tlslite.GenericFault.faults:
-            connection = connect()
-            connection.fault = fault
-            try:            
-                connection.handshakeServer(certChain=x509Chain, privateKey=x509Key)
-                assert()
-            except:
-                pass
-            connection.sock.close()
-    
-    if cryptoIDlibLoaded:
-        print "Test 12 - good cryptoID"
-        connection = connect()
-        connection.handshakeServer(certChain=cryptoIDChain, privateKey=cryptoIDKey)
-        connection.close()
-        connection.sock.close()
-
-        print "Test 13 - cryptoID faults"
-        for fault in tlslite.ClientNoAuthFault.faults + tlslite.GenericFault.faults:
-            connection = connect()
-            connection.fault = fault
-            try:            
-                connection.handshakeServer(certChain=cryptoIDChain, privateKey=cryptoIDKey)
-                assert()
-            except:
-                pass
-            connection.sock.close()
-
-    if tlslite.m2cryptoLoaded:
-        print "Test 14 - good mutual X.509"
-        connection = connect()
-        connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, reqCert=True)
-        assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
-        connection.close()
-        connection.sock.close()
-
-        print "Test 14a - good mutual X.509, SSLv3"
-        connection = connect()
-        settings = tlslite.HandshakeSettings()
-        settings.minVersion = (3,0)
-        settings.maxVersion = (3,0)
-        connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, reqCert=True, settings=settings)
-        assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
-        connection.close()
-        connection.sock.close()
-
-        print "Test 15 - mutual X.509 faults"
-        for fault in tlslite.ClientCertFault.faults + tlslite.GenericFault.faults:
-            connection = connect()
-            connection.fault = fault
-            try:            
-                connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, reqCert=True)
-                assert()
-            except:
-                pass
-            connection.sock.close()
-    
-    if cryptoIDlibLoaded:
-        print "Test 16 - good mutual cryptoID"
-        connection = connect()
-        connection.handshakeServer(certChain=cryptoIDChain, privateKey=cryptoIDKey, reqCert=True)
-        assert(isinstance(connection.session.serverCertChain, cryptoIDlib.CertChain))
-        assert(connection.session.serverCertChain.validate())        
-        connection.close()
-        connection.sock.close()
-
-        print "Test 17 - mutual cryptoID faults"
-        for fault in tlslite.ClientCertFault.faults + tlslite.GenericFault.faults:
-            connection = connect()
-            connection.fault = fault
-            try:            
-                connection.handshakeServer(certChain=cryptoIDChain, privateKey=cryptoIDKey, reqCert=True)
-                assert()
-            except:
-                pass
-            connection.sock.close()
-        
-    print "Test 18 - good SRP, prepare to resume"
-    sessionCache = tlslite.SessionCache()
-    connection = connect()
-    connection.handshakeServer(verifierDB=verifierDB, sessionCache=sessionCache)
-    connection.close()
-    connection.sock.close()
-    
-    print "Test 19 - resumption"    
-    connection = connect()
-    connection.handshakeServer(verifierDB=verifierDB, sessionCache=sessionCache)
-    #Don't close! -- see next test
-
-    print "Test 20 - invalidated resumption"    
-    try:
-        connection.read(min=1, max=1)
-        assert() #Client is going to close the socket without a close_notify
-    except socket.error, e:
-        pass           
-    connection = connect()
-    try:   
-        connection.handshakeServer(verifierDB=verifierDB, sessionCache=sessionCache)
-    except tlslite.TLSLocalAlert, alert:
-        if alert.description != tlslite.AlertDescription.bad_record_mac:
-            raise
-    connection.sock.close()            
-
-    if tlslite.m2cryptoLoaded:
-        print "Test 21 - HTTPS test X.509"
-
-        #Close the current listening socket
-        lsock.close()
-
-        #Create and run an HTTP Server using TLSMixIn
-        class MyHTTPServer(tlslite.TLSMixIn, BaseHTTPServer.HTTPServer):
-            def handshake(self, tlsConnection):
-                    tlsConnection.handshakeServer(certChain=x509Chain, privateKey=x509Key)
-                    return True                                          
-        cd = os.getcwd()                    
-        os.chdir(dir)
-        httpd = MyHTTPServer(address, SimpleHTTPServer.SimpleHTTPRequestHandler)
-        for x in range(6):
-            httpd.handle_request()
-        httpd.server_close()
-        cd = os.chdir(cd)
-
-        #Re-connect the listening socket
-        lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        lsock.bind(address)
-        lsock.listen(5)
-
-        def connect():
-            return tlslite.TLSConnection(lsock.accept()[0])
-
-    if cryptoIDlibLoaded:
-        print "Test 21a - HTTPS test SRP+cryptoID"
-
-        #Close the current listening socket
-        lsock.close()
-
-        #Create and run an HTTP Server using TLSMixIn
-        class MyHTTPServer(tlslite.TLSMixIn, BaseHTTPServer.HTTPServer):
-            def handshake(self, tlsConnection):
-                    tlsConnection.handshakeServer(certChain=cryptoIDChain, privateKey=cryptoIDKey,
-                                                  verifierDB=verifierDB)
-                    return True                                          
-        cd = os.getcwd()                    
-        os.chdir(dir)
-        httpd = MyHTTPServer(address, SimpleHTTPServer.SimpleHTTPRequestHandler)
-        for x in range(6):
-            httpd.handle_request()
-        httpd.server_close()
-        cd = os.chdir(cd)
-
-        #Re-connect the listening socket
-        lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        lsock.bind(address)
-        lsock.listen(5)
-
-        def connect():
-            return tlslite.TLSConnection(lsock.accept()[0])
-
-        
-
-    implementations = []
-    if tlslite.cryptlibpyLoaded:
-        implementations.append("cryptlib")
-    if tlslite.m2cryptoLoaded:
-        implementations.append("openssl")
-    implementations.append("python")
-        
-    print "Test 22 - different ciphers"    
-    for implementation in ["python"] * len(implementations):
-        for cipher in ["aes128", "aes256", "rc4"]:
-
-            print "Test 22:",
-            connection = connect()      
-            
-            settings = tlslite.HandshakeSettings()
-            settings.cipherNames = [cipher]
-            settings.cipherImplementations = [implementation, "python"]
-     
-            connection.handshakeServer(sharedKeyDB=sharedKeyDB, settings=settings)
-            print connection.getCipherName(), connection.getCipherImplementation()        
-            h = connection.read(min=5, max=5)
-            assert(h == "hello")
-            connection.write(h)
-            connection.close()
-            connection.sock.close()    
-
-    print "Test 23 - throughput test"    
-    for implementation in implementations:
-        for cipher in ["aes128", "aes256", "3des", "rc4"]:
-            if cipher == "3des" and implementation not in ("openssl", "cryptlib"):
-                continue
-        
-            print "Test 23:",
-            connection = connect()      
-            
-            settings = tlslite.HandshakeSettings()
-            settings.cipherNames = [cipher]
-            settings.cipherImplementations = [implementation, "python"]
-     
-            connection.handshakeServer(sharedKeyDB=sharedKeyDB, settings=settings)
-            print connection.getCipherName(), connection.getCipherImplementation()        
-            h = connection.read(min=50000, max=50000)
-            assert(h == "hello"*10000)
-            connection.write(h)
-            connection.close()
-            connection.sock.close()    
-
-    print "Test succeeded"
-
-
-
-
-
-
-
-
-
-
-
-
-if len(sys.argv) == 1 or (len(sys.argv)==2 and sys.argv[1].lower().endswith("help")):
-    print ""
-    print "Version: 0.2.0"
-    print ""
-    print "Modules:"   
-    if tlslite.cryptlibpyLoaded:
-        print "  cryptlib_py : Loaded"
-    else:
-        print "  cryptlib_py : Not Loaded"
-    if tlslite.m2cryptoLoaded:
-        print "  M2Crypto    : Loaded"
-    else:
-        print "  M2Crypto    : Not Loaded"
-    if cryptoIDlibLoaded:
-        print "  cryptoIDlib : Loaded"
-    else:
-        print "  cryptoIDlib : Not Loaded"        
-    print ""
-    print "Commands:"
-    print ""    
-    print "  clientnoauth    <server>"    
-    print "  clientsrp       <server> <user> <pass>"
-    print "  clientsharedkey <server> <user> <pass>"
-    print "  clientcert      <server> <chain> <key>"
-    print "  clienttest      <server> <dir>"
-    print ""    
-    print "  serversrp       <server> <verifierDB>"
-    print "  servercert      <server> <chain> <key> [req]"
-    print "  serversrpcert   <server> <verifierDB> <chain> <key>"
-    print "  serversharedkey <server> <sharedkeyDB>"
-    print "  servertest      <server> <dir>"
-    sys.exit()
-
-cmd = sys.argv[1].lower()
-
-class Args:
-    def __init__(self, argv):
-        self.argv = argv
-    def get(self, index):
-        if len(self.argv)<=index:
-            raise SyntaxError("Not enough arguments")
-        return self.argv[index]
-    def getLast(self, index):
-        if len(self.argv)>index+1:
-            raise SyntaxError("Too many arguments")
-        return self.get(index)
-
-args = Args(sys.argv)
-
-def reformatDocString(s):
-    lines = s.splitlines()
-    newLines = []
-    for line in lines:
-        newLines.append("  " + line.strip())
-    return "\n".join(newLines)
-
-try:
-    if cmd == "clienttest":
-        address = args.get(2)
-        dir = args.getLast(3)
-        clientTest(address, dir)
-        sys.exit()
-
-    elif cmd.startswith("client"):
-        address = args.get(2)
-        
-        #Split address into hostname/port tuple
-        address = address.split(":")
-        if len(address)==1:
-            address.append("443")
-        address = ( address[0], int(address[1]) )    
-
-        def connect():
-            #Connect to server
-            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-            if hasattr(sock, "settimeout"):
-                sock.settimeout(5)
-            sock.connect(address)
-
-            #Instantiate TLSConnections
-            return tlslite.TLSConnection(sock)
-        
-        try:
-            if cmd == "clientnoauth":
-                args.getLast(2)
-                connection = connect()
-                connection.handshakeClientNoAuth()
-            elif cmd == "clientsrp":
-                username = args.get(3)
-                password = args.getLast(4)                
-                connection = connect()
-                connection.handshakeClientSRP(username, password)
-            elif cmd == "clientsharedkey":
-                username = args.get(3)
-                password = args.getLast(4)
-                connection = connect()
-                connection.handshakeClientSharedKey(username, password)
-            elif cmd == "clientcert":
-                certFilename = args.get(3)
-                keyFilename = args.getLast(4)
-
-                s1 = open(certFilename, "rb").read()
-                s2 = open(keyFilename, "rb").read()                
-
-                #Try to create cryptoID cert chain
-                if cryptoIDlibLoaded:
-                    try:
-                        certChain = cryptoIDlib.CertChain().parse(s1)
-                        privateKey = parsePrivateKey(s2)
-                    except:
-                        certChain = None
-                        privateKey = None
-
-                #Try to create X.509 cert chain
-                if not certChain:
-                    x509 = tlslite.X509()
-                    x509.parse(s1)
-                    certChain = tlslite.X509CertChain([x509])
-                    privateKey = parsePrivateKey(s2)
-
-                connection = connect()
-                connection.handshakeClientCert(certChain, privateKey)
-            else:
-                raise SyntaxError("Unknown command")
-
-        except tlslite.TLSLocalAlert, a:
-            if a.description == tlslite.AlertDescription.bad_record_mac:
-                if cmd == "clientsharedkey":
-                    print "Bad sharedkey password"
-                else:
-                    raise
-            elif a.description == tlslite.AlertDescription.user_canceled:
-                print str(a)
-            else:
-                raise
-            sys.exit()
-        except tlslite.TLSRemoteAlert, a:
-            if a.description == tlslite.AlertDescription.unknown_srp_username:
-                if cmd == "clientsrp":
-                    print "Unknown username"
-                else:
-                    raise
-            elif a.description == tlslite.AlertDescription.bad_record_mac:
-                if cmd == "clientsrp":
-                    print "Bad username or password"
-                else:
-                    raise
-            elif a.description == tlslite.AlertDescription.handshake_failure:
-                print "Unable to negotiate mutually acceptable parameters"
-            else:
-                raise
-            sys.exit()
-            
-        print "Handshake success"
-        print "  Version: %s.%s" % connection.version
-        print "  Cipher: %s %s" % (connection.getCipherName(), connection.getCipherImplementation())
-        if connection.session.srpUsername:
-            print "  Client SRP username: %s" % connection.session.srpUsername        
-        if connection.session.sharedKeyUsername:
-            print "  Client shared key username: %s" % connection.session.sharedKeyUsername        
-        if connection.session.clientCertChain:
-            print "  Client fingerprint: %s" % connection.session.clientCertChain.getFingerprint()
-        if connection.session.serverCertChain:
-            print "  Server fingerprint: %s" % connection.session.serverCertChain.getFingerprint()
-        connection.close()
-        connection.sock.close()
-    
-    elif cmd.startswith("server"):
-        address = args.get(2)
-        
-        #Split address into hostname/port tuple
-        address = address.split(":")
-        if len(address)==1:
-            address.append("443")
-        address = ( address[0], int(address[1]) )  
-        
-        verifierDBFilename = None
-        sharedKeyDBFilename = None
-        certFilename = None
-        keyFilename = None
-        sharedKeyDB = None
-        reqCert = False
-        
-        if cmd == "serversrp":
-            verifierDBFilename = args.getLast(3)        
-        elif cmd == "servercert":
-            certFilename = args.get(3)
-            keyFilename = args.get(4)
-            if len(sys.argv)>=6:
-                req = args.getLast(5)
-                if req.lower() != "req":
-                    raise SyntaxError()
-                reqCert = True
-        elif cmd == "serversrpcert":
-            verifierDBFilename = args.get(3)
-            certFilename = args.get(4)
-            keyFilename = args.getLast(5)
-        elif cmd == "serversharedkey":
-            sharedKeyDBFilename = args.getLast(3)
-        elif cmd == "servertest":
-            address = args.get(2)
-            dir = args.getLast(3)
-            serverTest(address, dir)
-            sys.exit()
-        
-        verifierDB = None            
-        if verifierDBFilename:
-            verifierDB = tlslite.VerifierDB(verifierDBFilename)
-            verifierDB.open()
-
-        sharedKeyDB = None
-        if sharedKeyDBFilename:
-            sharedKeyDB = tlslite.SharedKeyDB(sharedKeyDBFilename)
-            sharedKeyDB.open()
-
-        certChain = None
-        privateKey = None
-        if certFilename:        
-            s1 = open(certFilename, "rb").read()
-            s2 = open(keyFilename, "rb").read()                
-
-            #Try to create cryptoID cert chain
-            if cryptoIDlibLoaded:
-                try:
-                    certChain = cryptoIDlib.CertChain().parse(s1)
-                    privateKey = parsePrivateKey(s2)
-                except:
-                    certChain = None
-                    privateKey = None
-            
-            #Try to create X.509 cert chain
-            if not certChain:
-                x509 = tlslite.X509()
-                x509.parse(s1)
-                certChain = tlslite.X509CertChain([x509])
-                privateKey = parsePrivateKey(s2)
-        
-        
-        
-        #Create handler function - performs handshake, then echos all bytes received
-        def handler(sock):
-            try:
-                connection = tlslite.TLSConnection(sock)
-                settings = tlslite.HandshakeSettings()
-                connection.handshakeServer(sharedKeyDB=sharedKeyDB, verifierDB=verifierDB, \
-                                           certChain=certChain, privateKey=privateKey, \
-                                           reqCert=reqCert, settings=settings)
-                print "Handshake success"
-                print "  Version: %s.%s" % connection.version
-                print "  Cipher: %s %s" % (connection.getCipherName(), connection.getCipherImplementation())
-                if connection.session.srpUsername:
-                    print "  Client SRP username: %s" % connection.session.srpUsername
-                if connection.session.sharedKeyUsername:
-                    print "  Client shared key username: %s" % connection.session.sharedKeyUsername
-                if connection.session.clientCertChain:
-                    print "  Client fingerprint: %s" % connection.session.clientCertChain.getFingerprint()
-                if connection.session.serverCertChain:
-                    print "  Server fingerprint: %s" % connection.session.serverCertChain.getFingerprint()
-
-                s = ""
-                while 1:
-                    newS = connection.read()
-                    if not newS:
-                        break
-                    s += newS                        
-                    if s[-1]=='\n':
-                        connection.write(s)
-                        s = ""
-            except tlslite.TLSLocalAlert, a:
-                if a.description == tlslite.AlertDescription.unknown_srp_username:
-                    print "Unknown SRP username"
-                elif a.description == tlslite.AlertDescription.bad_record_mac:
-                    if cmd == "serversrp" or cmd == "serversrpcert":
-                        print "Bad SRP password"
-                    else:
-                        raise
-                elif a.description == tlslite.AlertDescription.handshake_failure:
-                    print "Unable to negotiate mutually acceptable parameters"                    
-                else:
-                    raise
-            except tlslite.TLSRemoteAlert, a:
-                if a.description == tlslite.AlertDescription.bad_record_mac:
-                    if cmd == "serversharedkey":
-                        print "Bad sharedkey password"
-                    else:
-                        raise
-                elif a.description == tlslite.AlertDescription.user_canceled:
-                    print "Handshake cancelled"
-                elif a.description == tlslite.AlertDescription.handshake_failure:
-                    print "Unable to negotiate mutually acceptable parameters"
-                elif a.description == tlslite.AlertDescription.close_notify:
-                    pass
-                else:
-                    raise
-            
-        #Run multi-threaded server        
-        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        
-        sock.bind(address)
-        sock.listen(5)
-        while 1:
-            (newsock, cliAddress) = sock.accept()
-            thread.start_new_thread(handler, (newsock,))
-
-    
-    else:        
-        print "Bad command: '%s'" % cmd
-except tlslite.TLSRemoteAlert, a:
-    print str(a)
-    raise
-    
-    
-    
-    
-    
+#! python
+
+import sys
+import os
+import os.path
+import socket
+import thread
+import time
+import httplib
+import BaseHTTPServer
+import SimpleHTTPServer
+
+
+try:
+    import cryptoIDlib
+    cryptoIDlibLoaded = True
+except:
+    cryptoIDlibLoaded = False
+
+if __name__ != "__main__":
+    raise "This must be run as a command, not used as a module!"
+
+
+import tlslite
+from tlslite.utils.jython_compat import formatExceptionTrace
+
+
+def parsePrivateKey(s):
+    try:
+        return tlslite.parsePEMKey(s, private=True)
+    except:
+        return tlslite.parseXMLKey(s, private=True)
+
+
+def clientTest(address, dir):
+
+    #Split address into hostname/port tuple
+    address = address.split(":")
+    if len(address)==1:
+        address.append("443")
+    address = ( address[0], int(address[1]) )
+
+    def connect():
+        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        if hasattr(sock, 'settimeout'): #It's a python 2.3 feature
+            sock.settimeout(5)
+        sock.connect(address)
+        c = tlslite.TLSConnection(sock)
+        return c
+
+    test = 0
+
+    badFault = False
+
+    print "Test 1 - good shared key"
+    connection = connect()
+    connection.handshakeClientSharedKey("shared", "key")
+    connection.close()
+    connection.sock.close()
+
+    print "Test 2 - shared key faults"
+    for fault in tlslite.ClientSharedKeyFault.faults + tlslite.GenericFault.faults:
+        connection = connect()
+        connection.fault = fault
+        try:
+            connection.handshakeClientSharedKey("shared", "key")
+            print "  Good Fault %s" % (tlslite.faultNames[fault])
+        except tlslite.FaultError, e:
+            print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
+            badFault = True
+        connection.sock.close()
+
+    print "Test 3 - good SRP"
+    connection = connect()
+    connection.handshakeClientSRP("test", "password")
+    connection.close()
+
+    print "Test 4 - SRP faults"
+    for fault in tlslite.ClientSRPFault.faults + tlslite.GenericFault.faults:
+        connection = connect()
+        connection.fault = fault
+        try:
+            connection.handshakeClientSRP("test", "password")
+            print "  Good Fault %s" % (tlslite.faultNames[fault])
+        except tlslite.FaultError, e:
+            print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
+            badFault = True
+        connection.sock.close()
+
+    print "Test 5 - good SRP: unknown_srp_username idiom"
+    def srpCallback():
+        return ("test", "password")
+    connection = connect()
+    connection.handshakeClientUnknown(srpCallback=srpCallback)
+    connection.close()
+    connection.sock.close()
+
+    if tlslite.m2cryptoLoaded:
+        print "Test 6 - good SRP: with X.509 certificate"
+        connection = connect()
+        connection.handshakeClientSRP("test", "password")
+        assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
+        connection.close()
+        connection.sock.close()
+
+        print "Test 7 - X.509 with SRP faults"
+        for fault in tlslite.ClientSRPFault.faults + tlslite.GenericFault.faults:
+            connection = connect()
+            connection.fault = fault
+            try:
+                connection.handshakeClientSRP("test", "password")
+                print "  Good Fault %s" % (tlslite.faultNames[fault])
+            except tlslite.FaultError, e:
+                print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
+                badFault = True
+            connection.sock.close()
+
+
+    if cryptoIDlibLoaded:
+        print "Test 8 - good SRP: with cryptoID certificate chain"
+        connection = connect()
+        connection.handshakeClientSRP("test", "password")
+        assert(isinstance(connection.session.serverCertChain, cryptoIDlib.CertChain))
+        if not (connection.session.serverCertChain.validate()):
+            print connection.session.serverCertChain.validate(listProblems=True)
+
+        connection.close()
+        connection.sock.close()
+
+        print "Test 9 - CryptoID with SRP faults"
+        for fault in tlslite.ClientSRPFault.faults + tlslite.GenericFault.faults:
+            connection = connect()
+            connection.fault = fault
+            try:
+                connection.handshakeClientSRP("test", "password")
+                print "  Good Fault %s" % (tlslite.faultNames[fault])
+            except tlslite.FaultError, e:
+                print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
+                badFault = True
+            connection.sock.close()
+
+    if tlslite.m2cryptoLoaded:
+        print "Test 10 - good X509"
+        connection = connect()
+        connection.handshakeClientNoAuth()
+        assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
+        connection.close()
+        connection.sock.close()
+
+        print "Test 10.a - good X509, SSLv3"
+        connection = connect()
+        settings = tlslite.HandshakeSettings()
+        settings.minVersion = (3,0)
+        settings.maxVersion = (3,0)
+        connection.handshakeClientNoAuth(settings=settings)
+        assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
+        connection.close()
+        connection.sock.close()
+
+        print "Test 11 - X.509 faults"
+        for fault in tlslite.ClientNoAuthFault.faults + tlslite.GenericFault.faults:
+            connection = connect()
+            connection.fault = fault
+            try:
+                connection.handshakeClientNoAuth()
+                print "  Good Fault %s" % (tlslite.faultNames[fault])
+            except tlslite.FaultError, e:
+                print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
+                badFault = True
+            connection.sock.close()
+
+    if cryptoIDlibLoaded:
+        print "Test 12 - good cryptoID"
+        connection = connect()
+        connection.handshakeClientNoAuth()
+        assert(isinstance(connection.session.serverCertChain, cryptoIDlib.CertChain))
+        assert(connection.session.serverCertChain.validate())
+        connection.close()
+        connection.sock.close()
+
+        print "Test 13 - cryptoID faults"
+        for fault in tlslite.ClientNoAuthFault.faults + tlslite.GenericFault.faults:
+            connection = connect()
+            connection.fault = fault
+            try:
+                connection.handshakeClientNoAuth()
+                print "  Good Fault %s" % (tlslite.faultNames[fault])
+            except tlslite.FaultError, e:
+                print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
+                badFault = True
+            connection.sock.close()
+
+    if tlslite.m2cryptoLoaded:
+        print "Test 14 - good mutual X509"
+        x509Cert = tlslite.X509().parse(open(os.path.join(dir, "clientX509Cert.pem")).read())
+        x509Chain = tlslite.X509CertChain([x509Cert])
+        s = open(os.path.join(dir, "clientX509Key.pem")).read()
+        x509Key = tlslite.parsePEMKey(s, private=True)
+
+        connection = connect()
+        connection.handshakeClientCert(x509Chain, x509Key)
+        assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
+        connection.close()
+        connection.sock.close()
+
+        print "Test 14.a - good mutual X509, SSLv3"
+        connection = connect()
+        settings = tlslite.HandshakeSettings()
+        settings.minVersion = (3,0)
+        settings.maxVersion = (3,0)
+        connection.handshakeClientCert(x509Chain, x509Key, settings=settings)
+        assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
+        connection.close()
+        connection.sock.close()
+
+        print "Test 15 - mutual X.509 faults"
+        for fault in tlslite.ClientCertFault.faults + tlslite.GenericFault.faults:
+            connection = connect()
+            connection.fault = fault
+            try:
+                connection.handshakeClientCert(x509Chain, x509Key)
+                print "  Good Fault %s" % (tlslite.faultNames[fault])
+            except tlslite.FaultError, e:
+                print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
+                badFault = True
+            connection.sock.close()
+
+    if cryptoIDlibLoaded:
+        print "Test 16 - good mutual cryptoID"
+        cryptoIDChain = cryptoIDlib.CertChain().parse(open(os.path.join(dir, "serverCryptoIDChain.xml"), "r").read())
+        cryptoIDKey = tlslite.parseXMLKey(open(os.path.join(dir, "serverCryptoIDKey.xml"), "r").read(), private=True)
+
+        connection = connect()
+        connection.handshakeClientCert(cryptoIDChain, cryptoIDKey)
+        assert(isinstance(connection.session.serverCertChain, cryptoIDlib.CertChain))
+        assert(connection.session.serverCertChain.validate())
+        connection.close()
+        connection.sock.close()
+
+        print "Test 17 - mutual cryptoID faults"
+        for fault in tlslite.ClientCertFault.faults + tlslite.GenericFault.faults:
+            connection = connect()
+            connection.fault = fault
+            try:
+                connection.handshakeClientCert(cryptoIDChain, cryptoIDKey)
+                print "  Good Fault %s" % (tlslite.faultNames[fault])
+            except tlslite.FaultError, e:
+                print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
+                badFault = True
+            connection.sock.close()
+
+    print "Test 18 - good SRP, prepare to resume..."
+    connection = connect()
+    connection.handshakeClientSRP("test", "password")
+    connection.close()
+    connection.sock.close()
+    session = connection.session
+
+    print "Test 19 - resumption"
+    connection = connect()
+    connection.handshakeClientSRP("test", "garbage", session=session)
+    #Don't close! -- see below
+
+    print "Test 20 - invalidated resumption"
+    connection.sock.close() #Close the socket without a close_notify!
+    connection = connect()
+    try:
+        connection.handshakeClientSRP("test", "garbage", session=session)
+        assert()
+    except tlslite.TLSRemoteAlert, alert:
+        if alert.description != tlslite.AlertDescription.bad_record_mac:
+            raise
+    connection.sock.close()
+
+    if tlslite.m2cryptoLoaded:
+        print "Test 21 - HTTPS test X.509"
+        time.sleep(2)
+        htmlBody = open(os.path.join(dir, "index.html")).read()
+        fingerprint = None
+        for y in range(2):
+            h = tlslite.HTTPTLSConnection(address[0], address[1], x509Fingerprint=fingerprint)
+            for x in range(3):
+                h.request("GET", "/index.html")
+                r = h.getresponse()
+                assert(r.status == 200)
+                s = r.read()
+                assert(s == htmlBody)
+            fingerprint = h.tlsSession.serverCertChain.getFingerprint()
+            assert(fingerprint)
+        time.sleep(2)
+
+    if cryptoIDlibLoaded:
+        print "Test 21a - HTTPS test SRP+cryptoID"
+        time.sleep(2) #Time to generate key and cryptoID
+        htmlBody = open(os.path.join(dir, "index.html")).read()
+        fingerprint = None
+        protocol = None
+        for y in range(2):
+            h = tlslite.HTTPTLSConnection(address[0], address[1],
+                         username="test", password="password",
+                         cryptoID=fingerprint, protocol=protocol)
+            for x in range(3):
+                h.request("GET", "/index.html")
+                r = h.getresponse()
+                assert(r.status == 200)
+                s = r.read()
+                assert(s == htmlBody)
+            fingerprint = h.tlsSession.serverCertChain.cryptoID
+            assert(fingerprint)
+            protocol = "urn:whatever"
+        time.sleep(2)
+
+    implementations = []
+    if tlslite.cryptlibpyLoaded:
+        implementations.append("cryptlib")
+    if tlslite.m2cryptoLoaded:
+        implementations.append("openssl")
+    implementations.append("python")
+
+    print "Test 22 - different ciphers"
+    for implementation in implementations:
+        for cipher in ["aes128", "aes256", "rc4"]:
+
+            print "Test 22:",
+            connection = connect()
+
+            settings = tlslite.HandshakeSettings()
+            settings.cipherNames = [cipher]
+            settings.cipherImplementations = [implementation, "python"]
+            connection.handshakeClientSharedKey("shared", "key", settings=settings)
+            print ("%s %s" % (connection.getCipherName(), connection.getCipherImplementation()))
+
+            connection.write("hello")
+            h = connection.read(min=5, max=5)
+            assert(h == "hello")
+            connection.close()
+            connection.sock.close()
+
+    print "Test 23 - throughput test"
+    for implementation in implementations:
+        for cipher in ["aes128", "aes256", "3des", "rc4"]:
+            if cipher == "3des" and implementation not in ("openssl", "cryptlib"):
+                continue
+
+            print "Test 23:",
+            connection = connect()
+
+            settings = tlslite.HandshakeSettings()
+            settings.cipherNames = [cipher]
+            settings.cipherImplementations = [implementation, "python"]
+            connection.handshakeClientSharedKey("shared", "key", settings=settings)
+            print ("%s %s:" % (connection.getCipherName(), connection.getCipherImplementation())),
+
+            startTime = time.clock()
+            connection.write("hello"*10000)
+            h = connection.read(min=50000, max=50000)
+            stopTime = time.clock()
+            print "100K exchanged at rate of %d bytes/sec" % int(100000/(stopTime-startTime))
+
+            assert(h == "hello"*10000)
+            connection.close()
+            connection.sock.close()
+
+    if not badFault:
+        print "Test succeeded"
+    else:
+        print "Test failed"
+
+
+
+
+
+def serverTest(address, dir):
+    #Split address into hostname/port tuple
+    address = address.split(":")
+    if len(address)==1:
+        address.append("443")
+    address = ( address[0], int(address[1]) )
+
+    #Connect to server
+    lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    lsock.bind(address)
+    lsock.listen(5)
+
+    def connect():
+        return tlslite.TLSConnection(lsock.accept()[0])
+
+    print "Test 1 - good shared key"
+    sharedKeyDB = tlslite.SharedKeyDB()
+    sharedKeyDB["shared"] = "key"
+    sharedKeyDB["shared2"] = "key2"
+    connection = connect()
+    connection.handshakeServer(sharedKeyDB=sharedKeyDB)
+    connection.close()
+    connection.sock.close()
+
+    print "Test 2 - shared key faults"
+    for fault in tlslite.ClientSharedKeyFault.faults + tlslite.GenericFault.faults:
+        connection = connect()
+        connection.fault = fault
+        try:
+            connection.handshakeServer(sharedKeyDB=sharedKeyDB)
+            assert()
+        except:
+            pass
+        connection.sock.close()
+
+    print "Test 3 - good SRP"
+    #verifierDB = tlslite.VerifierDB(os.path.join(dir, "verifierDB"))
+    #verifierDB.open()
+    verifierDB = tlslite.VerifierDB()
+    verifierDB.create()
+    entry = tlslite.makeVerifier("test", "password", 1536)
+    verifierDB["test"] = entry
+
+    connection = connect()
+    connection.handshakeServer(verifierDB=verifierDB)
+    connection.close()
+    connection.sock.close()
+
+    print "Test 4 - SRP faults"
+    for fault in tlslite.ClientSRPFault.faults + tlslite.GenericFault.faults:
+        connection = connect()
+        connection.fault = fault
+        try:
+            connection.handshakeServer(verifierDB=verifierDB)
+            assert()
+        except:
+            pass
+        connection.sock.close()
+
+    print "Test 5 - good SRP: unknown_srp_username idiom"
+    connection = connect()
+    connection.handshakeServer(verifierDB=verifierDB)
+    connection.close()
+    connection.sock.close()
+
+
+    if tlslite.m2cryptoLoaded:
+        print "Test 6 - good SRP: with X.509 cert"
+        x509Cert = tlslite.X509().parse(open(os.path.join(dir, "serverX509Cert.pem")).read())
+        x509Chain = tlslite.X509CertChain([x509Cert])
+        s = open(os.path.join(dir, "serverX509Key.pem")).read()
+        x509Key = tlslite.parsePEMKey(s, private=True)
+
+        connection = connect()
+        connection.handshakeServer(verifierDB=verifierDB, \
+                                   certChain=x509Chain, privateKey=x509Key)
+        connection.close()
+        connection.sock.close()
+
+        print "Test 7 - X.509 with SRP faults"
+        for fault in tlslite.ClientSRPFault.faults + tlslite.GenericFault.faults:
+            connection = connect()
+            connection.fault = fault
+            try:
+                connection.handshakeServer(verifierDB=verifierDB, \
+                                           certChain=x509Chain, privateKey=x509Key)
+                assert()
+            except:
+                pass
+            connection.sock.close()
+
+    if cryptoIDlibLoaded:
+        print "Test 8 - good SRP: with cryptoID certs"
+        cryptoIDChain = cryptoIDlib.CertChain().parse(open(os.path.join(dir, "serverCryptoIDChain.xml"), "r").read())
+        cryptoIDKey = tlslite.parseXMLKey(open(os.path.join(dir, "serverCryptoIDKey.xml"), "r").read(), private=True)
+        connection = connect()
+        connection.handshakeServer(verifierDB=verifierDB, \
+                                   certChain=cryptoIDChain, privateKey=cryptoIDKey)
+        connection.close()
+        connection.sock.close()
+
+        print "Test 9 - cryptoID with SRP faults"
+        for fault in tlslite.ClientSRPFault.faults + tlslite.GenericFault.faults:
+            connection = connect()
+            connection.fault = fault
+            try:
+                connection.handshakeServer(verifierDB=verifierDB, \
+                                           certChain=cryptoIDChain, privateKey=cryptoIDKey)
+                assert()
+            except:
+                pass
+            connection.sock.close()
+
+
+
+    if tlslite.m2cryptoLoaded:
+        print "Test 10 - good X.509"
+        connection = connect()
+        connection.handshakeServer(certChain=x509Chain, privateKey=x509Key)
+        connection.close()
+        connection.sock.close()
+
+        print "Test 10.a - good X.509, SSL v3"
+        connection = connect()
+        settings = tlslite.HandshakeSettings()
+        settings.minVersion = (3,0)
+        settings.maxVersion = (3,0)
+        connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, settings=settings)
+        connection.close()
+        connection.sock.close()
+
+        print "Test 11 - X.509 faults"
+        for fault in tlslite.ClientNoAuthFault.faults + tlslite.GenericFault.faults:
+            connection = connect()
+            connection.fault = fault
+            try:
+                connection.handshakeServer(certChain=x509Chain, privateKey=x509Key)
+                assert()
+            except:
+                pass
+            connection.sock.close()
+
+    if cryptoIDlibLoaded:
+        print "Test 12 - good cryptoID"
+        connection = connect()
+        connection.handshakeServer(certChain=cryptoIDChain, privateKey=cryptoIDKey)
+        connection.close()
+        connection.sock.close()
+
+        print "Test 13 - cryptoID faults"
+        for fault in tlslite.ClientNoAuthFault.faults + tlslite.GenericFault.faults:
+            connection = connect()
+            connection.fault = fault
+            try:
+                connection.handshakeServer(certChain=cryptoIDChain, privateKey=cryptoIDKey)
+                assert()
+            except:
+                pass
+            connection.sock.close()
+
+    if tlslite.m2cryptoLoaded:
+        print "Test 14 - good mutual X.509"
+        connection = connect()
+        connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, reqCert=True)
+        assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
+        connection.close()
+        connection.sock.close()
+
+        print "Test 14a - good mutual X.509, SSLv3"
+        connection = connect()
+        settings = tlslite.HandshakeSettings()
+        settings.minVersion = (3,0)
+        settings.maxVersion = (3,0)
+        connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, reqCert=True, settings=settings)
+        assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
+        connection.close()
+        connection.sock.close()
+
+        print "Test 15 - mutual X.509 faults"
+        for fault in tlslite.ClientCertFault.faults + tlslite.GenericFault.faults:
+            connection = connect()
+            connection.fault = fault
+            try:
+                connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, reqCert=True)
+                assert()
+            except:
+                pass
+            connection.sock.close()
+
+    if cryptoIDlibLoaded:
+        print "Test 16 - good mutual cryptoID"
+        connection = connect()
+        connection.handshakeServer(certChain=cryptoIDChain, privateKey=cryptoIDKey, reqCert=True)
+        assert(isinstance(connection.session.serverCertChain, cryptoIDlib.CertChain))
+        assert(connection.session.serverCertChain.validate())
+        connection.close()
+        connection.sock.close()
+
+        print "Test 17 - mutual cryptoID faults"
+        for fault in tlslite.ClientCertFault.faults + tlslite.GenericFault.faults:
+            connection = connect()
+            connection.fault = fault
+            try:
+                connection.handshakeServer(certChain=cryptoIDChain, privateKey=cryptoIDKey, reqCert=True)
+                assert()
+            except:
+                pass
+            connection.sock.close()
+
+    print "Test 18 - good SRP, prepare to resume"
+    sessionCache = tlslite.SessionCache()
+    connection = connect()
+    connection.handshakeServer(verifierDB=verifierDB, sessionCache=sessionCache)
+    connection.close()
+    connection.sock.close()
+
+    print "Test 19 - resumption"
+    connection = connect()
+    connection.handshakeServer(verifierDB=verifierDB, sessionCache=sessionCache)
+    #Don't close! -- see next test
+
+    print "Test 20 - invalidated resumption"
+    try:
+        connection.read(min=1, max=1)
+        assert() #Client is going to close the socket without a close_notify
+    except socket.error, e:
+        pass
+    connection = connect()
+    try:
+        connection.handshakeServer(verifierDB=verifierDB, sessionCache=sessionCache)
+    except tlslite.TLSLocalAlert, alert:
+        if alert.description != tlslite.AlertDescription.bad_record_mac:
+            raise
+    connection.sock.close()
+
+    if tlslite.m2cryptoLoaded:
+        print "Test 21 - HTTPS test X.509"
+
+        #Close the current listening socket
+        lsock.close()
+
+        #Create and run an HTTP Server using TLSMixIn
+        class MyHTTPServer(tlslite.TLSMixIn, BaseHTTPServer.HTTPServer):
+            def handshake(self, tlsConnection):
+                    tlsConnection.handshakeServer(certChain=x509Chain, privateKey=x509Key)
+                    return True
+        cd = os.getcwd()
+        os.chdir(dir)
+        httpd = MyHTTPServer(address, SimpleHTTPServer.SimpleHTTPRequestHandler)
+        for x in range(6):
+            httpd.handle_request()
+        httpd.server_close()
+        cd = os.chdir(cd)
+
+        #Re-connect the listening socket
+        lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        lsock.bind(address)
+        lsock.listen(5)
+
+        def connect():
+            return tlslite.TLSConnection(lsock.accept()[0])
+
+    if cryptoIDlibLoaded:
+        print "Test 21a - HTTPS test SRP+cryptoID"
+
+        #Close the current listening socket
+        lsock.close()
+
+        #Create and run an HTTP Server using TLSMixIn
+        class MyHTTPServer(tlslite.TLSMixIn, BaseHTTPServer.HTTPServer):
+            def handshake(self, tlsConnection):
+                    tlsConnection.handshakeServer(certChain=cryptoIDChain, privateKey=cryptoIDKey,
+                                                  verifierDB=verifierDB)
+                    return True
+        cd = os.getcwd()
+        os.chdir(dir)
+        httpd = MyHTTPServer(address, SimpleHTTPServer.SimpleHTTPRequestHandler)
+        for x in range(6):
+            httpd.handle_request()
+        httpd.server_close()
+        cd = os.chdir(cd)
+
+        #Re-connect the listening socket
+        lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        lsock.bind(address)
+        lsock.listen(5)
+
+        def connect():
+            return tlslite.TLSConnection(lsock.accept()[0])
+
+
+
+    implementations = []
+    if tlslite.cryptlibpyLoaded:
+        implementations.append("cryptlib")
+    if tlslite.m2cryptoLoaded:
+        implementations.append("openssl")
+    implementations.append("python")
+
+    print "Test 22 - different ciphers"
+    for implementation in ["python"] * len(implementations):
+        for cipher in ["aes128", "aes256", "rc4"]:
+
+            print "Test 22:",
+            connection = connect()
+
+            settings = tlslite.HandshakeSettings()
+            settings.cipherNames = [cipher]
+            settings.cipherImplementations = [implementation, "python"]
+
+            connection.handshakeServer(sharedKeyDB=sharedKeyDB, settings=settings)
+            print connection.getCipherName(), connection.getCipherImplementation()
+            h = connection.read(min=5, max=5)
+            assert(h == "hello")
+            connection.write(h)
+            connection.close()
+            connection.sock.close()
+
+    print "Test 23 - throughput test"
+    for implementation in implementations:
+        for cipher in ["aes128", "aes256", "3des", "rc4"]:
+            if cipher == "3des" and implementation not in ("openssl", "cryptlib"):
+                continue
+
+            print "Test 23:",
+            connection = connect()
+
+            settings = tlslite.HandshakeSettings()
+            settings.cipherNames = [cipher]
+            settings.cipherImplementations = [implementation, "python"]
+
+            connection.handshakeServer(sharedKeyDB=sharedKeyDB, settings=settings)
+            print connection.getCipherName(), connection.getCipherImplementation()
+            h = connection.read(min=50000, max=50000)
+            assert(h == "hello"*10000)
+            connection.write(h)
+            connection.close()
+            connection.sock.close()
+
+    print "Test succeeded"
+
+
+
+
+
+
+
+
+
+
+
+
+if len(sys.argv) == 1 or (len(sys.argv)==2 and sys.argv[1].lower().endswith("help")):
+    print ""
+    print "Version: 0.2.1"
+    print ""
+    print "PRNG: %s" % tlslite.prngName
+    print ""
+    print "Modules:"
+    if tlslite.cryptlibpyLoaded:
+        print "  cryptlib_py : Loaded"
+    else:
+        print "  cryptlib_py : Not Loaded"
+    if tlslite.m2cryptoLoaded:
+        print "  M2Crypto    : Loaded"
+    else:
+        print "  M2Crypto    : Not Loaded"
+    if cryptoIDlibLoaded:
+        print "  cryptoIDlib : Loaded"
+    else:
+        print "  cryptoIDlib : Not Loaded"
+    print ""
+    print "Commands:"
+    print ""
+    print "  clientnoauth    <server>"
+    print "  clientsrp       <server> <user> <pass>"
+    print "  clientsharedkey <server> <user> <pass>"
+    print "  clientcert      <server> <chain> <key>"
+    print "  clienttest      <server> <dir>"
+    print ""
+    print "  serversrp       <server> <verifierDB>"
+    print "  servercert      <server> <chain> <key> [req]"
+    print "  serversrpcert   <server> <verifierDB> <chain> <key>"
+    print "  serversharedkey <server> <sharedkeyDB>"
+    print "  servertest      <server> <dir>"
+    sys.exit()
+
+cmd = sys.argv[1].lower()
+
+class Args:
+    def __init__(self, argv):
+        self.argv = argv
+    def get(self, index):
+        if len(self.argv)<=index:
+            raise SyntaxError("Not enough arguments")
+        return self.argv[index]
+    def getLast(self, index):
+        if len(self.argv)>index+1:
+            raise SyntaxError("Too many arguments")
+        return self.get(index)
+
+args = Args(sys.argv)
+
+def reformatDocString(s):
+    lines = s.splitlines()
+    newLines = []
+    for line in lines:
+        newLines.append("  " + line.strip())
+    return "\n".join(newLines)
+
+try:
+    if cmd == "clienttest":
+        address = args.get(2)
+        dir = args.getLast(3)
+        clientTest(address, dir)
+        sys.exit()
+
+    elif cmd.startswith("client"):
+        address = args.get(2)
+
+        #Split address into hostname/port tuple
+        address = address.split(":")
+        if len(address)==1:
+            address.append("443")
+        address = ( address[0], int(address[1]) )
+
+        def connect():
+            #Connect to server
+            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+            if hasattr(sock, "settimeout"):
+                sock.settimeout(5)
+            sock.connect(address)
+
+            #Instantiate TLSConnections
+            return tlslite.TLSConnection(sock)
+
+        try:
+            if cmd == "clientnoauth":
+                args.getLast(2)
+                connection = connect()
+                connection.handshakeClientNoAuth()