Why RecipientInfos throwing CryptographicException

309 Views Asked by At

I've got some class for encrypting and signing emails.

Signing process is going without problems , but when I trying to encrypt the message using "Encrypt" method on EnvelopedCms instance ,I've got exception with information "invalid cryptographic message type".

I've tried to specify ContentType in contentInfo by setting Oid="1.2.840.113549.1.7.2",which is "signedData" type (according to msdn library), but is not working.

 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();
    }
0

There are 0 best solutions below