1. clach04
  2. tlslite

Commits

trevp  committed 948ee7e

Initial revision

  • Participants
  • Branches default

Comments (0)

Files changed (59)

File m2crypto/__m2crypto.pyd

Binary file added.

File m2crypto/m2.py

View file
+"""M2Crypto
+
+Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved."""
+
+RCS_id='$Id$'
+
+from __m2crypto import *
+lib_init()
+
+

File make_release.py

View file
+
+#When run on (my) windows box, this builds and cleans everything in
+#preparation for a release.
+
+import os
+import sys
+
+#Replace version strings
+if len(sys.argv)>1:
+    oldVersion = sys.argv[1]
+    newVersion = sys.argv[2]
+    query = raw_input("Replace %s with %s?: " % (oldVersion, newVersion))
+    if query == "y":
+        #First, scan through and make sure the replacement is possible
+        for filename in ("setup.py", "tlslite\\__init__.py", "scripts\\tls.py", "scripts\\tlsdb.py"):
+            s = open(filename, "r").read()
+            x = s.count(oldVersion)
+            if x != 1:
+                print "Error, old version appears in %s %s times" % (filename, x)
+                sys.exit()    
+                
+        #Then perform it
+        for filename in ("setup.py", "tlslite\\__init__.py", "scripts\\tls.py", "scripts\\tlsdb.py"):
+            os.system("copy %s .." % filename) #save a backup copy in case something goes awry
+            s = open(filename, "r").read()
+            f = open(filename, "w")
+            f.write(s.replace(oldVersion, newVersion))
+            f.close()
+
+#Make windows installer
+os.system("rmdir build /s /q")
+os.system("setup.py bdist_wininst -o")
+os.system("del installers\*.exe")
+os.system("copy dist\* installers")
+
+#Delete excess files
+os.system("del tlslite\\*.pyc")
+os.system("del tlslite\\utils\\*.pyc")
+os.system("rmdir build /s /q")
+os.system("rmdir dist /s /q")

File readme.txt

View file
+
+tlslite version 0.2.0                                        February 19, 2004
+Trevor Perrin <trevp at trevp.net>
+http://trevp.net/tlslite
+===============================================================================
+
+
+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
+python, however it can access OpenSSL [4] or cryptlib [5] for faster crypto
+operations.
+
+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.
+
+All other code here is public domain.
+
+
+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.
+
+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 cryptlib_py [7] interface to cryptlib, this will be used
+  for good randomness generation and fast ciphers.
+
+  - If you have cryptoIDlib [8], you can use cryptoID certificate chains for
+  authentication.
+
+  - These modules don't need to be present at installation - you can install
+  them any time.
+
+On Windows:
+  - Run the installer in the 'installers' directory.
+  *OR*
+  - Run 'python setup.py install' (this only works if your system has a compiler
+  available).
+
+Anywhere else:
+  - Run 'python setup.py install'
+
+Test the Installation:
+  - From the distribution's root directory, run:
+    'python tls.py servertest ./test'
+  - While the test server is waiting, run:
+    'python tls.py clienttest ./test'
+  If both say "Test succeeded" at the end, you're ready to go.
+
+
+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.
+
+'tlsdb.py' lets you manage shared key or verifier databases.  These databases
+store usernames associated with either shared keys, or SRP password verifiers.
+These databases are used by a TLS server when authenticating clients with shared
+keys or SRP.
+
+'tls.py' lets you run test clients and servers.  It can be used for testing
+other TLS implementations, or as example code for using tlslite.  To run an SRP
+server, try something like:
+
+  tlsdb.py createsrp verifierDB
+  tlsdb.py add verifierDB alice abra123cadabra 1024
+  tlsdb.py add verifierDB bob swordfish 2048
+
+  tls.py serversrp localhost:443 verifierDB
+
+Then you can try connecting to the server with:
+
+  tls.py clientsrp localhost:443 alice abra123cadabra
+
+
+Getting Started with the Library
+=================================
+Using the library is simple.  Whether you're writing a client or server, there
+are six steps:
+1) Create a socket and connect it to the other party.
+2) Construct a TLSConnection instance with the socket.
+3) Call a handshake function on the TLSConnection to perform the TLS handshake.
+4) Check the results to make sure you're talking to the right party.
+5) Use the TLSConnection to exchange data.
+6) Call close() on the TLSConnection when you're done.
+
+TLS Lite also integrates with Python's httplib module and SocketServer
+framework.  When used with these, some of the steps are performed for you.  See
+the next section for details.
+
+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.
+
+  from socket import *
+  sock = socket(AF_INET, SOCK_STREAM)
+  sock.connect( ("www.amazon.com", 443) )
+  sock.settimeout(10)  #Only on python 2.3
+
+Step 2 - construct a TLSConnection
+-----------------------------------
+  import tlslite
+  connection = tlslite.TLSConnection(sock)
+
+Step 3 - call a handshake function (client)
+--------------------------------------------
+If you're a client, there's several different handshake functions you can call,
+depending on how you want to authenticate:
+
+  connection.handshakeClientNoAuth()
+  connection.handshakeClientCert(certChain, privateKey)
+  connection.handshakeClientSRP("alice", "abra123cadabra")
+  connection.handshakeClientSharedKey("alice", "PaVBVZkYqAjCQCu6UBL2xgsnZhw")
+  connection.handshakeClientUnknown(srpCallback, certCallback)
+
+The ClientNoAuth function is used when connecting to a site like Amazon, which
+doesn't require client authentication.  The server will authenticate with a
+certificate chain.
+
+The ClientCert function is used to do client authentication with an X.509 or
+cryptoID certificate chain.  To use cryptoID certificate chains, you'll need the
+cryptoIDlib library [8].  To use X.509 certificate chains, you'll need some way
+of creating these, and you'll need M2Crypto and OpenSSL to load up the PEM-
+encoded private key.
+
+  #Load cryptoID certChain and privateKey.  Requires cryptoIDlib.
+  import cryptoIDlib
+  s = open("./test/clientCryptoIDChain.xml").read()
+  certChain = cryptoIDlib.CertChain()
+  certChain.parse(s)
+  s = open("./test/clientCryptoIDKey.xml").read()
+  privateKey = tlslite.parseXMLKey(s, private=True)
+
+  #Load X.509 certChain and privateKey.  Requires M2Crypto/OpenSSL.
+  s = open("./test/clientX509Cert.pem").read()
+  x509 = tlslite.X509()
+  x509.parse(s)
+  certChain = tlslite.X509CertChain([x509])
+  s = open("./test/clientX509Key.pem").read()
+  privateKey = tlslite.parsePEMKey(s, private=True)
+
+The SRP and SharedKey functions both do mutual authentication with a username
+and password.  The difference is this: SRP is slow but safer when using low-
+entropy passwords, since the SRP protocol is not vulnerable to offline
+dictionary attacks.  Using shared keys is faster, but it's only safe when
+used with high-entropy secrets.  In general, you should prefer SRP for human-
+memorable passwords, and use shared keys only when your performance needs
+outweigh the inconvenience of handling large random strings.
+
+[WARNING: shared keys and SRP are internet-drafts; these protocols may change,
+which means future versions of tlslite may not be compatible with this one.
+This is less likely with SRP, more likely with shared-keys.]
+
+The Unknown function is used when you're not sure if the server requires client
+authentication.	 If the server requests SRP or certificate-based authentication,
+the appropriate callback will be triggered, and you should return a tuple
+containing either a (username, password) or (certChain, privateKey), as
+appropriate.  Alternatively, you can return None, which will cancel the
+handshake from an SRP callback, or cause it to continue without client
+authentication (if the server is willing) from a certificate callback.
+
+If you want more control over the handshake, you can pass in a HandshakeSettings
+instance.  For example, if you're performing SRP, but you only want to use SRP
+parameters of at least 2048 bits, and you only want to use the AES-256 cipher,
+and you only want to allow TLS (version 3.1), not SSL (version 3.0), you can do:
+
+  settings = tlslite.HandshakeSettings()
+  settings.minKeySize = 2048
+  settings.cipherNames = ["aes256"]
+  settings.minVersion = (3,1)
+  connection.handshakeClientSRP("alice", "abra123cadabra", settings=settings)
+
+Finally, every TLSConnection has a session object.  You can try to resume a
+previous session by passing in the session object from the old session.  If the
+server remembers this old session and supports resumption, the handshake will
+finish more quickly.  Otherwise, the full handshake will be done.  For example:
+
+  connection.handshakeClientSRP("alice", "abra123cadabra")
+  .
+  .
+  oldSession = connection.session
+  connection2.handshakeClientSRP("alice", "abra123cadabra", session=oldSession)
+
+Step 3 - call a handshake function (server)
+--------------------------------------------
+If you're a server, there's only one handshake function, but you can pass it
+several different parameters, depending on which types of authentication you're
+willing to perform.
+
+To perform SRP authentication, you have to pass in a database of password
+verifiers.  The VerifierDB class manages an in-memory or on-disk verifier
+database.
+
+  #On-disk database (use no-arg constructor if you want an in-memory DB)
+  verifierDB = tlslite.VerifierDB("./test/verifierDB")
+
+  #Open the pre-existing database (can also 'create()' a new one)
+  verifierDB.open()
+
+  #Add to the database
+  N, g, salt, verifier = tlslite.makeVerifier("alice", "abra123cadabra", 2048)
+  verifierDB["alice"] = N, g, salt, verifier
+
+  #Perform a handshake using the database
+  connection.handshakeServer(verifierDB=verifierDB)
+
+To perform shared key authentication, you have to pass in a database of shared
+keys.  The SharedKeyDB class manages an in-memory or on-disk shared key
+database.
+
+  sharedKeyDB = tlslite.SharedKeyDB("./test/sharedkeyDB")
+  sharedKeyDB.open()
+  sharedKeyDB["alice"] = "PaVBVZkYqAjCQCu6UBL2xgsnZhw"
+  connection.handshakeServer(sharedKeyDB=sharedKeyDB)
+
+To perform authentication with a certificate and private key, the server must
+load these as described in the previous section, then pass them in.  If the
+server sets the reqCert boolean to True, a certificate chain will be requested
+from the client.
+
+  connection.handshakeServer(certChain=certChain, privateKey=privateKey,
+                             reqCert=True)
+
+You can pass in any combination of a verifier database, a shared key database,
+and a certificate chain/private key.  The client will use one of them to
+authenticate.  In the case of SRP and a certificate chain/private key, they
+both may be used.
+
+You can also pass in a HandshakeSettings object, as described in the last
+section, for finer control over handshaking details.  Finally, the server can
+maintain a SessionCache, which will allow clients to use session resumption:
+
+  sessionCache = tlslite.SessionCache()
+  connection.handshakeServer(verifierDB=verifierDB, sessionCache=sessionCache)
+
+It should be noted that the session cache, and the verifier and shared key
+databases, are all thread-safe.
+
+Step 4 - check the results
+---------------------------
+If the handshake completes without raising an exception, authentication results
+will be stored in the connection's session object.  The following variables will
+be populated if applicable, or else set to None:
+
+  connection.session.srpUsername       #string
+  connection.session.sharedKeyUsername #string
+  connection.session.clientCertChain   #X509CertChain or cryptoIDlib.CertChain
+  connection.session.serverCertChain   #X509CertChain or cryptoIDlib.CertChain
+
+Both types of certificate chain object support the getFingerprint() function,
+but with a difference.  X.509 objects return the end-entity fingerprint, and
+ignore the other certificates.  CryptoID fingerprints (aka "cryptoIDs") are
+based on the root cryptoID certificate, so you have to call validate() on the
+CertChain to be sure you're really talking to the cryptoID.
+
+To save yourself the trouble of inspecting fingerprints after the handshake, you
+can pass a Checker object into the handshake function.  The checker will be
+called if the handshake completes successfully.  If the other party's
+fingerprint isn't approved by the checker, a subclass of AuthenticationError
+will be raised.  For example, to perform a handshake with a server based on its
+X.509 fingerprint, do:
+
+  try:
+    checker = tlslite.Checker(\
+              x509Fingerprint='e049ff930af76d43ff4c658b268786f4df1296f2')
+    connection.handshakeClientNoAuth(checker=checker)
+  except tlslite.AuthenticationError:
+    print "Authentication failure"
+
+If the handshake fails for any reason, an exception will be raised.  If the
+socket timed out or was unexpectedly closed, a socket.error will be raised.
+Otherwise, either a TLSLocalAlert or TLSRemoteAlert will be raised, depending on
+whether the local or remote implementation signalled the error.  The exception
+object has a 'description' member which identifies the error based on the codes
+in RFC 2246.  A TLSLocalAlert also has a 'message' string that may have more
+details.
+
+Example of handling a remote alert:
+
+  try:
+      [...]
+  except tlslite.TLSRemoteAlert, alert:
+      if alert.description == tlslite.AlertDescription.unknown_srp_username:
+          print "Unknown user."
+  [...]
+
+Figuring out what went wrong based on the alert may require some interpretation,
+particularly with remote alerts where you don't have an error string, and where
+the remote implementation may not be signalling alerts properly.  Many alerts
+signal an implementation error, and so should rarely be seen in normal operation
+(unexpected_message, decode_error, illegal_parameter, internal_error, etc.).
+
+Others alerts are more likely to occur.  Below are some common alerts and their
+probable causes, and whether they are signalled by the client or server.
+
+Client bad_record_mac:
+ - bad shared key password
+
+Client handshake failure:
+ - SRP parameters are not recognized by client
+
+Client user_canceled:
+ - server isn't what the client was expecting (for example, the client might
+ have called handshakeClientCert(), but the server didn't request a client
+ certificate.  Or, the client might have returned None from an SRP callback).
+
+Client insufficient_security:
+ - SRP parameters are too small
+
+Server protocol_version:
+ - Server or client doesn't support your protocol version
+
+Server bad_record_mac:
+ - bad SRP username or password
+
+Server unknown_srp_username
+ - bad SRP username (bad_record_mac could be used for the same thing)
+
+Server handshake_failure:
+ - bad shared key username
+ - no matching cipher suites
+
+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
+socket.error, just like the handshake functions.
+
+Once the TLS connection is closed by the other side, calls to read() will return
+an empty string.  If the socket is closed by the other side without first
+closing the TLS connection, a call to read() or write() will return a
+socket.error.
+
+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
+data, the session object can be used for session resumption, and the connection
+object can be re-used by calling another handshake function.
+
+If a socket.error or alert is raised, the connection will be automatically
+closed; you don't need to call close().  Furthermore, you will probably not be
+able to re-use the socket, the connection object, or the session object, and
+you shouldn't even try.
+
+By default, calling close() will leave the socket open.  If you set the
+connection's closeSocket flag to True, the connection will take ownership of the
+socket, and close it when the connection is closed.
+
+
+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:
+
+  #No authentication whatsoever
+  h = tlslite.HTTPTLSConnection("www.amazon.com", 443)
+  h.request("GET", "")
+  r = h.getresponse()
+  [...]
+
+  #Authenticate server based on its X.509 fingerprint
+  h = tlslite.HTTPTLSConnection("www.amazon.com", 443,
+          x509Fingerprint="e049ff930af76d43ff4c658b268786f4df1296f2")
+  [...]
+
+  #Authenticate server based on its cryptoID
+  h = tlslite.HTTPTLSConnection("localhost", 443,
+          cryptoID="dmqb6.fq345.cxk6g.5fha3")
+  [...]
+
+  #Mutually authenticate with SRP
+  h = tlslite.HTTPTLSConnection("localhost", 443,
+          username="alice", password="abra123cadabra")
+  [...]
+
+  #Mutually authenticate with a shared key
+  h = tlslite.HTTPTLSConnection("localhost", 443,
+          username="alice", sharedKey="PaVBVZkYqAjCQCu6UBL2xgsnZhw")
+  [...]
+
+  #Mutually authenticate with SRP, *AND* authenticate the server based
+  #on its cryptoID
+  h = tlslite.HTTPTLSConnection("localhost", 443,
+          username="alice", password="abra123cadabra",
+          cryptoID="dmqb6.fq345.cxk6g.5fha3")
+  [...]
+
+You can also use TLS Lite to implement servers using Python's SocketServer
+framework.  TLS Lite comes with a TLSMixIn class.  You can combine this with a
+TCPServer such as HTTPServer.  To combine them, define a new class that inherits
+from both of them (with the mix-in first). Then implement the handshake()
+method, doing some sort of server handshake on the connection argument.  If the
+handshake method returns True, the RequestHandler will be triggered.  Below is a
+complete example of a threaded HTTPS server.
+
+  from SocketServer import *
+  from BaseHTTPServer import *
+  from SimpleHTTPServer import *
+  from tlslite import *
+
+  s = open("./serverX509Cert.pem").read()
+  x509 = X509()
+  x509.parse(s)
+  certChain = X509CertChain([x509])
+
+  s = open("./serverX509Key.pem").read()
+  privateKey = parsePEMKey(s, private=True)
+
+  sessionCache = SessionCache()
+
+  class MyHTTPServer(ThreadingMixIn, TLSMixIn, HTTPServer):
+      def handshake(self, tlsConnection):
+          try:
+              tlsConnection.handshakeServer(certChain=certChain,
+                                            privateKey=privateKey,
+                                            sessionCache=sessionCache)
+              return True
+          except TLSAlert, alert:
+              print "Handshake failure:", str(alert)
+              return False
+
+  httpd = MyHTTPServer(('localhost', 443), SimpleHTTPRequestHandler)
+  httpd.serve_forever()
+
+
+History
+========
+0.2.0 - 2/19/2004
+ - changed VerifierDB to take per-user parameters
+ - renamed tlslite -> tlslite
+0.1.9 - 2/16/2004
+ - added post-handshake 'Checker'
+ - made compatible with Python 2.2
+ - made more forgiving of abrupt closure, since everyone does it:
+   if the socket is closed while sending/recv'ing close_notify,
+   just ignore it.
+0.1.8 - 2/12/2004
+ - TLSConnections now emulate sockets, including makefile()
+ - HTTPTLSConnection and TLSMixIn simplified as a result
+0.1.7 - 2/11/2004
+ - fixed httplib.HTTPTLSConnection with multiple requests
+ - fixed SocketServer to handle close_notify
+ - changed handshakeClientNoAuth() to ignore CertificateRequests
+ - changed handshakeClient() to ignore non-resumable session arguments
+0.1.6 - 2/10/2004
+ - fixed httplib support
+0.1.5 - 2/09/2004
+ - added support for httplib and SocketServer
+ - added support for SSLv3
+ - added support for 3DES
+ - cleaned up read()/write() behavior
+ - improved HMAC speed
+0.1.4 - 2/06/2004
+ - fixed dumb bug in tls.py
+0.1.3 - 2/05/2004
+ - change read() to only return requested number of bytes
+ - added support for shared-key and in-memory databases
+ - added support for PEM-encoded X.509 certificates
+ - added support for SSLv2 ClientHello
+ - fixed shutdown/re-handshaking behavior
+ - cleaned up handling of missing_srp_username
+ - renamed readString()/writeString() -> read()/write()
+ - added documentation
+0.1.2 - 2/04/2004
+ - added clienttest/servertest functions
+ - improved OpenSSL cipher wrappers speed
+ - fixed server when it has a key, but client selects plain SRP
+ - fixed server to postpone errors until it has read client's messages
+ - fixed ServerHello to only include extension data if necessary
+0.1.1 - 2/02/2004
+ - fixed close_notify behavior
+ - fixed handling of empty application data packets
+ - fixed socket reads to not consume extra bytes
+ - added testing functions to tls.py
+0.1.0 - 2/01/2004
+ - first release
+
+
+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
+[3] http://www.trevp.net/cryptoID/
+[4] http://www.openssl.org/
+[5] http://www.cs.auckland.ac.nz/~pgut001/cryptlib/
+[6] http://sandbox.rulemaker.net/ngps/m2/
+[7] http://trevp.net/cryptlibConverter/
+[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.]
+
+
+
+

File scripts/tls.py

View file
+#! 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
+    
+    
+    
+    
+    

File scripts/tlsdb.py

View file
+#! python
+
+import sys
+import os
+import socket
+import thread
+
+
+if __name__ != "__main__":
+    raise "This must be run as a command, not used as a module!"
+
+
+from tlslite import *
+
+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 cryptlibpyLoaded:
+        print "  cryptlib_py : Loaded"
+    else:
+        print "  cryptlib_py : Not Loaded"
+    if m2cryptoLoaded:
+        print "  M2Crypto    : Loaded"
+    else:
+        print "  M2Crypto    : Not Loaded"
+    print ""
+    print "Commands:"
+    print ""
+    print "  createsrp       <db>"
+    print "  createsharedkey <db>"
+    print ""
+    print "  add    <db> <user> <pass> [<bits>]"
+    print "  del    <db> <user>"    
+    print "  check  <db> <user> [<pass>]"    
+    print "  list   <db>"
+    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 == "help":
+        command = args.getLast(2).lower()
+        if command == "valid":
+            print ""
+        else:
+            print "Bad command: '%s'" % command      
+
+    elif cmd == "createsrp":
+        dbName = args.get(2)
+                  
+        db = VerifierDB(dbName)
+        db.create()
+
+    elif cmd == "createsharedkey":
+        dbName = args.getLast(2)
+                    
+        db = SharedKeyDB(dbName)
+        db.create()
+        
+    elif cmd == "add":
+        dbName = args.get(2)
+        username = args.get(3)
+        password = args.get(4)
+        
+        try:
+            db = VerifierDB(dbName)
+            db.open()
+            bits = int(args.getLast(5))
+            N, g, salt, verifier = makeVerifier(username, password, bits)
+            db[username] = N, g, salt, verifier
+        except ValueError:
+            db = SharedKeyDB(dbName)
+            db.open()
+            args.getLast(4)        
+            db[username] = password
+        
+    elif cmd == "del":
+        dbName = args.get(2)
+        username = args.getLast(3)
+    
+        try:
+            db = VerifierDB(dbName)
+            db.open()
+        except ValueError:
+            db = SharedKeyDB(dbName)
+            db.open()
+                            
+        del(db[username])
+        
+    elif cmd == "check":
+        dbName = args.get(2)
+        username = args.get(3)
+        if len(sys.argv)>=5:
+            password = args.getLast(4)
+        else:
+            password = None
+        
+        try:
+            db = VerifierDB(dbName)
+            db.open()
+        except ValueError:
+            db = SharedKeyDB(dbName)
+            db.open()
+        
+        try:
+            db[username]
+            print "Username exists"
+            
+            if password:
+                if db.check(username, password):
+                    print "Password is correct"
+                else:
+                    print "Password is wrong"
+        except KeyError:
+            print "Username does not exist"
+            sys.exit()
+    
+    elif cmd == "list":
+        dbName = args.get(2)
+        
+        try:
+            db = VerifierDB(dbName)
+            db.open()
+        except ValueError:
+            db = SharedKeyDB(dbName)
+            db.open()
+        
+        if isinstance(db, VerifierDB):
+            print "SRP Database"
+        else:
+            print "Shared Key Database"
+        for username in db.keys():
+            N, g, s, v = db[username]
+            print cryptomath.numBits(N), username        
+    else:        
+        print "Bad command: '%s'" % cmd
+except:
+    raise

File setup.py

View file
+#!/usr/bin/env python
+
+import os
+from distutils.core import setup, Extension
+
+
+#************************************************
+#if this is a Windows platform without M2Crypto, install
+#a stripped-down binary version of M2Crypto alongside cryptoIDlib:
+data_files = []
+if os.name == "nt":
+    try:
+        import M2Crypto
+    except:
+        data_files = [("lib/site-packages/tlslite/utils",
+                       ["m2crypto/__m2crypto.pyd", "m2crypto/m2.py"])]        
+#************************************************    
+
+
+setup(name="tlslite",
+      version="0.2.0",
+      author="Trevor Perrin",
+      author_email="trevp@trevp.net",
+      url="http://trevp.net/tlslite",
+      description="tlslite implements SSL v3 and TLS v1 with SRP, shared-keys, cryptoID, or X.509 authentication.",
+      license="public domain",
+      scripts=["scripts/tls.py", "scripts/tlsdb.py"],
+      packages=["tlslite", "tlslite.utils"],
+      data_files=data_files
+      )

File test/clientCryptoIDChain.xml

View file
+<certChain chainID="IsGREhHlshkWoHuav8A2jsQt/8Y=" cryptoID="eget4.y8nwk.q5r9m.tb6fy" xmlns="http://trevp.net/cryptoID">
+	<certs>
+		<rootCert certID="n5aV90we0tH06HhBASXhZSY7MSw=">
+			<keyExpression expr="((2 of A,B,C) and (D or E))">
+				<keyHash>X5ln1ow0DHgkYtGsPUsgGN4Na88=</keyHash>
+				<keyHash>zWc79K42ddgHzAEgPIzkHotnUjg=</keyHash>
+				<keyHash>GlblYv2k2PqbAleiiJ/lEmzJQqc=</keyHash>
+				<keyHash>S9GWmIoEFfjuGBVRgfjXJNESTyw=</keyHash>
+				<keyHash>m9Ey/7x3v54LhZiJ1CSBf1To6AI=</keyHash>
+			</keyExpression>
+			<modifier zeroCount="2">41379045</modifier>
+		</rootCert>
+		<cert certID="OsVOj1gQ5h0tS7cIBiQUvLZHb4I=">
+			<keyExpression expr="(F and (D or E))">
+				<keyHash>aaHOUPvkxuzF9/3mb7NO4dDv63Q=</keyHash>
+			</keyExpression>
+		</cert>
+	</certs>
+	<publicKeys keys="ACEF">
+		<publicKey xmlns="http://trevp.net/rsa">
+			<n>wFf6H4cTogXHo2OS4h5/g0TqMnhB3axey7/p/eUenlobTb1KCAMJPMX3eUWHlf9mwfi1VdHJREcdy3ykyok99p59nrKYScMpge6cCeg1aJVtxUwB9JeuJpuLQW4mRYFN1UX/1UM26dzETiTKSOcD9Ju9E30AteZ0UPnK5srraqk=</n>
+			<e>Aw==</e>
+		</publicKey>
+		<publicKey xmlns="http://trevp.net/rsa">
+			<n>tAV5ofc3dWVdPSDmoaBDJvXxMfu8AeAwcciyb5mBtuvlyXwpNzXBeguMJZKBPHuPCi2vjlxnEXrdmR3c5pqY39skHHOhkynnFCaJenm3T3q1XAdXRiU0qa5JYQWAqE/wK10N3MFHq7nT+FYNVljhURr+BssdH/U/qpWyZs5RAD0=</n>
+			<e>Aw==</e>
+		</publicKey>
+		<publicKey xmlns="http://trevp.net/rsa">
+			<n>yd49UL8BwSD2TBj6qEy2J4eKxsm02/jogv3+SaBrgI+4JI2ZucTGuqBoJ65phrRJlHOi1gJxM3BFRMWLu66fDG0eTT+WvRLYyEPKH6dZfe/u/WYebcExjGh2/uvqsBgo1M/lyScoLeOV6Kf5S6JnuwEq2f+iYiTBG0zL1ZbIaZE=</n>
+			<e>Aw==</e>
+		</publicKey>
+		<publicKey xmlns="http://trevp.net/rsa">
+			<n>4a5yzB8oGNlHo866CAspAC47M4Fvx58zwK8pouFocqnSDCoXYI6vkVly8tUsJ3ZsvDadPpN9687EFKrEU8nosH+FPFCfvzExOs2SZm1y6uFXFRa6sHnA+Z7c58cjozol3eCe0cad/hHDOkINar35aEzhQt00AiYLltDts9wN1e8=</n>
+			<e>Aw==</e>
+		</publicKey>
+	</publicKeys>
+	<signatures>
+		<signature chaff="PmPMbklu5iYD1IHoRaEiDO" key="A" listCA="0" notAfter="2006-05-16T08:27:55Z" sigAlgo="pkcs1-sha1">SKq5M9NfXCQih75CkATqn0R+hbmojBNy6IcltN/4IAm1EIVoHnMrH4kTNVu0ExUhycjLmHz+qv6BDVv1srXET54+i+IfRPFv7DHElOQ+XQ5M9sDWSPd3xlyANpmVbjiOgFn5ouLGJf2vu1hO4Te/QQjb7f1/n8+F2TBDVKcCSno=</signature>
+		<signature chaff="+LYUt3zqeoYbDpRd+OYMQZ" key="C" listCA="0" sigAlgo="pkcs1-sha1">YBOBIbnCbpHGVcEdsqg2VtTFS35P8njL1VTIJ9HCy0hFzrpE6UiuNrnueQSVBRVH2AAz0FKCVzl5W4l2yJv7iMD6GN5L92BXbimebjIOzO03y8ALRT5NoNHjfG7aEk3wkrlJ5Hil9nQ7sW5przrwH9/lmri16pqLDvi0gJdRfpA=</signature>
+		<signature chaff="AqM/IG/X/qUbqyQH8OzZWK" key="E" listCA="0" listVA="1" notAfter="2005-03-25T16:28:46Z" sigAlgo="pkcs1-sha1">W95rfg8oeY0U/qJvNYcwJR2fsi9BGafco5ipK5hCcrI3VprKlspvk80O9gvy2bI5RjFVLZFrzp0f9KPgwfy+zDE2T7hMpZqO7auP0dCI5V/ThPYrj4BX/hAcCG7pjZyM3p5Z2T+7+14sGpi46wCh/5eGK7qbUVrko5wavXkG9wM=</signature>
+	</signatures>
+</certChain>

File test/clientCryptoIDKey.xml

View file
+<privateKey xmlns="http://trevp.net/rsa">
+	<n>4a5yzB8oGNlHo866CAspAC47M4Fvx58zwK8pouFocqnSDCoXYI6vkVly8tUsJ3ZsvDadPpN9687EFKrEU8nosH+FPFCfvzExOs2SZm1y6uFXFRa6sHnA+Z7c58cjozol3eCe0cad/hHDOkINar35aEzhQt00AiYLltDts9wN1e8=</n>
+	<e>Aw==</e>
+	<d>JZ0TIgUxWXmL8KJ0VqyG1V0J3ern9pqIoB0xmyWRaHGjAgcD5W0dQuQ90yOHW+kSH15vim3qUffLWMcguKGmx8UJvQVeQnuRB/zz7u+4H4aWaLD1Y+L3NXqvVPqgnd4T/WDQLFjDuSx7KbKTUhR2C2th7e6qkFY5nJh35JtooEM=</d>
+	<p>5PreIj6z6ldIGL1V4+1C36dQFHNCQHJvW52GXcbLExybv8Q9QMgtVi07WoXreoe8uee9A4Pmc+sspbHeTl5OmQ==</p>
+	<q>/E/wDit8YXPCxx126zTq2ilQ3IcW54NJYyNjiZkk8pFR2/mKcT95sLMEuBOSyK1nDq3yQbC5rMa+mGx56TvFxw==</q>
+	<dP>mKc+wX8inDowEH45Qp4slRo1YveBgExKPROu6S8yDL29KoLTgIVzjsjSPFlHpwUoe+/TV61ETUdzGSE+3umJuw==</dP>
+	<dQ>qDVKtBz9lk0shL5PR3ickXDgkwS576zbl2ztBmYYobY2kqZcS3+mdcyt0A0MhcjvXx6hgSB7yIR/EEhRRifZLw==</dQ>
+	<qInv>j6E8EA7dNsTImaXexAmLA1DoeArsYeFAInrAkt9yhYfrvt/mvY793/px3x1Hx8nQnSIiHnflcNtKEGaWRBMheg==</qInv>
+</privateKey>
+

File test/clientX509Cert.pem

View file
+-----BEGIN CERTIFICATE-----
+MIICoDCCAgmgAwIBAgIBADANBgkqhkiG9w0BAQQFADBFMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMB4XDTA0MDIwNjA2NDkxM1oXDTA0MDMwNzA2NDkxM1owRTELMAkGA1UE
+BhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp
+ZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2LHLqDM7
+BpltKQGLJsh5bcQdk3cB0tHSJn4wjH2kg5Hy3WWOfnTljkVZ7PXrVp69feJkhgNR
+dD5bP1SVvPnF/ft77SVfM0nQDT2FKEH9Ez+1ZScZB3UkZFGxKM+WwALP/ve9LqLO
+5+4l0CJ4vt3q1E3WBJNolpzAY05Y34Gyv3UCAwEAAaOBnzCBnDAdBgNVHQ4EFgQU
+zir4m5L6TMX16qGLDzzTSSEsMwQwbQYDVR0jBGYwZIAUzir4m5L6TMX16qGLDzzT
+SSEsMwShSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEw
+HwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCAQAwDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQQFAAOBgQBWiYArf5Z0hMDB7TeHONS6NYFktMndJnctOTGV
+lmBV4I9Eg+TeYGIGfGkkZMm/zS2gfPRY12KyXVEL7+aBzguF/vPV+8nb5ByHlMu+
+K+4j3YnbkwMQ8QLZwwHOjc2quyMnm1hVKPPTpEWhXGK86lbbinidHgSe8cNKqjjg
+xor7mA==
+-----END CERTIFICATE-----

File test/clientX509Key.pem

View file
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQDYscuoMzsGmW0pAYsmyHltxB2TdwHS0dImfjCMfaSDkfLdZY5+
+dOWORVns9etWnr194mSGA1F0Pls/VJW8+cX9+3vtJV8zSdANPYUoQf0TP7VlJxkH
+dSRkUbEoz5bAAs/+970uos7n7iXQIni+3erUTdYEk2iWnMBjTljfgbK/dQIDAQAB
+AoGAJHoJZk75aKr7DSQNYIHuruOMdv5ZeDuJvKERWxTrVJqE32/xBKh42/IgqRrc
+esBN9ZregRCd7YtxoL+EVUNWaJNVx2mNmezEznrc9zhcYUrgeaVdFO2yBF1889zO
+gCOVwrO8uDgeyj6IKa25H6c1N13ih/o7ZzEgWbGG+ylU1yECQQDv4ZSJ4EjSh/Fl
+aHdz3wbBa/HKGTjC8iRy476Cyg2Fm8MZUe9Yy3udOrb5ZnS2MTpIXt5AF3h2TfYV
+VoFXIorjAkEA50FcJmzT8sNMrPaV8vn+9W2Lu4U7C+K/O2g1iXMaZms5PC5zV5aV
+CKXZWUX1fq2RaOzlbQrpgiolhXpeh8FjxwJBAOFHzSQfSsTNfttp3KUpU0LbiVvv
+i+spVSnA0O4rq79KpVNmK44Mq67hsW1P11QzrzTAQ6GVaUBRv0YS061td1kCQHnP
+wtN2tboFR6lABkJDjxoGRvlSt4SOPr7zKGgrWjeiuTZLHXSAnCY+/hr5L9Q3ZwXG
+6x6iBdgLjVIe4BZQNtcCQQDXGv/gWinCNTN3MPWfTW/RGzuMYVmyBFais0/VrgdH
+h1dLpztmpQqfyH/zrBXQ9qL/zR4ojS6XYneO/U18WpEe
+-----END RSA PRIVATE KEY-----

File test/index.html

View file
+<html>
+<head>
+<title>Trevor Perrin</title>
+</head>
+<body>
+<H1>Trevor Perrin</H1>
+<b>Email:</b> trevp at trevp.net<br>
+<b>PGP Key:</b> <a href="pgp/key.asc">8035 47B9 D1F9 C148 619A  7948 D8C0 0F11 2F2F F9E3</a>
+<p>I'm a programmer, here are some projects I'm involved in.
+
+<p>My current interest is cryptographic key management and alternatives to PKI.
+<p>
+
+<a name="cryptoID">
+<H2><a href="cryptoID/">CryptoIDs</a></H2>
+<b>Paper 1:</b> Public Key Distribution through "cryptoIDs" (<a href="cryptoID/cryptoID.pdf">.pdf</a>, <a href="cryptoID/cryptoID.html">.html</a>) <i>(presented at <a href="http://www.nspw.org/2003/">NSPW 2003</a>)</i><br>
+<b>Paper 2:</b> The CryptoID Key Management Protocols (<a href="cryptoID/cryptoID2.pdf">.pdf</a>) <i>(the best introduction)</i><br>
+<b>Schema:</b>  XML Schema for &lt;certChain&gt; (<a href="cryptoID/cryptoID.xsd">.xsd</a>)<br>
+<b>Code:</b>  CryptoIDlib Python and Java library and command-line tool v0.1.8 (<a href="cryptoID/cryptoIDlib-0.1.8.zip">.zip</a>, <a href="cryptoID/readme.txt">readme.txt</a>)
+<p>PKI isn't working for person-to-person communications.  Few people use
+secure email, voice, instant-messaging, or anything else.
+<p>CryptoIDs are an alternative.  The idea is for people to exchange small,
+user-friendly fingerprints (aka "cryptoIDs") like 'cyhf4.9ajd8.kbdx4.rk98c'.
+These could be passed around and stored in address books as if they were phone
+numbers or postal addresses.
+<p>The cryptoID for each user would correspond to that user's <i>root key</i>.
+The user would keep his root key in a safe place - his employer or
+some commercial service might hold it for him.  The rootholder would operate
+an online service which would issue short-lived <i>subkey certificates</i> or <i>validation signatures</i> to the user.
+<p>CryptoIDs, then, are about combining <i>fingerprint-based public-key distribution</i> with
+<i>certificate-based private-key management</i>.  The first paper above presents the
+cryptoID fingerprint and certificate formats, which are designed specifically for
+this.  CryptoIDlib lets you test-drive these formats.
+<p>The second paper presents private-key management protocols for use with online servers.
+Support for these is being added to cryptoIDlib.
+
+<a name="tls_lite">
+<H2><a href="tls_lite/">TLS Lite</a></H2>
+<b>Code:</b> tls_lite python library v0.1.8 (<a href="tls_lite/tls_lite-0.1.8.zip">.zip</a>, <a href="tls_lite/readme.txt">readme.txt</a>)<br>
+<p>
+TLS Lite is a free python library that implements SSL 3.0 and <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0</a>.
+TLS Lite supports non-traditional authentication methods such as <a href="http://trevp.net/tls_srp/index.html">SRP</a>,
+<a href="http://www.ietf.org/internet-drafts/draft-ietf-tls-sharedkeys-02.txt">shared keys</a>,
+and <a href="http://trevp.net/cryptoID/index.html">cryptoIDs</a>, in addition to X.509 certificates.  TLS Lite is pure
+<a href="http://www.python.org">Python</a>, however it can access <a href="http://www.openssl.org/">OpenSSL</a> or
+<a href="http://www.cs.auckland.ac.nz/~pgut001/cryptlib/">cryptlib</a> for faster crypto operations.
+
+<a name="tlssrp">
+<H2><a href="tls_srp/">TLS/SRP</a></H2>
+<b>Internet-Draft:</b>  Using SRP for TLS Authentication (<a href="tls_srp/draft-ietf-tls-srp-06.txt">.txt</a>, <a href="tls_srp/draft-ietf-tls-srp-06.html">.html</a>)
+<p><a href="http://srp.stanford.edu">SRP</a> is the best way to do password authentication
+across a network.  <a href="http://www.ietf.org/html.charters/tls-charter.html">TLS</a> (aka SSL v3.1)
+is the best way to do channel security.  What could go better together?
+<p>This draft modifies the TLS handshake to use SRP.  This combination of
+password-based mutual authentication and the TLS record layer is
+ideal for protecting protocols like POP3 and HTTP.
+
+<a name="dss">
+<H2>DSS</H2>
+<b>Requirements:</b>  DSS Use Case Requirements Analysis (<a href="dss/oasis-dss-1.0-requirements-wd-12.pdf">.pdf</a>, <a href="dss/oasis-dss-1.0-requirements-wd-12.doc">.doc</a>)<br>
+<b>Specification Working Draft:</b> Digital Signature Service Core Protocol and Elements (<a href="dss/oasis-dss-1.0-core-spec-wd-10.pdf">.pdf</a>, <a href="dss/oasis-dss-1.0-core-spec-wd-10.doc">.doc</a>)<br>
+<b>Schema Working Draft:</b> oasis-dss-1.0-core-schema-wd-10 (<a href="dss/oasis-dss-1.0-core-schema-wd-10.xsd">.xsd</a>)<br>
+<b>Somewhat Related Paper:</b> Delegated Cryptography, Online Trusted Third Parties, and PKI
+(<a href="delegatedCrypto/delegatedCrypto.pdf">.pdf</a>, <a href="delegatedCrypto/delegatedCrypto.html">.html</a>)<br>
+<i>(presented at the <a href="http://www.cs.dartmouth.edu/~pki02/">1st Annual PKI Research Workshop</a>)</i>
+<p>The <a href="http://www.oasis-open.org/">OASIS</a> <a href="http://www.oasis-open.org/committees/dss/">Digital Signature Service Technical Committee</a>
+is designing protocols for signing, verifying, and
+time-stamping of XML documents and other data.  The idea is to perform these
+operations on servers, thus freeing clients from having to manage private
+keys, calculate certificate paths, and so on.
+<p>Also listed is a paper arguing for the server-based approach vs. client-side PKI.
+
+<a name="cryptoURL">
+<H2>CryptoURLs</H2>
+<b>Draft of potential Internet-Draft:</b> The "crypto" URL scheme (<a href="cryptoURL/draft-ietf-cryptoURL-01.txt">.txt</a>, <a href="cryptoURL/draft-ietf-cryptoURL-01.html">.html</a>)<br>
+<p>
+CryptoURLs add "crypto metadata" like content hashes and key fingerprints to normal URLs.
+The resulting URLs are <a href="http://zooko.com/distnames.html">self-authenticating</a>,
+like <a href="http://citeseer.nj.nec.com/mazieres99separating.html">SFS file names</a> or
+<a href="http://research.microsoft.com/users/tuomaura/CGA/">Cryptographically Generated Addresses</a>.
+These could be useful in:
+<dir>
+<LI>web pages:
+  <dir>
+  <LI>a page could link to software binaries and include their hash
+  <LI>a portal could provide secure introductions to a community of sites
+  </dir>
+<LI>XML documents (e.g. extending an <a href="http://www.w3.org/TR/xmldsig-core/">XML-DSIG</a> over external references)
+<LI>protocols (e.g. HTTP Redirects or LDAP Referrals)
+<LI>software configuration (you could configure a client with the address and fingerprint of a server in one step)
+</dir>
+<a href="http://www.waterken.com/dev/YURL/">YURLs</a> are another approach to self-authenticating URLs.