PGP-podpisu vícedílné e-maily s Python

hlasů
9

Já jsem v současné době snaží přidat podporu PGP podpisu na mé malé odesílání e-mailu skript (který používá Python 3.xa python-gnupg modul).

Kód, který podepisuje zprávu je:

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!')

(Zde basemsgje email.message.Messagetypu.)

A messageFromSignaturefunkce:

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

Pak přidám všechny potřebné záhlaví zprávy ( msg) a odeslat ji.

To funguje dobře pro non-vícedílné zprávy, ale selže při basemsgje vícedílný ( multipart/alternativenebo multipart/mixed).

Ruční ověření podpisu proti odpovídajícím dílu textových děl, ale Evolution a Mutt zpráva, že podpis je špatný.

Může mi někdo prosím, místo abych se moje chyba?

Položena 08/05/2012 v 11:32
zdroj uživatelem
V jiných jazycích...                            


3 odpovědí

hlasů
5

Problém je v tom, že Python email.generatormodul nepřidá nový řádek před podpisem části. Jsem uvedl, že proti proudu jako http://bugs.python.org/issue14983 .

Odpovězeno 08/06/2012 v 09:31
zdroj uživatelem

hlasů
2

Jaký je vlastně MIME struktura basemsg? Zdá se, že má příliš mnoho vnořených dílů v něm. Pokud exportovat podepsanou zprávu od např Evolution, uvidíte, že to má jen dvě části: tělo a podpis.

Zde je příklad, který generuje zprávy na standardní výstup, který lze číst a podpis ověřit na obou voříšek ( mutt -f test.mbox) a Evolution (Soubor -> Import).

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'] = "sender@example.com"
    msg['To'] = "recipient@example.com"
    print(msg.as_string(unixfrom=True)) # or send
else:
    print('Warning: failed to sign the message!')

Všimněte si, že tady, jsem za předpokladu klíčenku s přístupovým heslem, ale nemusí to.

Odpovězeno 31/05/2012 v 10:15
zdroj uživatelem

hlasů
0

Existuje mnohem problém s python vestavěným emailknihovny. Pokud volání as_stringprocedury, budou hlavičky být vyhledány maxlinelengthpouze v aktuální třídě a v Childs ( _payload) ne! Takhle:

msgRoot (You call `to_string` during sending to smtp and headers will be checked)
->msgMix (headers will be not checked for maxlinelength)
-->msgAlt (headers will be not checked for maxlinelength)
--->msgText (headers will be not checked for maxlinelength)
--->msgHtml (headers will be not checked for maxlinelength)
-->msgSign (headers will be not checked for maxlinelength)

Jsem podepsal msgMix.to_string()a pak připojí podepsanou zprávu do msgRoot. Ale během odesílání do SMTP msgMixčást byla jiná, hlavičky v msgMixnebyl hodil. OFC, znamení byl neplatný.

Trvalo to dva dny, abych se rozumět všemu .. Zde je můj kód, co funguje a mohu použít pro odesílání automatické e-maily:

#imports
import smtplib, gnupg
from email import Charset, Encoders
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.message import Message
from email.generator import _make_boundary
#constants
EMAIL_SMTP = "localhost"
EMAIL_FROM = "Fusion Wallet <no-reply@fusionwallet.io>"
EMAIL_RETURN = "Fusion Wallet Support <support@fusionwallet.io>"
addr = 'some_target_email@gmail.com'
subject = 'test'
html = '<b>test</b>'
txt = 'test'
#character set
Charset.add_charset('utf-8', Charset.QP, Charset.QP, 'utf-8')
#MIME handlers
msgTEXT = MIMEText(txt, 'plain', 'UTF-8')
msgHTML = MIMEText(html, 'html', 'UTF-8')
msgRoot = MIMEMultipart(_subtype="signed", micalg="pgp-sha512", protocol="application/pgp-signature")
msgMix = MIMEMultipart('mixed')
msgAlt = MIMEMultipart('alternative')
msgSIGN = Message()
msgOWNKEY = MIMEBase('application', "octet-stream")
#Data
msgRoot.add_header('From', EMAIL_FROM)
msgRoot.add_header('To', addr)
msgRoot.add_header('Reply-To', EMAIL_FROM)
msgRoot.add_header('Reply-Path', EMAIL_RETURN)
msgRoot.add_header('Subject', subject)
msgMix.add_header('From', EMAIL_FROM)
msgMix.add_header('To', addr)
msgMix.add_header('Reply-To', EMAIL_FROM)
msgMix.add_header('Reply-Path', EMAIL_RETURN)
msgMix.add_header('Subject', subject)
msgMix.add_header('protected-headers', 'v1')
#Attach own key
ownKey = gpg.export_keys('6B6C0EBB6DC42AA4')
if ownKey:
    msgOWNKEY.add_header("Content-ID", "<0x6B6C0EBB.asc>")
    msgOWNKEY.add_header("Content-Disposition", "attachment", filename='0x6B6C0EBB.asc')
    msgOWNKEY.set_payload(ownKey)
#Attaching
msgAlt.attach(msgTEXT)
msgAlt.attach(msgHTML)
msgMix.attach(msgAlt)
if ownKey:
    msgMix.attach(msgOWNKEY)
#Sign
gpg = gnupg.GPG()
msgSIGN.add_header('Content-Type', 'application/pgp-signature; name="signature.asc"')
msgSIGN.add_header('Content-Description', 'OpenPGP digital signature')
msgSIGN.add_header("Content-Disposition", "attachment", filename='signature.asc')
originalSign = gpg.sign(msgMix.as_string().replace('\n', '\r\n').strip()).data
spos = originalSign.index('-----BEGIN PGP SIGNATURE-----')
sign = originalSign[spos:]
msgSIGN.set_payload(sign)
#Create new boundary
msgRoot.set_boundary(_make_boundary(msgMix.as_string()))
#Set the payload
msgRoot.set_payload(
    "--%(boundary)s\n%(mix)s--%(boundary)s\n%(sign)s\n--%(boundary)s--\n" % {
        'boundary':msgRoot.get_boundary(),
        'mix':msgMix.as_string(),
        'sign':msgSIGN.as_string(),
    }
)
#Send to SMTP
s = smtplib.SMTP(EMAIL_SMTP)
s.sendmail(EMAIL_FROM, addr, msgRoot.as_string())
s.quit()

Já bych rád přijímat dary:

Ethereum: 0x610E3B4e804b367c182c5FC4D65d09c089723389

BTC: 1iFA88LxbGYpVgis6v6PzN8JeV1C58wJd

Odpovězeno 20/03/2018 v 13:02
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more