forked from trevp/tlslite
-
Notifications
You must be signed in to change notification settings - Fork 0
/
README
executable file
·626 lines (501 loc) · 22.6 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
tlslite version 0.4.3 Sep 25 2012
Trevor Perrin <tlslite at trevp.net>
http://trevp.net/tlslite/
============================================================================
Table of Contents
==================
1 Introduction
2 License/Acknowledgements
3 Installation
4 Getting Started with the Command-Line Tools
5 Getting Started with the Library
6 Using TLS Lite with httplib
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.
2 Licenses/Acknowledgements
============================
TLS Lite is written (mostly) by Trevor Perrin. It includes code from Bram
Cohen, Google, Kees Bos, Sam Rushing, and Dimitris Moraitis.
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.
3 Installation
===============
Requirements:
Python 2.6 or higher is required. Python 3 is not supported.
Options:
- If you have the M2Crypto interface to OpenSSL, this will be used for fast
RSA operations and fast ciphers.
- If you have pycrypto this will be used for fast RSA operations and fast
ciphers.
- 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.
Run 'python setup.py install'
Test the Installation:
- From the distribution's ./tests subdirectory, run:
./tlstest.py server localhost:4443 .
- While the test server is waiting, run:
./tlstest.py client localhost:4443 .
If both say "Test succeeded" at the end, you're ready to go.
4 Getting Started with the Command-Line Tools
==============================================
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 SRP verifier databases. These databases are used by
a TLS server when authenticating clients with SRP.
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 -b TACK_Break_Sigs.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 server -v verifierDB localhost:4443
Then try connecting to the server with:
tls.py client localhost:4443 alice abra123cadabra
HTTPS
------
To run an HTTPS server with less typing, run ./tests/httpsserver.sh.
To run an HTTPS client, run ./tests/httpsclient.py.
5 Getting Started with the Library
===================================
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.
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 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.
from socket import *
sock = socket(AF_INET, SOCK_STREAM)
sock.connect( ("www.amazon.com", 443) )
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 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
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)
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)
5 Step 3 - call a handshake function (server)
----------------------------------------------
If you're a server, there's only one handshake function, but you can pass it
several different parameters, depending on which types of authentication
you're willing to perform.
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.
5 Step 4 - check the results
-----------------------------
If the handshake completes without raising an exception, authentication
results will be stored in the connection's session object. The following
variables will be populated if applicable, or else set to None:
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 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 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:
- SRP parameters are not recognized by client
- Server's TACK was unrelated to its certificate chain
Client insufficient_security:
- SRP parameters are too small
Client protocol_version:
- Client doesn't support the server's protocol version
Server protocol_version:
- Server doesn't support the client's protocol version
Server bad_record_mac:
- bad SRP username or password
Server unknown_psk_identity
- bad SRP username (bad_record_mac could be used for the same thing)
Server handshake_failure:
- 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,
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.
5 Step 6 - close the connection
--------------------------------
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.)
6 Using TLS Lite with httplib
==============================
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.
#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")
[...]
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
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")
[...]
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
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")
[...]
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
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.
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.
11 Security Considerations
===========================
TLS Lite is beta-quality code. It hasn't received much security analysis. Use
at your own risk.
12 History
===========
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
- Fixed occassional timing problems with test suite
0.3.7 - 10/05/2004
- Added support for Python 2.2
- Cleaned up compatibility code, and docs, a bit
0.3.6 - 9/28/2004
- Fixed script installation on UNIX
- Give better error message on old Python versions
0.3.5 - 9/16/2004
- TLS 1.1 support
- os.urandom() support
- Fixed win32prng on some systems
0.3.4 - 9/12/2004
- Updated for TLS/SRP draft 8
- Bugfix: was setting _versioncheck on SRP 1st hello, causing problems
with GnuTLS (which was offering TLS 1.1)
- Removed _versioncheck checking, since it could cause interop problems
- Minor bugfix: when cryptlib_py and and cryptoIDlib present, cryptlib
was complaining about being initialized twice
0.3.3 - 6/10/2004
- Updated for TLS/SRP draft 7
- Updated test cryptoID cert chains for cryptoIDlib 0.3.1
0.3.2 - 5/21/2004
- fixed bug when handling multiple handshake messages per record (e.g. IIS)
0.3.1 - 4/21/2004
- added xmlrpclib integration
- fixed hanging bug in Twisted integration
- fixed win32prng to work on a wider range of win32 sytems
- fixed import problem with cryptoIDlib
- fixed port allocation problem when test scripts are run on some UNIXes
- made tolerant of buggy IE sending wrong version in premaster secret
0.3.0 - 3/20/2004
- added API docs thanks to epydoc
- added X.509 path validation via cryptlib
- much cleaning/tweaking/re-factoring/minor fixes
0.2.7 - 3/12/2004
- changed Twisted error handling to use connectionLost()
- added ignoreAbruptClose
0.2.6 - 3/11/2004
- added Twisted errorHandler
- added TLSAbruptCloseError
- added 'integration' subdirectory
0.2.5 - 3/10/2004
- improved asynchronous support a bit
- added first-draft of Twisted support
0.2.4 - 3/5/2004
- cleaned up asyncore support
- added proof-of-concept for Twisted
0.2.3 - 3/4/2004
- added pycrypto RSA support
- added asyncore support
0.2.2 - 3/1/2004
- added GMPY support
- added pycrypto support
- added support for PEM-encoded private keys, in pure python
0.2.1 - 2/23/2004
- improved PRNG use (cryptlib, or /dev/random, or CryptoAPI)
- added RSA blinding, to avoid timing attacks
- don't install local copy of M2Crypto, too problematic
0.2.0 - 2/19/2004
- changed VerifierDB to take per-user parameters
- renamed tls_lite -> 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