/// <summary> /// Cryptographically signs the specified entity. /// </summary> /// <remarks> /// <para>Signs the entity using the supplied signer, digest algorithm and <see cref="SecureMimeContext"/>.</para> /// <para>For better interoperability with other mail clients, you should use /// <see cref="MultipartSigned.Create(SecureMimeContext, CmsSigner, MimeEntity)"/> /// instead as the multipart/signed format is supported among a much larger /// subset of mail client software.</para> /// </remarks> /// <returns>The signed entity.</returns> /// <param name="ctx">The S/MIME 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.</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="Org.BouncyCastle.Cms.CmsException"> /// An error occurred in the cryptographic message syntax subsystem. /// </exception> public static ApplicationPkcs7Mime Sign(SecureMimeContext ctx, MailboxAddress signer, DigestAlgorithm digestAlgo, MimeEntity entity) { if (ctx == null) { throw new ArgumentNullException("ctx"); } if (signer == null) { throw new ArgumentNullException("signer"); } if (entity == null) { throw new ArgumentNullException("entity"); } using (var memory = new MemoryBlockStream()) { var options = FormatOptions.GetDefault(); options.NewLineFormat = NewLineFormat.Dos; entity.WriteTo(options, memory); memory.Position = 0; return(ctx.EncapsulatedSign(signer, digestAlgo, memory)); } }
/// <summary> /// Encrypts the specified entity. /// </summary> /// <remarks> /// Encrypts the entity to the specified recipients using the supplied <see cref="SecureMimeContext"/>. /// </remarks> /// <returns>The encrypted entity.</returns> /// <param name="ctx">The S/MIME context to use for encrypting.</param> /// <param name="recipients">The recipients.</param> /// <param name="entity">The entity.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="ctx"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="recipients"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="entity"/> is <c>null</c>.</para> /// </exception> /// <exception cref="System.ArgumentException"> /// Valid certificates could not be found for one or more of the <paramref name="recipients"/>. /// </exception> /// <exception cref="CertificateNotFoundException"> /// A certificate could not be found for one or more of the <paramref name="recipients"/>. /// </exception> /// <exception cref="Org.BouncyCastle.Cms.CmsException"> /// An error occurred in the cryptographic message syntax subsystem. /// </exception> public static ApplicationPkcs7Mime Encrypt(SecureMimeContext ctx, IEnumerable <MailboxAddress> recipients, MimeEntity entity) { if (ctx == null) { throw new ArgumentNullException("ctx"); } if (recipients == null) { throw new ArgumentNullException("recipients"); } if (entity == null) { throw new ArgumentNullException("entity"); } using (var memory = new MemoryBlockStream()) { var options = FormatOptions.GetDefault(); options.NewLineFormat = NewLineFormat.Dos; entity.WriteTo(options, memory); memory.Position = 0; return((ApplicationPkcs7Mime)ctx.Encrypt(recipients, memory)); } }
/// <summary> /// Verifies the multipart/signed part. /// </summary> /// <remarks> /// Verifies the multipart/signed part using the supplied cryptography context. /// </remarks> /// <returns>A signer info collection.</returns> /// <param name="ctx">The cryptography context to use for verifying the signature.</param> /// <exception cref="System.ArgumentNullException"> /// <paramref name="ctx"/> is <c>null</c>. /// </exception> /// <exception cref="System.FormatException"> /// The multipart is malformed in some way. /// </exception> /// <exception cref="System.NotSupportedException"> /// <paramref name="ctx"/> does not support verifying the signature part. /// </exception> /// <exception cref="Org.BouncyCastle.Cms.CmsException"> /// An error occurred in the cryptographic message syntax subsystem. /// </exception> public DigitalSignatureCollection Verify(CryptographyContext ctx) { if (ctx == null) { throw new ArgumentNullException("ctx"); } var protocol = ContentType.Parameters["protocol"]; if (string.IsNullOrEmpty(protocol)) { throw new FormatException("The multipart/signed part did not specify a protocol."); } if (!ctx.Supports(protocol.Trim())) { throw new NotSupportedException("The specified cryptography context does not support the signature protocol."); } if (Count < 2) { throw new FormatException("The multipart/signed part did not contain the expected children."); } var signature = this[1] as MimePart; if (signature == null || signature.ContentObject == null) { throw new FormatException("The signature part could not be found."); } var ctype = signature.ContentType; var value = string.Format("{0}/{1}", ctype.MediaType, ctype.MediaSubtype); if (!ctx.Supports(value)) { throw new NotSupportedException(string.Format("The specified cryptography context does not support '{0}'.", value)); } using (var signatureData = new MemoryBlockStream()) { signature.ContentObject.DecodeTo(signatureData); signatureData.Position = 0; using (var cleartext = new MemoryBlockStream()) { // Note: see rfc2015 or rfc3156, section 5.1 var options = FormatOptions.GetDefault(); options.NewLineFormat = NewLineFormat.Dos; this[0].WriteTo(options, cleartext); cleartext.Position = 0; return(ctx.Verify(cleartext, signatureData)); } } }
/// <summary> /// Creates a new <see cref="MultipartEncrypted"/>. /// </summary> /// <remarks> /// Signs the entity using the supplied signer and digest algorithm and then encrypts to /// the specified recipients, encapsulating the result in a new multipart/encrypted part. /// </remarks> /// <returns>A new <see cref="MultipartEncrypted"/> instance containing /// the signed and encrypted version of the specified entity.</returns> /// <param name="ctx">The OpenPGP cryptography context to use for signing and encrypting.</param> /// <param name="signer">The signer to use to sign the entity.</param> /// <param name="digestAlgo">The digest algorithm to use for signing.</param> /// <param name="recipients">The recipients for the encrypted entity.</param> /// <param name="entity">The entity to sign and encrypt.</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="recipients"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="entity"/> is <c>null</c>.</para> /// </exception> /// <exception cref="PrivateKeyNotFoundException"> /// The private key for <paramref name="signer"/> could not be found. /// </exception> /// <exception cref="PublicKeyNotFoundException"> /// A public key for one or more of the <paramref name="recipients"/> could not be found. /// </exception> /// <exception cref="System.OperationCanceledException"> /// The user chose to cancel the password prompt. /// </exception> /// <exception cref="System.UnauthorizedAccessException"> /// 3 bad attempts were made to unlock the secret key. /// </exception> public static MultipartEncrypted Create(OpenPgpContext ctx, MailboxAddress signer, DigestAlgorithm digestAlgo, IEnumerable <MailboxAddress> recipients, MimeEntity entity) { if (ctx == null) { throw new ArgumentNullException("ctx"); } if (signer == null) { throw new ArgumentNullException("signer"); } if (recipients == null) { throw new ArgumentNullException("recipients"); } if (entity == null) { throw new ArgumentNullException("entity"); } using (var memory = new MemoryBlockStream()) { var options = FormatOptions.GetDefault(); options.NewLineFormat = NewLineFormat.Dos; entity.WriteTo(options, memory); memory.Position = 0; var encrypted = new MultipartEncrypted(); encrypted.ContentType.Parameters["protocol"] = ctx.EncryptionProtocol; // add the protocol version part encrypted.Add(new ApplicationPgpEncrypted()); // add the encrypted entity as the second part encrypted.Add(ctx.SignAndEncrypt(signer, digestAlgo, recipients, memory)); return(encrypted); } }
/// <summary> /// Compresses the specified entity. /// </summary> /// <remarks> /// <para>Compresses the specified entity using the specified <see cref="SecureMimeContext"/>.</para> /// <para>It should be noted that this feature is not supported by most mail clients, /// even among those that support S/MIME.</para> /// </remarks> /// <returns>The compressed entity.</returns> /// <param name="ctx">The S/MIME context to use for compressing.</param> /// <param name="entity">The entity.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="ctx"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="entity"/> is <c>null</c>.</para> /// </exception> /// <exception cref="Org.BouncyCastle.Cms.CmsException"> /// An error occurred in the cryptographic message syntax subsystem. /// </exception> public static ApplicationPkcs7Mime Compress(SecureMimeContext ctx, MimeEntity entity) { if (ctx == null) { throw new ArgumentNullException("ctx"); } if (entity == null) { throw new ArgumentNullException("entity"); } using (var memory = new MemoryBlockStream()) { var options = FormatOptions.GetDefault(); options.NewLineFormat = NewLineFormat.Dos; entity.WriteTo(options, memory); memory.Position = 0; return(ctx.Compress(memory)); } }