【问题标题】:base64-Encoding breaks smime-encrypted emaildatabase64 编码会破坏 smime 加密的电子邮件数据
【发布时间】:2012-04-01 00:12:16
【问题描述】:

我正在使用 Mime::Lite 创建和发送电子邮件。现在我需要添加对 S/Mime 加密的支持,最后可以加密我的电子邮件(我可以安装的唯一 Perllib 似乎坏了,所以我使用系统调用和 openssl smime),但是当我尝试创建一个 mime -object ,只要我将 Content-Transfer-Encoding 设置为 base64,电子邮件就会被破坏。更让人好奇的是,只有当我通过$myMessage->attr 设置它时才会发生这种情况。如果我使用构造函数 ->new 一切都很好,除了我使用 MIME::Lite->quiet(1); 抑制的一点警告之外。

这是一个错误还是我的错?以下是我创建 mime 对象的两种方式。

  1. 通过构造器设置 Content-Transfer-Encoding 并抑制警告:

    MIME::Lite->quiet(1); 
    my $msgEncr = MIME::Lite->new(From   =>'me@myhost.com',
                            To     => 'you@yourhost.com',
                           Subject => 'SMIME Test',
                           Data    => $myEncryptedMessage,
                           'Content-Transfer-Encoding' => 'base64');
    
    $msgEncr->attr('Content-Disposition'        =>  'attachment');
    $msgEncr->attr('Content-Disposition.filename'   =>  'smime.p7m');
    $msgEncr->attr('Content-Type' => 'application/x-pkcs7-mime');
    $msgEncr->attr('Content-Type.smime-type' => 'enveloped-data');
    $msgEncr->attr('Content-Type.name' => 'smime.p7m');
    
    $msgEncr->send;             
    
    MIME::Lite->quiet(0);
    
  2. 通过 $myMessage->attr 设置 Content-Transfer-Encoding 会破坏加密数据,但不会导致警告:

    my $msgEncr = MIME::Lite->new(From  => 'me@myhost.com',
                           To         => 'you@yourhost.com',
                           Subject    => 'SMIME Test',
                           Data => $myEncryptedMessage);
    
    $msgEncr->attr('Content-Disposition'        =>  'attachment');
    $msgEncr->attr('Content-Disposition.filename'       =>  'smime.p7m');
    $msgEncr->attr('Content-Type' => 'application/x-pkcs7-mime');
    $msgEncr->attr('Content-Type.smime-type' => 'enveloped-data');
    $msgEncr->attr('Content-Type.name' => 'smime.p7m');
    $msgEncr->attr('Content-Transfer-Encoding' => 'base64');
    
    $msgEncr->send; 
    

我只是不明白为什么在使用属性设置器时我的消息被破坏了。提前感谢您的帮助!

此外,如果不再次破坏加密邮件,我无法将任何文件附加到此电子邮件。

【问题讨论】:

  • 您需要在列表项之后将它们撞到另外 4 个空格,以便降价以表明您的意思是将它们作为代码。

标签: perl smime


【解决方案1】:

调试这个 进行脚本调用 showmail.pl

#!/usr/bin/perl
while (<STDIN>) { print $_; }

像这样测试它

use MIME::Lite;
use Net::SMTP;
use MIME::Base64;
$myEncryptedMessage = encode_base64("This is not valid encrypted message\n");
MIME::Lite->send('sendmail', "./showmail.pl"); ## Add this for debugging.
MIME::Lite->quiet(1); my $msgEncr = MIME::Lite->new(From   =>'me@localhost',
                 To     => 'you@localhost',
                 Subject => 'SMIME Test',
                 Data    => $myEncryptedMessage,
                 'Content-Transfer-Encoding' => 'base64');
$msgEncr->attr('Content-Disposition'        =>  'attachment');
$msgEncr->attr('Content-Disposition.filename'   =>  'smime.p7m');
$msgEncr->attr('Content-Type' => 'application/x-pkcs7-mime');
$msgEncr->attr('Content-Type.smime-type' => 'enveloped-data');
$msgEncr->attr('Content-Type.name' => 'smime.p7m');
$msgEncr->send();

你应该看到类似的东西。

MIME-Version: 1.0
Content-Disposition: attachment; filename="smime.p7m"
Content-Length: 49
Content-Type: application/x-pkcs7-mime; name="smime.p7m"; smime-type="enveloped-data"
X-Mailer: MIME::Lite 3.028 (F2.74; B3.07; Q3.07)
Date: Mon, 23 Mar 2012 10:40:51 -0400
From: me@localhost
To: you@localhost
Subject: SMIME Test
Content-Transfer-Encoding: base64

VGhpcyBpcyBub3QgdmFsaWQgZW5jcnlwdGVkIG1lc3NhZ2UK

消息是base64编码的,但真正的消息还是需要正确的 加密。您需要确保是这种情况,因为 $myEncryptedMessage 是 传入。通过调试输出,您可以与已知良好的加密邮件进行比较 看看标题是否很好,据我所知,标题很好,可能是 无效的数据。

【讨论】:

  • base64 编码的问题在于,如果您通过$myObject-&gt;attr() 设置 Content-Transfer-Encoding,那么 mimelite 似乎会对给定对象进行编码。所以我对消息进行编码,通过系统调用对其进行加密,并根据该数据重建一个(新的)mimeobject。如果我在此对象上设置 Content-Transfer-Encoding,则不应再次对数据进行编码。我想我会重新审视我的问题以澄清它。
  • 如果我没记错的话,我的测试显示 $myEncryptedMessage 被逐字传递给正文,而不管 attr 设置如何。您可能想进行一些测试,看看它对消息的实际作用。
  • 它是逐字传递的,因为您通过 mimeobject 的构造器设置了 Content-Transfer-Encoding。因此没有进行编码,但这会引发警告。这就是为什么我使用-&gt;quiet(1) 来抑制这个警告。所以我想知道为什么它会发出警告,但工作方式不同,就好像我通过-&gt;attr 单独设置它一样。
  • 你说得对,我还检查了 Lite.pm 的 base64 实现是否正确,我怀疑数据本身不正确。你能验证吗?
  • 目前我在抑制此警告的同时创建电子邮件,以便我的数据不会再次编码,并且我的客户可以正确解密电子邮件,因为数据没有被 mimelite 更改。我需要扩展我的测试脚本以便也能够添加附件,因此可能需要通过-&gt;attr du 将传输编码设置为多部分/混合。我不确定我是否只是对所有这些“尝试和错误”的东西感到非常困惑,或者从 perl(通过系统调用加密)发送 smime 加密的电子邮件(带有附件)是否同样复杂。跨度>
【解决方案2】:

我无法使用真正的邮件客户端对此进行测试,但我认为这可能适用于多部分。

use MIME::Lite;
use Net::SMTP;
use MIME::Base64;
MIME::Lite->send('sendmail', "./showmail.pl"); ## <---- for testing only
my $from_address = "nobody@localhost";
my $to_address = "somebody@localhost";
my $mail_host = "localhost";
my $subject = "Subject list";
my $message_body = "Attachment list";
my @files = ("crypt.data1","crypt.data2");
$msg = MIME::Lite->new (
  From => $from_address,
  To => $to_address,
  Subject => $subject,
  Type =>'multipart/mixed'
) or die "Error creating multipart container: $!\n";

foreach $c(@files) {
   $msg->attach (
     Disposition => 'attachment',
     Type => "application/x-pkcs7-mime; name=smime.p7m; smime-type=enveloped-data",
     Path => $c,
   ) or die "Error adding $c: $!\n";
}
$msg->send;

【讨论】:

  • 我在回答中添加了一些信息,我是如何解决附件问题的 :)
【解决方案3】:

正如我在一条评论中所说,在 mimeobject 的构造函数或 -&gt;attr-Setter 中设置编码的区别在于,构造函数只是在 mimeheader 中设置编码。通过使用-&gt;attr-Setter mime 使用 base64 对数据进行编码。

所以在我的例子中,我之前生成的 mimeobject - 它是 base64 编码和 s/mime 加密的 - 从文件中读取 需要 在构造函数中设置编码(并抑制警告)因此 mime 将不再进行编码。否则,mime 将再次对数据进行编码,从而破坏加密和电子邮件本身。

我终于有附件工作了。为了实现这一点,我创建了一个普通的多部分/混合 mimeobject,将此对象打印到一个普通文件中,使用 openssl smime 加密此文件,将整个文件(6 个标题行除外)读入一个变量并将其用作数据输入。此外,我使用构造函数将 Content-Transfer-Encoding 设置为 base64(因此不对我的数据进行编码)。

我希望这会帮助别人,然后是我;)

【讨论】:

  • 我在search.cpan.org/~rjbs/MIME-Lite-3.028/lib/MIME/Lite.pm 中找到了关于 MIME:Lite 的这条小信息@等等! MIME::Lite 不被当前的维护者推荐。有许多替代方案,例如 Email::MIME 或 MIME::Entity 和 Email::Sender,您可能应该使用它们。 MIME::Lite 继续产生奇怪的错误报告,并且由于有更好的替代方案,它没有收到大量的重构。请考虑使用其他东西。
【解决方案4】:

将 $myEncryptedMessage 替换为 encode_base64($myEncryptedMessage)

并使用 MIME::Base64;

【讨论】:

  • 如果我使用这种方法,加密的数据仍然会被破坏。
猜你喜欢
  • 1970-01-01
  • 2012-04-24
  • 2011-12-30
  • 1970-01-01
  • 2020-12-20
  • 2018-01-03
  • 2015-09-21
  • 2018-07-04
  • 2021-10-20
相关资源
最近更新 更多