| OLD | NEW |
| (Empty) |
| 1 | |
| 2 tlslite version 0.3.8 February 21, 2005 | |
| 3 Trevor Perrin <trevp at trevp.net> | |
| 4 http://trevp.net/tlslite/ | |
| 5 ============================================================================ | |
| 6 | |
| 7 | |
| 8 Table of Contents | |
| 9 ================== | |
| 10 1 Introduction | |
| 11 2 License/Acknowledgements | |
| 12 3 Installation | |
| 13 4 Getting Started with the Command-Line Tools | |
| 14 5 Getting Started with the Library | |
| 15 6 Using TLS Lite with httplib | |
| 16 7 Using TLS Lite with xmlrpclib | |
| 17 8 Using TLS Lite with poplib or imaplib | |
| 18 9 Using TLS Lite with smtplib | |
| 19 10 Using TLS Lite with SocketServer | |
| 20 11 Using TLS Lite with asyncore | |
| 21 12 Using TLS Lite with Twisted | |
| 22 13 SECURITY CONSIDERATIONS | |
| 23 14 History | |
| 24 15 References | |
| 25 | |
| 26 | |
| 27 1 Introduction | |
| 28 =============== | |
| 29 TLS Lite is a free python library that implements SSL v3, TLS v1, and | |
| 30 TLS v1.1 [0]. TLS Lite supports non-traditional authentication methods | |
| 31 such as SRP [1], shared keys [2], and cryptoIDs [3], in addition to X.509 | |
| 32 certificates. TLS Lite is pure python, however it can access OpenSSL [4], | |
| 33 cryptlib [5], pycrypto [9], and GMPY [10] for faster crypto operations. TLS | |
| 34 Lite integrates with httplib, xmlrpclib, poplib, imaplib, smtplib, | |
| 35 SocketServer, asyncore, and Twisted. | |
| 36 | |
| 37 API documentation is available in the 'docs' directory. | |
| 38 | |
| 39 If you have questions or feedback, feel free to contact me. | |
| 40 | |
| 41 | |
| 42 2 Licenses/Acknowledgements | |
| 43 ============================ | |
| 44 All code here is public domain. | |
| 45 | |
| 46 Thanks to Bram Cohen for his public domain Rijndael implementation. | |
| 47 | |
| 48 Thanks to Edward Loper for Epydoc, which generated the API docs. | |
| 49 | |
| 50 | |
| 51 3 Installation | |
| 52 =============== | |
| 53 Requirements: | |
| 54 Python 2.2 or greater is required. | |
| 55 | |
| 56 Options: | |
| 57 - If you have cryptoIDlib [8], you can use cryptoID certificate chains for | |
| 58 authentication. CryptoIDlib is the sister library to TLS Lite; it was | |
| 59 written by the same author, and has a similar interface. | |
| 60 | |
| 61 - If you have the M2Crypto [6] interface to OpenSSL, this will be used for | |
| 62 fast RSA operations and fast ciphers. | |
| 63 | |
| 64 - If you have the cryptlib_py [7] interface to cryptlib, this will be used | |
| 65 for random number generation and fast ciphers. If TLS Lite can't find an | |
| 66 OS-level random-number generator (i.e. /dev/urandom on UNIX or CryptoAPI on | |
| 67 Windows), then you must MUST install cryptlib. | |
| 68 | |
| 69 - If you have pycrypto [9], this will be used for fast ciphers and fast RSA | |
| 70 operations. | |
| 71 | |
| 72 - If you have the GMPY [10] interface to GMP, this will be used for fast RSA | |
| 73 and SRP operations. | |
| 74 | |
| 75 - These modules don't need to be present at installation - you can install | |
| 76 them any time. | |
| 77 | |
| 78 On Windows: | |
| 79 Run the installer in the 'installers' directory. | |
| 80 *OR* | |
| 81 Run 'setup.py install' (this only works if your system has a compiler | |
| 82 available). | |
| 83 | |
| 84 Anywhere else: | |
| 85 - Run 'python setup.py install' | |
| 86 | |
| 87 Test the Installation: | |
| 88 - The 'tls.py' script should have been copied onto your path. If not, | |
| 89 you may have to copy it there manually. | |
| 90 - From the distribution's ./test subdirectory, run: | |
| 91 tls.py servertest localhost:4443 . | |
| 92 - While the test server is waiting, run: | |
| 93 tls.py clienttest localhost:4443 . | |
| 94 | |
| 95 If both say "Test succeeded" at the end, you're ready to go. | |
| 96 | |
| 97 (WARNING: Be careful running these (or any) scripts from the distribution's | |
| 98 root directory. Depending on your path, the scripts may load the local copy | |
| 99 of the library instead of the installed version, with unpredictable | |
| 100 results). | |
| 101 | |
| 102 | |
| 103 4 Getting Started with the Command-Line Tools | |
| 104 ============================================== | |
| 105 tlslite comes with two command-line scripts: 'tlsdb.py' and 'tls.py'. They | |
| 106 can be run with no arguments to see a list of commands. | |
| 107 | |
| 108 'tlsdb.py' lets you manage shared key or verifier databases. These databases | |
| 109 store usernames associated with either shared keys, or SRP password verifiers. | |
| 110 These databases are used by a TLS server when authenticating clients with | |
| 111 shared keys or SRP. | |
| 112 | |
| 113 'tls.py' lets you run test clients and servers. It can be used for testing | |
| 114 other TLS implementations, or as example code for using tlslite. To run an | |
| 115 SRP server, try something like: | |
| 116 | |
| 117 tlsdb.py createsrp verifierDB | |
| 118 tlsdb.py add verifierDB alice abra123cadabra 1024 | |
| 119 tlsdb.py add verifierDB bob swordfish 2048 | |
| 120 | |
| 121 tls.py serversrp localhost:443 verifierDB | |
| 122 | |
| 123 Then you can try connecting to the server with: | |
| 124 | |
| 125 tls.py clientsrp localhost:443 alice abra123cadabra | |
| 126 | |
| 127 | |
| 128 5 Getting Started with the Library | |
| 129 =================================== | |
| 130 Using the library is simple. Whether you're writing a client or server, there | |
| 131 are six steps: | |
| 132 1) Create a socket and connect it to the other party. | |
| 133 2) Construct a TLSConnection instance with the socket. | |
| 134 3) Call a handshake function on TLSConnection to perform the TLS handshake. | |
| 135 4) Check the results to make sure you're talking to the right party. | |
| 136 5) Use the TLSConnection to exchange data. | |
| 137 6) Call close() on the TLSConnection when you're done. | |
| 138 | |
| 139 TLS Lite also integrates with httplib, xmlrpclib, poplib, imaplib, smtplib, | |
| 140 SocketServer, asyncore, and Twisted. When used with these, some of the steps | |
| 141 are performed for you. See the sections following this one for details. | |
| 142 | |
| 143 5 Step 1 - create a socket | |
| 144 --------------------------- | |
| 145 Below demonstrates a socket connection to Amazon's secure site. It's a good | |
| 146 idea to set the timeout value, so if the other side fails to respond you won't | |
| 147 end up waiting forever. | |
| 148 | |
| 149 from socket import * | |
| 150 sock = socket(AF_INET, SOCK_STREAM) | |
| 151 sock.connect( ("www.amazon.com", 443) ) | |
| 152 sock.settimeout(10) #Only on python 2.3 or greater | |
| 153 | |
| 154 5 Step 2 - construct a TLSConnection | |
| 155 ------------------------------------- | |
| 156 from tlslite.api import * | |
| 157 connection = TLSConnection(sock) | |
| 158 | |
| 159 5 Step 3 - call a handshake function (client) | |
| 160 ---------------------------------------------- | |
| 161 If you're a client, there's several different handshake functions you can | |
| 162 call, depending on how you want to authenticate: | |
| 163 | |
| 164 connection.handshakeClientCert() | |
| 165 connection.handshakeClientCert(certChain, privateKey) | |
| 166 connection.handshakeClientSRP("alice", "abra123cadabra") | |
| 167 connection.handshakeClientSharedKey("alice", "PaVBVZkYqAjCQCu6UBL2xgsnZhw") | |
| 168 connection.handshakeClientUnknown(srpCallback, certCallback) | |
| 169 | |
| 170 The ClientCert function without arguments is used when connecting to a site | |
| 171 like Amazon, which doesn't require client authentication. The server will | |
| 172 authenticate with a certificate chain. | |
| 173 | |
| 174 The ClientCert function can also be used to do client authentication with an | |
| 175 X.509 or cryptoID certificate chain. To use cryptoID chains, you'll need the | |
| 176 cryptoIDlib library [8]. To use X.509 chains, you'll need some way of | |
| 177 creating these, such as OpenSSL (see http://www.openssl.org/docs/HOWTO/ for | |
| 178 details). | |
| 179 | |
| 180 Below are examples of loading cryptoID and X.509 certificate chains: | |
| 181 | |
| 182 #Load cryptoID certChain and privateKey. Requires cryptoIDlib. | |
| 183 from cryptoIDlib.CertChain import CertChain | |
| 184 s = open("./test/clientCryptoIDChain.xml").read() | |
| 185 certChain = CertChain() | |
| 186 certChain.parse(s) | |
| 187 s = open("./test/clientCryptoIDKey.xml").read() | |
| 188 privateKey = parseXMLKey(s, private=True) | |
| 189 | |
| 190 #Load X.509 certChain and privateKey. | |
| 191 s = open("./test/clientX509Cert.pem").read() | |
| 192 x509 = X509() | |
| 193 x509.parse(s) | |
| 194 certChain = X509CertChain([x509]) | |
| 195 s = open("./test/clientX509Key.pem").read() | |
| 196 privateKey = parsePEMKey(s, private=True) | |
| 197 | |
| 198 The SRP and SharedKey functions both do mutual authentication with a username | |
| 199 and password. The difference is this: SRP is slow but safer when using low- | |
| 200 entropy passwords, since the SRP protocol is not vulnerable to offline | |
| 201 dictionary attacks. Using shared keys is faster, but it's only safe when | |
| 202 used with high-entropy secrets. In general, you should prefer SRP for human- | |
| 203 memorable passwords, and use shared keys only when your performance needs | |
| 204 outweigh the inconvenience of handling large random strings. | |
| 205 | |
| 206 [WARNING: shared keys and SRP are internet-drafts; these protocols may change, | |
| 207 which means future versions of tlslite may not be compatible with this one. | |
| 208 This is less likely with SRP, more likely with shared-keys.] | |
| 209 | |
| 210 The Unknown function is used when you're not sure if the server requires | |
| 211 client authentication. If the server requests SRP or certificate-based | |
| 212 authentication, the appropriate callback will be triggered, and you should | |
| 213 return a tuple containing either a (username, password) or (certChain, | |
| 214 privateKey), as appropriate. Alternatively, you can return None, which will | |
| 215 cancel the handshake from an SRP callback, or cause it to continue without | |
| 216 client authentication (if the server is willing) from a certificate callback. | |
| 217 | |
| 218 If you want more control over the handshake, you can pass in a | |
| 219 HandshakeSettings instance. For example, if you're performing SRP, but you | |
| 220 only want to use SRP parameters of at least 2048 bits, and you only want to use | |
| 221 the AES-256 cipher, and you only want to allow TLS (version 3.1), not SSL | |
| 222 (version 3.0), you can do: | |
| 223 | |
| 224 settings = HandshakeSettings() | |
| 225 settings.minKeySize = 2048 | |
| 226 settings.cipherNames = ["aes256"] | |
| 227 settings.minVersion = (3,1) | |
| 228 connection.handshakeClientSRP("alice", "abra123cadabra", settings=settings) | |
| 229 | |
| 230 Finally, every TLSConnection has a session object. You can try to resume a | |
| 231 previous session by passing in the session object from the old session. If | |
| 232 the server remembers this old session and supports resumption, the handshake | |
| 233 will finish more quickly. Otherwise, the full handshake will be done. For | |
| 234 example: | |
| 235 | |
| 236 connection.handshakeClientSRP("alice", "abra123cadabra") | |
| 237 . | |
| 238 . | |
| 239 oldSession = connection.session | |
| 240 connection2.handshakeClientSRP("alice", "abra123cadabra", session= | |
| 241 oldSession) | |
| 242 | |
| 243 5 Step 3 - call a handshake function (server) | |
| 244 ---------------------------------------------- | |
| 245 If you're a server, there's only one handshake function, but you can pass it | |
| 246 several different parameters, depending on which types of authentication | |
| 247 you're willing to perform. | |
| 248 | |
| 249 To perform SRP authentication, you have to pass in a database of password | |
| 250 verifiers. The VerifierDB class manages an in-memory or on-disk verifier | |
| 251 database. | |
| 252 | |
| 253 #On-disk database (use no-arg constructor if you want an in-memory DB) | |
| 254 verifierDB = VerifierDB("./test/verifierDB") | |
| 255 | |
| 256 #Open the pre-existing database (can also 'create()' a new one) | |
| 257 verifierDB.open() | |
| 258 | |
| 259 #Add to the database | |
| 260 verifier = VerifierDB.makeVerifier("alice", "abra123cadabra", 2048) | |
| 261 verifierDB["alice"] = verifier | |
| 262 | |
| 263 #Perform a handshake using the database | |
| 264 connection.handshakeServer(verifierDB=verifierDB) | |
| 265 | |
| 266 To perform shared key authentication, you have to pass in a database of shared | |
| 267 keys. The SharedKeyDB class manages an in-memory or on-disk shared key | |
| 268 database. | |
| 269 | |
| 270 sharedKeyDB = SharedKeyDB("./test/sharedkeyDB") | |
| 271 sharedKeyDB.open() | |
| 272 sharedKeyDB["alice"] = "PaVBVZkYqAjCQCu6UBL2xgsnZhw" | |
| 273 connection.handshakeServer(sharedKeyDB=sharedKeyDB) | |
| 274 | |
| 275 To perform authentication with a certificate and private key, the server must | |
| 276 load these as described in the previous section, then pass them in. If the | |
| 277 server sets the reqCert boolean to True, a certificate chain will be requested | |
| 278 from the client. | |
| 279 | |
| 280 connection.handshakeServer(certChain=certChain, privateKey=privateKey, | |
| 281 reqCert=True) | |
| 282 | |
| 283 You can pass in any combination of a verifier database, a shared key database, | |
| 284 and a certificate chain/private key. The client will use one of them to | |
| 285 authenticate. In the case of SRP and a certificate chain/private key, they | |
| 286 both may be used. | |
| 287 | |
| 288 You can also pass in a HandshakeSettings object, as described in the last | |
| 289 section, for finer control over handshaking details. Finally, the server can | |
| 290 maintain a SessionCache, which will allow clients to use session resumption: | |
| 291 | |
| 292 sessionCache = SessionCache() | |
| 293 connection.handshakeServer(verifierDB=verifierDB, sessionCache=sessionCache) | |
| 294 | |
| 295 It should be noted that the session cache, and the verifier and shared key | |
| 296 databases, are all thread-safe. | |
| 297 | |
| 298 5 Step 4 - check the results | |
| 299 ----------------------------- | |
| 300 If the handshake completes without raising an exception, authentication | |
| 301 results will be stored in the connection's session object. The following | |
| 302 variables will be populated if applicable, or else set to None: | |
| 303 | |
| 304 connection.session.srpUsername #string | |
| 305 connection.session.sharedKeyUsername #string | |
| 306 connection.session.clientCertChain #X509CertChain or | |
| 307 #cryptoIDlib.CertChain.CertChain | |
| 308 connection.session.serverCertChain #X509CertChain or | |
| 309 #cryptoIDlib.CertChain.CertChain | |
| 310 | |
| 311 Both types of certificate chain object support the getFingerprint() function, | |
| 312 but with a difference. X.509 objects return the end-entity fingerprint, and | |
| 313 ignore the other certificates. CryptoID fingerprints (aka "cryptoIDs") are | |
| 314 based on the root cryptoID certificate, so you have to call validate() on the | |
| 315 CertChain to be sure you're really talking to the cryptoID. | |
| 316 | |
| 317 X.509 certificate chain objects may also be validated against a list of | |
| 318 trusted root certificates. See the API documentation for details. | |
| 319 | |
| 320 To save yourself the trouble of inspecting fingerprints after the handshake, | |
| 321 you can pass a Checker object into the handshake function. The checker will be | |
| 322 called if the handshake completes successfully. If the other party's | |
| 323 certificate chain isn't approved by the checker, a subclass of | |
| 324 TLSAuthenticationError will be raised. For example, to perform a handshake | |
| 325 with a server based on its X.509 fingerprint, do: | |
| 326 | |
| 327 try: | |
| 328 checker = Checker(\ | |
| 329 x509Fingerprint='e049ff930af76d43ff4c658b268786f4df1296f2') | |
| 330 connection.handshakeClientCert(checker=checker) | |
| 331 except TLSAuthenticationError: | |
| 332 print "Authentication failure" | |
| 333 | |
| 334 If the handshake fails for any reason, an exception will be raised. If the | |
| 335 socket timed out or was unexpectedly closed, a socket.error or | |
| 336 TLSAbruptCloseError will be raised. Otherwise, either a TLSLocalAlert or | |
| 337 TLSRemoteAlert will be raised, depending on whether the local or remote | |
| 338 implementation signalled the error. The exception object has a 'description' | |
| 339 member which identifies the error based on the codes in RFC 2246. A | |
| 340 TLSLocalAlert also has a 'message' string that may have more details. | |
| 341 | |
| 342 Example of handling a remote alert: | |
| 343 | |
| 344 try: | |
| 345 [...] | |
| 346 except TLSRemoteAlert, alert: | |
| 347 if alert.description == AlertDescription.unknown_srp_username: | |
| 348 print "Unknown user." | |
| 349 [...] | |
| 350 | |
| 351 Figuring out what went wrong based on the alert may require some | |
| 352 interpretation, particularly with remote alerts where you don't have an error | |
| 353 string, and where the remote implementation may not be signalling alerts | |
| 354 properly. Many alerts signal an implementation error, and so should rarely be | |
| 355 seen in normal operation (unexpected_message, decode_error, illegal_parameter, | |
| 356 internal_error, etc.). | |
| 357 | |
| 358 Others alerts are more likely to occur. Below are some common alerts and | |
| 359 their probable causes, and whether they are signalled by the client or server. | |
| 360 | |
| 361 Client bad_record_mac: | |
| 362 - bad shared key password | |
| 363 | |
| 364 Client handshake failure: | |
| 365 - SRP parameters are not recognized by client | |
| 366 | |
| 367 Client user_canceled: | |
| 368 - The client might have returned None from an SRP callback. | |
| 369 | |
| 370 Client insufficient_security: | |
| 371 - SRP parameters are too small | |
| 372 | |
| 373 Client protocol_version: | |
| 374 - Client doesn't support the server's protocol version | |
| 375 | |
| 376 Server protocol_version: | |
| 377 - Server doesn't support the client's protocol version | |
| 378 | |
| 379 Server bad_record_mac: | |
| 380 - bad SRP username or password | |
| 381 | |
| 382 Server unknown_srp_username | |
| 383 - bad SRP username (bad_record_mac could be used for the same thing) | |
| 384 | |
| 385 Server handshake_failure: | |
| 386 - bad shared key username | |
| 387 - no matching cipher suites | |
| 388 | |
| 389 5 Step 5 - exchange data | |
| 390 ------------------------- | |
| 391 Now that you have a connection, you can call read() and write() as if it were | |
| 392 a socket.SSL object. You can also call send(), sendall(), recv(), and | |
| 393 makefile() as if it were a socket. These calls may raise TLSLocalAlert, | |
| 394 TLSRemoteAlert, socket.error, or TLSAbruptCloseError, just like the handshake | |
| 395 functions. | |
| 396 | |
| 397 Once the TLS connection is closed by the other side, calls to read() or recv() | |
| 398 will return an empty string. If the socket is closed by the other side | |
| 399 without first closing the TLS connection, calls to read() or recv() will return | |
| 400 a TLSAbruptCloseError, and calls to write() or send() will return a | |
| 401 socket.error. | |
| 402 | |
| 403 5 Step 6 - close the connection | |
| 404 -------------------------------- | |
| 405 When you're finished sending data, you should call close() to close the | |
| 406 connection down. When the connection is closed properly, the socket stays | |
| 407 open and can be used for exchanging non-secure data, the session object can be | |
| 408 used for session resumption, and the connection object can be re-used by | |
| 409 calling another handshake function. | |
| 410 | |
| 411 If an exception is raised, the connection will be automatically closed; you | |
| 412 don't need to call close(). Furthermore, you will probably not be able to re- | |
| 413 use the socket, the connection object, or the session object, and you | |
| 414 shouldn't even try. | |
| 415 | |
| 416 By default, calling close() will leave the socket open. If you set the | |
| 417 connection's closeSocket flag to True, the connection will take ownership of | |
| 418 the socket, and close it when the connection is closed. | |
| 419 | |
| 420 | |
| 421 6 Using TLS Lite with httplib | |
| 422 ============================== | |
| 423 TLS Lite comes with an HTTPTLSConnection class that extends httplib to work | |
| 424 over SSL/TLS connections. Depending on how you construct it, it will do | |
| 425 different types of authentication. | |
| 426 | |
| 427 #No authentication whatsoever | |
| 428 h = HTTPTLSConnection("www.amazon.com", 443) | |
| 429 h.request("GET", "") | |
| 430 r = h.getresponse() | |
| 431 [...] | |
| 432 | |
| 433 #Authenticate server based on its X.509 fingerprint | |
| 434 h = HTTPTLSConnection("www.amazon.com", 443, | |
| 435 x509Fingerprint="e049ff930af76d43ff4c658b268786f4df1296f2") | |
| 436 [...] | |
| 437 | |
| 438 #Authenticate server based on its X.509 chain (requires cryptlib_py [7]) | |
| 439 h = HTTPTLSConnection("www.amazon.com", 443, | |
| 440 x509TrustList=[verisignCert], | |
| 441 x509CommonName="www.amazon.com") | |
| 442 [...] | |
| 443 | |
| 444 #Authenticate server based on its cryptoID | |
| 445 h = HTTPTLSConnection("localhost", 443, | |
| 446 cryptoID="dmqb6.fq345.cxk6g.5fha3") | |
| 447 [...] | |
| 448 | |
| 449 #Mutually authenticate with SRP | |
| 450 h = HTTPTLSConnection("localhost", 443, | |
| 451 username="alice", password="abra123cadabra") | |
| 452 [...] | |
| 453 | |
| 454 #Mutually authenticate with a shared key | |
| 455 h = HTTPTLSConnection("localhost", 443, | |
| 456 username="alice", sharedKey="PaVBVZkYqAjCQCu6UBL2xgsnZhw") | |
| 457 [...] | |
| 458 | |
| 459 #Mutually authenticate with SRP, *AND* authenticate the server based | |
| 460 #on its cryptoID | |
| 461 h = HTTPTLSConnection("localhost", 443, | |
| 462 username="alice", password="abra123cadabra", | |
| 463 cryptoID="dmqb6.fq345.cxk6g.5fha3") | |
| 464 [...] | |
| 465 | |
| 466 | |
| 467 7 Using TLS Lite with xmlrpclib | |
| 468 ================================ | |
| 469 TLS Lite comes with an XMLRPCTransport class that extends xmlrpclib to work | |
| 470 over SSL/TLS connections. This class accepts the same parameters as | |
| 471 HTTPTLSConnection (see previous section), and behaves similarly. Depending on | |
| 472 how you construct it, it will do different types of authentication. | |
| 473 | |
| 474 from tlslite.api import XMLRPCTransport | |
| 475 from xmlrpclib import ServerProxy | |
| 476 | |
| 477 #No authentication whatsoever | |
| 478 transport = XMLRPCTransport() | |
| 479 server = ServerProxy("https://localhost", transport) | |
| 480 server.someFunc(2, 3) | |
| 481 [...] | |
| 482 | |
| 483 #Authenticate server based on its X.509 fingerprint | |
| 484 transport = XMLRPCTransport(\ | |
| 485 x509Fingerprint="e049ff930af76d43ff4c658b268786f4df1296f2") | |
| 486 [...] | |
| 487 | |
| 488 | |
| 489 8 Using TLS Lite with poplib or imaplib | |
| 490 ======================================== | |
| 491 TLS Lite comes with POP3_TLS and IMAP4_TLS classes that extend poplib and | |
| 492 imaplib to work over SSL/TLS connections. These classes can be constructed | |
| 493 with the same parameters as HTTPTLSConnection (see previous section), and | |
| 494 behave similarly. | |
| 495 | |
| 496 #To connect to a POP3 server over SSL and display its fingerprint: | |
| 497 from tlslite.api import * | |
| 498 p = POP3_TLS("---------.net") | |
| 499 print p.sock.session.serverCertChain.getFingerprint() | |
| 500 [...] | |
| 501 | |
| 502 #To connect to an IMAP server once you know its fingerprint: | |
| 503 from tlslite.api import * | |
| 504 i = IMAP4_TLS("cyrus.andrew.cmu.edu", | |
| 505 x509Fingerprint="00c14371227b3b677ddb9c4901e6f2aee18d3e45") | |
| 506 [...] | |
| 507 | |
| 508 | |
| 509 9 Using TLS Lite with smtplib | |
| 510 ============================== | |
| 511 TLS Lite comes with an SMTP_TLS class that extends smtplib to work | |
| 512 over SSL/TLS connections. This class accepts the same parameters as | |
| 513 HTTPTLSConnection (see previous section), and behaves similarly. Depending | |
| 514 on how you call starttls(), it will do different types of authentication. | |
| 515 | |
| 516 #To connect to an SMTP server once you know its fingerprint: | |
| 517 from tlslite.api import * | |
| 518 s = SMTP_TLS("----------.net") | |
| 519 s.starttls(x509Fingerprint="7e39be84a2e3a7ad071752e3001d931bf82c32dc") | |
| 520 [...] | |
| 521 | |
| 522 | |
| 523 10 Using TLS Lite with SocketServer | |
| 524 ==================================== | |
| 525 You can use TLS Lite to implement servers using Python's SocketServer | |
| 526 framework. TLS Lite comes with a TLSSocketServerMixIn class. You can combine | |
| 527 this with a TCPServer such as HTTPServer. To combine them, define a new class | |
| 528 that inherits from both of them (with the mix-in first). Then implement the | |
| 529 handshake() method, doing some sort of server handshake on the connection | |
| 530 argument. If the handshake method returns True, the RequestHandler will be | |
| 531 triggered. Below is a complete example of a threaded HTTPS server. | |
| 532 | |
| 533 from SocketServer import * | |
| 534 from BaseHTTPServer import * | |
| 535 from SimpleHTTPServer import * | |
| 536 from tlslite.api import * | |
| 537 | |
| 538 s = open("./serverX509Cert.pem").read() | |
| 539 x509 = X509() | |
| 540 x509.parse(s) | |
| 541 certChain = X509CertChain([x509]) | |
| 542 | |
| 543 s = open("./serverX509Key.pem").read() | |
| 544 privateKey = parsePEMKey(s, private=True) | |
| 545 | |
| 546 sessionCache = SessionCache() | |
| 547 | |
| 548 class MyHTTPServer(ThreadingMixIn, TLSSocketServerMixIn, HTTPServer): | |
| 549 def handshake(self, tlsConnection): | |
| 550 try: | |
| 551 tlsConnection.handshakeServer(certChain=certChain, | |
| 552 privateKey=privateKey, | |
| 553 sessionCache=sessionCache) | |
| 554 tlsConnection.ignoreAbruptClose = True | |
| 555 return True | |
| 556 except TLSError, error: | |
| 557 print "Handshake failure:", str(error) | |
| 558 return False | |
| 559 | |
| 560 httpd = MyHTTPServer(('localhost', 443), SimpleHTTPRequestHandler) | |
| 561 httpd.serve_forever() | |
| 562 | |
| 563 | |
| 564 11 Using TLS Lite with asyncore | |
| 565 ================================ | |
| 566 TLS Lite can be used with subclasses of asyncore.dispatcher. See the comments | |
| 567 in TLSAsyncDispatcherMixIn.py for details. This is still experimental, and | |
| 568 may not work with all asyncore.dispatcher subclasses. | |
| 569 | |
| 570 Below is an example of combining Medusa's http_channel with | |
| 571 TLSAsyncDispatcherMixIn: | |
| 572 | |
| 573 class http_tls_channel(TLSAsyncDispatcherMixIn, | |
| 574 http_server.http_channel): | |
| 575 ac_in_buffer_size = 16384 | |
| 576 | |
| 577 def __init__ (self, server, conn, addr): | |
| 578 http_server.http_channel.__init__(self, server, conn, addr) | |
| 579 TLSAsyncDispatcherMixIn.__init__(self, conn) | |
| 580 self.tlsConnection.ignoreAbruptClose = True | |
| 581 self.setServerHandshakeOp(certChain=certChain, | |
| 582 privateKey=privateKey) | |
| 583 | |
| 584 | |
| 585 12 Using TLS Lite with Twisted | |
| 586 =============================== | |
| 587 TLS Lite can be used with Twisted protocols. Below is a complete example of | |
| 588 using TLS Lite with a Twisted echo server. | |
| 589 | |
| 590 There are two server implementations below. Echo is the original protocol, | |
| 591 which is oblivious to TLS. Echo1 subclasses Echo and negotiates TLS when the | |
| 592 client connects. Echo2 subclasses Echo and negotiates TLS when the client | |
| 593 sends "STARTTLS". | |
| 594 | |
| 595 from twisted.internet.protocol import Protocol, Factory | |
| 596 from twisted.internet import reactor | |
| 597 from twisted.protocols.policies import WrappingFactory | |
| 598 from twisted.protocols.basic import LineReceiver | |
| 599 from twisted.python import log | |
| 600 from twisted.python.failure import Failure | |
| 601 import sys | |
| 602 from tlslite.api import * | |
| 603 | |
| 604 s = open("./serverX509Cert.pem").read() | |
| 605 x509 = X509() | |
| 606 x509.parse(s) | |
| 607 certChain = X509CertChain([x509]) | |
| 608 | |
| 609 s = open("./serverX509Key.pem").read() | |
| 610 privateKey = parsePEMKey(s, private=True) | |
| 611 | |
| 612 verifierDB = VerifierDB("verifierDB") | |
| 613 verifierDB.open() | |
| 614 | |
| 615 class Echo(LineReceiver): | |
| 616 def connectionMade(self): | |
| 617 self.transport.write("Welcome to the echo server!\r\n") | |
| 618 | |
| 619 def lineReceived(self, line): | |
| 620 self.transport.write(line + "\r\n") | |
| 621 | |
| 622 class Echo1(Echo): | |
| 623 def connectionMade(self): | |
| 624 if not self.transport.tlsStarted: | |
| 625 self.transport.setServerHandshakeOp(certChain=certChain, | |
| 626 privateKey=privateKey, | |
| 627 verifierDB=verifierDB) | |
| 628 else: | |
| 629 Echo.connectionMade(self) | |
| 630 | |
| 631 def connectionLost(self, reason): | |
| 632 pass #Handle any TLS exceptions here | |
| 633 | |
| 634 class Echo2(Echo): | |
| 635 def lineReceived(self, data): | |
| 636 if data == "STARTTLS": | |
| 637 self.transport.setServerHandshakeOp(certChain=certChain, | |
| 638 privateKey=privateKey, | |
| 639 verifierDB=verifierDB) | |
| 640 else: | |
| 641 Echo.lineReceived(self, data) | |
| 642 | |
| 643 def connectionLost(self, reason): | |
| 644 pass #Handle any TLS exceptions here | |
| 645 | |
| 646 factory = Factory() | |
| 647 factory.protocol = Echo1 | |
| 648 #factory.protocol = Echo2 | |
| 649 | |
| 650 wrappingFactory = WrappingFactory(factory) | |
| 651 wrappingFactory.protocol = TLSTwistedProtocolWrapper | |
| 652 | |
| 653 log.startLogging(sys.stdout) | |
| 654 reactor.listenTCP(1079, wrappingFactory) | |
| 655 reactor.run() | |
| 656 | |
| 657 | |
| 658 13 Security Considerations | |
| 659 =========================== | |
| 660 TLS Lite is beta-quality code. It hasn't received much security analysis. | |
| 661 Use at your own risk. | |
| 662 | |
| 663 | |
| 664 14 History | |
| 665 =========== | |
| 666 0.3.8 - 2/21/2005 | |
| 667 - Added support for poplib, imaplib, and smtplib | |
| 668 - Added python 2.4 windows installer | |
| 669 - Fixed occassional timing problems with test suite | |
| 670 0.3.7 - 10/05/2004 | |
| 671 - Added support for Python 2.2 | |
| 672 - Cleaned up compatibility code, and docs, a bit | |
| 673 0.3.6 - 9/28/2004 | |
| 674 - Fixed script installation on UNIX | |
| 675 - Give better error message on old Python versions | |
| 676 0.3.5 - 9/16/2004 | |
| 677 - TLS 1.1 support | |
| 678 - os.urandom() support | |
| 679 - Fixed win32prng on some systems | |
| 680 0.3.4 - 9/12/2004 | |
| 681 - Updated for TLS/SRP draft 8 | |
| 682 - Bugfix: was setting _versioncheck on SRP 1st hello, causing problems | |
| 683 with GnuTLS (which was offering TLS 1.1) | |
| 684 - Removed _versioncheck checking, since it could cause interop problems | |
| 685 - Minor bugfix: when cryptlib_py and and cryptoIDlib present, cryptlib | |
| 686 was complaining about being initialized twice | |
| 687 0.3.3 - 6/10/2004 | |
| 688 - Updated for TLS/SRP draft 7 | |
| 689 - Updated test cryptoID cert chains for cryptoIDlib 0.3.1 | |
| 690 0.3.2 - 5/21/2004 | |
| 691 - fixed bug when handling multiple handshake messages per record (e.g. IIS) | |
| 692 0.3.1 - 4/21/2004 | |
| 693 - added xmlrpclib integration | |
| 694 - fixed hanging bug in Twisted integration | |
| 695 - fixed win32prng to work on a wider range of win32 sytems | |
| 696 - fixed import problem with cryptoIDlib | |
| 697 - fixed port allocation problem when test scripts are run on some UNIXes | |
| 698 - made tolerant of buggy IE sending wrong version in premaster secret | |
| 699 0.3.0 - 3/20/2004 | |
| 700 - added API docs thanks to epydoc | |
| 701 - added X.509 path validation via cryptlib | |
| 702 - much cleaning/tweaking/re-factoring/minor fixes | |
| 703 0.2.7 - 3/12/2004 | |
| 704 - changed Twisted error handling to use connectionLost() | |
| 705 - added ignoreAbruptClose | |
| 706 0.2.6 - 3/11/2004 | |
| 707 - added Twisted errorHandler | |
| 708 - added TLSAbruptCloseError | |
| 709 - added 'integration' subdirectory | |
| 710 0.2.5 - 3/10/2004 | |
| 711 - improved asynchronous support a bit | |
| 712 - added first-draft of Twisted support | |
| 713 0.2.4 - 3/5/2004 | |
| 714 - cleaned up asyncore support | |
| 715 - added proof-of-concept for Twisted | |
| 716 0.2.3 - 3/4/2004 | |
| 717 - added pycrypto RSA support | |
| 718 - added asyncore support | |
| 719 0.2.2 - 3/1/2004 | |
| 720 - added GMPY support | |
| 721 - added pycrypto support | |
| 722 - added support for PEM-encoded private keys, in pure python | |
| 723 0.2.1 - 2/23/2004 | |
| 724 - improved PRNG use (cryptlib, or /dev/random, or CryptoAPI) | |
| 725 - added RSA blinding, to avoid timing attacks | |
| 726 - don't install local copy of M2Crypto, too problematic | |
| 727 0.2.0 - 2/19/2004 | |
| 728 - changed VerifierDB to take per-user parameters | |
| 729 - renamed tls_lite -> tlslite | |
| 730 0.1.9 - 2/16/2004 | |
| 731 - added post-handshake 'Checker' | |
| 732 - made compatible with Python 2.2 | |
| 733 - made more forgiving of abrupt closure, since everyone does it: | |
| 734 if the socket is closed while sending/recv'ing close_notify, | |
| 735 just ignore it. | |
| 736 0.1.8 - 2/12/2004 | |
| 737 - TLSConnections now emulate sockets, including makefile() | |
| 738 - HTTPTLSConnection and TLSMixIn simplified as a result | |
| 739 0.1.7 - 2/11/2004 | |
| 740 - fixed httplib.HTTPTLSConnection with multiple requests | |
| 741 - fixed SocketServer to handle close_notify | |
| 742 - changed handshakeClientNoAuth() to ignore CertificateRequests | |
| 743 - changed handshakeClient() to ignore non-resumable session arguments | |
| 744 0.1.6 - 2/10/2004 | |
| 745 - fixed httplib support | |
| 746 0.1.5 - 2/09/2004 | |
| 747 - added support for httplib and SocketServer | |
| 748 - added support for SSLv3 | |
| 749 - added support for 3DES | |
| 750 - cleaned up read()/write() behavior | |
| 751 - improved HMAC speed | |
| 752 0.1.4 - 2/06/2004 | |
| 753 - fixed dumb bug in tls.py | |
| 754 0.1.3 - 2/05/2004 | |
| 755 - change read() to only return requested number of bytes | |
| 756 - added support for shared-key and in-memory databases | |
| 757 - added support for PEM-encoded X.509 certificates | |
| 758 - added support for SSLv2 ClientHello | |
| 759 - fixed shutdown/re-handshaking behavior | |
| 760 - cleaned up handling of missing_srp_username | |
| 761 - renamed readString()/writeString() -> read()/write() | |
| 762 - added documentation | |
| 763 0.1.2 - 2/04/2004 | |
| 764 - added clienttest/servertest functions | |
| 765 - improved OpenSSL cipher wrappers speed | |
| 766 - fixed server when it has a key, but client selects plain SRP | |
| 767 - fixed server to postpone errors until it has read client's messages | |
| 768 - fixed ServerHello to only include extension data if necessary | |
| 769 0.1.1 - 2/02/2004 | |
| 770 - fixed close_notify behavior | |
| 771 - fixed handling of empty application data packets | |
| 772 - fixed socket reads to not consume extra bytes | |
| 773 - added testing functions to tls.py | |
| 774 0.1.0 - 2/01/2004 | |
| 775 - first release | |
| 776 | |
| 777 | |
| 778 15 References | |
| 779 ============== | |
| 780 [0] http://www.ietf.org/html.charters/tls-charter.html | |
| 781 [1] http://www.trevp.net/tls_srp/draft-ietf-tls-srp-07.html | |
| 782 [2] http://www.ietf.org/internet-drafts/draft-ietf-tls-sharedkeys-02.txt | |
| 783 [3] http://www.trevp.net/cryptoID/ | |
| 784 [4] http://www.openssl.org/ | |
| 785 [5] http://www.cs.auckland.ac.nz/~pgut001/cryptlib/ | |
| 786 [6] http://sandbox.rulemaker.net/ngps/m2/ | |
| 787 [7] http://trevp.net/cryptlibConverter/ | |
| 788 [8] http://www.trevp.net/cryptoID/ | |
| 789 [9] http://www.amk.ca/python/code/crypto.html | |
| 790 [10] http://gmpy.sourceforge.net/ | |
| 791 | |
| 792 | |
| 793 | |
| 794 | |
| 795 | |
| 796 | |
| 797 | |
| 798 | |
| 799 | |
| 800 | |
| 801 | |
| 802 | |
| 803 | |
| 804 | |
| 805 | |
| 806 | |
| 807 | |
| 808 | |
| 809 | |
| 810 | |
| 811 | |
| 812 | |
| 813 | |
| 814 | |
| 815 | |
| OLD | NEW |