http://www.pedro.jmrezende.com.br/sd.htm

SSLServer em python

Uma implementação utilizando M2Crypto *

Trabalho de Segurança de Dados

Bruno Couto Kümmel
Universidade de Brasília
1 de fevereiro de 2005

* - Vide
NOTA DO EDITOR no rodapé


  Usando Python e a biblioteca M2Crypto

O objetivo deste trabalho é implementar um mini servidor web, que utilize o protocolo SSL como dispositivo de segurança. A escolha da linguagem Python foi feita para que o programa tenha uma portabilidade superior a implementações em C ou C++. A única restrição existente nesse aspecto é quanto a utilização da biblioteca M2Crypto[1] como ferramenta de implementação. Essa biblioteca deve estar instalada no sistema onde o servidor funcionará.

A M2Crypto é uma biblioteca, que de acordo com seus desenvolvedores, é dividida em duas camadas. a camada inferior utiliza a interface SWIG[2] para fazer chamadas das funções API da OpenSSL[3](que utiliza a linguagem C) tornando-as disponíveis para as funções em Python. Por outro lado, a camada superior disponibiliza uma interface orientada a objetos para os programadores em python. Muitas das chamadas de funções repassadas da camada superior para a camada inferior possuem uma denominação semelhante a que se encontra na documentação do OpenSSL, o que facilita a busca dos comandos necessários para ativar as funcionalidades do OpenSSL.

Desenvolvendo o código

Inicialmente o servidor deve inicializar o que se denomina de  contexto SSL . Esse contexto é uma estrutura de dados utilizada para armazenar os dados importantes do serviço SSL como por exemplo o certificado e a chave privada do próprio servidor,  os certificados das autoridades certificadoras que possuem relação de confiança com servidor, versão do SSL sendo utilizado, entre outras informações. Esse contexto é utilizado para que se evite uma sobrecarga do servidor quando múltiplos acessos simultâneos ocorrem, pois através dele os dados não precisam ser carregados do disco a cada conexão estabelecida. Na implementação proposta, o contexto é inicializado pela função init_context().

Chamada da função:

contexto= init_context('sslv23', 'server.pem', 'ca.pem', SSL.verify_none)

Definição:

def init_context(protocol, certfile, cafile, verify, verify_depth=10):

    contexto=SSL.Context(protocol)
    contexto.load_cert_chain(certfile)
    contexto.load_client_ca(cafile)
    contexto.load_verify_info(cafile)
    contexto.set_verify(verify, verify_depth)
    contexto.set_session_id_ctx('https_srv')
    contexto.set_info_callback()
    contexto.set_tmp_dh('dh1024.pem')
    return contexto

A Primeira ação dentro de init_context é a chamada da função SSL.Context() que cria o objeto contexto que será utilizado pelo servidor. Como parâmetro é passado a versão do protocolo SSL a ser usado, que nessa implementação utilizou-se a versão 3. Em seguida é necessário configurar esse objeto para que tenha as informações próprias do nosso servidor. Sendo assim configuramos o nosso contexto com as seguintes funções:

Uma vez criado o contexto, ele é inserido na configuração do servidor SSL. Para isso precisamos carregar o contexto no serviço que será disponibilizado, fazemos isso através do comando: 


httpsd = HTTPS_Server(('', 8888), HTTP_Handler, contexto)

Onde HTTPS_Server inicializa um objeto de uma classe criada a partir de uma extensão da classe abstrata ThreadingSSLServer da biblioteca M2Crypto. Nesse exemplo, foi definido apenas as operações de inicialização e de finalização do servidor.  Além do contexto recém criado, também são passados para o serviço SSL o endereço da máquina(nesse caso deixamos como default locahost:''),  a porta TCP onde o serviço irá ser executado(porta 8888) e o manipulador de requisições (HTTP_Handler).

O HTTP_Handler utilizado é também uma extensão de classe, só que essa classe já vem como classe padrão do python que é a classe SimpleHTTPRequestHandler.  Como o objetivo desse trabalho é criar um servidor SSL simples, o handler utilizado foi mantido de forma mais padrão o possível. Dessa forma foram necessárias modificações apenas nos métodos onde há interação com o cliente, ou seja o método send_head: que envia os dados para o servidor e o método do_GET: que recebe as requisições do cliente.


Certificados Digitais

Para esse trabalho foi criado um certificado através do programa CA.pl. Esse programa desenvolvida em Perl por Steven Hanson é um script que faz chamadas ao OpenSSL de forma a simplificar o número de comandos que o usuário deve digitar para criar seus próprios certificados[3]. Hoje em dia o CA.pl vem junto com a instalação padrão do OpenSSL.

Como criar seu próprio certificado CA[5]:

  1. Criar um diretório para utilizar a ferramenta, pois essa cria arquivos e diretórios, então é recomendado que voce tenha essas informações centralizadas em algum lugar. Nesse exemplo utilzamos o diretório chamado demo .

  2. Copiar CA.pl e o openssl.cnf para o demo.

  3. (OPCIONAL) Modificar  o CA.pl, para permitir gerar CA com a validade diferente do valor padrão(nesse exemplo usamos valor de 365 dias):

        --- CA.pl.org   Sat Mar 31 12:40:13 2001
    +++ CA.pl Sat Mar 31 12:41:15 2001
    @@ -97,7 +97,7 @@
    } else {
    print "Making CA certificate ...\n";
    system ("$REQ -new -x509 -keyout " .
    (RETIRAR) "${CATOP}/private/$CAKEY -out ${CATOP}/$CACERT $DAYS");
    (INSERIR) "${CATOP}/private/$CAKEY -out ${CATOP}/$CACERT -days 365");
    $RET=$?;
    }
    }
  4. para criar o novo certificado:

        ./CA.pl -newca

    A certificate filename (or enter to create) <enter>

    Making CA certificate ...
    Using configuration from openssl.cnf
    Generating a 1024 bit RSA private key
    ............++++++
    ......................++++++
    writing new private key to './demoCA/private/cakey.pem'
    Enter PEM pass phrase: <senha>
    Verifying password - Enter PEM pass phrase: <senha>
    -----
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [AU]:BR
    State or Province Name (full name) [Some-State]:Distrito Federal
    Locality Name (eg, city) []:Brasília
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:QualquerNome1
    Organizational Unit Name (eg, section) []:QualquerNome2
    Common Name (eg, YOUR name) []:Certificadora Mestre
    Email Address []: qualquer@email.com

    Esse procedimento cria um novo CA no diretório demoCA. O Ca auto-assinado está em demoCA/cacert.pem. Já o par de chaves RSA está em  demoCA/private/cakey.pem.

    O conteúdo de demoCA/private/cakey.pem

        cat demoCA/private/cakey.pem

    -----BEGIN RSA PRIVATE KEY-----
    Proc-Type: 4,ENCRYPTED
    DEK-Info: DES-EDE3-CBC,19973A9DBBB601BA

    eOq9WFScNiI4/UWEUaSnGTKpJv2JYuMD3HwQox2Q3Cd4zGqVjJ6gF3exa5126cKf
    X/bMVnwbPpuFZPiAIvaLyCjT6pYeXTBbSzs7/GQnvEOv+nYnDUFWi0Qm92qLk0uy
    pFi/M1aWheN3vir2ZlAw+DW0bOOZhj8tC7Co7lMYb0YE271b6/YRPZCwQ3GXAHUJ
    +aMYxlUDrK45aCUa/1CZDzTgk7h9cDgx2QJSIvYMYytCfI3zsuZMJS8/4OXLL0bI
    lKmAc1dwB3DqGJt5XK4WJesiNfdxeCNEgAcYtEAgYZTPIApU+kTgTCIxJl2nMW7j
    ax+Q1z7g+4MpgG20WD633D4z4dTlDdz+dnLi0rvuvxiwt+dUhrqiML1tyi+Z6EBH
    jU4/cLBWev3rYfrlp4x8J9mDte0YKOk3t0wQOHqRetTsIfdtjnFp/Hu3qDmTCWjD
    z/g7PPoO/bg/B877J9WBPbL/1hXXFYo88M+2aGlPOgDcFdiOqbLb2DCscohMbbVr
    A4mgiy2kwWfIE73qiyV7yyG8FlRvr1iib+jbT3LTGf743utYAAs7HNGuOUObhoyt
    jYvBD7ACn35P5YX7KTqvqErwdijxYCaNBCnvmRtmYSaNw9Kv1UJTxc5Vx7YLwIPk
    E9KyBgKI7vPOjWBZ27+zOvNycmv1ciNtpALAw4bWtXnhCDVTHaVDy34OkheMzNCg
    2cjcBFzOkMIjcI03KbTQXOFIQGlsTWXGzkNf/zBQ+KksT1MCj+zBXSCvlDASMckg
    kef21pGgUqPF14gKGfWX3sV4bjc1vbrRwq6zlG3nMuYqR5MtJJY9eQ==
    -----END RSA PRIVATE KEY-----
  5. Em seguida fazemos uma requisição de assinatura:

        ./CA.pl -newreq

    Using configuration from openssl.cnf
    Generating a 1024 bit RSA private key
    ..........++++++
    ..............++++++
    writing new private key to 'newreq.pem'
    Enter PEM pass phrase: <outra senha>
    Verifying password - Enter PEM pass phrase: <outra senha de novo>
    -----
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [AU]:BR
    State or Province Name (full name) [Some-State]:Distrito Federal
    Locality Name (eg, city) []:Brasília
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:OutroNome1
    Organizational Unit Name (eg, section) []:OutroNome2
    Common Name (eg, YOUR name) []:localhost
    Email Address []:qualquer@email.com

    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:<enter>
    An optional company name []:<enter>
    Request (and private key) is in newreq.pem

    O conteúdo de newreq.pem:

        cat newreq.pem

    -----BEGIN RSA PRIVATE KEY-----
    Proc-Type: 4,ENCRYPTED
    DEK-Info: DES-EDE3-CBC,41B2874DF3D02DD4

    mg611EoVkLEooSTv+qTM0Ddmm/M1jE/Jy5RD/sc3LSMhuGu9xc26OgsTJmkQuIAh
    J/B4lAw8G59VTG6DykeEtrG0rUBx4bggc7PKbFuiN423YjJODWcHvVgnPOzXMQt+
    lY4tPl5+217MRHyx2NsWGrpkQNdu3GeSPOVMl3jeQiaXupONbwQ7rj42+X/VtAJP
    W4D1NNwu8aGCPyShsEXHc/fI1WDpphYWke97pOjIZVQESFZOPty5HjIYZux4U+td
    W81xODtq2ecJXc8fn2Wpa9y5VD1LT7oJksOuL1+Z04OVaeUe4x0swM17HlBm2kVt
    fe/C/L6kN27MwZhE331VjtTjSGl4/gknqQDbLOtqT06f3OISsDJETm2itllyhgzv
    C6Fi3N03rGFmKectijC+tws5k+P+HRG6sai33usk8xPokJqA+HYSWPz1XVlpRmv4
    kdjQOdST7ovU62mOTgf3ARcduPPwuzTfxOlYONe5NioO1APVHBrInQwcpLkpOTQR
    vI4roIN+b75/nihUWGUJn/nbbBa2Yl0N5Gs1Tyiy9Z+CcRT2TfWKBBFlEUIFl7Mb
    J9fTV3DI+k+akbR4il1NkQ8EcSmCr3WpA0I9n0EHI7ZVpVaHxc0sqaPFl8YGdFHq
    1Qk53C/w6+qPpDzT3yKFmG2LZytAAM1czvb6RbNRJJP2ZrpBwn/h99sUTo/yPfxY
    nueYmFJDm0uVNtG0icXGNUfSfnjKNTtHPAgyKGetRIC3kgJz/bo2w7EI6iEjBAzK
    l5TRm4x6ZJxwuXXMiJCehMMd8TC8ybwWO4AO19B3ebFFeTVsUgxSGA==
    -----END RSA PRIVATE KEY-----
    -----BEGIN CERTIFICATE REQUEST-----
    MIIBnTCCAQYCAQAwXTELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIw
    EAYDVQQDEwlsb2NhbGhvc3QxJzAlBgkqhkiG9w0BCQEWGGFkbWluQHNlcnZlci5l
    eGFtcGxlLmRvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAr1nYY1Qrll1r
    uB/FqlCRrr5nvupdIN+3wF7q915tvEQoc74bnu6b8IbbGRMhzdzmvQ4SzFfVEAuM
    MuTHeybPq5th7YDrTNizKKxOBnqE2KYuX9X22A1Kh49soJJFg6kPb9MUgiZBiMlv
    tb7K3CHfgw5WagWnLl8Lb+ccvKZZl+8CAwEAAaAAMA0GCSqGSIb3DQEBBAUAA4GB
    AHpoRp5YS55CZpy+wdigQEwjL/wSluvo+WjtpvP0YoBMJu4VMKeZi405R7o8oEwi
    PdlrrliKNknFmHKIaCKTLRcU59ScA6ADEIWUzqmUzP5Cs6jrSRo3NKfg1bd09D1K
    9rsQkRc9Urv9mRBIsredGnYECNeRaK5R1yzpOowninXC
    -----END CERTIFICATE REQUEST-----
  6. O Próximo passo é assinar a requisição por certificado:

        ./CA.pl -sign

    Using configuration from openssl.cnf
    Enter PEM pass phrase: <senha do CA>
    Check that the request matches the signature
    Signature ok
    The Subjects Distinguished Name is as follows
    countryName :PRINTABLE:'BR'
    organizationName :PRINTABLE:'OutroNome1'
    commonName :PRINTABLE:'localhost'
    emailAddress :IA5STRING:'qualquer@email.com'
    Certificate is to be certified until Jan 25 02:57:30 2006 GMT (365 days)
    Sign the certificate? [y/n]:y


    1 out of 1 certificate requests certified, commit? [y/n]y
    Write out database with 1 new entries
    Data Base Updated
    Signed certificate is in newcert.pem

    O certificado armazenado em newcert.pem tem o seguinte formato:

        cat newcert.pem

    Certificate:
    Data:
    Version: 3 (0x2)
    Serial Number: 1 (0x1)
    Signature Algorithm: md5WithRSAEncryption
    Issuer: C=BR, O=QualquerNome1, CN=Certificadora Mestre /Email=qualquer@email.com
    Validity
    Not Before: Jan 25 02:57:30 2005 GMT
    Not After : Jan 25 02:57:30 2006 GMT
    Subject: C=BR, O=OutroNome1, CN=localhost/Email=qualquer@email.com
    Subject Public Key Info:
    Public Key Algorithm: rsaEncryption
    RSA Public Key: (1024 bit)
    Modulus (1024 bit):
    00:af:59:d8:63:54:2b:96:5d:6b:b8:1f:c5:aa:50:
    91:ae:be:67:be:ea:5d:20:df:b7:c0:5e:ea:f7:5e:
    6d:bc:44:28:73:be:1b:9e:ee:9b:f0:86:db:19:13:
    21:cd:dc:e6:bd:0e:12:cc:57:d5:10:0b:8c:32:e4:
    c7:7b:26:cf:ab:9b:61:ed:80:eb:4c:d8:b3:28:ac:
    4e:06:7a:84:d8:a6:2e:5f:d5:f6:d8:0d:4a:87:8f:
    6c:a0:92:45:83:a9:0f:6f:d3:14:82:26:41:88:c9:
    6f:b5:be:ca:dc:21:df:83:0e:56:6a:05:a7:2e:5f:
    0b:6f:e7:1c:bc:a6:59:97:ef
    Exponent: 65537 (0x10001)
    X509v3 extensions:
    X509v3 Basic Constraints:
    Certificate:
    Data:
    Version: 3 (0x2)
    Serial Number: 1 (0x1)
    Signature Algorithm: md5WithRSAEncryption
    Issuer: C=BR, O=QualquerNome1, CN=Certificadora Mestre /Email=qualquer@email.com
    Validity
    Not Before: Jan 25 02:57:30 2005 GMT
    Not After : Jan 25 02:57:30 2006 GMT
    Subject: C=BR, O=OutroNome1, CN=localhost/Email=qualquer@email.com
    Subject Public Key Info:
    Public Key Algorithm: rsaEncryption
    RSA Public Key: (1024 bit)
    Modulus (1024 bit):
    00:af:59:d8:63:54:2b:96:5d:6b:b8:1f:c5:aa:50:
    91:ae:be:67:be:ea:5d:20:df:b7:c0:5e:ea:f7:5e:
    6d:bc:44:28:73:be:1b:9e:ee:9b:f0:86:db:19:13:
    21:cd:dc:e6:bd:0e:12:cc:57:d5:10:0b:8c:32:e4:
    c7:7b:26:cf:ab:9b:61:ed:80:eb:4c:d8:b3:28:ac:
    4e:06:7a:84:d8:a6:2e:5f:d5:f6:d8:0d:4a:87:8f:
    6c:a0:92:45:83:a9:0f:6f:d3:14:82:26:41:88:c9:
    6f:b5:be:ca:dc:21:df:83:0e:56:6a:05:a7:2e:5f:
    0b:6f:e7:1c:bc:a6:59:97:ef
    Exponent: 65537 (0x10001)
    X509v3 extensions:
    X509v3 Basic Constraints:
    CA:FALSE
    Netscape Comment:
    OpenSSL Generated Certificate
    X509v3 Subject Key Identifier:
    B3:D6:89:88:2F:B1:15:40:EC:0A:C0:30:35:3A:B7:DA:72:73:1B:4D
    X509v3 Authority Key Identifier:
    keyid:F9:6A:A6:34:97:6B:BC:BB:5A:17:0D:19:FC:62:21:0B:00:B5:0E:29
    DirName:/C=BR/O=QualquerNome1/CN=Certificadora Mestre/Email=qualquer@email.com
    serial:00

    Signature Algorithm: md5WithRSAEncryption // (*) - vide NOTA DO EDITOR
  7. Nessa implementação em particular precisamos que a chave privada esteja em sua forma não-cifrada para que o servidor funcione de forma autônoma. Assim precisamos do comando abaixo para decifrar a chave privada que está no arquivo newreq.pem

        openssl rsa < newreq.pem > newkey.pem

    read RSA key
    Enter PEM pass phrase:<senha>
    writing RSA key

    conteúdo de newkey.pem :

        cat newkey.pem

    -----BEGIN RSA PRIVATE KEY-----
    MIICXgIBAAKBgQCvWdhjVCuWXWu4H8WqUJGuvme+6l0g37fAXur3Xm28RChzvhue
    7pvwhtsZEyHN3Oa9DhLMV9UQC4wy5Md7Js+rm2HtgOtM2LMorE4GeoTYpi5f1fbY
    DUqHj2ygkkWDqQ9v0xSCJkGIyW+1vsrcId+DDlZqBacuXwtv5xy8plmX7wIDAQAB
    AoGAbAkU8w3W1Qu15Hle1bJSL7GMReoreqeblOBmMAZz4by0l6sXZXJpjWXo86f/
    +dASMYTMPC4ZTYtv06N07AFbjL+kDfqDMTfzQkYMHp1LAq1Ihbq1rHWSBH5n3ekq
    KiY8JKpv8DR5Po1iKaXJFuDByGDENJwYbSRSpSK3P+vkWWECQQDkEUE/ZPqqqZkQ
    2iWRPAsCbEID8SAraQl3DdCLYs/GgARfmmj4yUHEwkys9Jo1H8k4BdxugmaUwNi5
    YQ/CVzrXAkEAxNO80ArbGxPUmr11GHG/bGBYj1DUBkHZSc7dgxZdtUCLGNxQnNsg
    Iwq3n6j1sUzS3UW6abQ8bivYNOUcMKJAqQJBANQxFaLU4b/NQaODQ3aoBZpAfP9L
    5eFdvbet+7zjt2r5CpikgkwOfAmDuXEltx/8LevY0CllW+nErx9zJgVrwUsCQQCu
    76H5JiznPBDSF2FjgHWqVVdgyW4owY3mU739LHvNBLicN/RN9VPy0Suy8/CqzKT9
    lWPBXzf2k3FuUdNkRlFBAkEAmpXoybuiFR2S5Bma/ax96lVs0/VihhfC1zZP/X/F
    Br77+h9dIul+2DnyOl50zu0Sdzst1/7ay4JSDHyiBCMGSQ==
    -----END RSA PRIVATE KEY-----

    Código fonte: 

cat ssl_web_srv.py

import os, sys
import time
from SimpleHTTPServer import SimpleHTTPRequestHandler
from M2Crypto import Rand, SSL
from M2Crypto.SSL.SSLServer import ThreadingSSLServer
try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO
def printHtmlPage(path, url,String):
    f = StringIO()
    f.write('<title>Trabalho de Seguranca de dados</title>\r\n' )
    f.write('<h1>Pagina utilizando SSL: %s </h1>\r\n' % (url,))
    f.write('<pre>\r\n')
    f.write('Universidade de Brasilia<br>')
    f.write('Instituto de Ciencias Exatas<br>')
    f.write('Departamento de Ciencia da Computacao<br>')
    f.write('-------------------------------------<br>')
    f.write('Seguranca de Dados<br>')
    f.write('Professor: Pedro Rezende<br><br>')
    f.write('01/34431 - Bruno Couto Kummel<br>')
    f.write('-------------------------------------<br><br>')
    f.write('Hora do Servidor: %s <br>' % (time.asctime()) )
    f.write('<a href="/ssl_web_srv.py">Codigo Fonte</a><br>\r\n')
    f.write('<a href="/kummel.html">Documentacao</a><br>\r\n')
    f.write('<br><br>Informacoes sobre a Sessao<br>')
    f.write('%s' % (String,))
    f.write('</pre>\r\n\r\n')
    f.reset()
    return f

class HTTP_Handler(SimpleHTTPRequestHandler): # extensao do SimpleHTTPRequestHandler
    server_version = "https_srv/0.1"
    extensions_map = {
            '': 'text/plain',
            '.html': 'text/html',
            '.htm': 'text/html',
            '.gif': 'image/gif',
            '.jpg': 'image/jpeg',
            '.jpeg': 'image/jpeg',
            '.der': 'application/x-x509-ca-cert'
            }

    def send_head(self):
    path = self.translate_path(self.path)
    if os.path.isdir(path):
        sess=self.request.get_session()
        f = printHtmlPage(path, self.path,sess.as_text())
            filetype = 'text/html'
    	else:
        try:
  f = open(path, 'rb')
                directory='/usr/home/kummel/SSL-TRAB/'
        if f.name==directory+'ssl_web_srv.py' or f.name==directory+'kummel.html':
            filetype = self.guess_type(path)
        else:
            self.send_error(403, "O Arquivo nao pode ser acessado")
                    return None
            	except IOError:
                self.send_error(404, "Arquivo nao encontrado")
                return None
    	self.send_response(200)
        self.send_header("Content-type", filetype)
        self.end_headers()
        return f
    def do_GET(self):
    if self.path[1:13] == '_newsession_':
            self.path = self.path[13:]
            self.request.renegotiate()
            sess = self.request.get_session()
    f = self.send_head()
        if f:
            self.copyfile(f, self.wfile)
            f.close()
class HTTPS_Server(ThreadingSSLServer):
    def __init__(self, server_addr, handler, ssl_ctx):
        ThreadingSSLServer.__init__(self, server_addr, handler, ssl_ctx)
        self.server_name = server_addr[0]
        self.server_port = server_addr[1]
    def finish(self):
        self.request.set_shutdown(SSL.SSL_RECEIVED_SHUTDOWN | SSL.SSL_SENT_SHUTDOWN)
        self.request.close()

def init_context(protocol, certfile, cafile, verify, verify_depth=10):
    contexto=SSL.Context(protocol)
    contexto.load_cert_chain(certfile)
    contexto.load_client_ca(cafile)
    contexto.load_verify_info(cafile)
    contexto.set_verify(verify, verify_depth)
    contexto.set_session_id_ctx('https_srv')
    contexto.set_info_callback()
    contexto.set_tmp_dh('dh1024.pem')
    return contexto

if __name__ == '__main__':
    print 'Iniciando Servidor WebSSL'
    contexto= init_context('sslv23', 'server.pem', 'ca.pem', SSL.verify_none)
    httpsd = HTTPS_Server(('', 8888), HTTP_Handler, contexto)
    try:
        httpsd.serve_forever()
    except KeyboardInterrupt:
        print '\nPrograma encerrado'

  

  
  


(*) - Nota do Editor

No final do item 6 acima, oberva-se que as bibliotecas utilizadas implementam o protocolo de assinatura digital com a seguinte configuração default
Signature Algorithm: md5WithRSAEncryption
Esta configuração faz uso da função de hash MD5. A função de hash MD5 não mais sustenta robustez necessária para protocolos de assinatura digital, sendo aqui empregada APENAS POR RAZÕES DIDÁTICAS. Uma das conclusões didáticas deste trabalho é, portanto, a de que aplicativos que integram bibliotecas criptográficas em produção devem ser REVISTOS em relação à configuração do protocolo de assinatura digital empregado, de forma a se evitar que continuem operando com configurações que se utilizam da função de hash MD5. A alternativa recomendada é o uso da função SHA-2.

No EUROCRYPT 2005, Xiaoyun Wang, Yiqun Lisa Yin e Hongbo Yu, da Shandong University na China, apresentaram artigo (em http://www.infosec.sdu.edu.cn/paper/md5-attack.pdf) onde mostram um ataque diferencial modular para busca semi-livre de colisão (ataque "de aniversário") com custo computacional equivalente ao tempo de exeucão numa estação de trabalho em cerca de uma hora.




Referências

  1. Página do projeto M2Crypto: http://sandbox.rulemaker.net/ngps/m2/
  2. Página do projeto SWIG: http://www.swig.org/exec.html
  3. Servidor SSL do aluno Hammurabi Mendes : http://www.pedro.jmrezende.com.br/segdadtop.htm
  4. Página sobre DH-RSA: http://www.openssl.org/docs/ssl/SSL_CTX_set_tmp_dh_callback.html
  5. Criando certificados com CA.pl: http://sandbox.rulemaker.net/ngps/m2/howto.ca.html