To create a signed/encrypted SMIME email using Mail.dll you need an X509Certificate2 instance:
MailBuilder builder = new MailBuilder();
builder.Text = "Hello";
builder.Subject = "Encrypted and signed";
builder.From.Add(new MailBox("alice@example.com", "Alice"));
builder.To.Add(new MailBox("bob@example.com", "Bob"));
builder.SignWith(new X509Certificate2("AlicePrivateSignCertificate.pfx", ""));
builder.EncryptWith(new X509Certificate2("AlicePublicCertificate.pfx", ""));
builder.EncryptWith(new X509Certificate2("BobsPublicCertificate.pfx", ""));
IMail email = builder.Create();
You can use this code to list certificates stored in CurrentUser store:
X509Store store = new X509Store(StoreName.My,StoreLocation.CurrentUser);
store.Open(OpenFlags.Read);
Trace.WriteLine("count = " + store.Certificates.Count);
foreach (X509Certificate2 certificate in store.Certificates)
{
Trace.WriteLine(certificate.Subject);
}
store.Close();
If your HSM device acts as a key-store you can use the code above.
Below is the code that shows how to sign data externally:
private byte[] ExternalSign_SmartCard_or_HSM(byte[] plainData)
{
// This is a .NET version, you use HSM device here to sign data.
SignedCms signedCms = new SignedCms(new ContentInfo(plainData), true);
X509Certificate2 certificate = new X509Certificate2("cert.pfx"),
"",
X509KeyStorageFlags.PersistKeySet)
CmsSigner signer = new CmsSigner(certificate);
signer.IncludeOption = X509IncludeOption.WholeChain;
signer.DigestAlgorithm = new System.Security.Cryptography.Oid(
CommonOids.Sha1);
signer.SignedAttributes.Add(new Pkcs9SigningTime(DateTime.Now));
signedCms.ComputeSignature(signer);
return signedCms.Encode();
}
[Test]
public void Build_ExternalSign_SmartCard_or_HSM_ValidSignature()
{
MailBuilder builder = new MailBuilder();
MimeData attachment = builder.AddAttachment(new byte[] { 1, 2, 3 });
attachment.SetFileName("file.bin", true);
builder.Html = "some <strong>html</strong> content";
IMail plain = builder.Create();
MimeBase plainRoot = plain.Document.Root;
// here you prepate a signature
byte[] plainData = plainRoot.Render();
byte[] signatureData = ExternalSign_SmartCard_or_HSM(plainData);
MimeFactory f = new MimeFactory();
MimeMultipart root = f.CreateMimeMultipart(ContentType.MultipartSigned);
root.ContentTypeHeader["protocol"] = "application/pkcs7-signature";
root.ContentTypeHeader["micalg"] = "sha-1";
root.Parts.Add(plainRoot); // you must use the same plain root you signed here
// (same random generated boundaries must be used).
// alternatively you can re-create it from plain Data:
// root.Parts.Add(f.Create(plainData));
MimePkcs7Signature signature = f.CreatePkcs7Signature(signatureData);
root.Parts.Add(signature);
IMail mail = new MailFactory().CreateMail(root);
mail.Subject = "subject";
mail.From.Add(new MailBox("email@in-the-certificate.com"));
mail.To.Add(new MailBox("to@example.com"));
Console.WriteLine(mail.RenderAsASCII());
byte[] eml = mail.Render();
// This parses eml and checks the signature
// No exception -> it's valid
IMail parsed = new MailBuilder().CreateFromEml(eml);
Assert.AreEqual("1.0", parsed.MimeVersion);
Assert.IsNotNull(parsed.Date);
Assert.IsNotNull(parsed.MessageID);
parsed.CheckSignature(true);
}