| Index: third_party/tlslite/README
|
| diff --git a/third_party/tlslite/readme.txt b/third_party/tlslite/README
|
| similarity index 40%
|
| rename from third_party/tlslite/readme.txt
|
| rename to third_party/tlslite/README
|
| index c1f1b3840c7eff91e1b40049633e4945c57ad660..1b3247abe4fc9ec3f7769a8e67507d87176f1978 100644
|
| --- a/third_party/tlslite/readme.txt
|
| +++ b/third_party/tlslite/README
|
| @@ -1,6 +1,6 @@
|
|
|
| -tlslite version 0.3.8 February 21, 2005
|
| -Trevor Perrin <trevp at trevp.net>
|
| +tlslite version 0.4.6 Mar 20 2013
|
| +Trevor Perrin <tlslite at trevp.net>
|
| http://trevp.net/tlslite/
|
| ============================================================================
|
|
|
| @@ -13,37 +13,36 @@ Table of Contents
|
| 4 Getting Started with the Command-Line Tools
|
| 5 Getting Started with the Library
|
| 6 Using TLS Lite with httplib
|
| -7 Using TLS Lite with xmlrpclib
|
| -8 Using TLS Lite with poplib or imaplib
|
| -9 Using TLS Lite with smtplib
|
| -10 Using TLS Lite with SocketServer
|
| -11 Using TLS Lite with asyncore
|
| -12 Using TLS Lite with Twisted
|
| -13 SECURITY CONSIDERATIONS
|
| -14 History
|
| -15 References
|
| -
|
| -
|
| -1 Introduction
|
| -===============
|
| -TLS Lite is a free python library that implements SSL v3, TLS v1, and
|
| -TLS v1.1 [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],
|
| -cryptlib [5], pycrypto [9], and GMPY [10] for faster crypto operations. TLS
|
| -Lite integrates with httplib, xmlrpclib, poplib, imaplib, smtplib,
|
| -SocketServer, asyncore, and Twisted.
|
| +7 Using TLS Lite with poplib or imaplib
|
| +8 Using TLS Lite with smtplib
|
| +9 Using TLS Lite with SocketServer
|
| +10 Using TLS Lite with asyncore
|
| +11 SECURITY CONSIDERATIONS
|
| +12 History
|
| +
|
| +
|
| +1 Introduction
|
| +===============
|
| +TLS Lite is an open source python library that implements SSL and TLS. TLS
|
| +Lite supports RSA and SRP ciphersuites. TLS Lite is pure python, however it
|
| +can use other libraries for faster crypto operations. TLS Lite integrates with
|
| +several stdlib neworking libraries.
|
|
|
| API documentation is available in the 'docs' directory.
|
|
|
| -If you have questions or feedback, feel free to contact me.
|
| +If you have questions or feedback, feel free to contact me. For discussing
|
| +improvements to tlslite, also see 'tlslite-dev@googlegroups.com'.
|
|
|
|
|
| 2 Licenses/Acknowledgements
|
| ============================
|
| -All code here is public domain.
|
| +TLS Lite is written (mostly) by Trevor Perrin. It includes code from Bram
|
| +Cohen, Google, Kees Bos, Sam Rushing, Dimitris Moraitis, Marcelo Fernandez,
|
| +Martin von Loewis, and Dave Baggett.
|
|
|
| -Thanks to Bram Cohen for his public domain Rijndael implementation.
|
| +All code in TLS Lite has either been dedicated to the public domain by its
|
| +authors, or placed under a BSD-style license. See the LICENSE file for
|
| +details.
|
|
|
| Thanks to Edward Loper for Epydoc, which generated the API docs.
|
|
|
| @@ -51,84 +50,86 @@ Thanks to Edward Loper for Epydoc, which generated the API docs.
|
| 3 Installation
|
| ===============
|
| Requirements:
|
| - Python 2.2 or greater is required.
|
| + Python 2.6 or higher is required. Python 3 is supported.
|
|
|
| Options:
|
| - - If you have cryptoIDlib [8], you can use cryptoID certificate chains for
|
| - authentication. CryptoIDlib is the sister library to TLS Lite; it was
|
| - written by the same author, and has a similar interface.
|
| -
|
| - - If you have the M2Crypto [6] interface to OpenSSL, this will be used for
|
| - fast RSA operations and fast ciphers.
|
| + - If you have the M2Crypto interface to OpenSSL, this will be used for fast
|
| + RSA operations and fast ciphers.
|
|
|
| - - If you have the cryptlib_py [7] interface to cryptlib, this will be used
|
| - 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 pycrypto this will be used for fast RSA operations and fast
|
| + ciphers.
|
|
|
| - - If you have pycrypto [9], this will be used for fast ciphers and fast RSA
|
| - operations.
|
| -
|
| - - If you have the GMPY [10] interface to GMP, this will be used for fast RSA
|
| - and SRP operations.
|
| + - If you have the GMPY interface to GMP, this will be used for fast RSA and
|
| + SRP operations.
|
|
|
| - These modules don't need to be present at installation - you can install
|
| - them any time.
|
| -
|
| -On Windows:
|
| - Run the installer in the 'installers' directory.
|
| - *OR*
|
| - Run 'setup.py install' (this only works if your system has a compiler
|
| - available).
|
| + them any time.
|
|
|
| -Anywhere else:
|
| - - Run 'python setup.py install'
|
| +Run 'python setup.py install'
|
|
|
| Test the Installation:
|
| - - The 'tls.py' script should have been copied onto your path. If not,
|
| - you may have to copy it there manually.
|
| - - From the distribution's ./test subdirectory, run:
|
| - tls.py servertest localhost:4443 .
|
| + - From the distribution's ./tests subdirectory, run:
|
| + ./tlstest.py server localhost:4443 .
|
| - While the test server is waiting, run:
|
| - tls.py clienttest localhost:4443 .
|
| + ./tlstest.py client localhost:4443 .
|
|
|
| If both say "Test succeeded" at the end, you're ready to go.
|
|
|
| - (WARNING: Be careful running these (or any) scripts from the distribution's
|
| - root directory. Depending on your path, the scripts may load the local copy
|
| - of the library instead of the installed version, with unpredictable
|
| - results).
|
| -
|
|
|
| 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.
|
| +tlslite installs two command-line scripts: 'tlsdb.py' and 'tls.py'.
|
| +
|
| +'tls.py' lets you run test clients and servers. It can be used for testing
|
| +other TLS implementations, or as example code. Note that 'tls.py server' runs
|
| +an HTTPS server which will serve files rooted at the current directory by
|
| +default, so be careful.
|
|
|
| -'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.
|
| +'tlsdb.py' lets you manage SRP verifier databases. These databases are used by
|
| +a TLS server when authenticating clients with 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:
|
| +X.509
|
| +------
|
| +To run an X.509 server, go to the ./tests directory and do:
|
| +
|
| + tls.py server -k serverX509Key.pem -c serverX509Cert.pem localhost:4443
|
| +
|
| +Try connecting to the server with a web browser, or with:
|
| +
|
| + tls.py client localhost:4443
|
| +
|
| +X.509 with TACK
|
| +----------------
|
| +To run an X.509 server using a TACK, install TACKpy, then run the same server
|
| +command as above with added arguments:
|
| +
|
| + ... -t TACK1.pem localhost:4443
|
| +
|
| +SRP
|
| +----
|
| +To run an SRP server, try something like:
|
|
|
| tlsdb.py createsrp verifierDB
|
| tlsdb.py add verifierDB alice abra123cadabra 1024
|
| tlsdb.py add verifierDB bob swordfish 2048
|
|
|
| - tls.py serversrp localhost:443 verifierDB
|
| + tls.py server -v verifierDB localhost:4443
|
| +
|
| +Then try connecting to the server with:
|
| +
|
| + tls.py client localhost:4443 alice abra123cadabra
|
|
|
| -Then you can try connecting to the server with:
|
| +HTTPS
|
| +------
|
| +To run an HTTPS server with less typing, run ./tests/httpsserver.sh.
|
|
|
| - tls.py clientsrp localhost:443 alice abra123cadabra
|
| +To run an HTTPS client, run ./tests/httpsclient.py.
|
|
|
|
|
| 5 Getting Started with the Library
|
| ===================================
|
| -Using the library is simple. Whether you're writing a client or server, there
|
| -are six steps:
|
| +Whether you're writing a client or server, there are six steps:
|
| +
|
| 1) Create a socket and connect it to the other party.
|
| 2) Construct a TLSConnection instance with the socket.
|
| 3) Call a handshake function on TLSConnection to perform the TLS handshake.
|
| @@ -136,58 +137,50 @@ are six steps:
|
| 5) Use the TLSConnection to exchange data.
|
| 6) Call close() on the TLSConnection when you're done.
|
|
|
| -TLS Lite also integrates with httplib, xmlrpclib, poplib, imaplib, smtplib,
|
| -SocketServer, asyncore, and Twisted. When used with these, some of the steps
|
| -are performed for you. See the sections following this one for details.
|
| +TLS Lite also integrates with several stdlib python libraries. See the
|
| +sections following this one for details.
|
|
|
| 5 Step 1 - create a socket
|
| ---------------------------
|
| -Below demonstrates a socket connection to Amazon's secure site. 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.
|
| +Below demonstrates a socket connection to Amazon's secure site.
|
|
|
| from socket import *
|
| sock = socket(AF_INET, SOCK_STREAM)
|
| sock.connect( ("www.amazon.com", 443) )
|
| - sock.settimeout(10) #Only on python 2.3 or greater
|
|
|
| 5 Step 2 - construct a TLSConnection
|
| -------------------------------------
|
| +You can import tlslite objects individually, such as:
|
| + from tlslite import TLSConnection
|
| +
|
| +Or import the most useful objects through:
|
| from tlslite.api import *
|
| +
|
| +Then do:
|
| connection = TLSConnection(sock)
|
|
|
| 5 Step 3 - call a handshake function (client)
|
| ----------------------------------------------
|
| -If you're a client, there's several different handshake functions you can
|
| -call, depending on how you want to authenticate:
|
| +If you're a client, there's two different handshake functions you can call,
|
| +depending on how you want to authenticate:
|
|
|
| connection.handshakeClientCert()
|
| connection.handshakeClientCert(certChain, privateKey)
|
| +
|
| connection.handshakeClientSRP("alice", "abra123cadabra")
|
| - connection.handshakeClientSharedKey("alice", "PaVBVZkYqAjCQCu6UBL2xgsnZhw")
|
| - connection.handshakeClientUnknown(srpCallback, certCallback)
|
|
|
| The ClientCert function without arguments is used when connecting to a site
|
| -like Amazon, which doesn't require client authentication. The server will
|
| -authenticate with a certificate chain.
|
| +like Amazon, which doesn't require client authentication, but which will
|
| +authenticate itself using an X.509 certificate chain.
|
|
|
| The ClientCert function can also be used to do client authentication with an
|
| -X.509 or cryptoID certificate chain. To use cryptoID chains, you'll need the
|
| -cryptoIDlib library [8]. To use X.509 chains, you'll need some way of
|
| -creating these, such as OpenSSL (see http://www.openssl.org/docs/HOWTO/ for
|
| -details).
|
| -
|
| -Below are examples of loading cryptoID and X.509 certificate chains:
|
| -
|
| - #Load cryptoID certChain and privateKey. Requires cryptoIDlib.
|
| - from cryptoIDlib.CertChain import CertChain
|
| - s = open("./test/clientCryptoIDChain.xml").read()
|
| - certChain = CertChain()
|
| - certChain.parse(s)
|
| - s = open("./test/clientCryptoIDKey.xml").read()
|
| - privateKey = parseXMLKey(s, private=True)
|
| -
|
| - #Load X.509 certChain and privateKey.
|
| +X.509 certificate chain and corresponding private key. To use X.509 chains,
|
| +you'll need some way of creating these, such as OpenSSL (see
|
| +http://www.openssl.org/docs/HOWTO/ for details).
|
| +
|
| +Below is an example of loading an X.509 chain and private key:
|
| +
|
| + from tlslite import X509, X509CertChain, parsePEMKey
|
| s = open("./test/clientX509Cert.pem").read()
|
| x509 = X509()
|
| x509.parse(s)
|
| @@ -195,43 +188,34 @@ Below are examples of loading cryptoID and X.509 certificate chains:
|
| s = open("./test/clientX509Key.pem").read()
|
| privateKey = 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.
|
| +The SRP function does mutual authentication with a username and password - see
|
| +RFC 5054 for details.
|
|
|
| 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
|
| +HandshakeSettings instance. For example, if you're performing SRP, but you
|
| +only want to use SRP parameters of at least 2048 bits, and you only want to
|
| +use the AES-256 cipher, and you only want to allow TLS (version 3.1), not SSL
|
| (version 3.0), you can do:
|
|
|
| settings = HandshakeSettings()
|
| settings.minKeySize = 2048
|
| settings.cipherNames = ["aes256"]
|
| settings.minVersion = (3,1)
|
| + settings.useExperimentalTACKExtension = True # Needed for TACK support
|
| +
|
| 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:
|
| +If you want to check the server's certificate using TACK, you should set the
|
| +"useExperiementalTACKExtension" value in HandshakeSettings. (Eventually, TACK
|
| +support will be enabled by default, but for now it is an experimental feature
|
| +which relies on a temporary TLS Extension number, and should not be used for
|
| +production software.) This will cause the client to request the server to send
|
| +you a TACK (and/or any TACK Break Signatures):
|
| +
|
| +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")
|
| .
|
| @@ -250,28 +234,10 @@ To perform SRP authentication, you have to pass in a database of password
|
| verifiers. The VerifierDB class manages an in-memory or on-disk verifier
|
| database.
|
|
|
| - #On-disk database (use no-arg constructor if you want an in-memory DB)
|
| verifierDB = VerifierDB("./test/verifierDB")
|
| -
|
| - #Open the pre-existing database (can also 'create()' a new one)
|
| verifierDB.open()
|
| -
|
| - #Add to the database
|
| - verifier = VerifierDB.makeVerifier("alice", "abra123cadabra", 2048)
|
| - verifierDB["alice"] = verifier
|
| -
|
| - #Perform a handshake using the database
|
| connection.handshakeServer(verifierDB=verifierDB)
|
|
|
| -To perform 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 = 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
|
| @@ -280,20 +246,30 @@ 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 pass in a verifier database and/or a certificate chain+private key.
|
| +The client will use one or both to authenticate the server.
|
|
|
| You can also pass in a HandshakeSettings object, as described in the last
|
| -section, for finer control over handshaking details. Finally, the server can
|
| -maintain a SessionCache, which will allow clients to use session resumption:
|
| +section, for finer control over handshaking details.
|
| +
|
| +If you are passing in a certificate chain+private key, you may additionally
|
| +provide a TACK to assist the client in authenticating your certificate chain.
|
| +This requires the TACKpy library. Load a TACKpy.TACK object, then do:
|
| +
|
| + settings = HandshakeSettings()
|
| + settings.useExperimentalTACKExtension = True # Needed for TACK support
|
| +
|
| + connection.handshakeServer(certChain=certChain, privateKey=privateKey,
|
| + tack=tack, settings=settings)
|
| +
|
| +Finally, the server can maintain a SessionCache, which will allow clients to
|
| +use session resumption:
|
|
|
| sessionCache = SessionCache()
|
| connection.handshakeServer(verifierDB=verifierDB, sessionCache=sessionCache)
|
|
|
| -It should be noted that the session cache, and the verifier and shared key
|
| -databases, are all thread-safe.
|
| +It should be noted that the session cache, and the verifier databases, are all
|
| +thread-safe.
|
|
|
| 5 Step 4 - check the results
|
| -----------------------------
|
| @@ -301,71 +277,47 @@ 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.CertChain
|
| - connection.session.serverCertChain #X509CertChain or
|
| - #cryptoIDlib.CertChain.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.
|
| -
|
| -X.509 certificate chain objects may also be validated against a list of
|
| -trusted root certificates. See the API documentation for details.
|
| -
|
| -To save yourself the trouble of inspecting fingerprints after the handshake,
|
| -you can pass a Checker object into the handshake function. The checker will be
|
| -called if the handshake completes successfully. If the other party's
|
| -certificate chain isn't approved by the checker, a subclass of
|
| -TLSAuthenticationError will be raised. For example, to perform a handshake
|
| -with a server based on its X.509 fingerprint, do:
|
| + connection.session.srpUsername # string
|
| + connection.session.clientCertChain # X509CertChain
|
| + connection.session.serverCertChain # X509CertChain
|
| + connection.session.tackExt # TACKpy.TACK_Extension
|
|
|
| - try:
|
| - checker = Checker(\
|
| - x509Fingerprint='e049ff930af76d43ff4c658b268786f4df1296f2')
|
| - connection.handshakeClientCert(checker=checker)
|
| - except TLSAuthenticationError:
|
| - print "Authentication failure"
|
| -
|
| -If the handshake fails for any reason, an exception will be raised. If the
|
| -socket timed out or was unexpectedly closed, a socket.error or
|
| -TLSAbruptCloseError will be raised. Otherwise, either a TLSLocalAlert or
|
| -TLSRemoteAlert will be raised, depending on whether the local or remote
|
| -implementation signalled the error. The exception object has a 'description'
|
| -member which identifies the error based on the codes in RFC 2246. A
|
| -TLSLocalAlert also has a 'message' string that may have more details.
|
| +X.509 chain objects return the end-entity fingerprint via getFingerprint(),
|
| +and ignore the other certificates.
|
| +
|
| +TACK objects return the (validated) TACK ID via getTACKID().
|
| +
|
| +To save yourself the trouble of inspecting certificates and/or TACKs 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 isn't approved by the checker, a subclass of TLSAuthenticationError will
|
| +be raised.
|
| +
|
| +If the handshake fails for any reason, including a Checker error, an exception
|
| +will be raised and the socket will be closed. If the socket timed out or was
|
| +unexpectedly closed, a socket.error or TLSAbruptCloseError will be raised.
|
| +
|
| +Otherwise, either a TLSLocalAlert or TLSRemoteAlert will be raised, depending
|
| +on whether the local or remote implementation signalled the error. The
|
| +exception object has a 'description' member which identifies the error based
|
| +on the codes in RFC 2246. A TLSLocalAlert also has a 'message' string that may
|
| +have more details.
|
|
|
| Example of handling a remote alert:
|
|
|
| try:
|
| [...]
|
| - except TLSRemoteAlert, alert:
|
| - if alert.description == AlertDescription.unknown_srp_username:
|
| + except TLSRemoteAlert as alert:
|
| + if alert.description == AlertDescription.unknown_psk_identity:
|
| print "Unknown user."
|
| [...]
|
|
|
| -Figuring out what went wrong based on the alert may require some
|
| -interpretation, particularly with remote alerts where you don't have an error
|
| -string, and where the remote implementation may not be signalling alerts
|
| -properly. Many alerts signal an implementation error, and so should rarely be
|
| -seen in normal operation (unexpected_message, decode_error, illegal_parameter,
|
| -internal_error, etc.).
|
| -
|
| -Others alerts are more likely to occur. Below are some common alerts and
|
| -their probable causes, and whether they are signalled by the client or server.
|
| +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:
|
| +Client handshake_failure:
|
| - SRP parameters are not recognized by client
|
| -
|
| -Client user_canceled:
|
| - - The client might have returned None from an SRP callback.
|
| + - Server's TACK was unrelated to its certificate chain
|
|
|
| Client insufficient_security:
|
| - SRP parameters are too small
|
| @@ -379,43 +331,42 @@ Server protocol_version:
|
| Server bad_record_mac:
|
| - bad SRP username or password
|
|
|
| -Server unknown_srp_username
|
| +Server unknown_psk_identity
|
| - bad SRP username (bad_record_mac could be used for the same thing)
|
|
|
| Server handshake_failure:
|
| - - bad shared key username
|
| - no matching cipher suites
|
|
|
| 5 Step 5 - exchange data
|
| -------------------------
|
| Now that you have a connection, you can call read() and write() as if it were
|
| -a socket.SSL object. You can also call send(), sendall(), recv(), and
|
| -makefile() as if it were a socket. These calls may raise TLSLocalAlert,
|
| +a socket.SSL object. You can also call send(), sendall(), recv(), and
|
| +makefile() as if it were a socket. These calls may raise TLSLocalAlert,
|
| TLSRemoteAlert, socket.error, or TLSAbruptCloseError, just like the handshake
|
| functions.
|
|
|
| Once the TLS connection is closed by the other side, calls to read() or recv()
|
| -will return an empty string. If the socket is closed by the other side
|
| -without first closing the TLS connection, calls to read() or recv() will return
|
| -a TLSAbruptCloseError, and calls to write() or send() will return a
|
| +will return an empty string. If the socket is closed by the other side without
|
| +first closing the TLS connection, calls to read() or recv() will return a
|
| +TLSAbruptCloseError, and calls to write() or send() will return a
|
| socket.error.
|
|
|
| 5 Step 6 - close the connection
|
| --------------------------------
|
| When you're finished sending data, you should call close() to close the
|
| -connection down. 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 an exception is raised, the connection will be automatically closed; you
|
| -don't need to call close(). Furthermore, you will probably not be able to re-
|
| -use the socket, the connection object, or the session object, and you
|
| +connection and socket. When the connection is closed properly, the session
|
| +object can be used for session resumption.
|
| +
|
| +If an exception is raised the connection will be automatically closed; you
|
| +don't need to call close(). Furthermore, you will probably not be able to
|
| +re-use the socket, the connection object, or the session object, and you
|
| shouldn't even try.
|
|
|
| -By default, calling close() will 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.
|
| +By default, calling close() will close the underlying socket. If you set the
|
| +connection's closeSocket flag to False, the socket will remain open after
|
| +close. (NOTE: some TLS implementations will not respond properly to the
|
| +close_notify alert that close() generates, so the connection will hang if
|
| +closeSocket is set to True.)
|
|
|
|
|
| 6 Using TLS Lite with httplib
|
| @@ -430,20 +381,9 @@ different types of authentication.
|
| r = h.getresponse()
|
| [...]
|
|
|
| - #Authenticate server based on its X.509 fingerprint
|
| - h = HTTPTLSConnection("www.amazon.com", 443,
|
| - x509Fingerprint="e049ff930af76d43ff4c658b268786f4df1296f2")
|
| - [...]
|
| -
|
| - #Authenticate server based on its X.509 chain (requires cryptlib_py [7])
|
| - h = HTTPTLSConnection("www.amazon.com", 443,
|
| - x509TrustList=[verisignCert],
|
| - x509CommonName="www.amazon.com")
|
| - [...]
|
| -
|
| - #Authenticate server based on its cryptoID
|
| - h = HTTPTLSConnection("localhost", 443,
|
| - cryptoID="dmqb6.fq345.cxk6g.5fha3")
|
| + #Authenticate server based on its TACK ID
|
| + h = HTTPTLSConnection("localhost", 4443,
|
| + tackID="B3ARS.EQ61B.F34EL.9KKLN.3WEW5", hardTack=False)
|
| [...]
|
|
|
| #Mutually authenticate with SRP
|
| @@ -451,42 +391,8 @@ different types of authentication.
|
| username="alice", password="abra123cadabra")
|
| [...]
|
|
|
| - #Mutually authenticate with a shared key
|
| - h = HTTPTLSConnection("localhost", 443,
|
| - username="alice", sharedKey="PaVBVZkYqAjCQCu6UBL2xgsnZhw")
|
| - [...]
|
| -
|
| - #Mutually authenticate with SRP, *AND* authenticate the server based
|
| - #on its cryptoID
|
| - h = HTTPTLSConnection("localhost", 443,
|
| - username="alice", password="abra123cadabra",
|
| - cryptoID="dmqb6.fq345.cxk6g.5fha3")
|
| - [...]
|
| -
|
| -
|
| -7 Using TLS Lite with xmlrpclib
|
| -================================
|
| -TLS Lite comes with an XMLRPCTransport class that extends xmlrpclib to work
|
| -over SSL/TLS connections. This class accepts the same parameters as
|
| -HTTPTLSConnection (see previous section), and behaves similarly. Depending on
|
| -how you construct it, it will do different types of authentication.
|
| -
|
| - from tlslite.api import XMLRPCTransport
|
| - from xmlrpclib import ServerProxy
|
| -
|
| - #No authentication whatsoever
|
| - transport = XMLRPCTransport()
|
| - server = ServerProxy("https://localhost", transport)
|
| - server.someFunc(2, 3)
|
| - [...]
|
| -
|
| - #Authenticate server based on its X.509 fingerprint
|
| - transport = XMLRPCTransport(\
|
| - x509Fingerprint="e049ff930af76d43ff4c658b268786f4df1296f2")
|
| - [...]
|
| -
|
|
|
| -8 Using TLS Lite with poplib or imaplib
|
| +7 Using TLS Lite with poplib or imaplib
|
| ========================================
|
| TLS Lite comes with POP3_TLS and IMAP4_TLS classes that extend poplib and
|
| imaplib to work over SSL/TLS connections. These classes can be constructed
|
| @@ -495,7 +401,7 @@ behave similarly.
|
|
|
| #To connect to a POP3 server over SSL and display its fingerprint:
|
| from tlslite.api import *
|
| - p = POP3_TLS("---------.net")
|
| + p = POP3_TLS("---------.net", port=995)
|
| print p.sock.session.serverCertChain.getFingerprint()
|
| [...]
|
|
|
| @@ -506,7 +412,7 @@ behave similarly.
|
| [...]
|
|
|
|
|
| -9 Using TLS Lite with smtplib
|
| +8 Using TLS Lite with smtplib
|
| ==============================
|
| TLS Lite comes with an SMTP_TLS class that extends smtplib to work
|
| over SSL/TLS connections. This class accepts the same parameters as
|
| @@ -515,12 +421,13 @@ on how you call starttls(), it will do different types of authentication.
|
|
|
| #To connect to an SMTP server once you know its fingerprint:
|
| from tlslite.api import *
|
| - s = SMTP_TLS("----------.net")
|
| + s = SMTP_TLS("----------.net", port=587)
|
| + s.ehlo()
|
| s.starttls(x509Fingerprint="7e39be84a2e3a7ad071752e3001d931bf82c32dc")
|
| [...]
|
|
|
|
|
| -10 Using TLS Lite with SocketServer
|
| +9 Using TLS Lite with SocketServer
|
| ====================================
|
| You can use TLS Lite to implement servers using Python's SocketServer
|
| framework. TLS Lite comes with a TLSSocketServerMixIn class. You can combine
|
| @@ -528,141 +435,112 @@ 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.api 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, TLSSocketServerMixIn, HTTPServer):
|
| - def handshake(self, tlsConnection):
|
| - try:
|
| - tlsConnection.handshakeServer(certChain=certChain,
|
| - privateKey=privateKey,
|
| - sessionCache=sessionCache)
|
| - tlsConnection.ignoreAbruptClose = True
|
| - return True
|
| - except TLSError, error:
|
| - print "Handshake failure:", str(error)
|
| - return False
|
| +triggered. See the tests/httpsserver.py example.
|
|
|
| - httpd = MyHTTPServer(('localhost', 443), SimpleHTTPRequestHandler)
|
| - httpd.serve_forever()
|
|
|
| -
|
| -11 Using TLS Lite with asyncore
|
| +10 Using TLS Lite with asyncore
|
| ================================
|
| TLS Lite can be used with subclasses of asyncore.dispatcher. See the comments
|
| in TLSAsyncDispatcherMixIn.py for details. This is still experimental, and
|
| may not work with all asyncore.dispatcher subclasses.
|
|
|
| -Below is an example of combining Medusa's http_channel with
|
| -TLSAsyncDispatcherMixIn:
|
| -
|
| - class http_tls_channel(TLSAsyncDispatcherMixIn,
|
| - http_server.http_channel):
|
| - ac_in_buffer_size = 16384
|
| -
|
| - def __init__ (self, server, conn, addr):
|
| - http_server.http_channel.__init__(self, server, conn, addr)
|
| - TLSAsyncDispatcherMixIn.__init__(self, conn)
|
| - self.tlsConnection.ignoreAbruptClose = True
|
| - self.setServerHandshakeOp(certChain=certChain,
|
| - privateKey=privateKey)
|
| -
|
| -
|
| -12 Using TLS Lite with Twisted
|
| -===============================
|
| -TLS Lite can be used with Twisted protocols. Below is a complete example of
|
| -using TLS Lite with a Twisted echo server.
|
| -
|
| -There are two server implementations below. Echo is the original protocol,
|
| -which is oblivious to TLS. Echo1 subclasses Echo and negotiates TLS when the
|
| -client connects. Echo2 subclasses Echo and negotiates TLS when the client
|
| -sends "STARTTLS".
|
| -
|
| - from twisted.internet.protocol import Protocol, Factory
|
| - from twisted.internet import reactor
|
| - from twisted.protocols.policies import WrappingFactory
|
| - from twisted.protocols.basic import LineReceiver
|
| - from twisted.python import log
|
| - from twisted.python.failure import Failure
|
| - import sys
|
| - from tlslite.api import *
|
| -
|
| - s = open("./serverX509Cert.pem").read()
|
| - x509 = X509()
|
| - x509.parse(s)
|
| - certChain = X509CertChain([x509])
|
| -
|
| - s = open("./serverX509Key.pem").read()
|
| - privateKey = parsePEMKey(s, private=True)
|
| -
|
| - verifierDB = VerifierDB("verifierDB")
|
| - verifierDB.open()
|
| -
|
| - class Echo(LineReceiver):
|
| - def connectionMade(self):
|
| - self.transport.write("Welcome to the echo server!\r\n")
|
| -
|
| - def lineReceived(self, line):
|
| - self.transport.write(line + "\r\n")
|
| -
|
| - class Echo1(Echo):
|
| - def connectionMade(self):
|
| - if not self.transport.tlsStarted:
|
| - self.transport.setServerHandshakeOp(certChain=certChain,
|
| - privateKey=privateKey,
|
| - verifierDB=verifierDB)
|
| - else:
|
| - Echo.connectionMade(self)
|
| -
|
| - def connectionLost(self, reason):
|
| - pass #Handle any TLS exceptions here
|
| -
|
| - class Echo2(Echo):
|
| - def lineReceived(self, data):
|
| - if data == "STARTTLS":
|
| - self.transport.setServerHandshakeOp(certChain=certChain,
|
| - privateKey=privateKey,
|
| - verifierDB=verifierDB)
|
| - else:
|
| - Echo.lineReceived(self, data)
|
| -
|
| - def connectionLost(self, reason):
|
| - pass #Handle any TLS exceptions here
|
| -
|
| - factory = Factory()
|
| - factory.protocol = Echo1
|
| - #factory.protocol = Echo2
|
| -
|
| - wrappingFactory = WrappingFactory(factory)
|
| - wrappingFactory.protocol = TLSTwistedProtocolWrapper
|
|
|
| - log.startLogging(sys.stdout)
|
| - reactor.listenTCP(1079, wrappingFactory)
|
| - reactor.run()
|
| -
|
| -
|
| -13 Security Considerations
|
| +11 Security Considerations
|
| ===========================
|
| -TLS Lite is beta-quality code. It hasn't received much security analysis.
|
| -Use at your own risk.
|
| +TLS Lite is beta-quality code. It hasn't received much security analysis. Use
|
| +at your own risk.
|
|
|
| +TLS Lite is probably vulnerable to the "Lucky 13" timing attack if AES or 3DES
|
| +are used. Thus, TLS Lite prefers the RC4 cipher.
|
|
|
| -14 History
|
| +
|
| +12 History
|
| ===========
|
| +0.4.6 - 3/20/2013
|
| + - **API CHANGE**: TLSClosedConnectionError instead of ValueError when writing
|
| + to a closed connection. This inherits from socket.error, so should
|
| + interact better with SocketServer (see http://bugs.python.org/issue14574)
|
| + and other things expecting a socket.error in this situation.
|
| + - Added support for RC4-MD5 ciphersuite (if enabled in settings)
|
| + - This is allegedly necessary to connect to some Internet servers.
|
| + - Added TLSConnection.unread() function
|
| + - Switched to New-style classes (inherit from 'object')
|
| + - Minor cleanups
|
| +
|
| +0.4.5 - (release engineering problem, skipped!)
|
| +
|
| +0.4.4 - 2/25/2013
|
| + - Added Python 3 support (Martin von Loewis)
|
| + - Added NPN client support (Marcelo Fernandez)
|
| + - Switched to RC4 as preferred cipher
|
| + - faster in Python, avoids "Lucky 13" timing attacks
|
| + - Fixed bug when specifying ciphers for anon ciphersuites
|
| + - Made RSA hashAndVerify() tolerant of sigs w/o encoded NULL AlgorithmParam
|
| + - (this function is not used for TLS currently, and this tolerance may
|
| + not even be necessary)
|
| +0.4.3 - 9/27/2012
|
| + - Minor bugfix (0.4.2 doesn't load tackpy)
|
| +0.4.2 - 9/25/2012
|
| + - Updated TACK (compatible with tackpy 0.9.9)
|
| +0.4.1 - 5/22/2012
|
| + - Fixed RSA padding bugs (w/help from John Randolph)
|
| + - Updated TACK (compatible with tackpy 0.9.7)
|
| + - Added SNI
|
| + - Added NPN server support (Sam Rushing/Google)
|
| + - Added AnonDH (Dimitris Moraitis)
|
| + - Added X509CertChain.parsePemList
|
| + - Improved XML-RPC (Kees Bos)
|
| +
|
| +0.4.0 - 2/11/2012
|
| + - Fixed pycrypto support
|
| + - Fixed python 2.6 problems
|
| +
|
| +0.3.9.x - 2/7/2012
|
| +
|
| +Much code cleanup, in particular decomposing the handshake functions so they
|
| +are readable. The main new feature is support for TACK, an experimental
|
| +authentication method that provides a new way to pin server certificates (See
|
| +https://github.com/moxie0/Convergence/wiki/TACK ).
|
| +
|
| +Also:
|
| +
|
| + - Security Fixes
|
| + - Sends SCSV ciphersuite as per RFC 5746, to signal non-renegotiated
|
| + Client Hello. Does not support renegotiation (never has).
|
| + - Change from e=3 to e=65537 for generated RSA keys, not strictly
|
| + necessary but mitigates risk of sloppy verifier.
|
| + - 1/(n-1) countermeasure for BEAST.
|
| +
|
| + - Behavior changes:
|
| + - Split cmdline into tls.py and tlstest.py, improved options.
|
| + - Formalized LICENSE.
|
| + - Defaults to closing socket after sending close_notify, fixes hanging.
|
| + problem that would occur sometime when waiting for other party's
|
| + close_notify.
|
| + - Update SRP to RFC 5054 compliance.
|
| + - Removed client handshake "callbacks", no longer support the SRP
|
| + re-handshake idiom within a single handshake function.
|
| +
|
| + - Bugfixes
|
| + - Added hashlib support, removes Deprecation Warning due to sha and md5.
|
| + - Handled GeneratorExit exceptions that are a new Python feature, and
|
| + interfere with the async code if not handled.
|
| +
|
| + - Removed:
|
| + - Shared keys (it was based on an ancient I-D, not TLS-PSK).
|
| + - cryptlib support, it wasn't used much, we have enough other options.
|
| + - cryptoIDs (TACK is better).
|
| + - win32prng extension module, as os.urandom is now available.
|
| + - Twisted integration (unused?, slowed down loading).
|
| + - Jython code (ancient, didn't work).
|
| + - Compat support for python versions < 2.7.
|
| +
|
| + - Additions
|
| + - Support for TACK via TACKpy.
|
| + - Support for CertificateRequest.certificate_authorities ("reqCAs")
|
| + - Added TLSConnection.shutdown() to better mimic socket.
|
| + - Enabled Session resumption for XMLRPCTransport.
|
| +
|
| 0.3.8 - 2/21/2005
|
| - Added support for poplib, imaplib, and smtplib
|
| - Added python 2.4 windows installer
|
| @@ -773,43 +651,3 @@ Use at your own risk.
|
| - added testing functions to tls.py
|
| 0.1.0 - 2/01/2004
|
| - first release
|
| -
|
| -
|
| -15 References
|
| -==============
|
| -[0] http://www.ietf.org/html.charters/tls-charter.html
|
| -[1] http://www.trevp.net/tls_srp/draft-ietf-tls-srp-07.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/
|
| -[9] http://www.amk.ca/python/code/crypto.html
|
| -[10] http://gmpy.sourceforge.net/
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
| -
|
|
|