使用RSASSA-PSS和RSAES-OAEP与MailKit

问题描述 投票:1回答:1

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

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

我在使用Mailkit设置这个问题时遇到了麻烦,实际上它背后是MailKit和BouncyCastle。这是我到目前为止的地方:

用于解密和签名验证

解密身体是可以的,我在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,我无法弄清楚如何使用它。

任何邮件专家的帮助将不胜感激!

c# cryptography mimekit
1个回答
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完全支持,那么PrivateKeyX509Certificate2属性将已经是RSASSA-PSS。如果没有,你将不得不使用Bouncy Castle(根据你在问题中找到的内容看起来它支持它)。

我不是询问如何使用Bouncy Castle创建这样一个私钥的最佳人选,但是一旦你想出来,你就可以轻松地使用任何带有Sign()CmsSigner方法,它允许你指定私钥,比如这个.ctor

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

首先,要使用S / MIME进行加密,您需要使用其中一种ApplicationPkcs7Mime.Encrypt()方法。[2]

采用MailboxAddress的Encrypt()方法将通过基于提供的电子邮件地址进行证书查找来自动为您创建CmsRecipients和CmsRecipientCollection(或者,如果这些邮箱中的任何一个实际上是SecureMailboxAddress,则使用Fingerprint,这是有用的如果该用户在您的数据库中有超过1个证书,或者您想要更加确定MimeKit选择正确的证书)。

当你给它添加一个MailboxAddresses列表时,MimeKit将为你做的另一件事是,它将查找存储在数据库中的所述用户支持的加密算法。

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

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

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

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

var recipient = new CmsRecipient (certificate);

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

recipient.EncryptionAlgorithms = new EncryptionAlgorithm[] {
    EncryptionAlgorithm.Aes128
};

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

将每个CmsRecipient添加到您的CmsRecipientCollection,然后将其传递给您首选的Encrypt()方法和whallah,它将使用AES-128 CBC加密。

笔记:

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