sexta-feira, março 07, 2008

Python + SSL + Certificado digital

É comum durante o desenvolvimento de um programa que este precise de comunicação com serviços de terceiros disponíveis na rede.

Em Python como em outras linguagens, todo meio de comunicação via rede utiliza basicamente socket em seu nível mais baixo para prover essa comunicação, seja o meio de comunicação SOAP, rpc, http, etc.

Algumas vezes estes serviços externos fornecem a possibilidade de utilização de canais seguros para comunicação (ssl). Em alguns casos o serviço a ser utilizado pode até mesmo obrigar o uso de comunicação segura, para isso precisamos utilizar socket + ssl. Dependendo da necessidade do projeto pode ser necessário utilizar também um certificado digital juntamente com a conexão ssl como forma de autenticação.

Para utilizar comunicação segura o módulo 'socket' prove a função 'ssl', que de maneira simples executa a comunicação com o serviço desejado via ssl. Essa função também pode receber dois parâmetros , 'key_file' e 'cert_file' respectivamente o 'path' do arquivo PEM para a chave privada e o 'path' para o arquivo PEM do certificado.

Uma assinatura digital geralmente é um arquivo binário no formato 'pkcs12' com a extensão '.pfx', sendo assim precisamos abrir esse arquivo e retirar as duas informações que o 'ssl' precisa (key_file, cer_file) e salvar nos arquivos com o formato PEM. Para isso utilizamos openssl e pyopenssl, 'bindings' para python da 'lib' 'openssl'.

Com os módulos instalados, vamos abrir o certificado no formato binário, transformar no objeto 'pkcs12' e então retirar as informações do certificado e da chave privada para em seguida salvar cada um em arquivo separado.

Alguns certificados podem estar codificados sendo necessário informar a frase para decodificação, para tal temos o parâmetro 'passphrase', se não for preciso é só não informar o parâmetro como no exemplo abaixo.


from OpenSSL import crypto

# Lendo o arquivo pfx no formato pkcs12 como binario
pkcs12 = crypto.load_pkcs12(open('certificado.pfx', 'rb').read(), 'passphrase')

# Retorna a string decodificado do certificado
cert_str = crypto.dump_certificate(crypto.FILETYPE_PEM, pkcs12.get_certificate())

# Retorna a string decodificado da chave privada
key_str = crypto.dump_privatekey(crypto.FILETYPE_PEM, pkcs12.get_privatekey())

# Gravando a string no dicso
open('cert.pem', 'wb').write(cert_str)

# Gravando a string no dicso
open('key.ptm', 'wb').write(key_str)


Agora para finalizar basta efetuar a comunicação com o serviço desejado utilizando o modulo 'socket' e a função 'ssl' passando os parâmetros de chave e certificado:


proxy = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
proxy.connect(('www.lzt.com.br', 80))
proxy_ssl = socket.ssl(proxy, 'key.pem', 'cert.pem')


Pronto! Com o objeto 'proxy' podemos fazer requisições a serviços que utilizem conexão 'ssl' com certificados digitais.

10 comentários:

Unknown disse...

Boa tarde!

Estou tentando fazer a comunicação com o webservice do sefaz, na implemetação da NFE, e não estou tento sucesso.

Os procedimentos citados nesse tutorial deveriam funcionar no caso da nota fiscal, certo?

proxy.connect(('https://homolog.sefaz.go.gov.br/nfe/services/NfeRecepcao',443))
Erro: Name or service not know

Alguma sugestão?

Victor Godoy Poluceno disse...

Re: Bruno

Boa tarde!

Bruno, no post estou conectando em endereço qualquer utilizando apenas socket. NFE é um serviço que utiliza SOAP para comunicação. Você precisa de um modulo para soap como SOAPy ou suds.

Antes de utilizar o webservice você precisa autenticar no serviço.

Eu não tenho acompanhado o serviço NFE mas posso tentar ajudar.

Fique a vontade para me contatar por email.

Unknown disse...

Obrigado pela ajuda, vou dar uma estudada em SOAPy.

Fred Chevitarese disse...

Também estou com esta demanda para Nota Fiscal eletrônica!

Eu dei uma olhada já no SOAPpy, mas parece que ele foi descontinuado...
O suds também olhei, mas não sei se é oreiada, mas não consegui conectar utilizando https com ele ...

Vocês tiveram algum sucesso na implementação desta solução ?!

Ricardo disse...

Boa tarde Victor!

Achei muito interessante sua explicação, parabéns. Você teria um código python exemplo da implantação da NFe.

Charles disse...

Bom, eu achei algo em python que implementa NFe, http://github.com/marinho/PyNFe ... Muito interessante.

Unknown disse...

Excelente post, gostaria de ajuda no sentido de me direcionar sobre como faço para autenticar uma aplicação django com token certificado digital A3

Unknown disse...

oi,
Simplesmente, admirável o que você fez aqui. É agradável ao olhar você expressa a partir do coração e sua clareza sobre este conteúdo significativo pode ser facilmente parecia. Pós Notável e aguardamos a sua atualização futura.

Thanks!
Certificado de assinatura digital

Ribamar disse...

INFO CC CARTÃO DE CREDITO
WhatsApp: 098 98 10 51 543

Somos correspondentes bancários das seguintes instituições: BANCO BRADESCO S.A. – (CNPJ 60.746.948.0001-12), BANCO SANTANDER BRASIL S.A. – (CNPJ 90.400.888/0001-42), CAIXA ECONÔMICA FEDERAL. – (CNPJ: 00.360.305/0001-04).

CNH

Dentre disso confeccionamos cartões e informações de várias instituições financeiras, caso você trabalha com esse tipo de material nos procure pelo WhatsApp. Estaremos aqui para tirar todas as suas dúvidas, lembrando quê nós não trabalhamos com Clone.

Obs: só nos procure pessoas realmente interessados.

Trabalhamos também com emissão de CNH ( carteira nacional de habilitação). Avisamos que dentro disso emitimos todas as categorias exemplo: AB, AC,AD e AE. Fazemos também a renovação da sua CNH e transferimos o seu prontuário para qualquer Estado Nacional.

WhatsApp: 088981051543

najidains disse...

Casinos in Lille - MapyRO
The best places 시흥 출장마사지 to gamble at the Casinos in 구미 출장마사지 Lille (Lille) · 경상남도 출장샵 Red Dog Resort Hotel, Spa, and Casino · Hollywood 하남 출장샵 Casino at Charles Town Races · Caesars Casino in 이천 출장샵