TLS implementation in pure python, focused on interoperability testing
271
stars
1,746
commits
Python
primary language
Sep 11, 2026
updated
tlslite-ng version 0.9.0b2 (2025-09-26)
tlslite-ng is an open source python library that implements SSL and TLS cryptographic protocols. It can be used either as a standalone wrapper around python socket interface or as a backend for multiple other libraries. tlslite-ng is pure python, however it can use other libraries for faster crypto operations. tlslite-ng integrates with several stdlib networking libraries.
API documentation is available in the docs/_build/html directory of the PyPI
package
or can be automatically generated using make docs with Sphinx installed.
If you have questions or feedback, feel free to contact me (Alicja Kario <hkario at redhat.com>). Issues and pull requests can also be submitted through github issue tracking system, at the project's main page at GitHub, see CONTRIBUTING.md file for more information.
tlslite-ng aims to be a drop in replacement for the original TLS Lite.
Security policy of the project is available in the SECURITY.md file.
Implemented TLS features include:
tlslite-ng is a fork of TLS Lite, it is currently maintained and developed by Alicja Kario. TLS Lite was written (mostly) by Trevor Perrin. It includes code from Bram Cohen, Google, Kees Bos, Sam Rushing, Dimitris Moraitis, Marcelo Fernandez, Martin von Loewis, Dave Baggett, Yngve N. Pettersen (ported by Paul Sokolovsky), Mirko Dziadzka, David Benjamin, Sidney Markowitz, and Alicja Kario.
Original 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.
Currently it is distributed under Gnu LGPLv2 license.
Requirements:
Options:
m2crypto interface to OpenSSL, this will be used for fast
RSA operations and fast ciphers.pycrypto this will be used for fast RSA operations and fast
ciphers.gmpy interface to libgmp, this will be used for fast RSA,
FFDH and SRP operations.Run:
pip install tlslite-ng
In case your system doesn't have pip, you can install it by first downloading get-pip.py and running
python get-pip.py
Run 'python setup.py install'
Test the Installation
From the distribution's directory, run:
make test
If it says "Test succeeded" at the end, you're ready to go.
tlslite-ng 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 SRP verifier databases. These databases are used by
a TLS server when authenticating clients with SRP.
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
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
To run an SRP server, try something like:
tlsdb.py createsrp verifierDB
tlsdb.py add verifierDB alice abra123cadabra 1024
tlsdb.py add verifierDB bob swordfish 2048
tls.py server -v verifierDB localhost:4443
Then try connecting to the server with:
tls.py client -u alice -p abra123cadabra localhost:4443
To run an HTTPS server with less typing, run ./tests/httpsserver.sh.
To run an HTTPS client, run ./tests/httpsclient.py.
Whether you're writing a client or server, there are six steps:
tlslite-ng also integrates with several stdlib python libraries. See the sections following this one for details.
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) )
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)
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")
The ClientCert function without arguments is used when connecting to a site 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 certificate chain and corresponding private key. To use X.509 chains, you'll need some way of creating these, such as OpenSSL (see 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)
certChain = X509CertChain([x509])
s = open("./test/clientX509Key.pem").read()
privateKey = parsePEMKey(s, private=True)
The SRP function does mutual authentication with a username and password - 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 (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)
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")
.
.
oldSession = connection.session
connection2.handshakeClientSRP("alice", "abra123cadabra", session=
oldSession)
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.
verifierDB = VerifierDB("./test/verifierDB")
verifierDB.open()
connection.handshakeServer(verifierDB=verifierDB)
To perform authentication with a certificate and private key, the server must load these as described in the previous section, then pass them in. If the server sets the reqCert boolean to True, a certificate chain will be requested from the client.
connection.handshakeServer(certChain=certChain, privateKey=privateKey,
reqCert=True)
You can pass in a verifier database and/or a certificate chain+private key. The client will use one or both to authenticate the server.
You can also pass in a HandshakeSettings object, as described in the last section, for finer control over handshaking details.
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 databases, are all thread-safe.
If the handshake completes without raising an exception, authentication results will be stored in the connection's session object. The following variables will be populated if applicable, or else set to None:
connection.session.srpUsername # string
connection.session.clientCertChain # X509CertChain
connection.session.serverCertChain # X509CertChain
connection.session.tackExt # TACKpy.TACK_Extension
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 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 as alert:
if alert.description == AlertDescription.unknown_psk_identity:
print "Unknown user."
[...]
Below are some common alerts and their probable causes, and whether they are signalled by the client or server.
Client handshake_failure:
Client insufficient_security:
Client protocol_version:
Server protocol_version:
Server bad_record_mac:
Server unknown_psk_identity:
bad_record_mac could be used for the same thing)Server handshake_failure:
Now that you have a connection, you can call read() and write() as if it were a socket.SSL object. You can also call send(), sendall(), recv(), and makefile() as if it were a socket. These calls may raise TLSLocalAlert, TLSRemoteAlert, socket.error, or TLSAbruptCloseError, just like the handshake functions.
Once the TLS connection is closed by the other side, calls to read() or recv() will return an empty string. If the socket is closed by the other side without first closing the TLS connection, calls to read() or recv() will return a TLSAbruptCloseError, and calls to write() or send() will return a socket.error.
When you're finished sending data, you should call close() to close the connection and socket. When the connection is closed properly, the session object can be used for session resumption.
If an exception is raised the connection will be automatically closed; you don't need to call close(). Furthermore, you will probably not be able to re-use the socket, the connection object, or the session object, and you shouldn't even try.
By default, calling close() will close the underlying socket. If you set the
connection's closeSocket flag to False, the socket will remain open after
close. (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.)
tlslite-ng comes with an HTTPTLSConnection class that extends httplib to work over SSL/TLS connections. Depending on how you construct it, it will do different types of authentication.
#No authentication whatsoever
h = HTTPTLSConnection("www.amazon.com", 443)
h.request("GET", "")
r = h.getresponse()
[...]
#Authenticate server based on its TACK ID
h = HTTPTLSConnection("localhost", 4443,
tackID="B3ARS.EQ61B.F34EL.9KKLN.3WEW5", hardTack=False)
[...]
#Mutually authenticate with SRP
h = HTTPTLSConnection("localhost", 443,
username="alice", password="abra123cadabra")
[...]
tlslite-ng comes with POP3_TLS and IMAP4_TLS classes that extend poplib and
imaplib to work over SSL/TLS connections. These classes can be constructed
with the same parameters as HTTPTLSConnection (see previous section), and
behave similarly.
#To connect to a POP3 server over SSL and display its fingerprint:
from tlslite.api import *
p = POP3_TLS("---------.net", port=995)
print p.sock.session.serverCertChain.getFingerprint()
[...]
#To connect to an IMAP server once you know its fingerprint:
from tlslite.api import *
i = IMAP4_TLS("cyrus.andrew.cmu.edu",
x509Fingerprint="00c14371227b3b677ddb9c4901e6f2aee18d3e45")
[...]
tlslite-ng comes with an SMTP_TLS class that extends smtplib to work
over SSL/TLS connections. This class accepts the same parameters as
HTTPTLSConnection (see previous section), and behaves similarly. Depending
on how you call starttls(), it will do different types of authentication.
#To connect to an SMTP server once you know its fingerprint:
from tlslite.api import *
s = SMTP_TLS("----------.net", port=587)
s.ehlo()
s.starttls(x509Fingerprint="7e39be84a2e3a7ad071752e3001d931bf82c32dc")
[...]
You can use tlslite-ng to implement servers using Python's SocketServer framework. tlslite-ng comes with a TLSSocketServerMixIn class. You can combine this with a TCPServer such as HTTPServer. To combine them, define a new class that inherits from both of them (with the mix-in first). Then implement the handshake() method, doing some sort of server handshake on the connection argument. If the handshake method returns True, the RequestHandler will be triggered. See the tests/httpsserver.py example.
tlslite-ng 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.
as said above, asyncore is deprecated in Python 3.12, and asyncio should be used. Implementation is similar to TLSAsyncDispatcherMixIn.py, but instead, use the class TLSAsyncioDispatcherMixIn.py.
credential toolThe credential tool is a command-line utility used to generate a Delegated Credential for a TLS 1.3 server.
To generate the Delegated Credential:
tls.py credential [-c CERT] [-k KEY] [--dc-pub KEY] [--dc-sig-scheme SIG] [--dc-file DCFILE]
To generate the DC the following MUST be provided: the certificate, the certificate's private key, the public key of the Delegated Credential and the output file. Providing signature scheme is optional.
The content is saved into the output file in .pem format.
The following command provides an illustrative example using RSA keys for both the main server certificate and the delegated credential's public key to create Delegated Credential. Go to the tests directory and run:
tls.py credential -k serverX509Key.pem -c serverX509Cert.pem --dc-pub serverDelCredRSAPSSPub.pem --dc-file serverRSAPSSDC.pem
After that the server can be run without the certificate's private key, but with the Delegated Credential:
tls.py server -c serverX509Cert.pem --dc-key serverDelCredRSAPSSKey.pem --dc-file serverRSAPSSDC.pem localhost:4433
The client must indicate the support of Delegated Credential by provideng the signature algorithm it supports in the Delegated Credential's extesion in Client Hello.
In case creating the file with saved Delegated Credential is not an option, the server can create the Delegated Credential on the fly before the handshake. To do so, run:
tls.py server -k serverX509Key.pem -c serverX509Cert.pem --dc-key serverDelCredRSAPSSKey.pem --dc-pub serverDelCredRSAPSSPub.pem localhost:4433
According to RFC 5280, Section 4.2.1.3 and specifically RFC 9260 (Delegated Credentials), Section 4, the X.509 certificate used by the server to sign a delegated credential MUST contain the digitalSignature Key Usage extension. The credential tool and the delegated credential generation feature within the server tool are designed primarily for testing and development purposes. Hence, these tools do not perform strict validation to ensure that the provided main server certificate actually possesses the digitalSignature Key Usage extension.
Similarly, while delegated credentials have a valid time option, it is not enforced. The current certificate implementation lacks time validation, a requirement that is also omitted for delegated credentials.
0.9.0b2 - 2025-09-26
0.8.2 - 2025-01-22
0.8.1 - 2025-01-02
ec_point_formats extension only when negotiating TLS 1.2
or earlier (Ganna Starovoytova)0.8.0 - 2024-12-17
-Wd to see where the depracated calls
are being made, the python standard DeprecationWarning will be emited there)async is now a keyword) (Pierre Ståhl)__eq__ supported on all Handshake messagestls.py) (Róbert Kolcún)tls.py scriptrsa_pss_pss_* signature methodstls.py (Ivan Nikolchev)scripts/speed.py)session_id field in ClientHellotls.py server0.7.0 - 2017-07-31
0.6.0 - 2016-09-07
0.5.1 - 2015-11-05
0.5.0 - 10/10/2015
FALLBACK_SCSV (David Benjamin - Chromium)0.4.8 - 11/12/2014
0.4.7 - 11/12/2014
PyCrypto_RSA integration0.4.5 - 3/20/2013
0.4.4 - 2/25/2013
0.4.3 - 9/27/2012
0.4.2 - 9/25/2012
0.4.1 - 5/22/2012
0.4.0 - 2/11/2012
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 moxie0/Convergance ).
Also:
Security Fixes
Behavior changes:
close_notify, fixes hanging.
problem that would occur sometime when waiting for other party's
close_notify.Bugfixes
Removed:
Additions
CertificateRequest.certificate_authorities ("reqCAs")0.3.8 - 2/21/2005
0.3.7 - 10/05/2004
0.3.6 - 9/28/2004
0.3.5 - 9/16/2004
0.3.4 - 9/12/2004
_versioncheck on SRP 1st hello, causing problems
with GnuTLS (which was offering TLS 1.1)_versioncheck checking, since it could cause interop problemscryptlib_py and and cryptoIDlib present, cryptlib
was complaining about being initialized twice0.3.3 - 6/10/2004
0.3.2 - 5/21/2004
0.3.1 - 4/21/2004
0.3.0 - 3/20/2004
0.2.7 - 3/12/2004
0.2.6 - 3/11/2004
0.2.5 - 3/10/2004
0.2.4 - 3/5/2004
0.2.3 - 3/4/2004
0.2.2 - 3/1/2004
0.2.1 - 2/23/2004
0.2.0 - 2/19/2004
tls_lite -> tlslite0.1.9 - 2/16/2004
close_notify,
just ignore it.0.1.8 - 2/12/2004
0.1.7 - 2/11/2004
close_notify0.1.6 - 2/10/2004
0.1.5 - 2/09/2004
0.1.4 - 2/06/2004
0.1.3 - 2/05/2004
missing_srp_username0.1.2 - 2/04/2004
0.1.1 - 2/02/2004
close_notify behavior0.1.0 - 2/01/2004
Python
99.8%
TLS implementation in pure python, focused on interoperability testing
271
stars
1,746
commits
Python
primary language
Sep 11, 2026
updated
tlslite-ng version 0.9.0b2 (2025-09-26)
tlslite-ng is an open source python library that implements SSL and TLS cryptographic protocols. It can be used either as a standalone wrapper around python socket interface or as a backend for multiple other libraries. tlslite-ng is pure python, however it can use other libraries for faster crypto operations. tlslite-ng integrates with several stdlib networking libraries.
API documentation is available in the docs/_build/html directory of the PyPI
package
or can be automatically generated using make docs with Sphinx installed.
If you have questions or feedback, feel free to contact me (Alicja Kario <hkario at redhat.com>). Issues and pull requests can also be submitted through github issue tracking system, at the project's main page at GitHub, see CONTRIBUTING.md file for more information.
tlslite-ng aims to be a drop in replacement for the original TLS Lite.
Security policy of the project is available in the SECURITY.md file.
Implemented TLS features include:
tlslite-ng is a fork of TLS Lite, it is currently maintained and developed by Alicja Kario. TLS Lite was written (mostly) by Trevor Perrin. It includes code from Bram Cohen, Google, Kees Bos, Sam Rushing, Dimitris Moraitis, Marcelo Fernandez, Martin von Loewis, Dave Baggett, Yngve N. Pettersen (ported by Paul Sokolovsky), Mirko Dziadzka, David Benjamin, Sidney Markowitz, and Alicja Kario.
Original 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.
Currently it is distributed under Gnu LGPLv2 license.
Requirements:
Options:
m2crypto interface to OpenSSL, this will be used for fast
RSA operations and fast ciphers.pycrypto this will be used for fast RSA operations and fast
ciphers.gmpy interface to libgmp, this will be used for fast RSA,
FFDH and SRP operations.Run:
pip install tlslite-ng
In case your system doesn't have pip, you can install it by first downloading get-pip.py and running
python get-pip.py
Run 'python setup.py install'
Test the Installation
From the distribution's directory, run:
make test
If it says "Test succeeded" at the end, you're ready to go.
tlslite-ng 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 SRP verifier databases. These databases are used by
a TLS server when authenticating clients with SRP.
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
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
To run an SRP server, try something like:
tlsdb.py createsrp verifierDB
tlsdb.py add verifierDB alice abra123cadabra 1024
tlsdb.py add verifierDB bob swordfish 2048
tls.py server -v verifierDB localhost:4443
Then try connecting to the server with:
tls.py client -u alice -p abra123cadabra localhost:4443
To run an HTTPS server with less typing, run ./tests/httpsserver.sh.
To run an HTTPS client, run ./tests/httpsclient.py.
Whether you're writing a client or server, there are six steps:
tlslite-ng also integrates with several stdlib python libraries. See the sections following this one for details.
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) )
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)
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")
The ClientCert function without arguments is used when connecting to a site 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 certificate chain and corresponding private key. To use X.509 chains, you'll need some way of creating these, such as OpenSSL (see 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)
certChain = X509CertChain([x509])
s = open("./test/clientX509Key.pem").read()
privateKey = parsePEMKey(s, private=True)
The SRP function does mutual authentication with a username and password - 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 (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)
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")
.
.
oldSession = connection.session
connection2.handshakeClientSRP("alice", "abra123cadabra", session=
oldSession)
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.
verifierDB = VerifierDB("./test/verifierDB")
verifierDB.open()
connection.handshakeServer(verifierDB=verifierDB)
To perform authentication with a certificate and private key, the server must load these as described in the previous section, then pass them in. If the server sets the reqCert boolean to True, a certificate chain will be requested from the client.
connection.handshakeServer(certChain=certChain, privateKey=privateKey,
reqCert=True)
You can pass in a verifier database and/or a certificate chain+private key. The client will use one or both to authenticate the server.
You can also pass in a HandshakeSettings object, as described in the last section, for finer control over handshaking details.
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 databases, are all thread-safe.
If the handshake completes without raising an exception, authentication results will be stored in the connection's session object. The following variables will be populated if applicable, or else set to None:
connection.session.srpUsername # string
connection.session.clientCertChain # X509CertChain
connection.session.serverCertChain # X509CertChain
connection.session.tackExt # TACKpy.TACK_Extension
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 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 as alert:
if alert.description == AlertDescription.unknown_psk_identity:
print "Unknown user."
[...]
Below are some common alerts and their probable causes, and whether they are signalled by the client or server.
Client handshake_failure:
Client insufficient_security:
Client protocol_version:
Server protocol_version:
Server bad_record_mac:
Server unknown_psk_identity:
bad_record_mac could be used for the same thing)Server handshake_failure:
Now that you have a connection, you can call read() and write() as if it were a socket.SSL object. You can also call send(), sendall(), recv(), and makefile() as if it were a socket. These calls may raise TLSLocalAlert, TLSRemoteAlert, socket.error, or TLSAbruptCloseError, just like the handshake functions.
Once the TLS connection is closed by the other side, calls to read() or recv() will return an empty string. If the socket is closed by the other side without first closing the TLS connection, calls to read() or recv() will return a TLSAbruptCloseError, and calls to write() or send() will return a socket.error.
When you're finished sending data, you should call close() to close the connection and socket. When the connection is closed properly, the session object can be used for session resumption.
If an exception is raised the connection will be automatically closed; you don't need to call close(). Furthermore, you will probably not be able to re-use the socket, the connection object, or the session object, and you shouldn't even try.
By default, calling close() will close the underlying socket. If you set the
connection's closeSocket flag to False, the socket will remain open after
close. (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.)
tlslite-ng comes with an HTTPTLSConnection class that extends httplib to work over SSL/TLS connections. Depending on how you construct it, it will do different types of authentication.
#No authentication whatsoever
h = HTTPTLSConnection("www.amazon.com", 443)
h.request("GET", "")
r = h.getresponse()
[...]
#Authenticate server based on its TACK ID
h = HTTPTLSConnection("localhost", 4443,
tackID="B3ARS.EQ61B.F34EL.9KKLN.3WEW5", hardTack=False)
[...]
#Mutually authenticate with SRP
h = HTTPTLSConnection("localhost", 443,
username="alice", password="abra123cadabra")
[...]
tlslite-ng comes with POP3_TLS and IMAP4_TLS classes that extend poplib and
imaplib to work over SSL/TLS connections. These classes can be constructed
with the same parameters as HTTPTLSConnection (see previous section), and
behave similarly.
#To connect to a POP3 server over SSL and display its fingerprint:
from tlslite.api import *
p = POP3_TLS("---------.net", port=995)
print p.sock.session.serverCertChain.getFingerprint()
[...]
#To connect to an IMAP server once you know its fingerprint:
from tlslite.api import *
i = IMAP4_TLS("cyrus.andrew.cmu.edu",
x509Fingerprint="00c14371227b3b677ddb9c4901e6f2aee18d3e45")
[...]
tlslite-ng comes with an SMTP_TLS class that extends smtplib to work
over SSL/TLS connections. This class accepts the same parameters as
HTTPTLSConnection (see previous section), and behaves similarly. Depending
on how you call starttls(), it will do different types of authentication.
#To connect to an SMTP server once you know its fingerprint:
from tlslite.api import *
s = SMTP_TLS("----------.net", port=587)
s.ehlo()
s.starttls(x509Fingerprint="7e39be84a2e3a7ad071752e3001d931bf82c32dc")
[...]
You can use tlslite-ng to implement servers using Python's SocketServer framework. tlslite-ng comes with a TLSSocketServerMixIn class. You can combine this with a TCPServer such as HTTPServer. To combine them, define a new class that inherits from both of them (with the mix-in first). Then implement the handshake() method, doing some sort of server handshake on the connection argument. If the handshake method returns True, the RequestHandler will be triggered. See the tests/httpsserver.py example.
tlslite-ng 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.
as said above, asyncore is deprecated in Python 3.12, and asyncio should be used. Implementation is similar to TLSAsyncDispatcherMixIn.py, but instead, use the class TLSAsyncioDispatcherMixIn.py.
credential toolThe credential tool is a command-line utility used to generate a Delegated Credential for a TLS 1.3 server.
To generate the Delegated Credential:
tls.py credential [-c CERT] [-k KEY] [--dc-pub KEY] [--dc-sig-scheme SIG] [--dc-file DCFILE]
To generate the DC the following MUST be provided: the certificate, the certificate's private key, the public key of the Delegated Credential and the output file. Providing signature scheme is optional.
The content is saved into the output file in .pem format.
The following command provides an illustrative example using RSA keys for both the main server certificate and the delegated credential's public key to create Delegated Credential. Go to the tests directory and run:
tls.py credential -k serverX509Key.pem -c serverX509Cert.pem --dc-pub serverDelCredRSAPSSPub.pem --dc-file serverRSAPSSDC.pem
After that the server can be run without the certificate's private key, but with the Delegated Credential:
tls.py server -c serverX509Cert.pem --dc-key serverDelCredRSAPSSKey.pem --dc-file serverRSAPSSDC.pem localhost:4433
The client must indicate the support of Delegated Credential by provideng the signature algorithm it supports in the Delegated Credential's extesion in Client Hello.
In case creating the file with saved Delegated Credential is not an option, the server can create the Delegated Credential on the fly before the handshake. To do so, run:
tls.py server -k serverX509Key.pem -c serverX509Cert.pem --dc-key serverDelCredRSAPSSKey.pem --dc-pub serverDelCredRSAPSSPub.pem localhost:4433
According to RFC 5280, Section 4.2.1.3 and specifically RFC 9260 (Delegated Credentials), Section 4, the X.509 certificate used by the server to sign a delegated credential MUST contain the digitalSignature Key Usage extension. The credential tool and the delegated credential generation feature within the server tool are designed primarily for testing and development purposes. Hence, these tools do not perform strict validation to ensure that the provided main server certificate actually possesses the digitalSignature Key Usage extension.
Similarly, while delegated credentials have a valid time option, it is not enforced. The current certificate implementation lacks time validation, a requirement that is also omitted for delegated credentials.
0.9.0b2 - 2025-09-26
0.8.2 - 2025-01-22
0.8.1 - 2025-01-02
ec_point_formats extension only when negotiating TLS 1.2
or earlier (Ganna Starovoytova)0.8.0 - 2024-12-17
-Wd to see where the depracated calls
are being made, the python standard DeprecationWarning will be emited there)async is now a keyword) (Pierre Ståhl)__eq__ supported on all Handshake messagestls.py) (Róbert Kolcún)tls.py scriptrsa_pss_pss_* signature methodstls.py (Ivan Nikolchev)scripts/speed.py)session_id field in ClientHellotls.py server0.7.0 - 2017-07-31
0.6.0 - 2016-09-07
0.5.1 - 2015-11-05
0.5.0 - 10/10/2015
FALLBACK_SCSV (David Benjamin - Chromium)0.4.8 - 11/12/2014
0.4.7 - 11/12/2014
PyCrypto_RSA integration0.4.5 - 3/20/2013
0.4.4 - 2/25/2013
0.4.3 - 9/27/2012
0.4.2 - 9/25/2012
0.4.1 - 5/22/2012
0.4.0 - 2/11/2012
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 moxie0/Convergance ).
Also:
Security Fixes
Behavior changes:
close_notify, fixes hanging.
problem that would occur sometime when waiting for other party's
close_notify.Bugfixes
Removed:
Additions
CertificateRequest.certificate_authorities ("reqCAs")0.3.8 - 2/21/2005
0.3.7 - 10/05/2004
0.3.6 - 9/28/2004
0.3.5 - 9/16/2004
0.3.4 - 9/12/2004
_versioncheck on SRP 1st hello, causing problems
with GnuTLS (which was offering TLS 1.1)_versioncheck checking, since it could cause interop problemscryptlib_py and and cryptoIDlib present, cryptlib
was complaining about being initialized twice0.3.3 - 6/10/2004
0.3.2 - 5/21/2004
0.3.1 - 4/21/2004
0.3.0 - 3/20/2004
0.2.7 - 3/12/2004
0.2.6 - 3/11/2004
0.2.5 - 3/10/2004
0.2.4 - 3/5/2004
0.2.3 - 3/4/2004
0.2.2 - 3/1/2004
0.2.1 - 2/23/2004
0.2.0 - 2/19/2004
tls_lite -> tlslite0.1.9 - 2/16/2004
close_notify,
just ignore it.0.1.8 - 2/12/2004
0.1.7 - 2/11/2004
close_notify0.1.6 - 2/10/2004
0.1.5 - 2/09/2004
0.1.4 - 2/06/2004
0.1.3 - 2/05/2004
missing_srp_username0.1.2 - 2/04/2004
0.1.1 - 2/02/2004
close_notify behavior0.1.0 - 2/01/2004
Python
99.8%