2012-05-08 11 views
8

Attualmente sto cercando di aggiungere il supporto per la firma PGP a my small e-mail sending script (che utilizza il modulo Python 3.xe python-gnupg).E-mail multiparte con firma PGP con Python

Il codice che firma messaggio è:

gpg = gnupg.GPG() 
basetext = basemsg.as_string().replace('\n', '\r\n') 
signature = str(gpg.sign(basetext, detach=True)) 
if signature: 
    signmsg = messageFromSignature(signature) 
    msg = MIMEMultipart(_subtype="signed", micalg="pgp-sha1", 
    protocol="application/pgp-signature") 
    msg.attach(basemsg) 
    msg.attach(signmsg) 
else: 
    print('Warning: failed to sign the message!') 

(Qui basemsg è di email.message.Message tipo.)

E messageFromSignature funzione è:

def messageFromSignature(signature): 
    message = Message() 
    message['Content-Type'] = 'application/pgp-signature; name="signature.asc"' 
    message['Content-Description'] = 'OpenPGP digital signature' 
    message.set_payload(signature) 
    return message 

poi aggiungo tutti gli header necessari al messaggio (msg) e inviarlo.

Questo funziona bene per messaggi non multipart, ma non riesce quando basemsg è multipart (multipart/alternative o multipart/mixed).

Verificare manualmente la firma rispetto alla parte di testo corrispondente, ma Evolution e Mutt riportano che la firma è errata.

Qualcuno può indicarmi il mio errore?

risposta

5

Il problema è che il modulo email.generator di Python non aggiunge una nuova riga prima della parte della firma. Ho riferito che a monte come http://bugs.python.org/issue14983.

+0

Come hai fatto a risolverlo? C'è un posto per aggiungere facilmente una nuova riga, o hai dovuto monkeypatch email.generator? Sto avendo lo stesso problema. – micah

+0

@MicahLee Non ho trovato alcun modo oltre a (scimmia-) patching 'email.generator'. –

2

Qual è in realtà la struttura MIME di basemsg? Sembra che abbia troppe parti annidate. Se esporti un messaggio firmato da ad es. Evoluzione, vedrai che ha solo due parti: il corpo e la firma.

Ecco un esempio che genera un messaggio su stdout che può essere letto e la firma verificata su entrambi i mutt() ed Evolution (File -> Importa).

import gnupg 
from email.message import Message 
from email.mime.text import MIMEText 
from email.mime.multipart import MIMEMultipart 

body = """ 
This is the original message text. 

:) 
""" 

gpg_passphrase = "xxxx" 

basemsg = MIMEText(body) 

def messageFromSignature(signature): 
    message = Message() 
    message['Content-Type'] = 'application/pgp-signature; name="signature.asc"' 
    message['Content-Description'] = 'OpenPGP digital signature' 
    message.set_payload(signature) 
    return message 

gpg = gnupg.GPG() 
basetext = basemsg.as_string().replace('\n', '\r\n') 
signature = str(gpg.sign(basetext, detach=True, passphrase=gpg_passphrase)) 
if signature: 
    signmsg = messageFromSignature(signature) 
    msg = MIMEMultipart(_subtype="signed", micalg="pgp-sha1", 
    protocol="application/pgp-signature") 
    msg.attach(basemsg) 
    msg.attach(signmsg) 
    msg['Subject'] = "Test message" 
    msg['From'] = "[email protected]" 
    msg['To'] = "[email protected]" 
    print(msg.as_string(unixfrom=True)) # or send 
else: 
    print('Warning: failed to sign the message!') 

Nota che qui, sto assumendo un portachiavi con una passphrase, ma potrebbe non essere necessario questo.

+0

La mia domanda era su come firmare ** e-mail multipart **. Nel tuo caso, 'basemsg' è un semplice messaggio MIMEText, non un messaggio multipart. Ho trovato la radice del mio problema - succede perché "email.generator" in Python non aggiunge una nuova riga dopo il confine finale. Non ne sono abbastanza sicuro; quando diventerò sicuro pubblicherò una risposta che descrive come risolvere il problema. –

+0

Dmitry Shachnev: Ah, non stavo guardando abbastanza da vicino. Spero che il bug venga risolto presto! –