title: Sign and Encrypt on MimeKit
body: <p>I was required to send signed and encrypted mails to our customers, however, this is my first time with the fight of sign and encrypt (I want to highlight this point).</p>
  
  <p>I have tried with OpaqueMail, and MimeKit.
  Because I really don't understand deeply OpaqueMail and I have my own clients to retrieve emails, I found far better to understand and implement MimeKit.</p>
  
  <p>I know it is a rudimentary implementation what I did in the following lines, but it is just the first contact with it and just a test. I can send signed emails with encrypted body, the problem come with the attachments (we just sent empty bodies with the attachment file, that comes from a DB).</p>
  
  <pre><code>try
      {
              X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
              store.Open(OpenFlags.ReadOnly);
  
              X509Certificate2Collection collection = store.Certificates.Find(X509FindType.FindBySubjectName, "senderEmail@something.com", false); //TODO Change to true after test
              X509Certificate2 senderCertificate = collection[0];
  
              store = new X509Store(StoreName.AddressBook, StoreLocation.CurrentUser);
              store.Open(OpenFlags.ReadOnly);
  
              collection = store.Certificates.Find(X509FindType.FindBySubjectName, "recipientEmail@something.com", false); //TODO Change to true after test
              X509Certificate2 recipientCertificate = collection[0];
  
              MimeMessage mimeMessage = new MimeMessage
              {
                  Date = DateTime.Now,
              };
  
              mimeMessage.From.Add(
                  new SecureMailboxAddress(
                      "senderEmail@gmail.com",
                      "senderEmail@gmail.com",
                      senderCertificate.Thumbprint));
  
              mimeMessage.To.Add(
                  new SecureMailboxAddress(
                      "recipientEmail@gmail.com",
                      "recipientEmail@gmail.com",
                      recipientCertificate.Thumbprint));
  
              mimeMessage.Subject = "S/MIME Test";
  
              using (Stream stream = "TestAttachmentFile".ToStream())
              {
                  //Attachment
                  MimePart attachment = new MimePart(new ContentType("text", "plain"))
                                        {
                                            ContentTransferEncoding =
                                                ContentEncoding.Base64,
                                            ContentDisposition = new ContentDisposition(ContentDisposition.Attachment),
                                            FileName = "TestAttachmentFileName.txt",
                                            ContentObject = new ContentObject(stream)
                                        };
  
                  Multipart multipart = new Multipart("mixed") { attachment};
  
                  mimeMessage.Body = multipart;
  
                  //Sign / Encryption
                  CmsSigner signer = new CmsSigner(senderCertificate);
  
                  CmsRecipientCollection colle = new CmsRecipientCollection();
                  X509Certificate bountyRecipientCertificate = DotNetUtilities.FromX509Certificate (recipientCertificate)
  
                  CmsRecipient recipient = new CmsRecipient(bountyRecipientCertificate);
                  colle.Add(recipient);
  
                  using (var ctx = new MySecureMimeContext ()) 
                  {
                        var signed = MultipartSigned.Create (ctx, signer, mimeMessage.Body);        
                        var encrypted = ApplicationPkcs7Mime.Encrypt (ctx, colle, signed);           
                        mimeMessage.Body = MultipartSigned.Create (ctx, signer, encrypted);
                  }
  
                  //Sending
                  using (SmtpClient smtpClient = InitSmtpClient(
                      "mail.smtp.com",
                      465,
                      "sender@something.com",
                      "Pwd",
                      true))
                  {
                      smtpClient.Send(mimeMessage);
                  }
              }
          }
          catch (Exception e)
          {
              Console.WriteLine(e);
          }
  </code></pre>
  
  <p>Well here the questions:</p>
  
  <p><em>Sign and body encrypt works. But when I try to add an attachment I can open it but always appear the BOM (ï»¿) I can see the attachment however thunderbird doesn't tell me it is an attachment, it's just like the body of the email. I don't know if it is a problem from the ToStream() I have implemented. Also Thunderbird was not able to show correct german characters (ÜüÖöÄäß) neither for spanish ñ</em></p>
  
  <p>EDIT MimeKit.Decryption methods works pretty well too, and also I get the correct encoding of the message without BOM and the attachment is there. It could be a problem for Thunderbird clients.</p>
  
  <hr>
  
  <p><em>Related to SecureMimeContext, we are using HanaDB and we want to store the certificates there, retrieve and use them, but I was not able to find the proper conversion for IX509CertificateDatabase, so, using WindowsStore for the moment.</em></p>
  
  <p>EDIT, I <em>solve</em> the problem with the DB creating a WindowsSecureMimeContext and overriding the import to get the certificates from the DB. Quick and dirty.</p>
  
  <p>EDIT 2, This was hard to implement, because our implementation with DAO templates, I've made subclass from SecureMimeContext, I look on the WindowsSecureMimeContext to understand what the methods exactly does and just change the code to fit with our DAO stuff.</p>
  
  <hr>
  
  <p><em>How can I convert from X509Certificate2 to X509Certificate(BouncyCastle) as is the parameter CmsRecipient?</em></p>
  
  <p>EDIT, DotNetUtilities.FromX509Certificate did the job.</p>
  
  <hr>
  
  <p><em>Is it possible to make a "Tripple Wrap"? Sign, Encrypt, Sign again.</em></p>
  
  <p>EDIT, Yes</p>
  
  <pre><code>using (var ctx = new MySecureMimeContext ()) {
      var signed = MultipartSigned.Create (ctx, signer, mimeMessage.Body);
      var encrypted = ApplicationPkcs7Mime.Encrypt (ctx, colle, signed);
      mimeMessage.Body = MultipartSigned.Create (ctx, signer, encrypted);
  }
  </code></pre>