对文件签名和加密非常新。在stackoverflow上找到MIMEKIT和代码。对代码的工作原理了解甚少或根本不了解,因此对其进行了更改。在程序包调用p7mViewer中打开创建的文件时,显示消息文件已损坏;签名信息可能会丢失。服务提供商无法解密使用以下代码生成的文件。
我需要使用SHA-256签名并使用DES-3进行加密。请参见下面的代码。
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Windows.Forms;
using Org.BouncyCastle.Cms;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using MimeKit;
using System.Text;
namespace ConsoleApplicationSignWithBouncyCastle
{
class Program
{
[STAThread]
static void Main(string[] args)
{
try
{
// First load a Certificate, filename/path and certificate password
Cert = ReadCertFromFile("c:/temp1/cert.pfx", "password");
// Select a binary file
var dialog = new OpenFileDialog
{
Filter = "All files (*.*)|*.*",
InitialDirectory = "./",
Title = "Select a text file"
};
var filename = (dialog.ShowDialog() == DialogResult.OK) ? dialog.FileName : null;
// Get the file
byte[] fileContent = File.ReadAllBytes( filename);
// Create the generator
var dataGenerator = new CmsEnvelopedDataStreamGenerator();
// Add receiver
// Cert is the user's X.509 Certificate set bellow
dataGenerator.AddKeyTransRecipient(Cert);
// Make the output stream
int startFileName = filename.LastIndexOf(@"\") +1;
string outFile = @"c:\temp1\"+ filename.Substring(startFileName, filename.LastIndexOf(".") - startFileName) + "_w_2.edi";
var outStream = new FileStream(outFile, FileMode.Create);
string Streamline = "";
byte[] StreamBytes = null;
byte[] newline = Encoding.ASCII.GetBytes(Environment.NewLine);
Streamline = "MIME-Version: 1.0";
StreamBytes = Encoding.ASCII.GetBytes(Streamline);
outStream.Write(StreamBytes , 0,Streamline.Length );
outStream.Write(newline, 0, newline.Length );
Streamline = "Date: " + DateTime.Now.ToString("ddd, dd MMM yyyy HH:mm:ss") + " +0000";
StreamBytes = Encoding.ASCII.GetBytes(Streamline);
outStream.Write(StreamBytes, 0, Streamline.Length);
outStream.Write(newline, 0, newline.Length);
Streamline = "X-Priority: 3 (Normal)";
StreamBytes = Encoding.ASCII.GetBytes(Streamline);
outStream.Write(StreamBytes, 0, Streamline.Length);
outStream.Write(newline, 0, newline.Length);
Streamline = "Message-ID: <10000003141>";
StreamBytes = Encoding.ASCII.GetBytes(Streamline);
outStream.Write(StreamBytes, 0, Streamline.Length);
outStream.Write(newline, 0, newline.Length);
Streamline = "Content-Disposition: attachment; filename="+@"""smime.p7m""";
StreamBytes = Encoding.ASCII.GetBytes(Streamline);
outStream.Write(StreamBytes, 0, Streamline.Length);
outStream.Write(newline, 0, newline.Length);
Streamline = "Content-Transfer-Encoding: binary";
StreamBytes = Encoding.ASCII.GetBytes(Streamline);
outStream.Write(StreamBytes, 0, Streamline.Length);
outStream.Write(newline, 0, newline.Length);
Streamline = "AS3-From: PILM";
StreamBytes = Encoding.ASCII.GetBytes(Streamline);
outStream.Write(StreamBytes, 0, Streamline.Length);
outStream.Write(newline, 0, newline.Length);
Streamline = "AS3-To: SARS";
StreamBytes = Encoding.ASCII.GetBytes(Streamline);
outStream.Write(StreamBytes, 0, Streamline.Length);
outStream.Write(newline, 0, newline.Length);
Streamline = "Subject: "+ filename.Substring(startFileName, filename.LastIndexOf(".") - startFileName) ;
StreamBytes = Encoding.ASCII.GetBytes(Streamline);
outStream.Write(StreamBytes, 0, Streamline.Length);
outStream.Write(newline, 0, newline.Length);
Streamline = "Content-Type: application/pkcs7-mime; smime-type="+@"""enveloped - data"""+ ";name="+@"""smime.p7m""";
StreamBytes = Encoding.ASCII.GetBytes(Streamline);
outStream.Write(StreamBytes, 0, Streamline.Length);
outStream.Write(newline, 0, newline.Length);
outStream.Write(newline, 0, newline.Length);
// Sign the stream
var cryptoStream = dataGenerator.Open(outStream, CmsEnvelopedGenerator.DesEde3Cbc );
// Store in our binary stream writer and write the signed content
var binWriter = new BinaryWriter(cryptoStream);
binWriter.Write(fileContent);
}
catch (Exception ex)
{
Console.WriteLine("So, you wanna make an exception huh! : " + ex.ToString());
Console.ReadKey();
}
}
public static Org.BouncyCastle.X509.X509Certificate Cert { get; set; }
// This reads a certificate from a file.
// Thanks to: http://blog.softwarecodehelp.com/2009/06/23/CodeForRetrievePublicKeyFromCertificateAndEncryptUsingCertificatePublicKeyForBothJavaC.aspx
public static Org.BouncyCastle.X509.X509Certificate ReadCertFromFile(string strCertificatePath, string strCertificatePassword)
{
try
{
X509Certificate2 myCert = new X509Certificate2(strCertificatePath, strCertificatePassword);
var cert = Org.BouncyCastle.Security.DotNetUtilities.FromX509Certificate(myCert);
return cert;
}
catch (Exception ex)
{
Console.WriteLine("So, you wanna make an exception huh! : " + ex.ToString());
Console.ReadKey();
return null;
}
}
}
}
答案 0 :(得分:1)
如果您使用MimeKit而不是尝试手动生成自己的MIME,则可以执行以下操作:
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Windows.Forms;
using MimeKit;
using MimeKit.Cryptography;
namespace ConsoleApplicationSignWithBouncyCastle
{
class Program
{
[STAThread]
static void Main (string[] args)
{
// Select a binary file
var dialog = new OpenFileDialog {
Filter = "All files (*.*)|*.*",
InitialDirectory = "./",
Title = "Select a text file"
};
var filename = (dialog.ShowDialog () == DialogResult.OK) ? dialog.FileName : null;
var certificate2 = new X509Certificate2 ("c:/temp1/cert.pfx", "password");
MimeEntity body;
using (var content = new MemoryStream (File.ReadAllBytes (filename)))
var part = new MimePart (MimeTypes.GetMimeType (filename)) {
ContentDisposition = new ContentDisposition (ContentDisposition.Attachment),
ContentTransferEncoding = ContentEncoding.Binary,
FileName = Path.GetFileName (filename),
Content = new MimeContent (content)
};
var recipient = new CmsRecipient (certificate2) {
EncryptionAlgorithms = new EncryptionAlgorithm[] { EncryptionAlgorithm.TripleDes }
};
var recipients = new CmsRecipientCollection ();
recipients.Add (recipient);
using (var ctx = new TemporarySecureMimeContext ())
body = ApplicationPkcs7Mime.Encrypt (ctx, recipients, part);
}
var message = new MimeMessage ();
message.Headers.Add ("AS3-From", "PILM");
message.Headers.Add ("AS3-To", "SARS");
message.Subject = Path.GetFileNameWithoutExtension (filename);
message.Date = DateTimeOffset.Now;
message.MessageId = "10000003141";
message.Body = body;
var outFile = @"c:\temp1\" + Path.GetFileNameWithoutExtension (filename) + "_w_2.edi";
message.WriteTo (outFile);
}
}
}
请注意,以上代码段比原始代码段要简单得多。白天和黑夜是不同的:)
如果您还想使用SHA-256签名,则可以这样做(差异很小):
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Windows.Forms;
using MimeKit;
using MimeKit.Cryptography;
namespace ConsoleApplicationSignWithBouncyCastle
{
class Program
{
[STAThread]
static void Main (string[] args)
{
// Select a binary file
var dialog = new OpenFileDialog {
Filter = "All files (*.*)|*.*",
InitialDirectory = "./",
Title = "Select a text file"
};
var filename = (dialog.ShowDialog () == DialogResult.OK) ? dialog.FileName : null;
var certificate2 = new X509Certificate2 ("c:/temp1/cert.pfx", "password");
MimeEntity body;
using (var content = new MemoryStream (File.ReadAllBytes (filename)))
var part = new MimePart (MimeTypes.GetMimeType (filename)) {
ContentDisposition = new ContentDisposition (ContentDisposition.Attachment),
ContentTransferEncoding = ContentEncoding.Binary,
FileName = Path.GetFileName (filename),
Content = new MimeContent (content)
};
var recipient = new CmsRecipient (certificate2) {
EncryptionAlgorithms = new EncryptionAlgorithm[] { EncryptionAlgorithm.TripleDes }
};
var recipients = new CmsRecipientCollection ();
recipients.Add (recipient);
var signer = new CmsSigner (certificate2) {
DigestAlgorithm = DigestAlgorithm.Sha256
};
using (var ctx = new TemporarySecureMimeContext ()) {
using (var stream = File.OpenRead ("c:/temp1/cert.pfx"))
ctx.Import (stream, "password");
body = ApplicationPkcs7Mime.SignAndEncrypt (ctx, signer, recipients, part);
}
}
var message = new MimeMessage ();
message.Headers.Add ("AS3-From", "PILM");
message.Headers.Add ("AS3-To", "SARS");
message.Subject = Path.GetFileNameWithoutExtension (filename);
message.Date = DateTimeOffset.Now;
message.MessageId = "10000003141";
message.Body = body;
var outFile = @"c:\temp1\" + Path.GetFileNameWithoutExtension (filename) + "_w_2.edi";
message.WriteTo (outFile);
}
}
}