From f3667e95188e8c14458a7943c7efab3776b04711 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 27 Nov 2020 13:24:55 -0500 Subject: Remove leakcheck (#965) It's not being run anywhere, and plainly doesn't support py3 so it's clearly not important to anyone. --- MANIFEST.in | 3 +- leakcheck/context-info-callback.py | 105 ----------------- leakcheck/context-passphrase-callback.py | 40 ------- leakcheck/context-verify-callback.py | 112 ------------------ leakcheck/crypto.py | 191 ------------------------------- leakcheck/dhparam.pem | 4 - leakcheck/thread-crash.py | 73 ------------ leakcheck/thread-key-gen.py | 41 ------- 8 files changed, 1 insertion(+), 568 deletions(-) delete mode 100644 leakcheck/context-info-callback.py delete mode 100644 leakcheck/context-passphrase-callback.py delete mode 100644 leakcheck/context-verify-callback.py delete mode 100644 leakcheck/crypto.py delete mode 100644 leakcheck/dhparam.pem delete mode 100644 leakcheck/thread-crash.py delete mode 100644 leakcheck/thread-key-gen.py diff --git a/MANIFEST.in b/MANIFEST.in index bc3ee4d..65b7dc3 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,7 +1,6 @@ include LICENSE MANIFEST.in *.rst tox.ini .coveragerc -exclude leakcheck codecov.yml +exclude codecov.yml recursive-include tests *.py recursive-include doc * -recursive-exclude leakcheck *.py *.pem prune doc/_build prune .travis diff --git a/leakcheck/context-info-callback.py b/leakcheck/context-info-callback.py deleted file mode 100644 index b99adc2..0000000 --- a/leakcheck/context-info-callback.py +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright (C) Jean-Paul Calderone -# See LICENSE for details. -# -# Stress tester for thread-related bugs in global_info_callback in -# src/ssl/context.c. In 0.7 and earlier, this will somewhat reliably -# segfault or abort after a few dozen to a few thousand iterations on an SMP -# machine (generally not on a UP machine) due to uses of Python/C API -# without holding the GIL. - -from itertools import count -from threading import Thread -from socket import socket - -from OpenSSL.SSL import Context, TLSv1_METHOD, Connection, WantReadError -from OpenSSL.crypto import FILETYPE_PEM, load_certificate, load_privatekey - -cleartextPrivateKeyPEM = ( - "-----BEGIN RSA PRIVATE KEY-----\n" - "MIICXAIBAAKBgQDaemNe1syksAbFFpF3aoOrZ18vB/IQNZrAjFqXPv9iieJm7+Tc\n" - "g+lA/v0qmoEKrpT2xfwxXmvZwBNM4ZhyRC3DPIFEyJV7/3IA1p5iuMY/GJI1VIgn\n" - "aikQCnrsyxtaRpsMBeZRniaVzcUJ+XnEdFGEjlo+k0xlwfVclDEMwgpXAQIDAQAB\n" - "AoGBALi0a7pMQqqgnriVAdpBVJveQtxSDVWi2/gZMKVZfzNheuSnv4amhtaKPKJ+\n" - "CMZtHkcazsE2IFvxRN/kgato9H3gJqq8nq2CkdpdLNVKBoxiCtkLfutdY4SQLtoY\n" - "USN7exk131pchsAJXYlR6mCW+ZP+E523cNwpPgsyKxVbmXSBAkEA9470fy2W0jFM\n" - "taZFslpntKSzbvn6JmdtjtvWrM1bBaeeqFiGBuQFYg46VaCUaeRWYw02jmYAsDYh\n" - "ZQavmXThaQJBAOHtlAQ0IJJEiMZr6vtVPH32fmbthSv1AUSYPzKqdlQrUnOXPQXu\n" - "z70cFoLG1TvPF5rBxbOkbQ/s8/ka5ZjPfdkCQCeC7YsO36+UpsWnUCBzRXITh4AC\n" - "7eYLQ/U1KUJTVF/GrQ/5cQrQgftwgecAxi9Qfmk4xqhbp2h4e0QAmS5I9WECQH02\n" - "0QwrX8nxFeTytr8pFGezj4a4KVCdb2B3CL+p3f70K7RIo9d/7b6frJI6ZL/LHQf2\n" - "UP4pKRDkgKsVDx7MELECQGm072/Z7vmb03h/uE95IYJOgY4nfmYs0QKA9Is18wUz\n" - "DpjfE33p0Ha6GO1VZRIQoqE24F8o5oimy3BEjryFuw4=\n" - "-----END RSA PRIVATE KEY-----\n" -) - - -cleartextCertificatePEM = ( - "-----BEGIN CERTIFICATE-----\n" - "MIICfTCCAeYCAQEwDQYJKoZIhvcNAQEEBQAwgYYxCzAJBgNVBAYTAlVTMRkwFwYD\n" - "VQQDExBweW9wZW5zc2wuc2YubmV0MREwDwYDVQQHEwhOZXcgWW9yazESMBAGA1UE\n" - "ChMJUHlPcGVuU1NMMREwDwYDVQQIEwhOZXcgWW9yazEQMA4GCSqGSIb3DQEJARYB\n" - "IDEQMA4GA1UECxMHVGVzdGluZzAeFw0wODAzMjUxOTA0MTNaFw0wOTAzMjUxOTA0\n" - "MTNaMIGGMQswCQYDVQQGEwJVUzEZMBcGA1UEAxMQcHlvcGVuc3NsLnNmLm5ldDER\n" - "MA8GA1UEBxMITmV3IFlvcmsxEjAQBgNVBAoTCVB5T3BlblNTTDERMA8GA1UECBMI\n" - "TmV3IFlvcmsxEDAOBgkqhkiG9w0BCQEWASAxEDAOBgNVBAsTB1Rlc3RpbmcwgZ8w\n" - "DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSwBsUWkXdqg6tnXy8H8hA1\n" - "msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nAE0zhmHJELcM8gUTIlXv/\n" - "cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXNxQn5ecR0UYSOWj6TTGXB\n" - "9VyUMQzCClcBAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAmm0Vzvv1O91WLl2LnF2P\n" - "q55LJdOnJbCCXIgxLdoVmvYAz1ZJq1eGKgKWI5QLgxiSzJLEU7KK//aVfiZzoCd5\n" - "RipBiEEMEV4eAY317bHPwPP+4Bj9t0l8AsDLseC5vLRHgxrLEu3bn08DYx6imB5Q\n" - "UBj849/xpszEM7BhwKE0GiQ=\n" - "-----END CERTIFICATE-----\n" -) - -count = count() - - -def go(): - port = socket() - port.bind(("", 0)) - port.listen(1) - - called = [] - - def info(conn, where, ret): - print count.next() - called.append(None) - - context = Context(TLSv1_METHOD) - context.set_info_callback(info) - context.use_certificate( - load_certificate(FILETYPE_PEM, cleartextCertificatePEM) - ) - context.use_privatekey( - load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM) - ) - - while 1: - client = socket() - client.setblocking(False) - client.connect_ex(port.getsockname()) - - clientSSL = Connection(Context(TLSv1_METHOD), client) - clientSSL.set_connect_state() - - server, ignored = port.accept() - server.setblocking(False) - - serverSSL = Connection(context, server) - serverSSL.set_accept_state() - - del called[:] - while not called: - for ssl in clientSSL, serverSSL: - try: - ssl.do_handshake() - except WantReadError: - pass - - -threads = [Thread(target=go, args=()) for i in xrange(2)] -for th in threads: - th.start() -for th in threads: - th.join() diff --git a/leakcheck/context-passphrase-callback.py b/leakcheck/context-passphrase-callback.py deleted file mode 100644 index 141ac8d..0000000 --- a/leakcheck/context-passphrase-callback.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (C) Jean-Paul Calderone -# See LICENSE for details. -# -# Stress tester for thread-related bugs in global_passphrase_callback in -# src/ssl/context.c. In 0.7 and earlier, this will somewhat reliably -# segfault or abort after a few dozen to a few thousand iterations on an SMP -# machine (generally not on a UP machine) due to uses of Python/C API -# without holding the GIL. - -from itertools import count -from threading import Thread - -from OpenSSL.SSL import Context, TLSv1_METHOD -from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM, PKey, dump_privatekey - -k = PKey() -k.generate_key(TYPE_RSA, 128) -file("pkey.pem", "w").write( - dump_privatekey(FILETYPE_PEM, k, "blowfish", "foobar") -) - -count = count() - - -def go(): - def cb(a, b, c): - print count.next() - return "foobar" - - c = Context(TLSv1_METHOD) - c.set_passwd_cb(cb) - while 1: - c.use_privatekey_file("pkey.pem") - - -threads = [Thread(target=go, args=()) for i in xrange(2)] -for th in threads: - th.start() -for th in threads: - th.join() diff --git a/leakcheck/context-verify-callback.py b/leakcheck/context-verify-callback.py deleted file mode 100644 index b9ce1d5..0000000 --- a/leakcheck/context-verify-callback.py +++ /dev/null @@ -1,112 +0,0 @@ -# Copyright (C) Jean-Paul Calderone -# See LICENSE for details. -# -# Stress tester for thread-related bugs in global_verify_callback in -# src/ssl/context.c. This will reliably segfault if context.c isn't a -# PyThreadState management technique which is compatible with the approach used -# by ssl.c. - - -from itertools import count -from threading import Thread -from socket import socket - -from OpenSSL.SSL import ( - Context, - TLSv1_METHOD, - VERIFY_PEER, - Connection, - WantReadError, -) -from OpenSSL.crypto import FILETYPE_PEM, load_certificate, load_privatekey - -cleartextPrivateKeyPEM = ( - "-----BEGIN RSA PRIVATE KEY-----\n" - "MIICXAIBAAKBgQDaemNe1syksAbFFpF3aoOrZ18vB/IQNZrAjFqXPv9iieJm7+Tc\n" - "g+lA/v0qmoEKrpT2xfwxXmvZwBNM4ZhyRC3DPIFEyJV7/3IA1p5iuMY/GJI1VIgn\n" - "aikQCnrsyxtaRpsMBeZRniaVzcUJ+XnEdFGEjlo+k0xlwfVclDEMwgpXAQIDAQAB\n" - "AoGBALi0a7pMQqqgnriVAdpBVJveQtxSDVWi2/gZMKVZfzNheuSnv4amhtaKPKJ+\n" - "CMZtHkcazsE2IFvxRN/kgato9H3gJqq8nq2CkdpdLNVKBoxiCtkLfutdY4SQLtoY\n" - "USN7exk131pchsAJXYlR6mCW+ZP+E523cNwpPgsyKxVbmXSBAkEA9470fy2W0jFM\n" - "taZFslpntKSzbvn6JmdtjtvWrM1bBaeeqFiGBuQFYg46VaCUaeRWYw02jmYAsDYh\n" - "ZQavmXThaQJBAOHtlAQ0IJJEiMZr6vtVPH32fmbthSv1AUSYPzKqdlQrUnOXPQXu\n" - "z70cFoLG1TvPF5rBxbOkbQ/s8/ka5ZjPfdkCQCeC7YsO36+UpsWnUCBzRXITh4AC\n" - "7eYLQ/U1KUJTVF/GrQ/5cQrQgftwgecAxi9Qfmk4xqhbp2h4e0QAmS5I9WECQH02\n" - "0QwrX8nxFeTytr8pFGezj4a4KVCdb2B3CL+p3f70K7RIo9d/7b6frJI6ZL/LHQf2\n" - "UP4pKRDkgKsVDx7MELECQGm072/Z7vmb03h/uE95IYJOgY4nfmYs0QKA9Is18wUz\n" - "DpjfE33p0Ha6GO1VZRIQoqE24F8o5oimy3BEjryFuw4=\n" - "-----END RSA PRIVATE KEY-----\n" -) - - -cleartextCertificatePEM = ( - "-----BEGIN CERTIFICATE-----\n" - "MIICfTCCAeYCAQEwDQYJKoZIhvcNAQEEBQAwgYYxCzAJBgNVBAYTAlVTMRkwFwYD\n" - "VQQDExBweW9wZW5zc2wuc2YubmV0MREwDwYDVQQHEwhOZXcgWW9yazESMBAGA1UE\n" - "ChMJUHlPcGVuU1NMMREwDwYDVQQIEwhOZXcgWW9yazEQMA4GCSqGSIb3DQEJARYB\n" - "IDEQMA4GA1UECxMHVGVzdGluZzAeFw0wODAzMjUxOTA0MTNaFw0wOTAzMjUxOTA0\n" - "MTNaMIGGMQswCQYDVQQGEwJVUzEZMBcGA1UEAxMQcHlvcGVuc3NsLnNmLm5ldDER\n" - "MA8GA1UEBxMITmV3IFlvcmsxEjAQBgNVBAoTCVB5T3BlblNTTDERMA8GA1UECBMI\n" - "TmV3IFlvcmsxEDAOBgkqhkiG9w0BCQEWASAxEDAOBgNVBAsTB1Rlc3RpbmcwgZ8w\n" - "DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSwBsUWkXdqg6tnXy8H8hA1\n" - "msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nAE0zhmHJELcM8gUTIlXv/\n" - "cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXNxQn5ecR0UYSOWj6TTGXB\n" - "9VyUMQzCClcBAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAmm0Vzvv1O91WLl2LnF2P\n" - "q55LJdOnJbCCXIgxLdoVmvYAz1ZJq1eGKgKWI5QLgxiSzJLEU7KK//aVfiZzoCd5\n" - "RipBiEEMEV4eAY317bHPwPP+4Bj9t0l8AsDLseC5vLRHgxrLEu3bn08DYx6imB5Q\n" - "UBj849/xpszEM7BhwKE0GiQ=\n" - "-----END CERTIFICATE-----\n" -) - -count = count() - - -def go(): - port = socket() - port.bind(("", 0)) - port.listen(1) - - called = [] - - def info(*args): - print count.next() - called.append(None) - return 1 - - context = Context(TLSv1_METHOD) - context.set_verify(VERIFY_PEER, info) - context.use_certificate( - load_certificate(FILETYPE_PEM, cleartextCertificatePEM) - ) - context.use_privatekey( - load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM) - ) - - while 1: - client = socket() - client.setblocking(False) - client.connect_ex(port.getsockname()) - - clientSSL = Connection(context, client) - clientSSL.set_connect_state() - - server, ignored = port.accept() - server.setblocking(False) - - serverSSL = Connection(context, server) - serverSSL.set_accept_state() - - del called[:] - while not called: - for ssl in clientSSL, serverSSL: - try: - ssl.send("foo") - except WantReadError, e: - pass - - -threads = [Thread(target=go, args=()) for i in xrange(2)] -for th in threads: - th.start() -for th in threads: - th.join() diff --git a/leakcheck/crypto.py b/leakcheck/crypto.py deleted file mode 100644 index c995610..0000000 --- a/leakcheck/crypto.py +++ /dev/null @@ -1,191 +0,0 @@ -# Copyright (C) Jean-Paul Calderone -# See LICENSE for details. - -import sys - -from OpenSSL.crypto import ( - FILETYPE_PEM, - TYPE_DSA, - Error, - PKey, - X509, - load_privatekey, - CRL, - Revoked, - get_elliptic_curves, - _X509_REVOKED_dup, -) - -from OpenSSL._util import lib as _lib - - -class BaseChecker(object): - def __init__(self, iterations): - self.iterations = iterations - - -class Checker_X509_get_pubkey(BaseChecker): - """ - Leak checks for L{X509.get_pubkey}. - """ - - def check_exception(self): - """ - Call the method repeatedly such that it will raise an exception. - """ - for i in xrange(self.iterations): - cert = X509() - try: - cert.get_pubkey() - except Error: - pass - - def check_success(self): - """ - Call the method repeatedly such that it will return a PKey object. - """ - small = xrange(3) - for i in xrange(self.iterations): - key = PKey() - key.generate_key(TYPE_DSA, 256) - for i in small: - cert = X509() - cert.set_pubkey(key) - for i in small: - cert.get_pubkey() - - -class Checker_load_privatekey(BaseChecker): - """ - Leak checks for :py:obj:`load_privatekey`. - """ - - ENCRYPTED_PEM = """\ ------BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: BF-CBC,3763C340F9B5A1D0 - -a/DO10mLjHLCAOG8/Hc5Lbuh3pfjvcTZiCexShP+tupkp0VxW2YbZjML8uoXrpA6 -fSPUo7cEC+r96GjV03ZIVhjmsxxesdWMpfkzXRpG8rUbWEW2KcCJWdSX8bEkuNW3 -uvAXdXZwiOrm56ANDo/48gj27GcLwnlA8ld39+ylAzkUJ1tcMVzzTjfcyd6BMFpR -Yjg23ikseug6iWEsZQormdl0ITdYzmFpM+YYsG7kmmmi4UjCEYfb9zFaqJn+WZT2 -qXxmo2ZPFzmEVkuB46mf5GCqMwLRN2QTbIZX2+Dljj1Hfo5erf5jROewE/yzcTwO -FCB5K3c2kkTv2KjcCAimjxkE+SBKfHg35W0wB0AWkXpVFO5W/TbHg4tqtkpt/KMn -/MPnSxvYr/vEqYMfW4Y83c45iqK0Cyr2pwY60lcn8Kk= ------END RSA PRIVATE KEY----- -""" - - def check_load_privatekey_callback(self): - """ - Call the function with an encrypted PEM and a passphrase callback. - """ - for i in xrange(self.iterations * 10): - load_privatekey( - FILETYPE_PEM, self.ENCRYPTED_PEM, lambda *args: "hello, secret" - ) - - def check_load_privatekey_callback_incorrect(self): - """ - Call the function with an encrypted PEM and a passphrase callback which - returns the wrong passphrase. - """ - for i in xrange(self.iterations * 10): - try: - load_privatekey( - FILETYPE_PEM, - self.ENCRYPTED_PEM, - lambda *args: "hello, public", - ) - except Error: - pass - - def check_load_privatekey_callback_wrong_type(self): - """ - Call the function with an encrypted PEM and a passphrase callback which - returns a non-string. - """ - for i in xrange(self.iterations * 10): - try: - load_privatekey( - FILETYPE_PEM, self.ENCRYPTED_PEM, lambda *args: {} - ) - except ValueError: - pass - - -class Checker_CRL(BaseChecker): - """ - Leak checks for L{CRL.add_revoked} and L{CRL.get_revoked}. - """ - - def check_add_revoked(self): - """ - Call the add_revoked method repeatedly on an empty CRL. - """ - for i in xrange(self.iterations * 200): - CRL().add_revoked(Revoked()) - - def check_get_revoked(self): - """ - Create a CRL object with 100 Revoked objects, then call the - get_revoked method repeatedly. - """ - crl = CRL() - for i in xrange(100): - crl.add_revoked(Revoked()) - for i in xrange(self.iterations): - crl.get_revoked() - - -class Checker_X509_REVOKED_dup(BaseChecker): - """ - Leak checks for :py:obj:`_X509_REVOKED_dup`. - """ - - def check_X509_REVOKED_dup(self): - """ - Copy an empty Revoked object repeatedly. The copy is not garbage - collected, therefore it needs to be manually freed. - """ - for i in xrange(self.iterations * 100): - revoked_copy = _X509_REVOKED_dup(Revoked()._revoked) - _lib.X509_REVOKED_free(revoked_copy) - - -class Checker_EllipticCurve(BaseChecker): - """ - Leak checks for :py:obj:`_EllipticCurve`. - """ - - def check_to_EC_KEY(self): - """ - Repeatedly create an EC_KEY* from an :py:obj:`_EllipticCurve`. The - structure should be automatically garbage collected. - """ - curves = get_elliptic_curves() - if curves: - curve = next(iter(curves)) - for i in xrange(self.iterations * 1000): - curve._to_EC_KEY() - - -def vmsize(): - return [x for x in file("/proc/self/status").readlines() if "VmSize" in x] - - -def main(iterations="1000"): - iterations = int(iterations) - for klass in globals(): - if klass.startswith("Checker_"): - klass = globals()[klass] - print klass - checker = klass(iterations) - for meth in dir(checker): - if meth.startswith("check_"): - print "\t", meth, vmsize(), "...", - getattr(checker, meth)() - print vmsize() - - -if __name__ == "__main__": - main(*sys.argv[1:]) diff --git a/leakcheck/dhparam.pem b/leakcheck/dhparam.pem deleted file mode 100644 index 9d33a4a..0000000 --- a/leakcheck/dhparam.pem +++ /dev/null @@ -1,4 +0,0 @@ ------BEGIN DH PARAMETERS----- -MEYCQQDM2LbvAjF5ahXHOUdDR09Vw/7kxjF/euWhNKBqUQQYT7FDSAMCCMq+Jhno -BKxWEDhlxR1Q1VZ4H/NVTAGtWai7AgEC ------END DH PARAMETERS----- diff --git a/leakcheck/thread-crash.py b/leakcheck/thread-crash.py deleted file mode 100644 index bd9426d..0000000 --- a/leakcheck/thread-crash.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright (C) Jean-Paul Calderone -# See LICENSE for details. -# -# Stress tester for thread-related bugs in ssl_Connection_send and -# ssl_Connection_recv in src/ssl/connection.c for usage of a single -# Connection object simultaneously in multiple threads. In 0.7 and earlier, -# this will somewhat reliably cause Python to abort with a "tstate mix-up" -# almost immediately, due to the incorrect sharing between threads of the -# `tstate` field of the connection object. - - -from socket import socket -from threading import Thread - -from OpenSSL.SSL import Connection, Context, TLSv1_METHOD - - -def send(conn): - while 1: - for i in xrange(1024 * 32): - conn.send("x") - print "Sent 32KB on", hex(id(conn)) - - -def recv(conn): - while 1: - for i in xrange(1024 * 64): - conn.recv(1) - print "Received 64KB on", hex(id(conn)) - - -def main(): - port = socket() - port.bind(("", 0)) - port.listen(5) - - client = socket() - client.setblocking(False) - client.connect_ex(port.getsockname()) - client.setblocking(True) - - server = port.accept()[0] - - clientCtx = Context(TLSv1_METHOD) - clientCtx.set_cipher_list("ALL:ADH") - clientCtx.load_tmp_dh("dhparam.pem") - - sslClient = Connection(clientCtx, client) - sslClient.set_connect_state() - - serverCtx = Context(TLSv1_METHOD) - serverCtx.set_cipher_list("ALL:ADH") - serverCtx.load_tmp_dh("dhparam.pem") - - sslServer = Connection(serverCtx, server) - sslServer.set_accept_state() - - t1 = Thread(target=send, args=(sslClient,)) - t2 = Thread(target=send, args=(sslServer,)) - t3 = Thread(target=recv, args=(sslClient,)) - t4 = Thread(target=recv, args=(sslServer,)) - - t1.start() - t2.start() - t3.start() - t4.start() - t1.join() - t2.join() - t3.join() - t4.join() - - -main() diff --git a/leakcheck/thread-key-gen.py b/leakcheck/thread-key-gen.py deleted file mode 100644 index 346ad7b..0000000 --- a/leakcheck/thread-key-gen.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (C) Jean-Paul Calderone -# See LICENSE for details. -# -# Stress tester for thread-related bugs in RSA and DSA key generation. 0.12 and -# older held the GIL during these operations. Subsequent versions release it -# during them. - -from threading import Thread - -from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, PKey - - -def generate_rsa(): - keys = [] - for i in range(100): - key = PKey() - key.generate_key(TYPE_RSA, 1024) - keys.append(key) - - -def generate_dsa(): - keys = [] - for i in range(100): - key = PKey() - key.generate_key(TYPE_DSA, 512) - keys.append(key) - - -def main(): - threads = [] - for i in range(3): - t = Thread(target=generate_rsa, args=()) - threads.append(t) - t = Thread(target=generate_dsa, args=()) - threads.append(t) - - for t in threads: - t.start() - - -main() -- cgit v1.2.1