From 0783e72f9cb5fd72e8e3ba4af76b1a5040a4b03f Mon Sep 17 00:00:00 2001 From: Glyph Date: Fri, 23 Dec 2016 12:31:55 -0800 Subject: [PATCH 1/6] generate certificates that don't provoke warnings. --- src/twisted/test/test_sslverify.py | 101 ++++++++++++++++++++++++----- 1 file changed, 84 insertions(+), 17 deletions(-) diff --git a/src/twisted/test/test_sslverify.py b/src/twisted/test/test_sslverify.py index eaac5b84cde..a39de573907 100644 --- a/src/twisted/test/test_sslverify.py +++ b/src/twisted/test/test_sslverify.py @@ -10,6 +10,7 @@ import sys import itertools +import datetime from zope.interface import implementer from twisted.python.reflect import requireModule @@ -24,6 +25,17 @@ from OpenSSL.crypto import PKey, X509 from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM + from cryptography import x509 + from cryptography.hazmat.backends import default_backend + from cryptography.hazmat.primitives import hashes + from cryptography.hazmat.primitives.asymmetric import rsa + from cryptography.hazmat.primitives.serialization import ( + PrivateFormat, NoEncryption + ) + + from cryptography.x509.oid import NameOID + from cryptography.hazmat.primitives.serialization import Encoding + try: ctx = SSL.Context(SSL.SSLv23_METHOD) ctx.set_npn_advertise_callback(lambda c: None) @@ -137,33 +149,88 @@ def makeCertificate(**kw): -def certificatesForAuthorityAndServer(commonName=b'example.com'): +def certificatesForAuthorityAndServer(serviceIdentity=b'example.com'): """ Create a self-signed CA certificate and server certificate signed by the CA. - @param commonName: The C{commonName} to embed in the certificate. - @type commonName: L{bytes} + @param serviceIdentity: The identity (hostname) of the server. + @type serviceIdentity: L{bytes} @return: a 2-tuple of C{(certificate_authority_certificate, server_certificate)} @rtype: L{tuple} of (L{sslverify.Certificate}, L{sslverify.PrivateCertificate}) """ - serverDN = sslverify.DistinguishedName(commonName=commonName) - serverKey = sslverify.KeyPair.generate() - serverCertReq = serverKey.certificateRequest(serverDN) - - caDN = sslverify.DistinguishedName(commonName=b'CA') - caKey= sslverify.KeyPair.generate() - caCertReq = caKey.certificateRequest(caDN) - caSelfCertData = caKey.signCertificateRequest( - caDN, caCertReq, lambda dn: True, 516) - caSelfCert = caKey.newCertificate(caSelfCertData) - - serverCertData = caKey.signCertificateRequest( - caDN, serverCertReq, lambda dn: True, 516) - serverCert = serverKey.newCertificate(serverCertData) + commonNameForCA = x509.Name( + [x509.NameAttribute(NameOID.COMMON_NAME, u'Testing Example CA')] + ) + commonNameForServer = x509.Name( + [x509.NameAttribute(NameOID.COMMON_NAME, u'Testing Example Server')] + ) + oneDay = datetime.timedelta(1, 0, 0) + privateKeyForCA = rsa.generate_private_key( + public_exponent=65537, + key_size=4096, + backend=default_backend() + ) + publicKeyForCA = privateKeyForCA.public_key() + caCertificate = ( + x509.CertificateBuilder() + .subject_name(commonNameForCA) + .issuer_name(commonNameForCA) + .not_valid_before(datetime.datetime.today() - oneDay) + .not_valid_after(datetime.datetime.today() + oneDay) + .serial_number(x509.random_serial_number()) + .public_key(publicKeyForCA) + .add_extension( + x509.BasicConstraints(ca=True, path_length=9), critical=True, + ) + .sign( + private_key=privateKeyForCA, algorithm=hashes.SHA256(), + backend=default_backend() + ) + ) + privateKeyForServer = rsa.generate_private_key( + public_exponent=65537, + key_size=4096, + backend=default_backend() + ) + publicKeyForServer = privateKeyForServer.public_key() + serverCertificate = ( + x509.CertificateBuilder() + .subject_name(commonNameForServer) + .issuer_name(commonNameForCA) + .not_valid_before(datetime.datetime.today() - oneDay) + .not_valid_after(datetime.datetime.today() + oneDay) + .serial_number(x509.random_serial_number()) + .public_key(publicKeyForServer) + .add_extension( + x509.BasicConstraints(ca=False, path_length=None), critical=True, + ) + .add_extension( + x509.SubjectAlternativeName( + [x509.DNSName(serviceIdentity.decode('ascii'))] + ), + critical=True, + ) + .sign( + private_key=privateKeyForCA, algorithm=hashes.SHA256(), + backend=default_backend() + ) + ) + caSelfCert = sslverify.Certificate.loadPEM( + caCertificate.public_bytes(Encoding.PEM) + ) + serverCert = sslverify.PrivateCertificate.loadPEM( + b"\n".join([privateKeyForServer.private_bytes( + Encoding.PEM, + PrivateFormat.TraditionalOpenSSL, + NoEncryption(), + ), + serverCertificate.public_bytes(Encoding.PEM)]) + ) + return caSelfCert, serverCert From a5584bca11854f18e551036689151adfd048664a Mon Sep 17 00:00:00 2001 From: Glyph Date: Fri, 23 Dec 2016 12:33:41 -0800 Subject: [PATCH 2/6] topfile --- src/twisted/topfiles/8962.misc | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/twisted/topfiles/8962.misc diff --git a/src/twisted/topfiles/8962.misc b/src/twisted/topfiles/8962.misc new file mode 100644 index 00000000000..e69de29bb2d From fc7b21f90176d0cd1996ed41f8d1bc8fad79eb5a Mon Sep 17 00:00:00 2001 From: Glyph Date: Fri, 23 Dec 2016 12:50:06 -0800 Subject: [PATCH 3/6] fix the one place it was a kwarg --- src/twisted/web/test/test_agent.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/twisted/web/test/test_agent.py b/src/twisted/web/test/test_agent.py index 626ecd3b355..f8a1fe73ddb 100644 --- a/src/twisted/web/test/test_agent.py +++ b/src/twisted/web/test/test_agent.py @@ -1465,8 +1465,7 @@ def integrationTest(self, hostName, expectedAddress, addressType): """ Wrap L{AgentTestsMixin.integrationTest} with TLS. """ - authority, server = certificatesForAuthorityAndServer( - commonName=hostName) + authority, server = certificatesForAuthorityAndServer(hostName) def tlsify(serverFactory): return TLSMemoryBIOFactory(server.options(), False, serverFactory) def tlsagent(reactor): From a20109774701bdb0ecf22883047e955788eed922 Mon Sep 17 00:00:00 2001 From: Glyph Date: Fri, 23 Dec 2016 13:20:10 -0800 Subject: [PATCH 4/6] switch to unicode, since it seems that's what most things want --- src/twisted/test/test_sslverify.py | 10 ++++++---- src/twisted/web/test/test_agent.py | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/twisted/test/test_sslverify.py b/src/twisted/test/test_sslverify.py index a39de573907..0119e4a8473 100644 --- a/src/twisted/test/test_sslverify.py +++ b/src/twisted/test/test_sslverify.py @@ -149,13 +149,13 @@ def makeCertificate(**kw): -def certificatesForAuthorityAndServer(serviceIdentity=b'example.com'): +def certificatesForAuthorityAndServer(serviceIdentity=u'example.com'): """ Create a self-signed CA certificate and server certificate signed by the CA. @param serviceIdentity: The identity (hostname) of the server. - @type serviceIdentity: L{bytes} + @type serviceIdentity: L{unicode} @return: a 2-tuple of C{(certificate_authority_certificate, server_certificate)} @@ -210,7 +210,7 @@ def certificatesForAuthorityAndServer(serviceIdentity=b'example.com'): ) .add_extension( x509.SubjectAlternativeName( - [x509.DNSName(serviceIdentity.decode('ascii'))] + [x509.DNSName(serviceIdentity)] ), critical=True, ) @@ -1768,7 +1768,9 @@ def serviceIdentitySetup(self, clientHostname, serverHostname, @rtype: see L{connectedServerAndClient}. """ serverIDNA = _idnaBytes(serverHostname) - serverCA, serverCert = certificatesForAuthorityAndServer(serverIDNA) + serverCA, serverCert = certificatesForAuthorityAndServer( + serverHostname + ) other = {} passClientCert = None clientCA, clientCert = certificatesForAuthorityAndServer(u'client') diff --git a/src/twisted/web/test/test_agent.py b/src/twisted/web/test/test_agent.py index f8a1fe73ddb..a84bc0c9488 100644 --- a/src/twisted/web/test/test_agent.py +++ b/src/twisted/web/test/test_agent.py @@ -1465,7 +1465,8 @@ def integrationTest(self, hostName, expectedAddress, addressType): """ Wrap L{AgentTestsMixin.integrationTest} with TLS. """ - authority, server = certificatesForAuthorityAndServer(hostName) + authority, server = certificatesForAuthorityAndServer(hostName + .decode('ascii')) def tlsify(serverFactory): return TLSMemoryBIOFactory(server.options(), False, serverFactory) def tlsagent(reactor): From fd2f26561693b3b27fd15ab20c02a631886c1b11 Mon Sep 17 00:00:00 2001 From: Glyph Date: Fri, 23 Dec 2016 13:29:47 -0800 Subject: [PATCH 5/6] one more invocation --- src/twisted/test/test_sslverify.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/twisted/test/test_sslverify.py b/src/twisted/test/test_sslverify.py index 0119e4a8473..fddd335a007 100644 --- a/src/twisted/test/test_sslverify.py +++ b/src/twisted/test/test_sslverify.py @@ -1767,7 +1767,6 @@ def serviceIdentitySetup(self, clientHostname, serverHostname, @return: see L{connectedServerAndClient}. @rtype: see L{connectedServerAndClient}. """ - serverIDNA = _idnaBytes(serverHostname) serverCA, serverCert = certificatesForAuthorityAndServer( serverHostname ) @@ -1792,7 +1791,7 @@ def serviceIdentitySetup(self, clientHostname, serverHostname, serverContextSetup(serverOpts.getContext()) if not validCertificate: serverCA, otherServer = certificatesForAuthorityAndServer( - serverIDNA + serverHostname ) if buggyInfoCallback: def broken(*a, **k): From 18cae5b765a8b7122d883ce8c186d50a25f5aa67 Mon Sep 17 00:00:00 2001 From: Glyph Date: Fri, 23 Dec 2016 13:32:04 -0800 Subject: [PATCH 6/6] pyflakes --- src/twisted/test/test_sslverify.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/twisted/test/test_sslverify.py b/src/twisted/test/test_sslverify.py index fddd335a007..5ad481f4ace 100644 --- a/src/twisted/test/test_sslverify.py +++ b/src/twisted/test/test_sslverify.py @@ -63,7 +63,7 @@ from twisted.trial import unittest, util from twisted.internet import protocol, defer, reactor -from twisted.internet._idna import _idnaText, _idnaBytes +from twisted.internet._idna import _idnaText from twisted.internet.error import CertificateError, ConnectionLost from twisted.internet import interfaces