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):
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:
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
load_cert_chain(self, certchainfile, keyfile, callback function): Carrega a corrente de certificados e a chave privada do servidor no contexto instanciado. A função callback é utilizada para decifrar a chave privada para que possa ser carregada no contexto. Pelo polimorfismo característico de programas orientados a objetos, existe um método polimórfico dessa função que permite que passemos um único arquivo como parâmetro. Para isso é necessário que esse contenha tanto a corrente de certificados como a chave privada não-cifrada dentro desse mesmo arquivo. Esse tipo de implementação é o mais utilizado para servidores SSL autônomos(servidores que não exigem o conhecimento da senha da chave privada para serem inicializados). Esse tipo de implementação exige um cuidado maior quanto a segurança do arquivo que contém a senha.
load_client_ca(self, cafile): Carrega certificados CA existentes no arquivo cafile no contexto instanciado. São esses certificados que são enviados aos clientes que se conectam com o servidor SSL durante a comunicação entre cliente e servidor. (SSLv3 certificate request).
load_verify_info(self, cafile=None, capath=None): Esse método é utilizado para carregar as informações contidas no certificado armazenado em cafile para poder verificar se esses estão corretos durante a comunicação entre o cliente e o servidor.
set_verify(verify, verify_depth): Esse método usa os dados obtidos do método anterior para verificar se o dados estão corretos. Nessa implementação em particular não se utilizará esse método tendo em vista que esse é apenas um trabalho didático onde os certificados utilizados serão auto-assinados e criados apenas para esse propósito.
set_session_id_ctx('https_srv'): Responsável pela criação de um identificador para o contexto.
set_info_callback(): Método padrão necessário para carregar as configurações feitas pelo programador no objeto contexto.
- set_tmp_dh('dh1024.pem'): Método opcional que modifica a cifra utilizada pelo servidor por uma cifra mais segura. Ou seja, de AES256-SHA para DHE-RSA-AES256-SHA. Esse método realiza isso carregando parâmetros temporários DH para que a troca de informações sobre a sessão seja feita de forma cifrada. Esse tipo de configuração é muito comum quando se usa autenticação de serviço com RSA[4].
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]:
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 .
Copiar CA.pl e o openssl.cnf para o demo.
(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=$?;
}
}
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-----
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-----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
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-----
cat ssl_web_srv.py
import os, sys
import timefrom SimpleHTTPServer import SimpleHTTPRequestHandler
from M2Crypto import Rand, SSLfrom M2Crypto.SSL.SSLServer import ThreadingSSLServertry:
from cStringIO import StringIOexcept ImportError:
from StringIO import StringIOdef 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 SimpleHTTPRequestHandlerserver_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 Noneexcept IOError:
self.send_error(404, "Arquivo nao encontrado")
return Noneself.send_response(200)
self.send_header("Content-type", filetype)
self.end_headers()
return fdef 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
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.Signature Algorithm: md5WithRSAEncryption
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
- Página do projeto M2Crypto: http://sandbox.rulemaker.net/ngps/m2/
- Página do projeto SWIG: http://www.swig.org/exec.html
- Servidor SSL do aluno Hammurabi Mendes : http://www.pedro.jmrezende.com.br/segdadtop.htm
- Página sobre DH-RSA: http://www.openssl.org/docs/ssl/SSL_CTX_set_tmp_dh_callback.html
- Criando certificados com CA.pl: http://sandbox.rulemaker.net/ngps/m2/howto.ca.html