2017-06-28 6 views
0

J'essaie d'envoyer un email SMIME signé et j'échoue. J'utilise Python 3, j'ai donc choisi la librairie poor-smime-sign. En utilisant Thunderbird pour recevoir, je reçois soit un email vide avec des "destinataires non divulgués" et pas de sujet, qui est signé ou je reçois tout en texte brut, en imprimant un énorme blob de base64 avec le corps du message - aucun signe de signer (jeu de mots non intentionnel, remarqué et laissé intact).Exemple utilisant poor-smime-sign

J'ai comparé la source d'un e-mail de travail (créé par Thunderbird à partir de mon dossier envoyé) avec mes mails franken, mais je ne vois pas vraiment la différence.

Voici le code:

from poor_smime_sign import smime_sign 
def signEmail(self, message :str) -> str: 
    """Sign the message-body. 

    The message is encoded in UTF-8, signed and then returned as Unicode. 

    Check this document on how to generate untrusted example-keys: 
    https://tools.ietf.org/doc/python-m2crypto/howto.smime.html 

    Check the settings ('invmail'->'keydir') where to put the keys. 
    The privateKey is called 'signer_key.pem' and publicKey 'signer.pem'. 
    """ 
    import os 
    privateKey = os.path.join(settings.SF.mail['keydir'], 'signer_key.pem') 
    publicKey = os.path.join(settings.SF.mail['keydir'], 'signer.pem') 

    try: 
     signed = smime_sign(publicKey, privateKey, message.encode('UTF-8')) 
    except Exception as e: 
     raise(Exception("Problem during signing: "+str(e))) 

    return signed.decode('UTF-8') 

poor_smime_sign BTW est assez humble au sujet de leur module, j'aime bien. J'ai regardé leur code et tout ce qu'ils font est d'appeler openssl, ce qui est ce que j'aurais fait, aussi, la prochaine étape. Si vous faites un dépannage, vous pouvez entrer dans le mod et consigner la commande qui est exécutée et la manipuler dans un shell jusqu'à ce que vous compreniez pourquoi elle échoue. Je p.ex. eu pub et priv cert dans le mauvais sens et a eu un message d'erreur vraiment stupide.

C'est ce qui met le message ensemble à la fin. Je l'avais copié à partir d'un exemple quelque part.

body = self.signEmail(body) 
emailAr = [ 
    "From: %s" % emailFrom, 
    "To: %s"  % emailTo, 
    "Subject: %s" % subject, 
    "",    # <- that one 
    body, 
] 
message = "\r\n".join(emailAr) 
#... 
server.sendmail(emailFrom, [emailTo], message.encode('UTF-8')) 

Répondre

0

TL; DR:

Obtenez les en-têtes droite: Signature crée déjà un en-tête. Ajoutez juste à cela. Pas de nouvelles lignes vides.

Eh bien, il se trouve que je n'avais aucune idée de la façon dont le courrier électronique fonctionne. Je me demandais en effet pourquoi j'utilise l'adresse TO deux fois (une fois la construction du message et une fois dans sendmail()) mais il a fallu du temps pour que je comprenne. Je savais que j'avais besoin d'une sorte de tête mais je ne savais pas où et pourquoi.

La solution était double:

  1. Le texte qui obtient signé a besoin d'un en-tête de sorte que le client de messagerie sait quoi faire avec elle. J'en ai pris un d'un courriel de travail que je traînais.

Cela ressemble à ceci.

cannedHeader = "\r\n".join([ 
    "Content-Type: text/plain; charset=utf-8; format=flowed", 
    "Content-Language: de-DE", 
    "Content-Transfer-Encoding: quoted-printable", 
    "","" # emtpy new line concludes header 
]) 
body = cannedHeader+bodyInput 
body = self.signEmail(body) 
  1. Le corps de message signé est déjà avec un en-tête partielle attaché. L'impression du résultat de la signature, vous voyez qu'il commence par

    MIME-Version: 1.0 Content-Type: multipart/signed; protocole = 3Dapplication/x-pkcs7-signature "; m = icalg = 3Dha-256"; boundary = 3D --- DF20A931579CC3CE98F68AEF4D387131"

    Ceci est un S/MIME message signé

    ------ DF20A931579CC3CE98F68AEF4D387131

    Et j'ai couru que, grâce à la version initiale du code, générer deux en-têtes dans le processus.Un avec les destinataires et le sujet suffixé par une nouvelle ligne vide, puis ajouté le corps du message signé, qui avait un autre en-tête, contenant des informations SMIME, également suffixé par une nouvelle ligne vide. Cela ne pourrait pas fonctionner. Donc, en supprimant la ligne vide (dans la question marquée par "cette ligne") a fixé cela.

Comme je l'ai pas trouvé aucun exemple sur StackExchange, je pensais que j'écrire cela, donc je peux le trouver quand j'ai besoin la prochaine fois.