I once made an application that receives digital certificates of type X509 (which implement PKCS#7) and I can put some suggestion codes here. Some of them are mine and some I tidied up online some time ago.
Cryptohelper
/// <summary>
/// Provides methods for performing commonly-used cryptographic tasks
/// </summary>
public static class CryptoHelper
{
/// <summary>
/// Generates a cryptographic signature for a given message
/// </summary>
/// <param name="message">The message to sign</param>
/// <param name="signingCertificate">The certificate to sign the message with</param>
/// <param name="encryptionCertificate">An optional encryption certificate to include along with the signature</param>
/// <returns>The signature for the specified message</returns>
internal static byte[] GetSignature(string message, X509Certificate2 signingCertificate, X509Certificate2 encryptionCertificate)
{
byte[] messageBytes = Encoding.ASCII.GetBytes(message);
SignedCms signedCms = new SignedCms(new ContentInfo(messageBytes), true);
CmsSigner cmsSigner = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, signingCertificate);
cmsSigner.IncludeOption = X509IncludeOption.WholeChain;
if (encryptionCertificate != null)
{
cmsSigner.Certificates.Add(encryptionCertificate);
}
Pkcs9SigningTime signingTime = new Pkcs9SigningTime();
cmsSigner.SignedAttributes.Add(signingTime);
signedCms.ComputeSignature(cmsSigner, false);
return signedCms.Encode();
}
/// <summary>
/// Encrypts a message
/// </summary>
/// <param name="message">The message to encrypt</param>
/// <param name="encryptionCertificates">A list of certificates to encrypt the message with</param>
/// <returns>The encrypted message</returns>
internal static byte[] EncryptMessage(string message, X509Certificate2Collection encryptionCertificates)
{
byte[] messageBytes = Encoding.ASCII.GetBytes(message);
EnvelopedCms envelopedCms = new EnvelopedCms(new ContentInfo(messageBytes));
CmsRecipientCollection recipients = new CmsRecipientCollection(SubjectIdentifierType.IssuerAndSerialNumber, encryptionCertificates);
envelopedCms.Encrypt(recipients);
return envelopedCms.Encode();
}
/// <summary>
/// Finds a certificates in the user's local store based on its serial number
/// </summary>
/// <param name="serialNumber">The serial number of the certificate to retrieve</param>
/// <returns>The requested certificate, or null if the certificate is not found</returns>
public static X509Certificate2 FindCertificate(string serialNumber)
{
X509Store localStore = new X509Store(StoreName.My);
localStore.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
try
{
X509Certificate2Collection matches = localStore.Certificates.Find(
X509FindType.FindBySerialNumber,
serialNumber,
true);
if (matches.Count > 0)
{
return matches[0];
}
else
{
return null;
}
}
finally
{
localStore.Close();
}
}
/// <summary>
/// Finds a certificate in the user's local store based on its subject and usage flags
/// </summary>
/// <param name="subjectDistinguishedName">The subject distinguished name of the certificate</param>
/// <param name="usage">The minimum usage flags the certificate must contain</param>
/// <returns>The requested certificate, or null if the certificate is not found</returns>
public static X509Certificate2 FindCertificate(string subjectDistinguishedName, X509KeyUsageFlags usage)
{
X509Store localStore = new X509Store(StoreName.My);
localStore.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
try
{
X509Certificate2Collection matches = localStore.Certificates.Find(
X509FindType.FindBySubjectDistinguishedName,
subjectDistinguishedName,
true);
if (matches.Count > 0)
{
foreach (X509Certificate2 cert in matches)
{
foreach (X509Extension extension in cert.Extensions)
{
X509KeyUsageExtension usageExtension = extension as X509KeyUsageExtension;
if (usageExtension != null)
{
bool matchesUsageRequirements = ((usage & usageExtension.KeyUsages) == usage);
if (matchesUsageRequirements)
{
return cert;
}
}
}
}
return null;
}
else
{
return null;
}
}
finally
{
localStore.Close();
}
}
}
The method below encrypts an email:
public static void SendCryptographedEmail(ScheduledEmail email, String certificatesDirectory, String attachmentsDirectory, bool attachmentsByLink = true)
{
var message = new SecureMailMessage();
// Look up your signing cert by serial number in your cert store
// X509Certificate2 signingCert = CryptoHelper.FindCertificate("1B37D3");
var signingCert = new X509Certificate2(certificatesDirectory + "\\" + email.User.CertificatePath, email.User.CertificatePassword);
// Look up your encryption cert the same way
// X509Certificate2 encryptionCert = CryptoHelper.FindCertificate("22C590");
var encryptionCert = new X509Certificate2(certificatesDirectory + "\\" + email.User.CertificatePath, email.User.CertificatePassword);
// Load the recipient's encryption cert from a file.
var recipientCert = new X509Certificate2(certificatesDirectory + "\\" + email.User.CertificatePath, email.User.CertificatePassword);
message.From = new SecureMailAddress
(email.User.Email, email.User.Name, encryptionCert, signingCert);
message.To.Add(new SecureMailAddress
(email.Recipient, email.Recipient, recipientCert));
message.Subject = email.Subject;
message.IsBodyHtml = true;
message.IsSigned = true;
message.IsEncrypted = true;
var messageBody = email.Message;
if (attachmentsByLink)
{
messageBody += "<p>Anexos</p>";
foreach (var scheduledEmailAttachment in email.ScheduledEmailAttachments)
{
messageBody += "<p><a href=\"" + BaseUrl() + "Attachments/Download/" +
scheduledEmailAttachment.ScheduledEmailAttachmentId + "\">" +
scheduledEmailAttachment.FileName + "</a></p>";
}
}
else
{
foreach (var scheduledEmailAttachment in email.ScheduledEmailAttachments)
{
byte[] fileBytes =
File.ReadAllBytes(Path.Combine(attachmentsDirectory, scheduledEmailAttachment.FileName));
message.Attachments.Add(
new SecureAttachment(fileBytes,
new SecureContentType(scheduledEmailAttachment.MimeType.ToValue()))
);
}
}
messageBody += "<img src=\"" + BaseUrl() + "/Emails/BrandImage/" + email.ScheduledEmailId + "\" />";
message.Body = messageBody;
// Instantiate a good old-fashioned SmtpClient to send your message
var client = new System.Net.Mail.SmtpClient(email.User.ConfigSMTP.FirstOrDefault().Server, (int)email.User.ConfigSMTP.FirstOrDefault().Port)
{
Credentials = new NetworkCredential(email.User.ConfigSMTP.FirstOrDefault().Username, email.User.ConfigSMTP.FirstOrDefault().Password)
};
// If your SMTP server requires you to authenticate, you need to specify your
// username and password here.
client.Send(message);
}
ScheduledEmail
is a Model MVC, but it doesn’t have to be:
public class ScheduledEmail
{
[Key]
public Guid ScheduledEmailId { get; set; }
public Guid UserId { get; set; }
[EmailAddress]
[Required(ErrorMessage = "É necessário um Destinatário")]
public string Recipient { get; set; }
public string Subject { get; set; }
[Required(ErrorMessage = "É necessário um conteúdo para a mensagem")]
public string Message { get; set; }
[Required(ErrorMessage = "É necessário uma data de agendamento para a mensagem")]
// [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy hh:mm}", ApplyFormatInEditMode = true)]
public DateTime ScheduleDate { get; set; }
public DateTime? SendDate { get; set; }
public string Sending { get; set; }
[NotMapped]
[Display(Name = "Files", ResourceType = typeof(Resources.Language))]
public IEnumerable<HttpPostedFileBase> Files { get; set; }
[Display(Name = "LastModified", ResourceType = typeof(Resources.Language))]
public DateTime LastModified { get; set; }
[Display(Name = "CreatedOn", ResourceType = typeof(Resources.Language))]
public DateTime CreatedOn { get; set; }
public virtual ICollection<ScheduledEmailAttachment> ScheduledEmailAttachments { get; set; }
public virtual User User { get; set; }
}
Basic Articles
You had no problem with the Signedcms class? I added
using System.Security.Cryptography.Pkcs;
but it did not happen.– eduardo mendonça
Added
System.Security
in the project references?– Leonel Sanches da Silva
Success! That was it, the strange thing is that the X509 worked
using System.Security.Cryptography.X509Certificates
.– eduardo mendonça
Beauty. I put another link that has all the fonts. It would not fit everything in the answer.
– Leonel Sanches da Silva