我必须交换加密&与一些商业伙伴签署了电子邮件。需要特定的算法,例如:
我在设置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,我无法弄清楚如何使用它。
非常感谢邮件专家提供的任何帮助!
答案 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进行加密。
注意:
Encrypt()
将生成MultipartSigned.Create()
MIME部分,而multipart/signed
将创建ApplicationPkcs7Mime.Sign()
MIME部分。无论您想要使用哪一个都由您决定,请记住,您的选择可能会影响与您的收件人使用的任何客户端的兼容性(我认为大多数客户支持这两种形式,但您可能需要检查以确保)。 application/pkcs7-mime
课程(如自述文件中简要描述的那样),那么您可以随意使用不采取的各种加密/解密/签名/验证/等方法密码学上下文参数,因为MimeKit将为您实例化默认上下文。否则你需要传递一个上下文。