Skip to main content

Implementando TLS/SSL em Python

Escrito por

Kingsley Ubah

feature python code purple

16 de outubro de 2022

0 minutos de leitura

Hoje em dia, fazemos praticamente tudo online: reservamos voos, pagamos por produtos, transferimos dinheiro, conversamos com amigos, armazenamos documentos e muito mais. Muitas dessas atividades exigem o compartilhamento de informações confidenciais, como dados de cartão de crédito e informações bancárias. Se um site usa uma rede insegura, um hacker mal-intencionado pode roubar facilmente as informações dos usuários. É por isso que a criptografia é tão importante.

O protocolo de segurança da camada de transporte (TLS) é a principal proteção das informações dos usuários em sites e aplicações web. O TLS usa um algoritmo criptográfico difícil de quebrar, que impede que qualquer pessoa além do servidor e do cliente web leia ou altere os dados transmitidos.

Neste artigo, vamos explorar o TLS e aprender a usar Python para verificar a validade do certificado TLS de um site. Em seguida, vamos mostrar como adicionar TLS à sua aplicação Python no Linux.

Entendendo TLS/SSL

O protocolo TLS, sucessor do protocolo SSL (secure socket layer), protege os dados com criptografia. Quando os usuários enviam informações para um site, o TLS as criptografa antes do envio. Depois, somente o servidor com a mesma chave pública do cliente pode abrir a mensagem. A mesma regra vale quando o servidor envia informações de volta ao cliente: somente o cliente com a chave correspondente pode ler os dados.

Para usar o protocolo TLS em um site, é necessário instalar um certificado TLS/SSL válido (geralmente chamado de certificado SSL). Com a instalação do certificado, o site passa de HTTP para HTTPS, um protocolo de transferência mais seguro. O certificado é um arquivo de dados que contém a identidade do site e a chave pública usada para abrir as mensagens da carga útil.

Para funcionar, um certificado SSL precisa ser válido. Isso significa que ele deve ser assinado por uma autoridade certificadora (CA) confiável e também estar ativo. Todo certificado tem uma data de emissão e uma data de vencimento. Após essa data, ele deixa de ser válido.

Sites sem um certificado SSL válido têm poucos sinais visíveis. Para começar, o endereço na barra do navegador usa o prefixo HTTP:// em vez de HTTPS://. Além disso, não há um ícone de cadeado ao lado do endereço — o símbolo que os navegadores usam para indicar um site seguro. Tenha cuidado com o que você compartilha se notar qualquer um desses sinais.

Agora que exploramos o TLS sobre SSL (TLS/SSL), vamos ver como implementá-lo com Python.

Trabalhando com TLS/SSL em Python

Ao criar um servidor web com Python, é fundamental saber como adicionar TLS/SSL à aplicação. Antes de aprender como fazer isso, vamos ver como usar Python para verificar se o certificado SSL de um site é válido.

Como verificar se um site tem um certificado SSL válido

Para verificar a validade do certificado SSL de um site, basta executar um script Python como este:

import requests

response=requests.get('https://twitter.com/')

print(response)

O código acima importa o módulo Python requests e o usa para enviar uma solicitação GET ao site do Twitter. (Para executar o script, é preciso instalar o módulo requests no Python usando o pip.) Podemos substituir a URL do Twitter pela URL do site cujo certificado SSL queremos verificar. A variável response armazena o valor recebido, que o código imprime na última linha.

Ao executar o código, recebemos a mensagem <Response [200]> (OK), o que significa que o site do Twitter está usando um certificado SSL válido, como esperado.

Agora, enviamos uma solicitação GET para outro site. Desta vez, usamos um site que sabemos não ter um certificado SSL válido.

import requests

response=requests.get('https://www.expired.badssl.com/')

print(response)

Desta vez, recebemos um erro informando que a verificação do certificado falhou:

requests.exceptions.SSLError: HTTPSConnectionPool(host='www. expired.badssl.com', port=443): Max retries exceeded with url : / (Caused by SSLError (SSLCertVerificationError(1, '[SSL:CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1131)’)))

A biblioteca SSL do Python

Usamos a biblioteca SSL do Python para fornecer criptografia TLS na comunicação baseada em sockets entre clientes e servidores Python. Ela usa criptografia e resumos de mensagens para proteger os dados e detectar tentativas de alteração na rede. Os certificados digitais fornecem autenticação.

A biblioteca SSL é compatível com Windows, macOS e outros sistemas UNIX modernos. Ela também depende do OpenSSL para funcionar.

Mais adiante neste artigo, vamos usar a biblioteca SSL do Python para encapsular nosso socket orientado à conexão com o certificado SSL que vamos gerar na próxima seção.

Criando um certificado SSL autoassinado em Python

Agora que sabemos como verificar se o TLS/SSL de um site é válido, vamos ver como usá-lo em um servidor web Python.

Podemos gerar e usar rapidamente um certificado autoassinado gratuito para desenvolvimento local. No entanto, se pretendemos publicar o site ou a aplicação na internet, precisamos comprar um certificado SSL de um registrador de domínios confiável, como GoDaddy e NameCheap.

O processo para gerar um certificado SSL para nossa aplicação Python local tem três etapas:

  1. Criar a chave privada RSA.

  2. Gerar uma solicitação de assinatura de certificado (CSR) usando a chave privada.

  3. Assinar a solicitação CSR para criar o certificado.

Depois de criar o certificado SSL, vamos usá-lo em uma aplicação Python ao fazer solicitações à API.

Mais uma vez: compre certificados SSL somente de uma autoridade certificadora autorizada. Muitos registradores de domínios incluem um certificado SSL gratuito na compra de um domínio.

Vamos começar!

Pré-requisito: instalar o OpenSSL no Linux

Se você usa Linux, é provável que o OpenSSL já esteja instalado na sua máquina. Caso ainda não esteja, você pode instalá-lo usando o gerenciador de pacotes. O comando a seguir instala o OpenSSL em distribuições baseadas no Debian e no Ubuntu:

sudo apt-get install openssl

Se não tiver certeza de que o OpenSSL já está instalado na sua máquina, você pode verificar executando o seguinte comando:

openssl version

Se o OpenSSL estiver instalado, você verá o número da versão. Se, após executar o comando acima, aparecer um erro informando que o comando não foi reconhecido, será necessário instalá-lo.

Criando a chave privada

Podemos criar a chave privada com ou sem uma frase secreta de proteção. Para adicionar uma frase secreta, basta usar uma cifra no comando, como -aes256.

As duas opções abaixo geram uma chave privada RSA de 2048 bits, mas a primeira cria a chave sem uma frase secreta.

openssl genrsa -out key.pem 2048

openssl genrsa -aes256 -out key.pem 2048

Criando a CSR com a chave

Nesta etapa, usamos a chave privada gerada na etapa anterior para criar uma CSR. Para isso, execute o seguinte comando:

openssl req -new -key key.pem -out signreq.csr

Você precisa preencher algumas informações adicionais sobre o certificado na linha de comando. Informe os dados e pressione Enter ao terminar.

Assinando o certificado com a chave

A última etapa é assinar a solicitação para criar o certificado. Execute o seguinte comando:

openssl x509 -req -days 365 -in signreq.csr -signkey key.pem -out certificate.pem

Aqui, estamos assinando a solicitação do certificado com a mesma chave usada para criá-la. É por isso que ele é chamado de certificado “autoassinado”.

Você pode ver os detalhes do certificado executando o seguinte comando:

openssl x509 -text -noout -in certificate.pem

Executando um servidor HTTPS com TLS/SSL em Python

Agora que geramos um certificado autoassinado, vamos usá-lo para criar um servidor HTTPS que emprega criptografia TLS em toda a comunicação com o cliente.

O programa Python abaixo inicia um servidor HTTPS no localhost, na porta 443.

import http.server
import ssl

httpd = http.server.HTTPServer(('localhost', 443),
http.server.SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket (httpd.socket,
certfile='./certificate.pem', server_side=True, ssl_version=ssl.PROTOCOL_TLS
httpd.serve_forever()

No código acima, importamos os módulos ssl e http.server modules. Em seguida, chamamos o método HTTPServer de http.server, passando o endereço e o número da porta do servidor. Depois, encapsulamos o socket com SSL, especificando o caminho do certificado no método wrap_socket. Por fim, iniciamos o servidor na parte inferior do arquivo.

Para conectar um cliente, você pode usar o módulo requests do Python para enviar uma solicitação GET ao endereço do servidor:

import requests
res = requests.get('https://localhost:443')

print(res)

Observe que o código acima deve ser adicionado a um arquivo diferente daquele que contém o código do servidor. Ao executá-lo, o cliente se conecta ao servidor e recebe a mensagem [200] (OK):

<Response [200]>

Resumo

Neste artigo, aprendemos sobre TLS/SSL e a importância de ter um certificado digital válido nos sites. Também vimos como verificar o SSL de um site usando o método requests.get.

Em seguida, apresentamos a biblioteca SSL do Python e mostramos como criar e usar um servidor web Python protegido por TLS/SSL. Geramos um certificado autoassinado com OpenSSL e adicionamos o certificado à conexão de socket HTTP antes de iniciar o servidor.

Com o aumento contínuo das transações online, o cibercrime também continuará crescendo em escala e complexidade. Usar certificados SSL nos sites não só dificulta a maioria das tentativas de invasão, como também ajuda a transmitir mais confiança aos visitantes. Acesse este artigo para saber por que você deve usar HTTPS.