Python + SSL para aplicações simples

Precisei relembrar uma forma de gerar uma conexão SSL(não apenas a camada de aplicação) para um projeto. O python faz isso de forma muito fluida e simples. Não requer prática, tampouco habilidade haha.

Para gerar o certificado, primeiro geramos uma chave com o openssl. Depois a usamos para gerar um certificado. Uma forma direta e automatica(e insegura, ja que não ha dados no certificado gerado) de fazer isso é:

openssl genrsa -out key.pem
yes '' | openssl req -new -x509 -key key.pem -out crt.pem -days 36500 || exit 1
cat key.pem crt.pem > cert.pem
rm key.pem crt.pem

Lembrando que estou ignorando as entradas para gerar o cert. Este tipo de coisa é mais usado para automatizar e gerar um cert novo a cada sessão. Depois disto é necessario pegar o fingerprint da chave, assim:

openssl x509 -in cert.pem -md5 -fingerprint -noout | sed 's/^[^=]\+=//;s/://g' | tr 'A-Z' 'a-z'

Agora o servidor, extremamente simples, para apenas uma conexão e printar o dado enviado:

import socket, ssl
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', 8081))
sock.listen(1)
newsock, fromaddr = sock.accept()
conn = ssl.wrap_socket(newsock, server_side=True, certfile='cert.pem', keyfile='cert.pem')
conn.setblocking(0)
while True:
    try:
        buf = conn.read(512)
        if buf == '':
            break
        else:
            print buf
    except:
        pass

O cliente é tão simples quanto o servidor. Só lembrar de pegar o fingerprint gerado e usar no client. Ele verifica e só loga no servidor se bater o fingerprint.

import socket, ssl, hashlib, time
CERT="fingerprint que voce pegou"
sock = socket.socket()
sock.settimeout(2)
sock.connect(('localhost', 8081))
conn = ssl.wrap_socket(sock)
if hashlib.md5(conn.getpeercert(True)).hexdigest() != CERT:
    conn.close()
    print 'CERT diferente do esperado, tentando me hackearrrrrrr'
else:
    print '200 OK'
    time.sleep(2)
    conn.write('CHUPA ESSA MANGA, WIRESHARK!1!!')
    print 'enviado'
    conn.close()

E é só isso, bem simples. É uma forma de encriptação e autenticação bem razoavel e resolve para a maioria das aplicações práticas contemporaneas.

link dos sources em : https://github.com/paoloo/simple-ssl

Serviço de checagem de CPF em bash script+python

Analisando um app de iPhone(depois mostro o passo a passo e as ferramentas), me vi precisando escrever um teste rápido no bash com o curl, que é uma ferramente absolutamente excepcional, mas me ví com problemas deevido a geração do HMAC e fazer parsing do resultado(sed+awk+cut é meio doloroso ne).
Acabei fazendo algo meio hibrido assim:

#!/bin/bash
cpfHASH=`echo "$1 $2" | python -c "from hashlib import sha1; from hmac import new as hmac; import sys; v=sys.stdin.read().strip().split(' '); print hmac('Sup3RbP4ssCr1t0grPhABr4sil','%s%s' % (v[0],v[1]),sha1).digest().encode('hex')"`

saidA=`curl https://movel01.receita.fazenda.gov.br/servicos-rfb/v2/IRPF/cpf -s -k -H "token: $cpfHASH" -H "plataforma: iPhone OS" -H "dispositivo: iPhone" -H "aplicativo: Pessoa Física" -H "versao: 8.3" -H "versao_app: 4.1" -d "cpf=$1&dataNascimento=$2" 2>&1`

python -c "null=None; a=$saidA; print ''.join(['%s = %s\n' % (c,a[c]) for c in a])"

Ficou meio porco usar o python para gerar o hash e para fazer o parsing, mas resolveu o meu problema. A execução é simples, o chato é que requer, além do CPF, a data de nascimento. Mas futuramente integrarei uma ferramenta para conseguir esta informação ;D

$ ./cpf.sh 13326724691 14121947
horaConsulta = 20:49:31
exception = None
codigoRetorno = 00
mensagemRetorno = OK
dataIsncricao = anterior a 10/11/1990
digitoVerificador = 00
nome = DILMA VANA ROUSSEFF
dataEmissao = 20/11/2015
horaEmissao = 08:49:32
mensagemObito = None
anoObito = 0000
codigoControle = CCA9.63A0.C92D.1C0D
codSituacaoCadastral = 0
dataConsulta = 20/11/2015
descSituacaoCadastral = REGULAR
dataNascimento = 14/12/1947

O código se encontra em https://github.com/paoloo/servicos/blob/master/cpf.sh

o/