使用RSASSA-PSS和RSAES-OAEP与MailKit

时间:2017-12-22 19:01:31

标签: c# cryptography mimekit

我必须交换加密&与一些商业伙伴签署了电子邮件。需要特定的算法,例如:

  • 用于签名,RSASSA-PSS作为签名算法,
  • 用于加密,RSAES-OAEP用于密钥加密&用于内容加密的AES-128 CBC

我在设置Mailkit时遇到了麻烦,实际上它背后是MailKit&充气城堡。 这是我到目前为止的地方:

用于解密&签名验证

解密正文是可以的,我在Windows商店中设置我的私钥后使用WindowsSecureMimeContext来实现它

验证签名不正确

case MultipartSigned signedBody:
    try
    {
        using (var ctx = new WindowsSecureMimeContext(StoreLocation.LocalMachine))
        {
            var verifiedData = signedBody.Verify(ctx);
            return verifiedData.All(o => o.Verify());
        }
    }
    catch (Exception e)
    {
        throw new Exception("Error during signature verification.", e);
    }

发件人的证书由公共CA签名,因此我再次使用WindowsSecureMimeContext,但VerifiedData.All(o => o.Verify())抛出DigitalSignatureVerifyException(“无法验证数字签名:未知错误“-1073700864”。“)

签名和加密

嗯,看起来很难......

对于签名,似乎我需要一个BouncyCastle的PssSigner,我可以通过覆盖DkimSigner,尤其是DigestSigner属性来获取

class TestSigner : DkimSigner
{
    protected TestSigner(string domain, string selector, DkimSignatureAlgorithm algorithm = DkimSignatureAlgorithm.RsaSha256) 
        : base(domain, selector, algorithm)
    {
    }

    public TestSigner(AsymmetricKeyParameter key, string domain, string selector, DkimSignatureAlgorithm algorithm = DkimSignatureAlgorithm.RsaSha256) 
        : base(key, domain, selector, algorithm)
    {
    }

    public TestSigner(string fileName, string domain, string selector, DkimSignatureAlgorithm algorithm = DkimSignatureAlgorithm.RsaSha256)
        : base(fileName, domain, selector, algorithm)
    {
    }

    public TestSigner(Stream stream, string domain, string selector, DkimSignatureAlgorithm algorithm = DkimSignatureAlgorithm.RsaSha256)
        : base(stream, domain, selector, algorithm)
    {
    }

    public override ISigner DigestSigner => SignerUtilities.GetSigner(PkcsObjectIdentifiers.IdRsassaPss);
}

但我不确切知道在哪里使用它。也许在使用MimeMessage.Sign()时,我对方法签名中的必需参数有点遗失

对于加密,我可以找到BouncyCastle库中的RsaesOaepParameters,我无法弄清楚如何使用它。

非常感谢邮件专家提供的任何帮助!

1 个答案:

答案 0 :(得分:1)

S / MIME签名

DkimSigner用于生成DKIM签名,您要执行的操作。 DKIM签名与没有与S / MIME。

对于使用S / MIME签名的内容,您希望使用MultipartSigned.Create()(显然不是采用PGP相关参数的版本)或ApplicationPkcs7Mime.Sign()。[1]

RSASSA-PSS是私钥算法(System.Security的AsymmetricAlgorithm或Bouncy Castle的AsymmetricKeyParameter)。

我应该注意WindowsSecureMimeContext使用System.Security作为后端而不是 Bouncy Castle,所以重要的是不要让他们感到困惑。

要使用Bouncy Castle后端,您需要使用其中一个BouncyCastleSecureMimeContext衍生物(或创建自己的衍生物)。作为玩弄事物的临时解决方案,我可能建议使用TemporarySecureMimeContext,但是为了长期使用,我建议查看DefaultSecureMimeContext - 尽管您仍然可能希望将其子类化为让它工作。

使用Windows后端,如果System.Security完全支持,PrivateKey的{​​{1}}属性将已经是RSASSA-PSS。如果没有,你将不得不使用Bouncy Castle(根据你在问题中找到的内容看起来它支持它)。

我不是询问如何使用Bouncy Castle创建这样一个私钥的最佳人选,但是一旦你弄清楚了,你就可以轻松地使用任何X509Certificate2方法来{{3}允许您指定私钥,例如此CmsSigner

使用AES-128 CBC(或任何其他特定算法)进行S / MIME加密

首先,要使用S / MIME进行加密,您需要使用.ctor方法之一。[2]

采用Sign()的Encrypt()方法会根据提供的电子邮件地址(或者,如果有的话)执行证书查找,为您自动创建ApplicationPkcs7Mime.Encrypt()CmsRecipient这些邮箱实际上是CmsRecipientCollection,而SecureMailboxAddress则被使用,如果该用户在您的数据库中拥有多个证书,或者您想要更加确定MimeKit选择正确的证书,这将非常有用。

MimeKit为您提供MailboxAddress es列表时将为您做的另一件事是,它将查找存储在数据库中的所述用户支持的加密算法。

对于MailboxAddress,这涉及查看S / MIME功能X509证书扩展属性并解码支持的加密算法。但是,根据我的经验,很多时候Windows证书存储中的X509证书上没有此扩展名,因此MimeKit必须假设只支持3DES CBC。

对于WindowsSecureMimeContext,如果您已经验证了所述收件人的任何S / MIME签名邮件,那么该用户的证书(链)和公布的加密算法将存储在MimeKit的自定义SQL数据库中(当您签署邮件时)使用S / MIME,客户端在S / MIME签名数据中包含S / MIME Capabilities属性是相当普遍的做法。

现在您已了解其工作原理,如果您想强制使用AES-128 CBC,那么这样做的方法是自己手动构建DefaultSecureMimeContext

当然,这涉及为每个收件人创建一个新的CmsRecipientCollection。要创建此类,您真正需要的只是该收件人的X509证书。

CmsRecipient

由于您要强制使用AES-128 CBC,现在您只需要覆盖此收件人支持的加密算法:

var recipient = new CmsRecipient (certificate);

(默认情况下,Fingerprint属性将设置为证书的S / MIME功能扩展属性(按优先顺序)中列出的算法(如果存在),否则它将仅包含3DES CBC)

将每个recipient.EncryptionAlgorithms = new EncryptionAlgorithm[] { EncryptionAlgorithm.Aes128 }; 添加到CmsRecipient,然后将其传递给您首选的CmsRecipientCollection方法和whallah,它将使用AES-128 CBC进行加密。

注意:

  1. Encrypt()将生成MultipartSigned.Create() MIME部分,而multipart/signed将创建ApplicationPkcs7Mime.Sign() MIME部分。无论您想要使用哪一个都由您决定,请记住,您的选择可能会影响与您的收件人使用的任何客户端的兼容性(我认为大多数客户支持这两种形式,但您可能需要检查以确保)。
  2. 如果您已经使用MimeKit注册了自定义application/pkcs7-mime课程(如自述文件中简要描述的那样),那么您可以随意使用不采取的各种加密/解密/签名/验证/等方法密码学上下文参数,因为MimeKit将为您实例化默认上下文。否则你需要传递一个上下文。
  3. Windows和Bouncy Castle都支持AES-128 CBC,因此您可以使用其中任何一种加密消息。