Exemple #1
0
    def test_client_chain_certificate(self):
        """
        A certificate chain in the *client-certificate* section of in the kube
        configuration file is used to configure the TLS context used when
        connecting to the API server.
        """
        def sign_ca_cert(key, requestObject, dn):
            from OpenSSL.crypto import X509, X509Extension
            from twisted.internet.ssl import Certificate

            req = requestObject.original
            cert = X509()
            dn._copyInto(cert.get_issuer())
            cert.set_subject(req.get_subject())
            cert.set_pubkey(req.get_pubkey())
            cert.gmtime_adj_notBefore(0)
            cert.gmtime_adj_notAfter(60 * 60)
            cert.set_serial_number(1)
            cert.add_extensions([
                X509Extension(b"basicConstraints", True, b"CA:TRUE"),
                # Not necessarily a good way to populate subjectAltName but it
                # quiets the deprecation warning we get from service_identity.
                X509Extension(b"subjectAltName", True, b"DNS:" + dn.commonName),
            ])
            cert.sign(key.original, "sha256")
            return Certificate(cert)

        ca_key = KeyPair.generate()
        ca_req = ca_key.requestObject(DN(commonName="kubernetes"))
        ca_cert = sign_ca_cert(ca_key, ca_req, DN(commonName="kubernetes"))

        intermediate_key = KeyPair.generate()
        intermediate_req = intermediate_key.requestObject(DN(commonName="intermediate"))
        intermediate_cert = sign_ca_cert(ca_key, intermediate_req, DN(commonName="kubernetes"))

        client_key = KeyPair.generate()
        client_req = client_key.requestObject(DN(commonName="client"))
        client_cert = intermediate_key.signRequestObject(DN(commonName="intermediate"), client_req, 1)

        chain = b"".join([
            client_cert.dumpPEM(),
            intermediate_cert.dumpPEM(),
        ])

        FilePath("ca.key").setContent(ca_key.dump(FILETYPE_PEM))
        FilePath("ca.crt").setContent(ca_cert.dump(FILETYPE_PEM))
        FilePath("intermediate.crt").setContent(intermediate_cert.dump(FILETYPE_PEM))
        FilePath("client.key").setContent(client_key.dump(FILETYPE_PEM))
        FilePath("client.crt").setContent(client_cert.dump(FILETYPE_PEM))
        FilePath("chain.crt").setContent(chain)

        config = self.write_config(ca_cert, chain, client_key)
        kubernetes = lambda reactor: network_kubernetes_from_context(
            reactor, "foo-ctx", path=config,
        )
        return self.check_tls_config(ca_key, ca_cert, kubernetes)
Exemple #2
0
    def setUp(self):
        """
        Create a L{PantheonHTTPChecker} pointed at a mock authentication service
        with some simple site and user information.
        """
        self.site = 'example.com'
        self.cwd = '/some/path'
        self.uid = 1542
        self.username = '******'
        self.password = '******'
        keyString = FilePath(__file__).sibling('id_rsa').getContent()
        self.privateKey = Key.fromString(keyString)

        caKeyString = FilePath(__file__).sibling('cakey.pem').getContent()
        self.caKey = KeyPair.load(caKeyString, FILETYPE_PEM)
        caCertString = FilePath(__file__).sibling('cacert.pem').getContent()
        self.caCert = PrivateCertificate.load(
            caCertString, self.caKey, FILETYPE_PEM)

        self.resource = MockPantheonAuthResource(
            sites={self.site: [self.username]},
            authorizations={self.site: dict(cwd=self.cwd, uid=self.uid)},
            passwords={self.username: self.password},
            keys={self.username: self.privateKey},
            )
        self.server = MockPantheonAuthServer(
            reactor, self.resource, self.caCert)
        self.server.startService()
        self.addCleanup(self.server.stopService)
Exemple #3
0
    def getServerContext(self):
        """
        Generate a new L{OpenSSL.SSL.Context} object configured to use a
        certificate signed by C{self.ca} and only accept connections from peers
        which are also using a certificate signed by C{self.ca}.
        """
        # Generate a new key for the server and have the CA sign a certificate
        # for it.
        key = KeyPair.generate(size=512)
        req = key.certificateRequest(DN(commonName='localhost'))
        certData = self.ca.signCertificateRequest(req, lambda dn: True, 1)
        cert = PrivateCertificate.load(certData, key)

        # Use the new key/certificate
        context = Context(TLSv1_METHOD)
        context.use_privatekey(key.original)
        context.use_certificate(cert.original)
        context.check_privatekey()

        # Allow peer certificates signed by the CA
        store = context.get_cert_store()
        store.add_cert(self.ca.original)

        # Verify the peer certificate and require that they have one.
        def verify(conn, cert, errno, depth, preverify_ok):
            return preverify_ok
        context.set_verify(VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify)
        return context
 def pems():
     for i in count():
         key = KeyPair.generate()
         cert = key.selfSignedCert(i, commonName=u"lae_automation testing")
         pem = PrivateCertificate.fromCertificateAndKeyPair(cert,
                                                            key).dumpPEM()
         yield pem.decode("ascii")
Exemple #5
0
 def test_ssl(self):
     """
     When passed an SSL strports description, L{clientFromString} returns a
     L{SSL4ClientEndpoint} instance initialized with the values from the
     string.
     """
     reactor = object()
     client = endpoints.clientFromString(
         reactor, "ssl:host=example.net:port=4321:privateKey=%s:"
         "certKey=%s:bindAddress=10.0.0.3:timeout=3:caCertsDir=%s" %
         (escapedPEMPathName, escapedPEMPathName, escapedCAsPathName))
     self.assertIsInstance(client, endpoints.SSL4ClientEndpoint)
     self.assertIdentical(client._reactor, reactor)
     self.assertEquals(client._host, "example.net")
     self.assertEquals(client._port, 4321)
     self.assertEquals(client._timeout, 3)
     self.assertEquals(client._bindAddress, "10.0.0.3")
     certOptions = client._sslContextFactory
     self.assertIsInstance(certOptions, CertificateOptions)
     ctx = certOptions.getContext()
     self.assertIsInstance(ctx, ContextType)
     self.assertEquals(Certificate(certOptions.certificate),
                       testCertificate)
     privateCert = PrivateCertificate(certOptions.certificate)
     privateCert._setPrivateKey(KeyPair(certOptions.privateKey))
     self.assertEquals(privateCert, testPrivateCertificate)
     expectedCerts = [
         Certificate.loadPEM(x.getContent()) for x in
         [casPath.child("thing1.pem"),
          casPath.child("thing2.pem")]
         if x.basename().lower().endswith('.pem')
     ]
     self.assertEquals([Certificate(x) for x in certOptions.caCerts],
                       expectedCerts)
Exemple #6
0
def clientCertFor(name):
    signingCert = getCAPrivateCert()
    clientKey = KeyPair.generate(size=4096)
    csr = clientKey.requestObject(DN(CN=name), "sha1")
    clientCert = signingCert.signRequestObject(
        csr, serialNumber=1, digestAlgorithm="sha1")
    return PrivateCertificate.fromCertificateAndKeyPair(clientCert, clientKey)
Exemple #7
0
def get_context_factory(cert_path, pkey_path):
    """OpenSSL context factory.

    Generates an OpenSSL context factory using Twisted's CertificateOptions class.
    This will keep a server cipher order.

    Args:
        cert_path (string): The path to the certificate file
        pkey_path (string): The path to the private key file

    Returns:
        twisted.internet.ssl.CertificateOptions: An OpenSSL context factory
    """

    with open(cert_path) as cert:
        certificate = Certificate.loadPEM(cert.read()).original
    with open(pkey_path) as pkey:
        private_key = KeyPair.load(pkey.read(), FILETYPE_PEM).original
    ciphers = AcceptableCiphers.fromOpenSSLCipherString(TLS_CIPHERS)
    cert_options = CertificateOptions(
        privateKey=private_key,
        certificate=certificate,
        raiseMinimumTo=TLSVersion.TLSv1_2,
        acceptableCiphers=ciphers,
    )
    ctx = cert_options.getContext()
    ctx.use_certificate_chain_file(cert_path)
    ctx.set_options(SSL_OP_NO_RENEGOTIATION)

    return cert_options
Exemple #8
0
def flocker_keypair():
    """
    Create a new 4096-bit RSA key pair.
    """
    return ComparableKeyPair(
        keypair=KeyPair.generate(crypto.TYPE_RSA, size=4096)
    )
Exemple #9
0
def flocker_keypair():
    """
    Create a new 4096-bit RSA key pair.
    """
    return ComparableKeyPair(
        keypair=KeyPair.generate(crypto.TYPE_RSA, size=4096)
    )
Exemple #10
0
    def testBadCertRequestSubject(self):
        kp = KeyPair.generate()
        subject = DistinguishedName(commonName='HACKERX',
                                    localityName='INTERNETANIA')
        reqobj = kp.requestObject(subject)

        fakereq = kp.requestObject(subject)
        ssigned = kp.signRequestObject(subject, fakereq, 1)
        certpair = PrivateCertificate.fromCertificateAndKeyPair
        fakecert = certpair(ssigned, kp)
        apc = self.serverService2.certificateStorage.addPrivateCertificate

        def _2(secured):
            D = secured.callRemote(
                q2q.Sign,
                certificate_request=reqobj,
                password='******')
            def _1(dcert):
                cert = dcert['certificate']
                privcert = certpair(cert, kp)
                apc(str(self.fromAddress), privcert)
            return D.addCallback(_1)

        d = self.serverService2.getSecureConnection(
            self.fromAddress, self.fromAddress.domainAddress(), authorize=False,
            usePrivateCertificate=fakecert,
            ).addCallback(_2)

        def unexpectedSuccess(result):
            self.fail("Expected BadCertificateRequest, got %r" % (result,))
        def expectedFailure(err):
            err.trap(q2q.BadCertificateRequest)
        d.addCallbacks(unexpectedSuccess, expectedFailure)
        return d
Exemple #11
0
def clientCertFor(p_name):
    l_signingCert = getCAPrivateCert()
    l_clientKey = KeyPair.generate(size = 4096)
    l_csr = l_clientKey.requestObject(DN(CN = p_name), "sha1")
    l_clientCert = l_signingCert.signRequestObject(
        l_csr, serialNumber = 1, digestAlgorithm = "sha1")
    return PrivateCertificate.fromCertificateAndKeyPair(l_clientCert, l_clientKey)
Exemple #12
0
def generate_keypair():
    """
    Create a new 4096-bit RSA key pair.
    """
    return FlockerKeyPair(
        keypair=KeyPair.generate(crypto.TYPE_RSA, size=4096)
    )
Exemple #13
0
def clientCertFor(name):
    signingCert = getCAPrivateCert()
    clientKey = KeyPair.generate(size=4096)
    csr = clientKey.requestObject(DN(CN=name), "sha1")
    clientCert = signingCert.signRequestObject(csr,
                                               serialNumber=1,
                                               digestAlgorithm="sha1")
    return PrivateCertificate.fromCertificateAndKeyPair(clientCert, clientKey)
 def getServerContext(self):
     """
     Return a new SSL context suitable for use in a test server.
     """
     pem = self._pem.getContent()
     cert = PrivateCertificate.load(
         pem, KeyPair.load(pem, FILETYPE_PEM), FILETYPE_PEM)
     return cert.options()
Exemple #15
0
 def getServerContext(self):
     """
     Return a new SSL context suitable for use in a test server.
     """
     cert = PrivateCertificate.load(
         self._certificateText,
         KeyPair.load(self._privateKeyText, FILETYPE_PEM), FILETYPE_PEM)
     return cert.options()
Exemple #16
0
 def getServerContext(self):
     """
     Return a new SSL context suitable for use in a test server.
     """
     pem = self._pem.getContent()
     cert = PrivateCertificate.load(
         pem, KeyPair.load(pem, FILETYPE_PEM), FILETYPE_PEM)
     return cert.options()
Exemple #17
0
def getCAPrivateCert():
    privatePath = FilePath(b"ca-private-cert.pem")
    if privatePath.exists():
        return PrivateCertificate.loadPEM(privatePath.getContent())
    else:
        caKey = KeyPair.generate(size=4096)
        caCert = caKey.selfSignedCert(1, CN="the-authority")
        privatePath.setContent(caCert.dumpPEM())
        return caCert
Exemple #18
0
def getCAPrivateCert():
    l_privatePath = FilePath(b"ca-private-cert.pem")
    if l_privatePath.exists():
        return PrivateCertificate.loadPEM(l_privatePath.getContent())
    else:
        l_caKey = KeyPair.generate(size=4096)
        l_caCert = l_caKey.selfSignedCert(1, CN="the-authority")
        l_privatePath.setContent(l_caCert.dumpPEM())
        return l_caCert
Exemple #19
0
def clientCertFor(p_name):
    l_signingCert = getCAPrivateCert()
    l_clientKey = KeyPair.generate(size=4096)
    l_csr = l_clientKey.requestObject(DN(CN=p_name), "sha1")
    l_clientCert = l_signingCert.signRequestObject(l_csr,
                                                   serialNumber=1,
                                                   digestAlgorithm="sha1")
    return PrivateCertificate.fromCertificateAndKeyPair(
        l_clientCert, l_clientKey)
Exemple #20
0
def requestCert(config):
    subject = config['subject']
    path = config['path']

    store = yield config.parent.storeDeferred

    key = KeyPair.loadPEM(path.getContent())
    req = generateCertificateRequest(key, subject)
    yield store.submitCertificateRequest(req)
Exemple #21
0
 def getServerContext(self):
     """
     Return a new SSL context suitable for use in a test server.
     """
     cert = PrivateCertificate.load(
         self._certificateText,
         KeyPair.load(self._privateKeyText, FILETYPE_PEM),
         FILETYPE_PEM)
     return cert.options()
Exemple #22
0
def makeCert(cn):
    """
    Create a self-signed cert.
    """
    sharedDN = DN(CN=cn)
    key = KeyPair.generate()
    cr = key.certificateRequest(sharedDN)
    sscrd = key.signCertificateRequest(sharedDN, cr, lambda dn: True, 1)
    return key.newCertificate(sscrd)
def new_tahoe_configuration(deploy_config, bucketname, key_prefix, publichost, privatehost, introducer_port, storageserver_port):
    """
    Create brand new secrets and configuration for use by an
    introducer/storage pair.
    """
    base_name = dict(
        organizationName=b"Least Authority Enterprises",
        organizationalUnitName=b"S4",
        emailAddress=bucketname,
    )

    keypair = KeyPair.generate(size=2048)
    introducer_certificate = keypair.selfSignedCert(
        serialNumber=1,
        commonName=b"introducer",
        **base_name
    )
    storage_certificate = keypair.selfSignedCert(
        serialNumber=1,
        commonName=b"storage",
        **base_name
    )
    def pem(key, cert):
        return b"\n".join((key.dump(FILETYPE_PEM), cert.dump(FILETYPE_PEM)))

    introducer_tub = Tub(certData=pem(keypair, introducer_certificate))
    introducer_tub.setLocation("{}:{}".format(publichost, introducer_port))
    storage_tub = Tub(certData=pem(keypair, storage_certificate))

    return marshal_tahoe_configuration(
        introducer_pem=introducer_tub.getCertData().strip(),

        storage_pem=storage_tub.getCertData().strip(),
        storage_privkey=keyutil.make_keypair()[0] + b"\n",

        introducer_port=introducer_port,
        storageserver_port=storageserver_port,

        bucket_name=bucketname,
        key_prefix=key_prefix,
        publichost=publichost,
        privatehost=privatehost,
        # The object of the reference is irrelevant.  The furl will
        # get hooked up to something else when Tahoe really runs.
        # Just need to pass something _weak referenceable_!  Which
        # rules out a lot of things...
        introducer_furl=introducer_tub.registerReference(introducer_tub),

        s3_access_key_id=deploy_config.s3_access_key_id,
        s3_secret_key=deploy_config.s3_secret_key,

        log_gatherer_furl=deploy_config.log_gatherer_furl,
        stats_gatherer_furl=deploy_config.stats_gatherer_furl,
    )
Exemple #24
0
def makeCertRequest(cn):
    """
    Create a certificate request with the given common name.

    @param cn: Common Name to use in certificate request.
    @type cn: L{bytes}

    @return: Certificate request.
    @rtype: L{CertificateRequest}
    """
    key = KeyPair.generate()
    return key.certificateRequest(DN(CN=cn))
Exemple #25
0
    def start_ssl(self):
        log.debug("Enabling SSL with PKey: %s, Cert: %s", self.pkey, self.cert)
        check_ssl_keys()

        with open(configmanager.get_config_dir(self.cert)) as cert:
            certificate = Certificate.loadPEM(cert.read()).original
        with open(configmanager.get_config_dir(self.pkey)) as pkey:
            private_key = KeyPair.load(pkey.read(), FILETYPE_PEM).original
        options = CertificateOptions(privateKey=private_key, certificate=certificate, method=SSL.SSLv23_METHOD)
        options.getContext().set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3)

        self.socket = reactor.listenSSL(self.port, self.site, options)
        log.info("Serving on %s:%s view at https://127.0.0.1:%s", "0.0.0.0", self.port, self.port)
Exemple #26
0
def createSSLCertificate(opts):
    sslopt = {}
    for x, y in (('country', 'C'), ('state', 'ST'), ('city', 'L'),
                 ('organization', 'O'), ('unit', 'OU'), ('hostname', 'CN'),
                 ('email', 'emailAddress')):
        sslopt[y] = opts[x]
    serialNumber = int(opts['serial-number'])
    ssc = KeyPair.generate().selfSignedCert(serialNumber, **sslopt)
    file(opts['filename'], 'w').write(ssc.dumpPEM())
    if not opts['quiet']:
        print 'Wrote SSL certificate:'
        print ssc.inspect()
    return ssc
Exemple #27
0
    def fromFilePath(cls, filePath):
        privatePath = filePath.child('private')
        publicPath = filePath.child('public')
        csrPath = filePath.child('csr')

        issuerPath = filePath.child('issuer')
        if issuerPath.exists():
            issuer = issuerPath.getContent()
            key = KeyPair.loadPEM(privatePath.child(issuer).getContent())
            cert = Certificate.loadPEM(publicPath.child(issuer).getContent())

        store = cls(publicPath, privatePath, csrPath, key, cert, issuer)
        return store
Exemple #28
0
def _create_tls_client_context(config, cbdir, log):
    """
    Create a CertificateOptions object for use with TLS listening endpoints.
    """
    # server hostname: The expected name of the remote host.
    hostname = config['hostname']

    # explicit trust (certificate) root
    ca_certs = None
    if 'ca_certificates' in config:
        log.info("TLS client using explicit trust ({cnt_certs} certificates)", cnt_certs=len(config['ca_certificates']))
        ca_certs = []
        for cert_fname in [os.path.abspath(os.path.join(cbdir, x)) for x in (config['ca_certificates'])]:
            cert = crypto.load_certificate(
                crypto.FILETYPE_PEM,
                six.u(open(cert_fname, 'r').read())
            )
            log.info("TLS client trust root CA certificate loaded from '{fname}'", fname=cert_fname)
            ca_certs.append(cert)
        ca_certs = OpenSSLCertificateAuthorities(ca_certs)
    else:
        log.info("TLS client using platform trust")

    # client key/cert to use
    client_cert = None
    if 'key' in config:
        if 'certificate' not in config:
            raise Exception('TLS client key present, but certificate missing')

        key_fname = os.path.abspath(os.path.join(cbdir, config['key']))
        with open(key_fname, 'r') as f:
            private_key = KeyPair.load(f.read(), format=crypto.FILETYPE_PEM)
            log.info("Loaded client TLS key from '{key_fname}'", key_fname=key_fname)

        cert_fname = os.path.abspath(os.path.join(cbdir, config['certificate']))
        with open(cert_fname, 'r') as f:
            cert = Certificate.loadPEM(f.read(),)
            log.info("Loaded client TLS certificate from '{cert_fname}' (cn='{cert_cn}', sha256={cert_sha256}..)",
                     cert_fname=cert_fname,
                     cert_cn=cert.getSubject().CN,
                     cert_sha256=cert.digest('sha256')[:12])

        client_cert = PrivateCertificate.fromCertificateAndKeyPair(cert, private_key)
    else:
        if 'certificate' in config:
            log.warn('TLS client certificate present, but key is missing')

    # create TLS client context
    ctx = optionsForClientTLS(hostname, trustRoot=ca_certs, clientCertificate=client_cert)

    return ctx
Exemple #29
0
def _create_tls_client_context(config, cbdir, log):
    """
    Create a CertificateOptions object for use with TLS listening endpoints.
    """
    # server hostname: The expected name of the remote host.
    hostname = config['hostname']

    # explicit trust (certificate) root
    ca_certs = None
    if 'ca_certificates' in config:
        log.info("TLS client using explicit trust ({cnt_certs} certificates)", cnt_certs=len(config['ca_certificates']))
        ca_certs = []
        for cert_fname in [os.path.abspath(os.path.join(cbdir, x)) for x in (config['ca_certificates'])]:
            cert = crypto.load_certificate(
                crypto.FILETYPE_PEM,
                six.u(open(cert_fname, 'r').read())
            )
            log.info("TLS client trust root CA certificate loaded from '{fname}'", fname=cert_fname)
            ca_certs.append(cert)
        ca_certs = OpenSSLCertificateAuthorities(ca_certs)
    else:
        log.info("TLS client using platform trust")

    # client key/cert to use
    client_cert = None
    if 'key' in config:
        if 'certificate' not in config:
            raise Exception('TLS client key present, but certificate missing')

        key_fname = os.path.abspath(os.path.join(cbdir, config['key']))
        with open(key_fname, 'r') as f:
            private_key = KeyPair.load(f.read(), format=crypto.FILETYPE_PEM)
            log.info("Loaded client TLS key from '{key_fname}'", key_fname=key_fname)

        cert_fname = os.path.abspath(os.path.join(cbdir, config['certificate']))
        with open(cert_fname, 'r') as f:
            cert = Certificate.loadPEM(f.read(),)
            log.info("Loaded client TLS certificate from '{cert_fname}' (cn='{cert_cn}', sha256={cert_sha256}..)",
                     cert_fname=cert_fname,
                     cert_cn=cert.getSubject().CN,
                     cert_sha256=cert.digest('sha256')[:12])

        client_cert = PrivateCertificate.fromCertificateAndKeyPair(cert, private_key)
    else:
        if 'certificate' in config:
            log.warn('TLS client certificate present, but key is missing')

    # create TLS client context
    ctx = optionsForClientTLS(hostname, trustRoot=ca_certs, clientCertificate=client_cert)

    return ctx
Exemple #30
0
    def from_path(cls, path):
        """
        :param FilePath path: Directory where private key and certificate are
            stored.
        """
        if not path.isdir():
            raise PathError(
                b"Path {path} is not a directory.".format(path=path.path)
            )

        certPath = path.child(certificate_filename)
        keyPath = path.child(key_filename)

        if not certPath.isfile():
            raise PathError(
                b"Certificate file {path} does not exist.".format(
                    path=certPath.path)
            )

        if not keyPath.isfile():
            raise PathError(
                b"Private key file {path} does not exist.".format(
                    path=keyPath.path)
            )

        try:
            certFile = certPath.open()
        except IOError:
            raise PathError(
                (b"Certificate file {path} could not be opened. "
                 b"Check file permissions.").format(
                    path=certPath.path)
            )

        try:
            keyFile = keyPath.open()
        except IOError:
            raise PathError(
                (b"Private key file {path} could not be opened. "
                 b"Check file permissions.").format(
                    path=keyPath.path)
            )

        certificate = Certificate.load(
            certFile.read(), format=crypto.FILETYPE_PEM)
        keypair = FlockerKeyPair(
            keypair=KeyPair.load(keyFile.read(), format=crypto.FILETYPE_PEM)
        )

        return cls(path=path, certificate=certificate, keypair=keypair)
Exemple #31
0
def createCertificate():
    # this is copied from test_sslverify.py
    dn = DistinguishedName(commonName="newpb_thingy")
    keypair = KeyPair.generate(size=2048)
    req = keypair.certificateRequest(dn, digestAlgorithm="sha256")
    certData = keypair.signCertificateRequest(dn, req,
                                              lambda dn: True,
                                              1, # serial number
                                              digestAlgorithm="sha256",
                                              )
    cert = keypair.newCertificate(certData)
    #opts = cert.options()
    # 'opts' can be given to reactor.listenSSL, or to transport.startTLS
    return cert
Exemple #32
0
    def start_ssl(self):
        log.debug("Enabling SSL with PKey: %s, Cert: %s", self.pkey, self.cert)
        check_ssl_keys()

        with open(configmanager.get_config_dir(self.cert)) as cert:
            certificate = Certificate.loadPEM(cert.read()).original
        with open(configmanager.get_config_dir(self.pkey)) as pkey:
            private_key = KeyPair.load(pkey.read(), FILETYPE_PEM).original
        options = CertificateOptions(privateKey=private_key, certificate=certificate, method=SSL.SSLv23_METHOD)
        ctx = options.getContext()
        ctx.set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3)
        ctx.use_certificate_chain_file(configmanager.get_config_dir(self.cert))

        self.socket = reactor.listenSSL(self.port, self.site, options, interface=self.interface)
        log.info("Serving on %s:%s view at https://%s:%s", self.interface, self.port, self.interface, self.port)
Exemple #33
0
def makeCert(cn):
    """
    Create a self-signed certificate with the given common name.

    @param cn: Common Name to use in certificate.
    @type cn: L{bytes}

    @return: Self-signed certificate.
    @rtype: L{Certificate<twisted.internet.ssl.Certificate>}
    """
    sharedDN = DN(CN=cn)
    key = KeyPair.generate()
    cr = key.certificateRequest(sharedDN)
    sscrd = key.signCertificateRequest(sharedDN, cr, lambda dn: True, 1)
    return key.newCertificate(sscrd)
Exemple #34
0
def createCertificate():
    # this is copied from test_sslverify.py
    dn = DistinguishedName(commonName="newpb_thingy")
    keypair = KeyPair.generate(size=2048)
    req = keypair.certificateRequest(dn, digestAlgorithm="sha256")
    certData = keypair.signCertificateRequest(
        dn,
        req,
        lambda dn: True,
        1,  # serial number
        digestAlgorithm="sha256",
    )
    cert = keypair.newCertificate(certData)
    #opts = cert.options()
    # 'opts' can be given to reactor.listenSSL, or to transport.startTLS
    return cert
Exemple #35
0
    def start_ssl(self):
        check_ssl_keys()
        log.debug('Enabling SSL with PKey: %s, Cert: %s', self.pkey, self.cert)

        with open(configmanager.get_config_dir(self.cert)) as cert:
            certificate = Certificate.loadPEM(cert.read()).original
        with open(configmanager.get_config_dir(self.pkey)) as pkey:
            private_key = KeyPair.load(pkey.read(), FILETYPE_PEM).original
        options = CertificateOptions(privateKey=private_key, certificate=certificate, method=SSL.SSLv23_METHOD)
        ctx = options.getContext()
        ctx.set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3)
        ctx.use_certificate_chain_file(configmanager.get_config_dir(self.cert))

        self.socket = reactor.listenSSL(self.port, self.site, options, interface=self.interface)
        ip = self.socket.getHost().host
        ip = '[%s]' % ip if is_ipv6(ip) else ip
        log.info('Serving at https://%s:%s%s', ip, self.port, self.base)
Exemple #36
0
def createSSLCertificate(opts):
    sslopt = {}
    for x, y in (('country','C'),
                 ('state', 'ST'),
                 ('city', 'L'),
                 ('organization', 'O'),
                 ('unit', 'OU'),
                 ('hostname', 'CN'),
                 ('email','emailAddress')):
        sslopt[y] = opts[x]
    serialNumber = int(opts['serial-number'])
    ssc = KeyPair.generate().selfSignedCert(serialNumber, **sslopt)
    file(opts['filename'], 'w').write(ssc.dumpPEM())
    if not opts['quiet']:
        print 'Wrote SSL certificate:'
        print ssc.inspect()
    return ssc
Exemple #37
0
def load_key_file(path):
    """
    Load a private key from a specified path.

    :param FilePath path: Absolute path to certificate file.

    :return: A ``ComparableKeyPair`` instance representing the parsed
        key data.
    """
    try:
        key_file = path.open()
    except IOError as e:
        code, failure = e
        raise PathError(b"Private key file could not be opened.", e.filename,
                        code, failure)
    keypair = ComparableKeyPair(
        keypair=KeyPair.load(key_file.read(), format=crypto.FILETYPE_PEM))
    return keypair
Exemple #38
0
def createDatabase(siteStore):
    """
    Populate the given Store with a TCPPort and SSLPort.
    """
    factory = WebSite(store=siteStore)
    installOn(factory, siteStore)
    installOn(TCPPort(store=siteStore, portNumber=TCP_PORT, factory=factory),
              siteStore)
    certificatePath = siteStore.newFilePath('certificate')

    key = KeyPair.generate()
    cert = key.selfSignedCert(1)
    certificatePath.setContent(
        cert.dump(FILETYPE_PEM) + key.dump(FILETYPE_PEM))

    installOn(
        SSLPort(store=siteStore,
                portNumber=SSL_PORT,
                certificatePath=certificatePath,
                factory=factory), siteStore)
Exemple #39
0
def objectsFromPEM(pemdata):
    """
    Load some objects from a PEM.
    """
    certificates = []
    keys = []
    for line in pemdata.split("\n"):
        if line.startswith('-----BEGIN'):
            if 'CERTIFICATE' in line:
                blobs = certificates
            else:
                blobs = keys
            blobs.append('')
        blobs[-1] += line
        blobs[-1] += '\n'
    keys = [KeyPair.load(key, FILETYPE_PEM) for key in keys]
    certificates = [
        Certificate.loadPEM(certificate) for certificate in certificates
    ]
    return PEMObjects(keys=keys, certificates=certificates)
def objectsFromPEM(pemdata):
    """
    Load some objects from a PEM.
    """
    certificates = []
    keys = []
    blobs = [b""]
    for line in pemdata.split(b"\n"):
        if line.startswith(b'-----BEGIN'):
            if b'CERTIFICATE' in line:
                blobs = certificates
            else:
                blobs = keys
            blobs.append(b'')
        blobs[-1] += line
        blobs[-1] += b'\n'
    keys = [KeyPair.load(key, FILETYPE_PEM) for key in keys]
    certificates = [Certificate.loadPEM(certificate)
                    for certificate in certificates]
    return PEMObjects(keys=keys, certificates=certificates)
Exemple #41
0
def load_key_file(path):
    """
    Load a private key from a specified path.

    :param FilePath path: Absolute path to certificate file.

    :return: A ``ComparableKeyPair`` instance representing the parsed
        key data.
    """
    try:
        key_file = path.open()
    except IOError as e:
        code, failure = e
        raise PathError(
            b"Private key file could not be opened.",
            e.filename, code, failure
        )
    keypair = ComparableKeyPair(
        keypair=KeyPair.load(key_file.read(), format=crypto.FILETYPE_PEM)
    )
    return keypair
Exemple #42
0
def createDatabase(siteStore):
    """
    Populate the given Store with a TCPPort and SSLPort.
    """
    factory = WebSite(store=siteStore)
    installOn(factory, siteStore)
    installOn(
        TCPPort(store=siteStore, portNumber=TCP_PORT, factory=factory),
        siteStore)
    certificatePath = siteStore.newFilePath('certificate')

    key = KeyPair.generate()
    cert = key.selfSignedCert(1)
    certificatePath.setContent(
        cert.dump(FILETYPE_PEM) +
        key.dump(FILETYPE_PEM))

    installOn(
        SSLPort(store=siteStore, portNumber=SSL_PORT,
                certificatePath=certificatePath,
                factory=factory),
        siteStore)
Exemple #43
0
def load_certificate_from_path(path, key_filename, cert_filename):
    """
    Load a certificate and keypair from a specified path.

    :param FilePath path: Directory where certificate and key files
        are stored.
    :param bytes key_filename: The file name of the private key.
    :param bytes cert_filename: The file name of the certificate.

    :return: A ``tuple`` containing the loaded key and certificate
        instances.
    """
    certPath = path.child(cert_filename)
    keyPath = path.child(key_filename)

    try:
        certFile = certPath.open()
    except IOError as e:
        code, failure = e
        raise PathError(
            b"Certificate file could not be opened.",
            e.filename, code, failure
        )

    try:
        keyFile = keyPath.open()
    except IOError as e:
        code, failure = e
        raise PathError(
            b"Private key file could not be opened.",
            e.filename, code, failure
        )

    certificate = Certificate.load(
        certFile.read(), format=crypto.FILETYPE_PEM)
    keypair = ComparableKeyPair(
        keypair=KeyPair.load(keyFile.read(), format=crypto.FILETYPE_PEM)
    )
    return (keypair, certificate)
Exemple #44
0
    def testBadCertRequestSubject(self):
        kp = KeyPair.generate()
        subject = DistinguishedName(commonName='HACKERX',
                                    localityName='INTERNETANIA')
        reqobj = kp.requestObject(subject)

        fakereq = kp.requestObject(subject)
        ssigned = kp.signRequestObject(subject, fakereq, 1)
        certpair = PrivateCertificate.fromCertificateAndKeyPair
        fakecert = certpair(ssigned, kp)
        apc = self.serverService2.certificateStorage.addPrivateCertificate

        def _2(secured):
            D = secured.callRemote(q2q.Sign,
                                   certificate_request=reqobj,
                                   password='******')

            def _1(dcert):
                cert = dcert['certificate']
                privcert = certpair(cert, kp)
                apc(str(self.fromAddress), privcert)

            return D.addCallback(_1)

        d = self.serverService2.getSecureConnection(
            self.fromAddress,
            self.fromAddress.domainAddress(),
            authorize=False,
            usePrivateCertificate=fakecert,
        ).addCallback(_2)

        def unexpectedSuccess(result):
            self.fail("Expected BadCertificateRequest, got %r" % (result, ))

        def expectedFailure(err):
            err.trap(q2q.BadCertificateRequest)

        d.addCallbacks(unexpectedSuccess, expectedFailure)
        return d
Exemple #45
0
    def start_ssl(self):
        check_ssl_keys()
        log.debug('Enabling SSL with PKey: %s, Cert: %s', self.pkey, self.cert)

        with open(configmanager.get_config_dir(self.cert)) as cert:
            certificate = Certificate.loadPEM(cert.read()).original
        with open(configmanager.get_config_dir(self.pkey)) as pkey:
            private_key = KeyPair.load(pkey.read(), FILETYPE_PEM).original
        options = CertificateOptions(privateKey=private_key,
                                     certificate=certificate,
                                     method=SSL.SSLv23_METHOD)
        ctx = options.getContext()
        ctx.set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3)
        ctx.use_certificate_chain_file(configmanager.get_config_dir(self.cert))

        self.socket = reactor.listenSSL(self.port,
                                        self.site,
                                        options,
                                        interface=self.interface)
        ip = self.socket.getHost().host
        ip = '[%s]' % ip if is_ipv6(ip) else ip
        log.info('Serving at https://%s:%s%s', ip, self.port, self.base)
Exemple #46
0
def load_certificate_from_path(path, key_filename, cert_filename):
    """
    Load a certificate and keypair from a specified path.

    :param FilePath path: Directory where certificate and key files
        are stored.
    :param bytes key_filename: The file name of the private key.
    :param bytes cert_filename: The file name of the certificate.

    :return: A ``tuple`` containing the loaded key and certificate
        instances.
    """
    certPath = path.child(cert_filename)
    keyPath = path.child(key_filename)

    try:
        certFile = certPath.open()
    except IOError as e:
        code, failure = e
        raise PathError(
            b"Certificate file could not be opened.",
            e.filename, code, failure
        )

    try:
        keyFile = keyPath.open()
    except IOError as e:
        code, failure = e
        raise PathError(
            b"Private key file could not be opened.",
            e.filename, code, failure
        )

    certificate = Certificate.load(
        certFile.read(), format=crypto.FILETYPE_PEM)
    keypair = ComparableKeyPair(
        keypair=KeyPair.load(keyFile.read(), format=crypto.FILETYPE_PEM)
    )
    return (keypair, certificate)
Exemple #47
0
def generateKey():
    return KeyPair.generate()
Exemple #48
0
def create_listening_endpoint_from_config(config, cbdir, reactor):
    """
    Create a Twisted stream server endpoint from a Crossbar.io transport configuration.

    See: https://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IStreamServerEndpoint.html

    :param config: The transport configuration.
    :type config: dict
    :param cbdir: Crossbar.io node directory (we need this for TLS key/certificates).
    :type cbdir: str
    :param reactor: The reactor to use for endpoint creation.
    :type reactor: obj

    :returns obj -- An instance implementing IStreamServerEndpoint
    """
    log = make_logger()
    endpoint = None

    # a TCP endpoint
    #
    if config['type'] == 'tcp':

        # the TCP protocol version (v4 or v6)
        #
        version = int(config.get('version', 4))

        # the listening port
        #
        if type(config['port']) is six.text_type:
            # read port from environment variable ..
            try:
                port = int(environ[config['port'][1:]])
            except Exception as e:
                print(
                    "Could not read listening port from env var: {}".format(e))
                raise e
        else:
            port = config['port']

        # the listening interface
        #
        interface = str(config.get('interface', '').strip())

        # the TCP accept queue depth
        #
        backlog = int(config.get('backlog', 50))

        if 'tls' in config:
            if _HAS_TLS:
                key_filepath = abspath(join(cbdir, config['tls']['key']))
                cert_filepath = abspath(
                    join(cbdir, config['tls']['certificate']))

                with open(key_filepath) as key_file:
                    with open(cert_filepath) as cert_file:

                        if 'dhparam' in config['tls']:
                            dhpath = FilePath(
                                abspath(join(cbdir, config['tls']['dhparam'])))
                            dh_params = DiffieHellmanParameters.fromFile(
                                dhpath)
                        else:
                            # XXX won't be doing ANY EDH
                            # curves... maybe make dhparam required?
                            # or do "whatever tlxctx was doing"
                            dh_params = None
                            log.warn(
                                "OpenSSL DH modes not active (no 'dhparam')")

                        # create a TLS context factory
                        #
                        key = key_file.read()
                        cert = cert_file.read()
                        ca_certs = None
                        if 'ca_certificates' in config['tls']:
                            ca_certs = []
                            for fname in config['tls']['ca_certificates']:
                                with open(fname, 'r') as f:
                                    ca_certs.append(
                                        Certificate.loadPEM(f.read()).original)

                        crossbar_ciphers = AcceptableCiphers.fromOpenSSLCipherString(
                            'ECDHE-RSA-AES128-GCM-SHA256:'
                            'DHE-RSA-AES128-GCM-SHA256:'
                            'ECDHE-RSA-AES128-SHA256:'
                            'DHE-RSA-AES128-SHA256:'
                            'ECDHE-RSA-AES128-SHA:'
                            'DHE-RSA-AES128-SHA')

                        ctx = CertificateOptions(
                            privateKey=KeyPair.load(
                                key, crypto.FILETYPE_PEM).original,
                            certificate=Certificate.loadPEM(cert).original,
                            verify=(ca_certs is not None),
                            caCerts=ca_certs,
                            dhParameters=dh_params,
                            acceptableCiphers=crossbar_ciphers,
                        )
                        if ctx._ecCurve is None:
                            log.warn(
                                "OpenSSL failed to set ECDH default curve")
                        else:
                            log.info(
                                "Ok, OpenSSL is using ECDH elliptic curve {curve}",
                                curve=ctx._ecCurve.snName,
                            )

                # create a TLS server endpoint
                #
                if version == 4:
                    endpoint = SSL4ServerEndpoint(reactor,
                                                  port,
                                                  ctx,
                                                  backlog=backlog,
                                                  interface=interface)
                elif version == 6:
                    raise Exception("TLS on IPv6 not implemented")
                else:
                    raise Exception(
                        "invalid TCP protocol version {}".format(version))
            else:
                raise Exception(
                    "TLS transport requested, but TLS packages not available:\n{}"
                    .format(_LACKS_TLS_MSG))

        else:
            # create a non-TLS server endpoint
            #
            if version == 4:
                endpoint = TCP4ServerEndpoint(reactor,
                                              port,
                                              backlog=backlog,
                                              interface=interface)
            elif version == 6:
                endpoint = TCP6ServerEndpoint(reactor,
                                              port,
                                              backlog=backlog,
                                              interface=interface)
            else:
                raise Exception(
                    "invalid TCP protocol version {}".format(version))

    # a Unix Domain Socket endpoint
    #
    elif config['type'] == 'unix':

        # the accept queue depth
        #
        backlog = int(config.get('backlog', 50))

        # the path
        #
        path = FilePath(join(cbdir, config['path']))

        # if there is already something there, delete it.
        #
        if path.exists():
            log.info(("{path} exists, attempting to remove before using as a "
                      "UNIX socket"),
                     path=path)
            path.remove()

        # create the endpoint
        #
        endpoint = UNIXServerEndpoint(reactor, path.path, backlog=backlog)

    else:
        raise Exception("invalid endpoint type '{}'".format(config['type']))

    return endpoint
Exemple #49
0
"""
This benchmarks runs a trivial Twisted TLSv1 echo server using a certificate
with a 2048 bit RSA key as well as a client which pumps as much data to that
server as it can in a fixed period of time.
"""

from twisted.internet.protocol import ServerFactory
from twisted.internet.endpoints import SSL4ClientEndpoint
from twisted.internet.ssl import (
    DN, KeyPair, PrivateCertificate, CertificateOptions)
from twisted.protocols.wire import Echo

from tcp_throughput import Client, driver

# Generate a new self-signed certificate
key = KeyPair.generate(size=2048)
req = key.certificateRequest(DN(commonName='localhost'), digestAlgorithm='sha1')
cert = PrivateCertificate.load(
    key.signCertificateRequest(
        DN(commonName='localhost'), req,
        lambda dn: True, 1, digestAlgorithm='sha1'),
    key)


def main(reactor, duration):
    chunkSize = 16384

    server = ServerFactory()
    server.protocol = Echo
    port = reactor.listenSSL(0, server, cert.options())
    client = Client(
Exemple #50
0
def create_connecting_endpoint_from_config(config, cbdir, reactor):
    """
    Create a Twisted stream client endpoint from a Crossbar.io transport configuration.

    See: https://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IStreamClientEndpoint.html

    :param config: The transport configuration.
    :type config: dict
    :param cbdir: Crossbar.io node directory (we need this for Unix domain socket paths and TLS key/certificates).
    :type cbdir: str
    :param reactor: The reactor to use for endpoint creation.
    :type reactor: obj

    :returns obj -- An instance implementing IStreamClientEndpoint
    """
    endpoint = None
    log = make_logger()

    # a TCP endpoint
    #
    if config['type'] == 'tcp':

        # the TCP protocol version (v4 or v6)
        #
        version = int(config.get('version', 4))

        # the host to connect to
        #
        host = str(config['host'])

        # the port to connect to
        #
        port = int(config['port'])

        # connection timeout in seconds
        #
        timeout = int(config.get('timeout', 10))

        if 'tls' in config:
            if _HAS_TLS:
                # if the config specified any CA certificates, we use those (only!)
                if 'ca_certificates' in config['tls']:
                    ca_certs = []
                    for cert_fname in config['tls']['ca_certificates']:
                        cert = crypto.load_certificate(
                            crypto.FILETYPE_PEM,
                            six.u(open(cert_fname, 'r').read()))
                        log.info("Loaded CA certificate '{fname}'",
                                 fname=cert_fname)
                        ca_certs.append(cert)

                    client_cert = None
                    if 'key' in config['tls']:
                        with open(config['tls']['certificate'], 'r') as f:
                            cert = Certificate.loadPEM(f.read(), )
                            log.info(
                                "{fname}: CN={subj.CN}, sha={sha}",
                                fname=config['tls']['certificate'],
                                subj=cert.getSubject(),
                                sha=cert.digest('sha'),
                            )

                        with open(config['tls']['key'], 'r') as f:
                            private_key = KeyPair.load(
                                f.read(),
                                format=crypto.FILETYPE_PEM,
                            )

                            log.info(
                                "{fname}: {key}",
                                fname=config['tls']['key'],
                                key=private_key.inspect(),
                            )

                        client_cert = PrivateCertificate.fromCertificateAndKeyPair(
                            cert, private_key)

                    # XXX OpenSSLCertificateAuthorities is a "private"
                    # class, in _sslverify, so we shouldn't really be
                    # using it. However, while you can pass a single
                    # Certificate as trustRoot= there's no way to pass
                    # multiple ones.
                    # XXX ...but maybe the config should only allow
                    # the user to configure a single cert to trust
                    # here anyway?
                    options = optionsForClientTLS(
                        config['tls']['hostname'],
                        trustRoot=OpenSSLCertificateAuthorities(ca_certs),
                        clientCertificate=client_cert,
                    )
                else:
                    options = optionsForClientTLS(config['tls']['hostname'])

                # create a TLS client endpoint
                #
                if version == 4:
                    endpoint = SSL4ClientEndpoint(
                        reactor,
                        host,
                        port,
                        options,
                        timeout=timeout,
                    )
                elif version == 6:
                    raise Exception("TLS on IPv6 not implemented")
                else:
                    raise Exception(
                        "invalid TCP protocol version {}".format(version))

            else:
                raise Exception(
                    "TLS transport requested, but TLS packages not available:\n{}"
                    .format(_LACKS_TLS_MSG))

        else:
            # create a non-TLS client endpoint
            #
            if version == 4:
                endpoint = TCP4ClientEndpoint(reactor,
                                              host,
                                              port,
                                              timeout=timeout)
            elif version == 6:
                endpoint = TCP6ClientEndpoint(reactor,
                                              host,
                                              port,
                                              timeout=timeout)
            else:
                raise Exception(
                    "invalid TCP protocol version {}".format(version))

    # a Unix Domain Socket endpoint
    #
    elif config['type'] == 'unix':

        # the path
        #
        path = abspath(join(cbdir, config['path']))

        # connection timeout in seconds
        #
        timeout = int(config.get('timeout', 10))

        # create the endpoint
        #
        endpoint = UNIXClientEndpoint(reactor, path, timeout=timeout)

    else:
        raise Exception("invalid endpoint type '{}'".format(config['type']))

    return endpoint
Exemple #51
0
def _create_tls_server_context(config, cbdir, log):
    """
    Create a CertificateOptions object for use with TLS listening endpoints.
    """
    # server private key
    key_filepath = abspath(join(cbdir, config['key']))
    log.info("Loading server TLS key from {key_filepath}", key_filepath=key_filepath)
    with open(key_filepath) as key_file:
        # server certificate (but only the server cert, no chain certs)
        cert_filepath = abspath(join(cbdir, config['certificate']))
        log.info("Loading server TLS certificate from {cert_filepath}", cert_filepath=cert_filepath)
        with open(cert_filepath) as cert_file:
            key = KeyPair.load(key_file.read(), crypto.FILETYPE_PEM).original
            cert = Certificate.loadPEM(cert_file.read()).original

    # list of certificates that complete your verification chain
    extra_certs = None
    if 'chain_certificates' in config:
        extra_certs = []
        for fname in config['chain_certificates']:
            extra_cert_filepath = abspath(join(cbdir, fname))
            with open(extra_cert_filepath, 'r') as f:
                extra_certs.append(Certificate.loadPEM(f.read()).original)
            log.info("Loading server TLS chain certificate from {extra_cert_filepath}", extra_cert_filepath=extra_cert_filepath)

    # list of certificate authority certificate objects to use to verify the peer's certificate
    ca_certs = None
    if 'ca_certificates' in config:
        ca_certs = []
        for fname in config['ca_certificates']:
            ca_cert_filepath = abspath(join(cbdir, fname))
            with open(ca_cert_filepath, 'r') as f:
                ca_certs.append(Certificate.loadPEM(f.read()).original)
            log.info("Loading server TLS CA certificate from {ca_cert_filepath}", ca_cert_filepath=ca_cert_filepath)

    # ciphers we accept
    #
    # We prefer to make every single cipher (6 in total) _explicit_ (to reduce chances either we or the pattern-matching
    # language inside OpenSSL messes up) and drop support for Windows XP (we do WebSocket anyway).
    #
    # We don't use AES256 and SHA384, to reduce number of ciphers and since the additional
    # security gain seems not worth the additional performance drain.
    #
    # We also don't use ECDSA, since EC certificates a rare in the wild.
    #
    # The effective list of ciphers determined from an OpenSSL cipher string:
    #
    #   openssl ciphers -v 'ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:'
    #
    # References:
    #
    #  * https://www.ssllabs.com/ssltest/analyze.html?d=myserver.com
    #  * http://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
    #  * http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT
    #  * https://wiki.mozilla.org/Talk:Security/Server_Side_TLS
    #
    if 'ciphers' in config:
        log.info("Using explicit TLS ciphers from config")
        crossbar_ciphers = AcceptableCiphers.fromOpenSSLCipherString(config['ciphers'])
    else:
        log.info("Using secure default TLS ciphers")
        crossbar_ciphers = AcceptableCiphers.fromOpenSSLCipherString(
            # AEAD modes (GCM)
            # 'ECDHE-ECDSA-AES128-GCM-SHA256:'
            'ECDHE-RSA-AES128-GCM-SHA256:'
            # 'ECDHE-ECDSA-AES256-GCM-SHA384:'
            # 'ECDHE-RSA-AES256-GCM-SHA384:'
            'DHE-RSA-AES128-GCM-SHA256:'
            # 'DHE-RSA-AES256-GCM-SHA384:'

            # CBC modes
            'ECDHE-RSA-AES128-SHA256:'
            'DHE-RSA-AES128-SHA256:'
            'ECDHE-RSA-AES128-SHA:'
            'DHE-RSA-AES128-SHA:'
        )

    # DH modes require a parameter file
    if 'dhparam' in config:
        dhpath = FilePath(abspath(join(cbdir, config['dhparam'])))
        dh_params = DiffieHellmanParameters.fromFile(dhpath)
    else:
        dh_params = None
        log.warn("No OpenSSL DH parameter file set - DH cipher modes will be deactive!")

    # create a TLS context factory
    # see: https://twistedmatrix.com/documents/current/api/twisted.internet.ssl.CertificateOptions.html
    ctx = CertificateOptions(
        privateKey=key,
        certificate=cert,
        extraCertChain=extra_certs,
        verify=(ca_certs is not None),
        caCerts=ca_certs,
        dhParameters=dh_params,
        acceptableCiphers=crossbar_ciphers,

        # TLS hardening
        method=TLSv1_2_METHOD,
        enableSingleUseKeys=True,
        enableSessions=False,
        enableSessionTickets=False,
        fixBrokenPeers=False,
    )

    # Without a curve being set, ECDH won't be available even if listed
    # in acceptable ciphers!
    #
    # The curves available in OpenSSL can be listed:
    #
    #   openssl ecparam -list_curves
    #
    # prime256v1: X9.62/SECG curve over a 256 bit prime field
    #
    # This is elliptic curve "NIST P-256" from here
    # http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
    #
    # This seems to be the most widely used curve
    #
    # http://crypto.stackexchange.com/questions/11310/with-openssl-and-ecdhe-how-to-show-the-actual-curve-being-used
    #
    # and researchers think it is "ok" (other than wrt timing attacks etc)
    #
    # https://twitter.com/hyperelliptic/status/394258454342148096
    #
    if ctx._ecCurve is None:
        log.warn("No OpenSSL elliptic curve set - EC cipher modes will be deactive!")
    else:
        if ctx._ecCurve.snName != "prime256v1":
            log.info("OpenSSL is using elliptic curve {curve}", curve=ctx._ecCurve.snName)
        else:
            log.info("OpenSSL is using elliptic curve prime256v1 (NIST P-256)")

    return ctx
Exemple #52
0
def _create_tls_server_context(config, cbdir, log):
    """
    Create a CertificateOptions object for use with TLS listening endpoints.
    """
    # server private key
    key_filepath = abspath(join(cbdir, config['key']))
    log.info("Loading server TLS key from {key_filepath}",
             key_filepath=key_filepath)
    with open(key_filepath) as key_file:
        # server certificate (but only the server cert, no chain certs)
        cert_filepath = abspath(join(cbdir, config['certificate']))
        log.info("Loading server TLS certificate from {cert_filepath}",
                 cert_filepath=cert_filepath)
        with open(cert_filepath) as cert_file:
            key = KeyPair.load(key_file.read(), crypto.FILETYPE_PEM).original
            cert = Certificate.loadPEM(cert_file.read()).original

    # list of certificates that complete your verification chain
    extra_certs = None
    if 'chain_certificates' in config:
        extra_certs = []
        for fname in config['chain_certificates']:
            extra_cert_filepath = abspath(join(cbdir, fname))
            with open(extra_cert_filepath, 'r') as f:
                extra_certs.append(Certificate.loadPEM(f.read()).original)
            log.info(
                "Loading server TLS chain certificate from {extra_cert_filepath}",
                extra_cert_filepath=extra_cert_filepath)

    # list of certificate authority certificate objects to use to verify the peer's certificate
    ca_certs = None
    if 'ca_certificates' in config:
        ca_certs = []
        for fname in config['ca_certificates']:
            ca_cert_filepath = abspath(join(cbdir, fname))
            with open(ca_cert_filepath, 'r') as f:
                ca_certs.append(Certificate.loadPEM(f.read()).original)
            log.info(
                "Loading server TLS CA certificate from {ca_cert_filepath}",
                ca_cert_filepath=ca_cert_filepath)

    # ciphers we accept
    #
    # We prefer to make every single cipher (6 in total) _explicit_ (to reduce chances either we or the pattern-matching
    # language inside OpenSSL messes up) and drop support for Windows XP (we do WebSocket anyway).
    #
    # We don't use AES256 and SHA384, to reduce number of ciphers and since the additional
    # security gain seems not worth the additional performance drain.
    #
    # We also don't use ECDSA, since EC certificates a rare in the wild.
    #
    # The effective list of ciphers determined from an OpenSSL cipher string:
    #
    #   openssl ciphers -v 'ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:'
    #
    # References:
    #
    #  * https://www.ssllabs.com/ssltest/analyze.html?d=myserver.com
    #  * http://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
    #  * http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT
    #  * https://wiki.mozilla.org/Talk:Security/Server_Side_TLS
    #
    if 'ciphers' in config:
        log.info("Using explicit TLS ciphers from config")
        crossbar_ciphers = AcceptableCiphers.fromOpenSSLCipherString(
            config['ciphers'])
    else:
        log.info("Using secure default TLS ciphers")
        crossbar_ciphers = AcceptableCiphers.fromOpenSSLCipherString(
            # AEAD modes (GCM)
            # 'ECDHE-ECDSA-AES128-GCM-SHA256:'
            'ECDHE-RSA-AES128-GCM-SHA256:'
            # 'ECDHE-ECDSA-AES256-GCM-SHA384:'
            # 'ECDHE-RSA-AES256-GCM-SHA384:'
            'DHE-RSA-AES128-GCM-SHA256:'
            # 'DHE-RSA-AES256-GCM-SHA384:'

            # CBC modes
            'ECDHE-RSA-AES128-SHA256:'
            'DHE-RSA-AES128-SHA256:'
            'ECDHE-RSA-AES128-SHA:'
            'DHE-RSA-AES128-SHA:')

    # DH modes require a parameter file
    if 'dhparam' in config:
        dhpath = FilePath(abspath(join(cbdir, config['dhparam'])))
        dh_params = DiffieHellmanParameters.fromFile(dhpath)
    else:
        dh_params = None
        log.warn(
            "No OpenSSL DH parameter file set - DH cipher modes will be deactive!"
        )

    ctx = CertificateOptions(
        privateKey=key,
        certificate=cert,
        extraCertChain=extra_certs,
        verify=(ca_certs is not None),
        caCerts=ca_certs,
        dhParameters=dh_params,
        acceptableCiphers=crossbar_ciphers,

        # Disable SSLv3 and TLSv1 -- only allow TLSv1.1 or higher
        #
        # We are using Twisted private stuff (from twisted.internet._sslverify import TLSVersion),
        # as OpenSSL.SSL.TLSv1_1_METHOD wont work:
        #
        # [ERROR] File "../twisted/internet/_sslverify.py", line 1530, in __init__
        #    if raiseMinimumTo > self._defaultMinimumTLSVersion:
        #       builtins.TypeError: '>' not supported between instances of 'int' and 'NamedConstant'
        #
        raiseMinimumTo=TLSVersion.TLSv1_1,

        # TLS hardening
        enableSingleUseKeys=True,
        enableSessions=False,
        enableSessionTickets=False,
        fixBrokenPeers=False,
    )

    # Without a curve being set, ECDH won't be available even if listed
    # in acceptable ciphers!
    #
    # The curves available in OpenSSL can be listed:
    #
    #   openssl ecparam -list_curves
    #
    # prime256v1: X9.62/SECG curve over a 256 bit prime field
    #
    # This is elliptic curve "NIST P-256" from here
    # http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
    #
    # This seems to be the most widely used curve
    #
    # http://crypto.stackexchange.com/questions/11310/with-openssl-and-ecdhe-how-to-show-the-actual-curve-being-used
    #
    # and researchers think it is "ok" (other than wrt timing attacks etc)
    #
    # https://twitter.com/hyperelliptic/status/394258454342148096
    #
    if False:
        # FIXME: this doesn't work anymore with Twisted 18.4. (there now seems more complex machinery
        # in self._ecChooser)
        if ctx._ecCurve is None:
            log.warn(
                "No OpenSSL elliptic curve set - EC cipher modes will be deactive!"
            )
        else:
            if ctx._ecCurve.snName != "prime256v1":
                log.info("OpenSSL is using elliptic curve {curve}",
                         curve=ctx._ecCurve.snName)
            else:
                log.info(
                    "OpenSSL is using elliptic curve prime256v1 (NIST P-256)")

    return ctx
 def pems():
     for i in count():
         key = KeyPair.generate()
         cert = key.selfSignedCert(i, commonName=u"lae_automation testing")
         pem = PrivateCertificate.fromCertificateAndKeyPair(cert, key).dumpPEM()
         yield pem.decode("ascii")