An S/MIME signer.
If the X.509 certificate is known for the signer, you may wish to use a CmsSigner as opposed to having the CryptographyContext do its own certificate lookup for the signer's MailboxAddress.
Beispiel #1
0
		public void TestArgumentExceptions ()
		{
			var signer = new CmsSigner (Path.Combine ("..", "..", "TestData", "smime", "smime.p12"), "no.secret");

			Assert.Throws<ArgumentNullException> (() => new CmsSigner ((IEnumerable<X509Certificate>) null, signer.PrivateKey));
			Assert.Throws<ArgumentException> (() => new CmsSigner (new X509Certificate[0], signer.PrivateKey));
			Assert.Throws<ArgumentNullException> (() => new CmsSigner (signer.CertificateChain, null));

			Assert.Throws<ArgumentNullException> (() => new CmsSigner ((X509Certificate) null, signer.PrivateKey));
			Assert.Throws<ArgumentNullException> (() => new CmsSigner (signer.Certificate, null));

			Assert.Throws<ArgumentNullException> (() => new CmsSigner ((X509Certificate2) null));

			Assert.Throws<ArgumentNullException> (() => new CmsSigner ((Stream) null, "password"));
			Assert.Throws<ArgumentNullException> (() => new CmsSigner (Stream.Null, null));

			Assert.Throws<ArgumentNullException> (() => new CmsSigner ((string) null, "password"));
			Assert.Throws<ArgumentNullException> (() => new CmsSigner ("fileName", null));
		}
Beispiel #2
0
        /// <summary>
        /// Cryptographically signs and encrypts the specified entity.
        /// </summary>
        /// <remarks>
        /// Cryptographically signs entity using the supplied signer and then
        /// encrypts the result to the specified recipients.
        /// </remarks>
        /// <returns>The signed and encrypted entity.</returns>
        /// <param name="signer">The signer.</param>
        /// <param name="recipients">The recipients.</param>
        /// <param name="entity">The entity.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <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="Org.BouncyCastle.Cms.CmsException">
        /// An error occurred in the cryptographic message syntax subsystem.
        /// </exception>
        public static ApplicationPkcs7Mime SignAndEncrypt(CmsSigner signer, CmsRecipientCollection recipients, MimeEntity entity)
        {
            if (signer == null)
            {
                throw new ArgumentNullException("signer");
            }

            if (recipients == null)
            {
                throw new ArgumentNullException("recipients");
            }

            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }

            using (var ctx = (SecureMimeContext)CryptographyContext.Create("application/pkcs7-mime")) {
                return(SignAndEncrypt(ctx, signer, recipients, entity));
            }
        }
Beispiel #3
0
        /// <summary>
        /// Signs and encrypts the specified content for the specified recipients.
        /// </summary>
        /// <param name="signer">The signer.</param>
        /// <param name="recipients">The recipients.</param>
        /// <param name="content">The content.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <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="content"/> is <c>null</c>.</para>
        /// </exception>
        public ApplicationPkcs7Mime SignAndEncrypt(CmsSigner signer, CmsRecipientCollection recipients, Stream content)
        {
            // FIXME: find out what exceptions BouncyCastle can throw...
            if (signer == null)
            {
                throw new ArgumentNullException("signer");
            }

            if (recipients == null)
            {
                throw new ArgumentNullException("recipients");
            }

            if (content == null)
            {
                throw new ArgumentNullException("content");
            }

            using (var signed = Sign(signer, content, true)) {
                return(new ApplicationPkcs7Mime(SecureMimeType.EnvelopedData, Envelope(recipients, signed)));
            }
        }
Beispiel #4
0
        /// <summary>
        /// Cryptographically signs and encrypts the specified entity.
        /// </summary>
        /// <remarks>
        /// Cryptographically signs entity using the supplied signer and then
        /// encrypts the result to the specified recipients.
        /// </remarks>
        /// <returns>The signed and encrypted entity.</returns>
        /// <param name="ctx">The S/MIME context to use for signing and encrypting.</param>
        /// <param name="signer">The signer.</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="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="Org.BouncyCastle.Cms.CmsException">
        /// An error occurred in the cryptographic message syntax subsystem.
        /// </exception>
        public static ApplicationPkcs7Mime SignAndEncrypt(SecureMimeContext ctx, CmsSigner signer, CmsRecipientCollection 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");
            }

            return(Encrypt(ctx, recipients, MultipartSigned.Create(ctx, signer, entity)));
        }
        /// <summary>
        /// Gets the <see cref="CmsSigner"/> for the specified mailbox.
        /// </summary>
        /// <remarks>
        /// <para>Constructs a <see cref="CmsSigner"/> with the appropriate signing certificate
        /// for the specified mailbox.</para>
        /// <para>If the mailbox is a <see cref="SecureMailboxAddress"/>, the
        /// <see cref="SecureMailboxAddress.Fingerprint"/> property will be used instead of
        /// the mailbox address for database lookups.</para>
        /// </remarks>
        /// <returns>A <see cref="CmsSigner"/>.</returns>
        /// <param name="mailbox">The mailbox.</param>
        /// <param name="digestAlgo">The preferred digest algorithm.</param>
        /// <exception cref="CertificateNotFoundException">
        /// A certificate for the specified <paramref name="mailbox"/> could not be found.
        /// </exception>
        protected override CmsSigner GetCmsSigner(MailboxAddress mailbox, DigestAlgorithm digestAlgo)
        {
            var now = DateTime.UtcNow;

            foreach (var certificate in certificates)
            {
                AsymmetricKeyParameter key;

                if (certificate.NotBefore > now || certificate.NotAfter < now)
                {
                    continue;
                }

                var keyUsage = certificate.GetKeyUsageFlags();
                if (keyUsage != 0 && (keyUsage & SecureMimeContext.DigitalSignatureKeyUsageFlags) == 0)
                {
                    continue;
                }

                if (!keys.TryGetValue(certificate, out key))
                {
                    continue;
                }

                var address = certificate.GetSubjectEmailAddress();

                if (address.Equals(mailbox.Address, StringComparison.OrdinalIgnoreCase))
                {
                    var signer = new CmsSigner(certificate, key);
                    signer.DigestAlgorithm = digestAlgo;
                    return(signer);
                }
            }

            throw new CertificateNotFoundException(mailbox, "A valid signing certificate could not be found.");
        }
Beispiel #6
0
		/// <summary>
		/// Creates a new <see cref="MultipartSigned"/>.
		/// </summary>
		/// <remarks>
		/// Cryptographically signs the entity using the supplied signer in order
		/// to generate a detached signature and then adds the entity along with
		/// the detached signature data to a new multipart/signed part.
		/// </remarks>
		/// <returns>A new <see cref="MultipartSigned"/> instance.</returns>
		/// <param name="signer">The signer.</param>
		/// <param name="entity">The entity to sign.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <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.NotSupportedException">
		/// A cryptography context suitable for signing could not be found.
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static MultipartSigned Create (CmsSigner signer, MimeEntity entity)
		{
			using (var ctx = (SecureMimeContext) CryptographyContext.Create ("application/pkcs7-signature")) {
				return Create (ctx, signer, entity);
			}
		}
Beispiel #7
0
		/// <summary>
		/// Creates a new <see cref="MultipartSigned"/>.
		/// </summary>
		/// <remarks>
		/// Cryptographically signs the entity using the supplied signer in order
		/// to generate a detached signature and then adds the entity along with
		/// the detached signature data to a new multipart/signed part.
		/// </remarks>
		/// <returns>A new <see cref="MultipartSigned"/> instance.</returns>
		/// <param name="ctx">The S/MIME context to use for signing.</param>
		/// <param name="signer">The signer.</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="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static MultipartSigned Create (SecureMimeContext ctx, CmsSigner signer, MimeEntity entity)
		{
			if (ctx == null)
				throw new ArgumentNullException ("ctx");

			if (signer == null)
				throw new ArgumentNullException ("signer");

			if (entity == null)
				throw new ArgumentNullException ("entity");

			PrepareEntityForSigning (entity);

			using (var memory = new MemoryBlockStream ()) {
				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 micalg = ctx.GetDigestAlgorithmName (signer.DigestAlgorithm);
				var signature = ctx.Sign (signer, memory);
				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;
			}
		}
		public void TestArgumentExceptions ()
		{
			var path = Path.Combine ("..", "..", "TestData", "smime", "smime.p12");
			var entity = new TextPart ("plain") { Text = "This is some text..." };
			var mailbox = new MailboxAddress ("MimeKit UnitTests", "*****@*****.**");
			var recipients = new CmsRecipientCollection ();
			var signer = new CmsSigner (path, "no.secret");
			var mailboxes = new [] { mailbox };

			recipients.Add (new CmsRecipient (signer.Certificate));

			using (var ctx = new TemporarySecureMimeContext ()) {
				using (var file = File.OpenRead (path))
					ctx.Import (file, "no.secret");

				// Compress
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Compress (null, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Compress (ctx, null));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Compress (null));

				// Encrypt
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Encrypt (null, mailboxes, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Encrypt (null, recipients, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Encrypt (ctx, (IEnumerable<MailboxAddress>) null, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Encrypt (ctx, (CmsRecipientCollection) null, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Encrypt (ctx, recipients, null));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Encrypt (ctx, mailboxes, null));

				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Encrypt ((IEnumerable<MailboxAddress>) null, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Encrypt ((CmsRecipientCollection) null, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Encrypt (recipients, null));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Encrypt (mailboxes, null));

				// Sign
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Sign (null, mailbox, DigestAlgorithm.Sha1, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Sign (null, signer, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Sign (ctx, (MailboxAddress) null, DigestAlgorithm.Sha1, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Sign (ctx, (CmsSigner) null, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Sign (ctx, mailbox, DigestAlgorithm.Sha1, null));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Sign (ctx, signer, null));

				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Sign ((MailboxAddress) null, DigestAlgorithm.Sha1, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Sign ((CmsSigner) null, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Sign (mailbox, DigestAlgorithm.Sha1, null));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.Sign (signer, null));

				// SignAndEncrypt
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.SignAndEncrypt (null, mailbox, DigestAlgorithm.Sha1, mailboxes, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.SignAndEncrypt (ctx, null, DigestAlgorithm.Sha1, mailboxes, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.SignAndEncrypt (ctx, mailbox, DigestAlgorithm.Sha1, null, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.SignAndEncrypt (ctx, mailbox, DigestAlgorithm.Sha1, mailboxes, null));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.SignAndEncrypt (null, DigestAlgorithm.Sha1, mailboxes, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.SignAndEncrypt (mailbox, DigestAlgorithm.Sha1, null, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.SignAndEncrypt (mailbox, DigestAlgorithm.Sha1, mailboxes, null));

				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.SignAndEncrypt (null, signer, recipients, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.SignAndEncrypt (ctx, null, recipients, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.SignAndEncrypt (ctx, signer, null, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.SignAndEncrypt (ctx, signer, recipients, null));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.SignAndEncrypt (null, recipients, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.SignAndEncrypt (signer, null, entity));
				Assert.Throws<ArgumentNullException> (() => ApplicationPkcs7Mime.SignAndEncrypt (signer, recipients, null));

				var compressed = ApplicationPkcs7Mime.Compress (ctx, entity);
				var encrypted = ApplicationPkcs7Mime.Encrypt (recipients, entity);
				var signed = ApplicationPkcs7Mime.Sign (signer, entity);

				// Decompress
				Assert.Throws<ArgumentNullException> (() => compressed.Decompress (null));
				Assert.Throws<InvalidOperationException> (() => encrypted.Decompress (ctx));
				Assert.Throws<InvalidOperationException> (() => signed.Decompress (ctx));

				// Decrypt
				Assert.Throws<ArgumentNullException> (() => encrypted.Decrypt (null));
				Assert.Throws<InvalidOperationException> (() => compressed.Decrypt (ctx));
				Assert.Throws<InvalidOperationException> (() => signed.Decrypt (ctx));

				// Verify
				Assert.Throws<ArgumentNullException> (() => {
					MimeEntity mime;

					signed.Verify (null, out mime);
				});
				Assert.Throws<InvalidOperationException> (() => {
					MimeEntity mime;

					compressed.Verify (ctx, out mime);
				});
				Assert.Throws<InvalidOperationException> (() => {
					MimeEntity mime;

					encrypted.Verify (ctx, out mime);
				});
			}
		}
Beispiel #9
0
 /// <summary>
 /// Cryptographically signs and encapsulates the content using the specified signer.
 /// </summary>
 /// <remarks>
 /// Cryptographically signs and encapsulates the content using the specified signer.
 /// </remarks>
 /// <returns>A new <see cref="MimeKit.Cryptography.ApplicationPkcs7Mime"/> instance
 /// containing the detached signature data.</returns>
 /// <param name="signer">The signer.</param>
 /// <param name="content">The content.</param>
 /// <exception cref="System.ArgumentNullException">
 /// <para><paramref name="signer"/> is <c>null</c>.</para>
 /// <para>-or-</para>
 /// <para><paramref name="content"/> is <c>null</c>.</para>
 /// </exception>
 public abstract ApplicationPkcs7Mime EncapsulatedSign(CmsSigner signer, Stream content);
        /// <summary>
        /// Sign the content using the specified signer.
        /// </summary>
        /// <returns>A new <see cref="MimeKit.Cryptography.ApplicationPkcs7Signature"/> instance
        /// containing the detached signature data.</returns>
        /// <param name="signer">The signer.</param>
        /// <param name="content">The content.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <para><paramref name="signer"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="content"/> is <c>null</c>.</para>
        /// </exception>
        /// <exception cref="Org.BouncyCastle.Cms.CmsException">
        /// An error occurred in the cryptographic message syntax subsystem.
        /// </exception>
        public ApplicationPkcs7Signature Sign(CmsSigner signer, Stream content)
        {
            if (signer == null)
                throw new ArgumentNullException ("signer");

            if (signer.Certificate == null)
                throw new ArgumentException ("No signer certificate specified.", "signer");

            if (signer.PrivateKey == null)
                throw new ArgumentException ("No private key specified.", "signer");

            if (content == null)
                throw new ArgumentNullException ("content");

            return new ApplicationPkcs7Signature (Sign (signer, content, false));
        }
Beispiel #11
0
		public void MultipartSign (MimeMessage message, X509Certificate2 certificate)
		{
			// digitally sign our message body using our custom S/MIME cryptography context
			using (var ctx = new MySecureMimeContext ()) {
				var signer = new CmsSigner (certificate) {
					DigestAlgorithm = DigestAlgorithm.Sha1
				};

				message.Body = MultipartSigned.Create (ctx, signer, message.Body);
			}
		}
        /// <summary>
        /// Gets the <see cref="CmsSigner"/> for the specified mailbox.
        /// </summary>
        /// <returns>A <see cref="CmsSigner"/>.</returns>
        /// <param name="mailbox">The mailbox.</param>
        /// <param name="digestAlgo">The preferred digest algorithm.</param>
        /// <exception cref="CertificateNotFoundException">
        /// A certificate for the specified <paramref name="mailbox"/> could not be found.
        /// </exception>
        protected override CmsSigner GetCmsSigner(MailboxAddress mailbox, DigestAlgorithm digestAlgo)
        {
            foreach (var certificate in certificates) {
                AsymmetricKeyParameter key;

                if (!keys.TryGetValue (certificate, out key))
                    continue;

                if (certificate.GetSubjectEmailAddress () == mailbox.Address) {
                    var signer = new CmsSigner (certificate, key);
                    signer.DigestAlgorithm = digestAlgo;
                    return signer;
                }
            }

            throw new CertificateNotFoundException (mailbox, "A valid signing certificate could not be found.");
        }
		/// <summary>
		/// Gets the <see cref="CmsSigner"/> for the specified mailbox.
		/// </summary>
		/// <remarks>
		/// <para>Constructs a <see cref="CmsSigner"/> with the appropriate signing certificate
		/// for the specified mailbox.</para>
		/// <para>If the mailbox is a <see cref="SecureMailboxAddress"/>, the
		/// <see cref="SecureMailboxAddress.Fingerprint"/> property will be used instead of
		/// the mailbox address for database lookups.</para>
		/// </remarks>
		/// <returns>A <see cref="CmsSigner"/>.</returns>
		/// <param name="mailbox">The mailbox.</param>
		/// <param name="digestAlgo">The preferred digest algorithm.</param>
		/// <exception cref="CertificateNotFoundException">
		/// A certificate for the specified <paramref name="mailbox"/> could not be found.
		/// </exception>
		protected override CmsSigner GetCmsSigner (MailboxAddress mailbox, DigestAlgorithm digestAlgo)
		{
			foreach (var record in dbase.Find (mailbox, DateTime.UtcNow, true, CmsSignerFields)) {
				if (record.KeyUsage != X509KeyUsageFlags.None && (record.KeyUsage & SecureMimeContext.DigitalSignatureKeyUsageFlags) == 0)
					continue;

				var signer = new CmsSigner (record.Certificate, record.PrivateKey);
				signer.DigestAlgorithm = digestAlgo;

				return signer;
			}

			throw new CertificateNotFoundException (mailbox, "A valid signing certificate could not be found.");
		}
        /// <summary>
        /// Gets the <see cref="CmsSigner"/> for the specified mailbox.
        /// </summary>
        /// <returns>A <see cref="CmsSigner"/>.</returns>
        /// <param name="mailbox">The mailbox.</param>
        /// <param name="digestAlgo">The preferred digest algorithm.</param>
        /// <exception cref="CertificateNotFoundException">
        /// A certificate for the specified <paramref name="mailbox"/> could not be found.
        /// </exception>
        protected override CmsSigner GetCmsSigner(MailboxAddress mailbox, DigestAlgorithm digestAlgo)
        {
            foreach (var certificate in store.Certificates) {
                var key = store.GetPrivateKey (certificate);

                if (key != null && certificate.GetSubjectEmailAddress () == mailbox.Address) {
                    var signer = new CmsSigner (certificate, key);
                    signer.DigestAlgorithm = digestAlgo;
                    return signer;
                }
            }

            throw new CertificateNotFoundException (mailbox, "A valid signing certificate could not be found.");
        }
Beispiel #15
0
 /// <summary>
 /// Creates a new <see cref="MultipartSigned"/>.
 /// </summary>
 /// <remarks>
 /// Cryptographically signs the entity using the supplied signer in order
 /// to generate a detached signature and then adds the entity along with
 /// the detached signature data to a new multipart/signed part.
 /// </remarks>
 /// <returns>A new <see cref="MultipartSigned"/> instance.</returns>
 /// <param name="signer">The signer.</param>
 /// <param name="entity">The entity to sign.</param>
 /// <exception cref="System.ArgumentNullException">
 /// <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.NotSupportedException">
 /// A cryptography context suitable for signing could not be found.
 /// </exception>
 /// <exception cref="Org.BouncyCastle.Cms.CmsException">
 /// An error occurred in the cryptographic message syntax subsystem.
 /// </exception>
 public static MultipartSigned Create(CmsSigner signer, MimeEntity entity)
 {
     using (var ctx = (SecureMimeContext)CryptographyContext.Create("application/pkcs7-signature"))
         return(Create(ctx, signer, entity));
 }
		/// <summary>
		/// Gets the <see cref="CmsSigner"/> for the specified mailbox.
		/// </summary>
		/// <returns>A <see cref="CmsSigner"/>.</returns>
		/// <param name="mailbox">The mailbox.</param>
		/// <param name="digestAlgo">The preferred digest algorithm.</param>
		/// <exception cref="CertificateNotFoundException">
		/// A certificate for the specified <paramref name="mailbox"/> could not be found.
		/// </exception>
		protected override CmsSigner GetCmsSigner (MailboxAddress mailbox, DigestAlgorithm digestAlgo)
		{
			var now = DateTime.Now;

			foreach (var certificate in certificates) {
				AsymmetricKeyParameter key;

				if (certificate.NotBefore > now || certificate.NotAfter < now)
					continue;

				var keyUsage = certificate.GetKeyUsageFlags ();
				if (keyUsage != 0 && (keyUsage & SecureMimeContext.DigitalSignatureKeyUsageFlags) == 0)
					continue;

				if (!keys.TryGetValue (certificate, out key))
					continue;

				if (certificate.GetSubjectEmailAddress () == mailbox.Address) {
					var signer = new CmsSigner (certificate, key);
					signer.DigestAlgorithm = digestAlgo;
					return signer;
				}
			}

			throw new CertificateNotFoundException (mailbox, "A valid signing certificate could not be found.");
		}
		/// <summary>
		/// Cryptographically signs the specified entity.
		/// </summary>
		/// <remarks>
		/// <para>Signs the entity using the supplied signer 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="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="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static ApplicationPkcs7Mime Sign (SecureMimeContext ctx, CmsSigner signer, 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.CloneDefault ();
				options.NewLineFormat = NewLineFormat.Dos;

				entity.WriteTo (options, memory);
				memory.Position = 0;

				return ctx.EncapsulatedSign (signer, memory);
			}
		}
        /// <summary>
        /// Sign and encapsulate the content using the specified signer.
        /// </summary>
        /// <returns>A new <see cref="MimeKit.Cryptography.ApplicationPkcs7Mime"/> instance
        /// containing the detached signature data.</returns>
        /// <param name="signer">The signer.</param>
        /// <param name="content">The content.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <para><paramref name="signer"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="content"/> is <c>null</c>.</para>
        /// </exception>
        /// <exception cref="Org.BouncyCastle.Cms.CmsException">
        /// An error occurred in the cryptographic message syntax subsystem.
        /// </exception>
        public ApplicationPkcs7Mime EncapsulatedSign(CmsSigner signer, Stream content)
        {
            if (signer == null)
                throw new ArgumentNullException ("signer");

            if (signer.Certificate == null)
                throw new ArgumentException ("No signer certificate specified.", "signer");

            if (signer.PrivateKey == null)
                throw new ArgumentException ("No private key specified.", "signer");

            if (content == null)
                throw new ArgumentNullException ("content");

            return new ApplicationPkcs7Mime (SecureMimeType.SignedData, Sign (signer, content, true));
        }
		/// <summary>
		/// Cryptographically signs the specified entity.
		/// </summary>
		/// <remarks>
		/// <para>Signs the entity using the supplied signer.</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="signer">The signer.</param>
		/// <param name="entity">The entity.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="signer"/> 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 Sign (CmsSigner signer, MimeEntity entity)
		{
			if (signer == null)
				throw new ArgumentNullException ("signer");

			if (entity == null)
				throw new ArgumentNullException ("entity");

			using (var ctx = (SecureMimeContext) CryptographyContext.Create ("application/pkcs7-mime")) {
				return Sign (ctx, signer, entity);
			}
		}
        Stream Sign(CmsSigner signer, Stream content, bool encapsulate)
        {
            var cms = new CmsSignedDataStreamGenerator ();

            cms.AddSigner (signer.PrivateKey, signer.Certificate, GetDigestOid (signer.DigestAlgorithm),
                signer.SignedAttributes, signer.UnsignedAttributes);

            var memory = new MemoryStream ();

            using (var stream = cms.Open (memory, encapsulate)) {
                content.CopyTo (stream, 4096);
            }

            memory.Position = 0;

            return memory;
        }
		/// <summary>
		/// Cryptographically signs and encrypts the specified entity.
		/// </summary>
		/// <remarks>
		/// Cryptographically signs entity using the supplied signer and then
		/// encrypts the result to the specified recipients.
		/// </remarks>
		/// <returns>The signed and encrypted entity.</returns>
		/// <param name="ctx">The S/MIME context to use for signing and encrypting.</param>
		/// <param name="signer">The signer.</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="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="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static ApplicationPkcs7Mime SignAndEncrypt (SecureMimeContext ctx, CmsSigner signer, CmsRecipientCollection 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");

			return Encrypt (ctx, recipients, MultipartSigned.Create (ctx, signer, entity));
		}
Beispiel #22
0
 /// <summary>
 /// Cryptographically signs the content using the specified signer.
 /// </summary>
 /// <remarks>
 /// Cryptographically signs the content using the specified signer.
 /// </remarks>
 /// <returns>A new <see cref="MimeKit.Cryptography.ApplicationPkcs7Signature"/> instance
 /// containing the detached signature data.</returns>
 /// <param name="signer">The signer.</param>
 /// <param name="content">The content.</param>
 /// <exception cref="System.ArgumentNullException">
 /// <para><paramref name="signer"/> is <c>null</c>.</para>
 /// <para>-or-</para>
 /// <para><paramref name="content"/> is <c>null</c>.</para>
 /// </exception>
 public abstract ApplicationPkcs7Signature Sign(CmsSigner signer, Stream content);
		/// <summary>
		/// Cryptographically signs and encrypts the specified entity.
		/// </summary>
		/// <remarks>
		/// Cryptographically signs entity using the supplied signer and then
		/// encrypts the result to the specified recipients.
		/// </remarks>
		/// <returns>The signed and encrypted entity.</returns>
		/// <param name="signer">The signer.</param>
		/// <param name="recipients">The recipients.</param>
		/// <param name="entity">The entity.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <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="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static ApplicationPkcs7Mime SignAndEncrypt (CmsSigner signer, CmsRecipientCollection recipients, MimeEntity entity)
		{
			if (signer == null)
				throw new ArgumentNullException ("signer");

			if (recipients == null)
				throw new ArgumentNullException ("recipients");

			if (entity == null)
				throw new ArgumentNullException ("entity");

			using (var ctx = (SecureMimeContext) CryptographyContext.Create ("application/pkcs7-mime")) {
				return SignAndEncrypt (ctx, signer, recipients, entity);
			}
		}