如何在不解密的情况下检查加密的S/MIME消息是否已签名

9

当一封 S/MIME 邮件加密后,如何在计算资源方面最简单地判断该邮件是否带有签名?

如果一封邮件仅仅是被签名了,那么很容易判断。它看起来应该是这样的:

对于带有附加签名的邮件:

   Content-Type: application/x-pkcs7-mime; smime-type=signed-data;
    name="smime.p7m"

或者:

对于分离的签名

   Content-Type: multipart/signed; protocol="application/x-pkcs7-signature";
    micalg=SHA1; boundary="----=_NextPart_000_00D2_01CD5850.61030BF0"

在消息头中。

但是,当一条消息被加密时,您无法确定它是否也被签名,因为对于这两种情况(仅加密和加密/签名),Content-Type头是相同的:

  Content-Type: application/x-pkcs7-mime;
    smime-type=enveloped-data;
    boundary="----=_NextPart_000_000D_01CDC82B.98454D80";
    name="smime.p7m"

这是否意味着我必须解密消息才能确定它是否也被签名了?目前,似乎在我解密消息之前我甚至无法确定我的消息是否已被签名(因为签名在加密数据中)。或者,S/MIME加密和签名数据仍然具有某些模式,可以让我在不解密的情况下区分已加密/已签名和已加密/未签名的数据(即使我没有解密所需的证书)?


如果用户签名后加密数据,那么他很可能想要隐藏消息已经被签名的事实,这与您想要做的相反。 - Eugene Mayevski 'Callback
我不这么认为。有些电子邮件客户端就是这样工作的。 - Alex
如果一条消息在签名之后被加密,唯一知道它已经被签名的方法是先解密它。请查看我的答案,了解为什么这是一个坏主意。 - Adam Liss
感谢您的评论,如果我需要加密或签署电子邮件,我会考虑到它。然而,我并没有实现一个安全系统。我只需要在我的电子邮件客户端中显示已签名和加密的电子邮件。因此,我只需要处理其他邮件客户端发送给我的内容。 - Alex
2个回答

11

S/MIME非常灵活,您可以按任意组合进行签名和/或加密。然而,电子邮件客户端通常都会以相同的方式运作:Outlook 2010、Apple的Mail和Thunderbird 17都会先签名再加密。这3个客户端的结果几乎完全相同。它们在消息头中包含以下3个标头:

Content-Type: application/pkcs7-mime; smime-type=enveloped-data;
    name="smime.p7m"
Content-Disposition: attachment; filename="smime.p7m"
Content-Transfer-Encoding: base64

他们加密并对消息的整个正文进行base64编码。

回答你的问题:

在计算资源方面,如何最容易地判断是否使用附加签名对s/mime电子邮件进行了签名,同时该消息也被加密?

唯一的方法是对其进行解密。

这是否意味着我必须解密消息才能判断它是否已签名?

是的。


应该说,虽然S/MIME标准本身是灵活的,但大多数邮件客户端不仅只实现签名/加密,而且似乎也不理解接收到的邮件中的加密/签名或签名/加密/签名。 - not2savvy

8
如果目标是确保:只有接收者可以解密消息,且接收者知道谁写了该消息,则正确的顺序是先签名、再加密,最后再次签名。否则,无论如何都无法信任它。原因在于:
已签名和已加密的消息:发送方首先签署消息,然后加密它。在这种情况下,接收方可以解密消息,然后重新加密并带有签名发送给第三方(伪造标头)。那第三方将认为原始作者直接向他发送了该消息,而实际上是由原始接收者转发的。
已加密和已签名的消息:发送方首先加密消息,然后签名它。任何攻击者都可以删除签名,替换成自己的签名,并声明是消息的作者,而不知道其内容。 加密、签名和再加密的消息:发送者先对消息进行加密和签名,然后再次加密。
这里,内部加密确保只有预期的接收者才能读取消息。签名意味着作者知道内容并且打算发送给接收者。外部加密防止攻击者知道或篡改消息。
  • 在这种情况下,接收者只有在解密后才会知道消息已签名。

  • 将消息加密两次更为复杂。

  • 更糟糕的是,加密-然后-签名已知容易受到攻击。

签名、加密和再签名的消息:发送者先对消息进行签名和加密,然后再次签名。
这里,内部签名意味着作者知道内容。加密确保只有接收者可以解密它。外部签名表示作者打算将消息发送给接收者。
如果攻击者试图通过删除外部签名并替换为自己的签名来声明所有权, 那么(替换后的)外部签名将无法匹配内部签名。
如果收件人解密并转发消息给第三方,他必须将最内层的签名保持完整或替换为自己的签名。在任何情况下,原作者都不需要对该消息负责。
结论
尽管当前的(已破解)标准存在,但您只有在最后一步签名时才能验证消息的发送者。因此,您不必担心已经先签名再加密的消息,因为您不能相信所谓的签名者向您发送了该消息。
例如,想象一下从总统那里收到了一条先签名后加密的消息,邀请您在白宫共进晚餐。事实上,总统确实写了那条消息,但他实际上是把它发送给了一个决定开个玩笑的人。

3
你在解释签名/加密消息的安全性方面做出了出色的努力,但忘记实际尝试回答问题了。 - Maarten Bodewes
4
@Owlstead: 首先,感谢您花时间(并拥有礼貌)解释您的负投票。从经验中学到的一个教训,就像我曾经告诉我的技术支持主管一样,不要专注于给客户想要的东西,而是要给他需要的东西。通过解释为什么信封签名后再加密的消息不可靠,我回答了潜在的问题。原帖问“我怎么能做到...?”正确的回答是,“别这么做,这就是原因。” - Adam Liss
这个方案存在很多问题,但它也能保护免受许多攻击。这取决于使用情况。例如,如果您只接受来自某些实体的消息,则不必担心有人声称这是他的消息。 - Maarten Bodewes
2
-1 这种傲慢的非回答评价过高了。它有很好的信息,但应该在其他地方成为博客文章。根据 OP 的评论,它对他们的即时任务没有用处。我完全理解想要向所有愚蠢的程序员解释“正确的做事方式”的愿望。(有时候,我就是那个愚蠢的程序员。)但当一个机械师要求你递给他一个扳手,而你却长篇大论地告诉他他正在修理错误的发动机时,这只会浪费他们的时间并试探他们的耐心。 - system PAUSE
不同选项的比较很好。关于为什么应该使用 sign/encrypt/sign,更详细的信息,我推荐阅读 Don Davis 的 S/MIME 中有缺陷的签名和加密 第 5 章。然而,似乎没有任何广泛使用的邮件客户端支持这个选项。事实上,我们发现只有 sign/encrypt 可以与它们一起使用。 - not2savvy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接