使用 C# 发送加密和签名的电子邮件

Posted

技术标签:

【中文标题】使用 C# 发送加密和签名的电子邮件【英文标题】:Send encrypted and signed email using C# 【发布时间】:2011-05-18 05:46:36 【问题描述】:

我想在不使用任何第三方 API 的情况下发送加密和签名的邮件。 如果我只发送带有签名的备用视图,Windows Mail 可以对其进行验证。如果我只发送带有加密数据的备用视图,Windows Mail 可以破译它。但如果我同时发送,Windows Mail 会收到 2 个附件。如果我对encryptedBytes 签名并将这些签名字节添加到替代视图中,它只会验证签名并且消息为空。 有什么想法吗?

MailMessage message = new MailMessage();
message.From = new MailAddress(lblMail.Text);
message.Subject = txtSubject.Text;

string body = "Content-Type: text/plain\r\nContent-Transfer-Encoding: 7Bit\r\n\r\n" + structForm();

byte[] messageData = Encoding.ASCII.GetBytes(body);
ContentInfo content = new ContentInfo(messageData);
EnvelopedCms envelopedCms = new EnvelopedCms(content);

message.To.Add(new MailAddress(provMail));

CmsRecipient recipient = new CmsRecipient(SubjectIdentifierType.SubjectKeyIdentifier, this.certificate);
envelopedCms.Encrypt(recipient);

byte[] encryptedBytes = envelopedCms.Encode();

SignedCms Cms = new SignedCms(new ContentInfo(encryptedBytes));
CmsSigner Signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, new X509Certificate2(@"c:\serv.pfx","123"));

Cms.ComputeSignature(Signer);
byte[] SignedBytes = Cms.Encode();

MemoryStream encryptedStream = new MemoryStream(encryptedBytes);
AlternateView encryptedView = new AlternateView(encryptedStream, "application/pkcs7-mime; smime-type=signed--data;name=smime.p7m");
message.AlternateViews.Add(encryptedView);
MemoryStream signedStream = new MemoryStream(SignedBytes);
AlternateView signedView = new AlternateView(signedStream, "application/pkcs7-mime; smime-type=signed-data;name=sig.p7m");
message.AlternateViews.Add(signedView);


System.Net.NetworkCredential SMTPUserInfo = new System.Net.NetworkCredential("emailaddress@xpto.com", "XXXXXX");
SmtpClient client = new SmtpClient("smtp.xpto.com");

client.UseDefaultCredentials = false;
client.Credentials = SMTPUserInfo;

client.Send(message);

Label2.Text = "Assinado e cifrado!";

【问题讨论】:

【参考方案1】:

您应该先签名,然后加密。

虽然最初的 CMS 和 S/MIME 规范允许您按任意顺序执行操作,但后来的工作指出,签署您无法阅读的文档是一个非常糟糕的主意。签名应该是纯文本。


生成的 MIME 消息应该只有一个部分,应该是 S/MIME 封装数据。您的消息有两部分,加密部分被错误标记为签名数据内容类型。创建并签署SignedCms 对象。对其进行编码,并将编码后的值用作EnvelopedCms 对象的内容。对其进行加密,并将其编码值用作MailMessage 的内容,内容类型为“application/pkcs7-mime; smime-type=envelope-data”。

【讨论】:

所以我确实在加密之前完成了签名。但是,它仍然是相同的效果。如果我只发送签名+加密它就不能正常工作 我相信你说要做这样的事情? pastebin.com/g1q6fkJL(对不起.. cmets 不接受代码...)我尝试过这种方式,在消息之后,我得到了乱码...

以上是关于使用 C# 发送加密和签名的电子邮件的主要内容,如果未能解决你的问题,请参考以下文章

如何使用laravel发送已签名/加密的消息?

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

双证书体系key usage扩展——Outlook使用证书发送加密签名邮件

GPG入门指南(加密/签名)

多方面保护邮件安全

通过未加密的连接发送电子邮件