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

Posted

技术标签:

【中文标题】如何在不解密的情况下检查加密的 S/MIME 消息是不是也被签名【英文标题】:How to check if encrypted S/MIME message is also signed, without decrypting it如何在不解密的情况下检查加密的 S/MIME 消息是否也被签名 【发布时间】:2012-11-10 19:29:00 【问题描述】:

在加密邮件时,判断 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 加密和签名数据仍然有一些模式可以让我区分加密/签名和加密/未签名数据而无需解密(如果我没有解密证书,这甚至可能)?

【问题讨论】:

如果用户签名,然后加密数据,他可能想隐藏消息已签名的事实,这与您想要做的相反。 我不这么认为。一些电子邮件客户端就是这样工作的。 如果消息被加密它被签名之后,唯一知道它已经被签名的方法就是首先解密它。请参阅我的answer,了解为什么这是一个坏主意。 感谢您的评论,如果我需要加密或签署电子邮件,我会考虑它。但是,我没有实施安全系统。我只需要在我的电子邮件客户端中显示签名和加密的电子邮件。所以我只需要处理其他邮寄给我的邮件。 【参考方案1】:

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 标准本身是灵活的,但大多数邮件客户端不仅实现了签名/加密,而且他们似乎也不理解 encrypt/sign 或 sign/加密/登录收到的邮件。【参考方案2】:

如果目标是确保:

    只有收件人可以解密邮件,并且 收件人知道谁写了邮件,

那么正确的顺序是签名加密,然后再次签名。否则无论如何你都不能相信它。原因如下。

签名和加密消息: 发件人首先对消息签名,然后对其进行加密。 在这里,接收者可以解密消息,然后用完整的签名重新加密它,然后将其发送给第三方(带有欺骗的标头)。该第三方会相信原始作者直接将消息发送给他,而实际上该消息是由原始收件人转发的。

加密和签名的消息: 发件人首先加密消息,然后对其进行签名。 任何攻击者都可以删除签名,将其替换为自己的签名,并在不知道其内容的情况下声明消息的作者身份。

加密、签名和加密的消息: 发件人对消息进行加密和签名,然后再次加密。 在这里,内部加密确保只有预期的收件人才能阅读邮件。签名意味着作者知道内容并打算将其提供给收件人。外部加密可防止攻击者知道或篡改消息。

在这种情况下,收件人在解密之前不会知道邮件已签名。

对消息加密两次更多

更糟糕的是,加密然后签名是 known 容易受到攻击。

签名、加密和签名的消息: 发件人对消息进行签名和加密,然后再次签名。 在这里,内部签名意味着作者知道内容。加密确保只有收件人可以解密它。并且外部签名意味着作者打算将消息发送给收件人。

如果攻击者试图通过移除外部签名并用自己的替换来声明所有权,那么(替换的)外部签名将与内部签名不匹配。

如果收件人将邮件解密并转发给第三方,他必须保持最里面的签名不变或用自己的签名替换。在任何一种情况下,原作者均不对信息承担责任。

结论

尽管有当前(失效的)标准,您只有在最后一步中签名后才能验证消息的发件人。因此,您不必担心首先签名并然后加密的消息,因为您无法相信所谓的签名者将消息发送给您。

例如,想象一下收到一封来自总统的签名然后加密的消息,邀请您到白宫共进晚餐。事实上,总统确实写了那条信息,但他实际上把它发送给了一个决定跟你开玩笑的人。

【讨论】:

-1,因为您在解释签名/加密消息的安全性方面做出了出色的努力,但忘记实际尝试回答问题。 @Owlstead:首先,感谢您抽出时间(并有礼貌)解释您的反对意见。正如我曾经告诉我的技术支持负责人那样,您从经验中吸取的教训之一就是不要专注于为客户提供他想要的东西;相反,给他他需要的。通过解释为什么在签名之后加密的消息上信任签名会产生误导,我回答了基本问题。 OP问“我怎么能......?”正确的答案是,“不要那样做,原因如下。” 该方案有很多错误,但它确实可以防止许多攻击。这取决于用例。例如。如果您只是接受来自某些实体的消息,那么您不在乎是否有人声称这是他的消息。 -1 这个傲慢的不回答的评价太高了。它有很好的信息;它应该是一篇博文。别处。根据 OP 评论,这对他们的直接任务没有用。我完全同情向所有愚蠢的程序员解释做事的正确方法的愿望。 (有时,我就是那个愚蠢的程序员。)但是当一个机械师让你给他们一把扳手,而你却详细地告诉他们为什么他们在错误的电机上工作时,这只会浪费他们的时间并考验他们的耐心。 不同选项的良好比较。有关为什么应该使用签名/加密/签名的更多详细信息,我推荐Defective Sign & Encrypt in S/MIME by Don Davis,第 5 章。但是,任何广泛使用的邮件客户端似乎都不支持此选项。事实上,我们发现只有签名/加密适用于它们。

以上是关于如何在不解密的情况下检查加密的 S/MIME 消息是不是也被签名的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PowerShell 中使用 S/MIME 对消息进行签名和加密

电子邮件安全:TLS 和 S/MIME

Java加密序列化消息

如何在python中加密和解密消息RSA?

尝试使用 Openssl 解密 S/MIME 文件

为啥 JSON Web Token (JWT) 在不知道密钥的情况下解密