How to implement PKCS#7 (components->class, library, dll, plugins and others) in a MVC5 web application

Asked

Viewed 1,007 times

2

I’m trying to implement PKCS#7 in an application web mvc5 found some solutions for application desktop, never added desktop(class,dll,Ference etc) solutions to a web application, maybe it’s the solution.

Has anyone ever worked or knows the best way to work with PKCS#7?

Below is an example with PKCS#1 that is more correct:

` /* Representa o acesso ao Store. O construtor dela exige que se estipule qual parte da estrutura deve ser acessada. Use as definições na classe StoreName para identificar, por exemplo, os certificados particulares (“My”) ou as Autoridades Certificadoras (“CA”). Pode optar também por informar apenas a localização, através da classe StoreLocation (somente os meus certicados ou todos os certificados presentes no computador). */

        X509Store store = new X509Store("My", StoreLocation.CurrentUser);
        store.Open(OpenFlags.ReadWrite);

        //Lista todos certificados encontrados
        List<X509Certificate2> certificado =  new List<X509Certificate2>();
        foreach (X509Certificate2 mCert in store.Certificates)
        {
            //adiciono todos certificados
            certificado.Add(mCert);
        }
        //no meu caso vou pegar a posição 1 para fim de treste msm
        X509Certificate2 certificate = certificado[1];

        /**
         * 2 chaves 
         */
        //publickey desabilitado para fim de teste
        //string publicKey = certificate.GetPublicKeyString();
        //privatekEy
        //AsymmetricAlgorithm privateKey = certificate.PrivateKey;

        //privatekEy
        RSACryptoServiceProvider privateKey
                                  = certificate.PrivateKey as RSACryptoServiceProvider;
        //poderia ser um pdf, imagem, doc etc
        byte[] buffer = Encoding.Default.GetBytes("uHulll ... !");

        //aqui ele solicita PIn do cartão
        byte[] signature = privateKey.SignData(buffer, new SHA1Managed());

        //publickey
        RSACryptoServiceProvider publicKey
                    = certificate.PublicKey.Key as RSACryptoServiceProvider;

        //aqui me parece que faz a liga da senha com as duas chaves publicas/privada e retorna true ou false
        bool verify = publicKey.VerifyData
                                (buffer, new SHA1Managed(), signature);


        if (verify)
        {
            //sucesso

            byte[] hash = SHA1Managed.Create().ComputeHash(buffer);
            //pkcs#1 or no
            RSAPKCS1SignatureFormatter formatter
                                = new RSAPKCS1SignatureFormatter(certificate.PrivateKey);
            formatter.SetHashAlgorithm("SHA1");
            signature = formatter.CreateSignature(hash);
        }`

1 answer

2


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.

  • Added System.Security in the project references?

  • Success! That was it, the strange thing is that the X509 worked using System.Security.Cryptography.X509Certificates .

  • Beauty. I put another link that has all the fonts. It would not fit everything in the answer.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.