/// <summary> /// Creates a new <see cref="MimeKit.Cryptography.MultipartSigned"/> instance with the entity as the content. /// </summary> /// <returns>A new <see cref="MimeKit.Cryptography.MultipartSigned"/> instance.</returns> /// <param name="ctx">The cryptography context to use for signing.</param> /// <param name="signer">The signer.</param> /// <param name="digestAlgo">The digest algorithm to use for signing.</param> /// <param name="entity">The entity to sign.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="ctx"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="signer"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="entity"/> is <c>null</c>.</para> /// </exception> /// <exception cref="CertificateNotFoundException"> /// A signing certificate could not be found for <paramref name="signer"/>. /// </exception> /// <exception cref="System.Security.Cryptography.CryptographicException"> /// An error occurred while signing. /// </exception> public static MultipartSigned Create(CryptographyContext ctx, MailboxAddress signer, DigestAlgorithm digestAlgo, MimeEntity entity) { if (signer == null) { throw new ArgumentNullException("signer"); } if (entity == null) { throw new ArgumentNullException("entity"); } PrepareEntityForSigning(entity); using (var memory = new MemoryStream()) { using (var filtered = new FilteredStream(memory)) { // Note: see rfc3156, section 3 - second note filtered.Add(new ArmoredFromFilter()); // Note: see rfc3156, section 5.4 (this is the main difference between rfc2015 and rfc3156) filtered.Add(new TrailingWhitespaceFilter()); // Note: see rfc2015 or rfc3156, section 5.1 filtered.Add(new Unix2DosFilter()); entity.WriteTo(filtered); filtered.Flush(); } memory.Position = 0; // Note: we need to parse the modified entity structure to preserve any modifications var parser = new MimeParser(memory, MimeFormat.Entity); var parsed = parser.ParseEntity(); memory.Position = 0; // sign the cleartext content var signature = ctx.Sign(signer, digestAlgo, memory); var micalg = ctx.GetMicAlgorithmName(digestAlgo); var signed = new MultipartSigned(); // set the protocol and micalg Content-Type parameters signed.ContentType.Parameters["protocol"] = ctx.SignatureProtocol; signed.ContentType.Parameters["micalg"] = micalg; // add the modified/parsed entity as our first part signed.Add(parsed); // add the detached signature as the second part signed.Add(signature); return(signed); } }
/// <summary> /// Creates a new <see cref="MimeKit.Cryptography.MultipartSigned"/> instance with the entity as the content. /// </summary> /// <returns>A new <see cref="MimeKit.Cryptography.MultipartSigned"/> instance.</returns> /// <param name="ctx">The cryptography context to use for signing.</param> /// <param name="signer">The signer.</param> /// <param name="digestAlgo">The digest algorithm to use for signing.</param> /// <param name="entity">The entity to sign.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="ctx"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="signer"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="entity"/> is <c>null</c>.</para> /// </exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// The <paramref name="digestAlgo"/> was out of range. /// </exception> /// <exception cref="System.NotSupportedException"> /// The <paramref name="digestAlgo"/> is not supported. /// </exception> /// <exception cref="CertificateNotFoundException"> /// A signing certificate could not be found for <paramref name="signer"/>. /// </exception> /// <exception cref="PrivateKeyNotFoundException"> /// The private key could not be found for <paramref name="signer"/>. /// </exception> /// <exception cref="Org.BouncyCastle.Cms.CmsException"> /// An error occurred in the cryptographic message syntax subsystem. /// </exception> public static MultipartSigned Create(CryptographyContext ctx, MailboxAddress signer, DigestAlgorithm digestAlgo, MimeEntity entity) { if (signer == null) throw new ArgumentNullException ("signer"); if (entity == null) throw new ArgumentNullException ("entity"); PrepareEntityForSigning (entity); using (var memory = new MemoryStream ()) { using (var filtered = new FilteredStream (memory)) { // Note: see rfc3156, section 3 - second note filtered.Add (new ArmoredFromFilter ()); // Note: see rfc3156, section 5.4 (this is the main difference between rfc2015 and rfc3156) filtered.Add (new TrailingWhitespaceFilter ()); // Note: see rfc2015 or rfc3156, section 5.1 filtered.Add (new Unix2DosFilter ()); entity.WriteTo (filtered); filtered.Flush (); } memory.Position = 0; // Note: we need to parse the modified entity structure to preserve any modifications var parser = new MimeParser (memory, MimeFormat.Entity); var parsed = parser.ParseEntity (); memory.Position = 0; // sign the cleartext content var signature = ctx.Sign (signer, digestAlgo, memory); var micalg = ctx.GetMicAlgorithmName (digestAlgo); var signed = new MultipartSigned (); // set the protocol and micalg Content-Type parameters signed.ContentType.Parameters["protocol"] = ctx.SignatureProtocol; signed.ContentType.Parameters["micalg"] = micalg; // add the modified/parsed entity as our first part signed.Add (parsed); // add the detached signature as the second part signed.Add (signature); return signed; } }