我有一些加密和签名电子邮件的课程。
签名过程没有问题,但是当我尝试时 使用"加密"加密消息在EnvelopedCms实例上的方法,我得到了信息异常"无效的加密消息类型"。
我尝试通过设置在contentInfo中指定ContentType Oid =" 1.2.840.113549.1.7.2"," signedData"类型(根据msdn库),但不工作。
public static void SignAndEncryptMessage(MailMessage message, X509Certificate2 signingCertificate, X509Certificate2 encryptionCertificate)
{
string content = BuildMessageContent(message);
content = SignContent(content, message.BodyEncoding, signingCertificate, encryptionCertificate);
Stream encryptedStream = Encrypt(content, message.BodyEncoding, encryptionCertificate);
AlternateView av = new AlternateView(encryptedStream,
"application/pkcs7-mime; smime-type=signed-data;name=smime.p7m");
message.AlternateViews.Add(av);
message.Body = null;
message.Attachments.Clear();
}
public static void SignMessage(MailMessage message, X509Certificate2 signingCertificate)
{
string content = BuildMessageContent(message);
content = SignContent(content, message.BodyEncoding, signingCertificate, null);
MemoryStream stream = new MemoryStream();
byte[] mimeMessage = Encoding.ASCII.GetBytes("This is a multi-part message in MIME format.\r\n\r\n");
stream.Write(mimeMessage, 0, mimeMessage.Length);
byte[] contentBytes = message.BodyEncoding.GetBytes(content);
stream.Write(contentBytes, 0, contentBytes.Length);
stream.Position = 0;
AlternateView av = new AlternateView(stream,
"multipart/signed; boundary=\"--PTBoundry=3\";protocol=\"application/x-pkcs7-signature\"; micalg=SHA1;");
av.TransferEncoding = TransferEncoding.SevenBit;
message.AlternateViews.Add(av);
message.Body = null;
message.Attachments.Clear();
}
public static Stream Encrypt(string content, Encoding contentEncoding, X509Certificate2 encryptionCertificate)
{
const string signatureBoundry2 = "--PTBoundry=3";
StringBuilder fullUnencryptedMessageBuilder = new StringBuilder();
fullUnencryptedMessageBuilder.Append("Content-Type: ");
fullUnencryptedMessageBuilder.Append("multipart/signed; ");
fullUnencryptedMessageBuilder.Append(" boundary=\"");
fullUnencryptedMessageBuilder.Append(signatureBoundry2);
fullUnencryptedMessageBuilder.Append("\"; protocol=\"application/x-pkcs7-signature\"; micalg=SHA1; ");
fullUnencryptedMessageBuilder.Append("\r\n");
fullUnencryptedMessageBuilder.Append("Content-Transfer-Encoding: ");
fullUnencryptedMessageBuilder.Append(TransferEncoding.SevenBit);
fullUnencryptedMessageBuilder.Append("\r\n\r\n");
fullUnencryptedMessageBuilder.Append(content);
string fullUnencryptedMessage = fullUnencryptedMessageBuilder.ToString();
byte[] encryptedBytes = DoEncrypt(fullUnencryptedMessage, contentEncoding, encryptionCertificate);
MemoryStream stream = new MemoryStream(encryptedBytes);
return stream;
}
private static byte[] DoEncrypt(string message, Encoding encoding, X509Certificate2 encryptionCertificates)
{
byte[] messageBytes = encoding.GetBytes(message);
var contentNfo = new ContentInfo(messageBytes);
var encms = new EnvelopedCms(contentNfo);
var recipient = new CmsRecipient(encryptionCertificates);
try
{
encms.Encrypt(recipient);
var asdf = encms.RecipientInfos;
return encms.Encode();
}
catch (Exception e)
{
throw e;
}
}
public static byte[] Decrypt(Stream stream)
{
byte[] cont = new byte[stream.Length];
stream.Read(cont, 0, cont.Length);
return Decrypt(cont);
}
public static byte[] Decrypt(byte[] message)
{
EnvelopedCms envelopedCms = new EnvelopedCms();
envelopedCms.Decode(message);
envelopedCms.Decrypt();
return envelopedCms.ContentInfo.Content;
}
public static string BuildMessageContent(MailMessage msg)
{
string messageBody = msg.Body;
if ((string.IsNullOrEmpty(messageBody) || string.Empty == messageBody.Trim()) && msg.AlternateViews.Count > 0)
{
messageBody = Encoding.UTF8.GetString(msg.AlternateViews[0].ContentStream.ToByteArray());
}
const string messageBoundry = "--PTBoundry=2";
StringBuilder message = new StringBuilder();
message.Append("\r\n");
message.Append("\r\n");
message.Append("--");
message.Append(messageBoundry + "\r\n");
message.Append(string.Format("Content-Type: {0}; charset={1}\r\n", msg.IsBodyHtml ? "text/html" : "text/plain", msg.BodyEncoding.WebName));
message.Append("Content-Transfer-Encoding: ");
message.Append(TransferEncoding.QuotedPrintable);
message.Append("\r\n\r\n");
message.Append(messageBody);
message.Append("\r\n");
foreach (Attachment attachment in msg.Attachments)
{
BinaryReader br = new BinaryReader(attachment.ContentStream);
byte[] buff = br.ReadBytes((int)attachment.ContentStream.Length);
String filecontent =
Convert.ToBase64String(buff, Base64FormattingOptions.InsertLineBreaks);
message.Append("--");
message.Append(messageBoundry);
message.Append("\r\n");
message.Append("Content-Type: ");
message.Append("application/octet-stream;");
message.Append(string.Format("name=\"{0}\"", attachment.Name));
message.Append("\r\n");
if (attachment.ContentDisposition.Inline)
{
message.Append("Content-Disposition: inline");
message.Append("\r\n");
message.Append("Content-ID: <").Append(attachment.ContentId).Append(">");
message.Append("\r\n");
}
message.Append("Content-Transfer-Encoding: base64\r\n\r\n");
message.Append(filecontent);
message.Append("\r\n\r\n");
}
message.Append("--");
message.Append(messageBoundry);
message.Append("--\r\n");
return message.ToString();
}
public static byte[] GetSignature(string message, Encoding encoding, X509Certificate2 signingCertificate, X509Certificate2 encryptionCertificate)
{
byte[] messageBytes = encoding.GetBytes(message);
SignedCms signedCms = new SignedCms(new ContentInfo(messageBytes), true);
if (!signingCertificate.HasPrivateKey)
{
_log.Error("Certyfikat do podpisywania nie posiada klucza prywatnego!");
}
CmsSigner cmsSigner = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, signingCertificate) { IncludeOption = X509IncludeOption.WholeChain };
if (encryptionCertificate != null)
{
cmsSigner.Certificates.Add(encryptionCertificate);
}
Pkcs9SigningTime signingTime = new Pkcs9SigningTime();
cmsSigner.SignedAttributes.Add(signingTime);
try
{
signedCms.ComputeSignature(cmsSigner, false);
return signedCms.Encode();
}
finally
{
cmsSigner.Certificates.Clear();
}
}
public static string SignContent(string content, Encoding contentEncoding, X509Certificate2 signingCertificate, X509Certificate2 encryptionCertificate)
{
const string signatureBoundry = "--PTBoundry=2";
const string signatureBoundry2 = "--PTBoundry=3";
StringBuilder fullUnsignedMessageBuilder = new StringBuilder();
fullUnsignedMessageBuilder.Append("Content-Type: ");
fullUnsignedMessageBuilder.Append("multipart/mixed;");
fullUnsignedMessageBuilder.Append(" boundary=\"");
fullUnsignedMessageBuilder.Append(signatureBoundry);
fullUnsignedMessageBuilder.Append("\"\r\n");
fullUnsignedMessageBuilder.Append("Content-Transfer-Encoding: ");
fullUnsignedMessageBuilder.Append(TransferEncoding.SevenBit);
fullUnsignedMessageBuilder.Append("\r\n");
fullUnsignedMessageBuilder.Append(content);
string fullUnsignedMessage = fullUnsignedMessageBuilder.ToString();
byte[] signature = GetSignature(fullUnsignedMessage, contentEncoding, signingCertificate, encryptionCertificate);
StringBuilder signedMessageBuilder = new StringBuilder();
signedMessageBuilder.Append("--");
signedMessageBuilder.Append(signatureBoundry2);
signedMessageBuilder.Append("\r\n");
signedMessageBuilder.Append(fullUnsignedMessage);
signedMessageBuilder.Append("\r\n");
signedMessageBuilder.Append("--");
signedMessageBuilder.Append(signatureBoundry2);
signedMessageBuilder.Append("\r\n");
signedMessageBuilder.Append("Content-Type: application/x-pkcs7-signature; name=\"smime.p7s\"\r\n");
signedMessageBuilder.Append("Content-Transfer-Encoding: base64\r\n");
signedMessageBuilder.Append("Content-Disposition: attachment; filename=\"smime.p7s\"\r\n\r\n");
signedMessageBuilder.Append(Convert.ToBase64String(signature));
signedMessageBuilder.Append("\r\n\r\n");
signedMessageBuilder.Append("--");
signedMessageBuilder.Append(signatureBoundry2);
signedMessageBuilder.Append("--\r\n");
return signedMessageBuilder.ToString();
}