gpt4 book ai didi

mimekit - 在 MimeKit 上签名和加密

转载 作者:行者123 更新时间:2023-12-04 12:50:31 28 4
gpt4 key购买 nike

我被要求向我们的客户发送签名和加密的邮件,但是,这是我第一次与签名和加密的斗争(我想强调这一点)。

我尝试过使用 OpaqueMail 和 MimeKit。
因为我真的不太了解 OpaqueMail,而且我有自己的客户端来检索电子邮件,所以我发现理解和实现 MimeKit 更好。

我知道这是我在以下几行中所做的基本实现,但这只是与它的第一次接触,只是一个测试。我可以发送带有加密正文的签名电子邮件,问题来自附件(我们只是发送了带有附件文件的空正文,它来自数据库)。

try
{
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);

X509Certificate2Collection collection = store.Certificates.Find(X509FindType.FindBySubjectName, "senderEmail@something.com", false); //TODO Change to true after test
X509Certificate2 senderCertificate = collection[0];

store = new X509Store(StoreName.AddressBook, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);

collection = store.Certificates.Find(X509FindType.FindBySubjectName, "recipientEmail@something.com", false); //TODO Change to true after test
X509Certificate2 recipientCertificate = collection[0];

MimeMessage mimeMessage = new MimeMessage
{
Date = DateTime.Now,
};

mimeMessage.From.Add(
new SecureMailboxAddress(
"senderEmail@gmail.com",
"senderEmail@gmail.com",
senderCertificate.Thumbprint));

mimeMessage.To.Add(
new SecureMailboxAddress(
"recipientEmail@gmail.com",
"recipientEmail@gmail.com",
recipientCertificate.Thumbprint));

mimeMessage.Subject = "S/MIME Test";

using (Stream stream = "TestAttachmentFile".ToStream())
{
//Attachment
MimePart attachment = new MimePart(new ContentType("text", "plain"))
{
ContentTransferEncoding =
ContentEncoding.Base64,
ContentDisposition = new ContentDisposition(ContentDisposition.Attachment),
FileName = "TestAttachmentFileName.txt",
ContentObject = new ContentObject(stream)
};

Multipart multipart = new Multipart("mixed") { attachment};

mimeMessage.Body = multipart;

//Sign / Encryption
CmsSigner signer = new CmsSigner(senderCertificate);

CmsRecipientCollection colle = new CmsRecipientCollection();
X509Certificate bountyRecipientCertificate = DotNetUtilities.FromX509Certificate (recipientCertificate)

CmsRecipient recipient = new CmsRecipient(bountyRecipientCertificate);
colle.Add(recipient);

using (var ctx = new MySecureMimeContext ())
{
var signed = MultipartSigned.Create (ctx, signer, mimeMessage.Body);
var encrypted = ApplicationPkcs7Mime.Encrypt (ctx, colle, signed);
mimeMessage.Body = MultipartSigned.Create (ctx, signer, encrypted);
}

//Sending
using (SmtpClient smtpClient = InitSmtpClient(
"mail.smtp.com",
465,
"sender@something.com",
"Pwd",
true))
{
smtpClient.Send(mimeMessage);
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}

那么问题来了:

签名和正文加密有效。但是当我尝试添加附件时,我可以打开它但总是出现 BOM () 我可以看到附件但是雷鸟没有告诉我它是一个附件,它就像电子邮件的正文。我不知道这是否是我实现的 ToStream() 的问题。此外,Thunderbird 也无法显示正确的德语字符 (ÜüÖöÄäß) 和西类牙语 ñ

编辑 MimeKit.Decryption 方法也很有效,而且我也得到了没有 BOM 的消息的正确编码,并且附件在那里。对于 Thunderbird 客户端来说,这可能是一个问题。

与 SecureMimeContext 相关,我们正在使用 HanaDB,我们想在那里存储证书,检索和使用它们,但我无法找到 IX509CertificateDatabase 的正确转换,因此,暂时使用 WindowsStore。

编辑,我解决了数据库创建 WindowsSecureMimeContext 并覆盖导入以从数据库获取证书的问题。又快又脏。

编辑 2,这很难实现,因为我们使用 DAO 模板实现,我从 SecureMimeContext 创建了子类,我查看了 WindowsSecureMimeContext 以了解这些方法究竟做了什么,只需更改代码以适应我们的 DAO 内容。

如何从 X509Certificate2 转换为 X509Certificate(BouncyCaSTLe) 就像参数 CmsRecipient 一样?

编辑,DotNetUtilities.FromX509Certificate 完成了这项工作。

是否可以制作“Triple Wrap”?签名,加密,再次签名。

编辑,是的
using (var ctx = new MySecureMimeContext ()) {
var signed = MultipartSigned.Create (ctx, signer, mimeMessage.Body);
var encrypted = ApplicationPkcs7Mime.Encrypt (ctx, colle, signed);
mimeMessage.Body = MultipartSigned.Create (ctx, signer, encrypted);
}

最佳答案

听起来您现在已经找到了使用 DotNetUtilities.FromX509Certificate() 的大部分方法。 .

看起来您剩下的最后一个问题是关于如何“三重包装”。

我会推荐的是这个:

using (var ctx = new MySecureMimeContext ()) {
var encrypted = ApplicationPkcs7Mime.SignAndEncrypt(ctx, signer, colle, mimeMessage.Body);
mimeMessage.Body = ApplicationPkcs7Mime.Sign (ctx, signer, encrypted);
}

或者:
using (var ctx = new MySecureMimeContext ()) {
var encrypted = ApplicationPkcs7Mime.SignAndEncrypt(ctx, signer, colle, mimeMessage.Body);
mimeMessage.Body = MultipartSigned.Sign (ctx, signer, encrypted);
}

或者:
using (var ctx = new MySecureMimeContext ()) {
var signed = MultipartSigned.Create (ctx, signer, mimeMessage.Body);
var encrypted = ApplicationPkcs7Mime.Encrypt (ctx, colle, signed);
mimeMessage.Body = MultipartSigned.Sign (ctx, signer, encrypted);
}

您可能想尝试使用所有 3 个选项,看看哪一个最适合您的客户使用的邮件客户端(Outlook、Thunderbird、Apple Mail?)。
ApplicationPkcs7Mime.SignAndEncrypt()使用 application/pkcs7-mime; smime-type=signed-data格式,然后加密与加密 multipart/signed 不同的内容。不同的客户可能会在不同程度上成功处理这些问题。

使用 multipart/signed 的一个很好的理由是即使用户的客户端无法解码 S/MIME,电子邮件仍然是可读的,因为它使用分离的签名,这意味着邮件的原始文本没有封装在二进制签名数据中。但是......因为你也在加密,所以它可能没有什么区别。

Related to SecureMimeContext, we are using HanaDB and we want to store the certificates there, retrieve and use them, but I was not able to find the proper conversion for IX509CertificateDatabase, so, using WindowsStore for the moment.



我建议看看 DefaultSecureMimeContext并实现您自己的 IX509CertificateDatabase .

如果 HanaDB 是基于 SQL 的,你可能可以子类化 SqlCertificateDatabase这是一个抽象的基于 SQL 的证书数据库实现。你可以看看 SqliteCertificateDatabase.csNpgsqlCertificateDatabase.cs (PostgreSQL) 来感受一下如何去做。

或者你可以看看 X509CertificateDatabase.cs查看如何实现通用版本。

老实说,我会避免 WindowsSecureMimeContext除非您实际将证书存储在 Windows 证书存储中。

关于mimekit - 在 MimeKit 上签名和加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30983883/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com