An S/MIME recipient.
If the X.509 certificates are known for each of the recipients, you may wish to use a CmsRecipient as opposed to having the CryptographyContext do its own certificate lookups for each MailboxAddress.
        /// <summary>
        /// Gets the <see cref="CmsRecipient"/> for the specified mailbox.
        /// </summary>
        /// <remarks>
        /// <para>Constructs a <see cref="CmsRecipient"/> with the appropriate certificate and
        /// <see cref="CmsRecipient.EncryptionAlgorithms"/> 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.</para>
        /// </remarks>
        /// <returns>A <see cref="CmsRecipient"/>.</returns>
        /// <param name="mailbox">The mailbox.</param>
        /// <exception cref="CertificateNotFoundException">
        /// A certificate for the specified <paramref name="mailbox"/> could not be found.
        /// </exception>
        protected override CmsRecipient GetCmsRecipient(MailboxAddress mailbox)
        {
            var now = DateTime.UtcNow;

            foreach (var certificate in certificates)
            {
                if (certificate.NotBefore > now || certificate.NotAfter < now)
                {
                    continue;
                }

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

                var address = certificate.GetSubjectEmailAddress();

                if (address != null && address.Equals(mailbox.Address, StringComparison.OrdinalIgnoreCase))
                {
                    var recipient = new CmsRecipient(certificate);
                    EncryptionAlgorithm[] algorithms;

                    if (capabilities.TryGetValue(certificate, out algorithms))
                    {
                        recipient.EncryptionAlgorithms = algorithms;
                    }

                    return(recipient);
                }
            }

            throw new CertificateNotFoundException(mailbox, "A valid certificate could not be found.");
        }
        /// <summary>
        /// Gets the <see cref="CmsRecipient"/> for the specified mailbox.
        /// </summary>
        /// <remarks>
        /// <para>Constructs a <see cref="CmsRecipient"/> with the appropriate certificate and
        /// <see cref="CmsRecipient.EncryptionAlgorithms"/> 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="CmsRecipient"/>.</returns>
        /// <param name="mailbox">The mailbox.</param>
        /// <exception cref="CertificateNotFoundException">
        /// A certificate for the specified <paramref name="mailbox"/> could not be found.
        /// </exception>
        protected override CmsRecipient GetCmsRecipient(MailboxAddress mailbox)
        {
            foreach (var record in dbase.Find(mailbox, DateTime.Now, false, CmsRecipientFields))
            {
                if (record.KeyUsage != 0 && (record.KeyUsage & X509KeyUsageFlags.KeyEncipherment) == 0)
                {
                    continue;
                }

                var recipient = new CmsRecipient(record.Certificate);
                if (record.Algorithms == null)
                {
                    var capabilities = record.Certificate.GetExtensionValue(SmimeAttributes.SmimeCapabilities);
                    if (capabilities != null)
                    {
                        var algorithms = DecodeEncryptionAlgorithms(capabilities.GetOctets());

                        if (algorithms != null)
                        {
                            recipient.EncryptionAlgorithms = algorithms;
                        }
                    }
                }
                else
                {
                    recipient.EncryptionAlgorithms = record.Algorithms;
                }

                return(recipient);
            }

            throw new CertificateNotFoundException(mailbox, "A valid certificate could not be found.");
        }
Esempio n. 3
0
		static void AssertDefaultValues (CmsRecipient recipient, X509Certificate certificate)
		{
			Assert.AreEqual (certificate, recipient.Certificate);
			Assert.AreEqual (1, recipient.EncryptionAlgorithms.Length);
			Assert.AreEqual (EncryptionAlgorithm.TripleDes, recipient.EncryptionAlgorithms[0]);
			Assert.AreEqual (SubjectIdentifierType.IssuerAndSerialNumber, recipient.RecipientIdentifierType);
		}
        /// <summary>
        /// Gets the preferred encryption algorithm to use for encrypting to the specified recipients.
        /// </summary>
        /// <remarks>
        /// <para>Gets the preferred encryption algorithm to use for encrypting to the specified recipients
        /// based on the encryption algorithms supported by each of the recipients, the
        /// <see cref="SecureMimeContext.EnabledEncryptionAlgorithms"/>, and the
        /// <see cref="SecureMimeContext.EncryptionAlgorithmRank"/>.</para>
        /// <para>If the supported encryption algorithms are unknown for any recipient, it is assumed that
        /// the recipient supports at least the Triple-DES encryption algorithm.</para>
        /// </remarks>
        /// <returns>The preferred encryption algorithm.</returns>
        /// <param name="recipients">The recipients.</param>
        protected virtual EncryptionAlgorithm GetPreferredEncryptionAlgorithm(RealCmsRecipientCollection recipients)
        {
            var votes = new int[EncryptionAlgorithmCount];

            foreach (var recipient in recipients)
            {
                var supported = CmsRecipient.GetEncryptionAlgorithms(recipient.Certificate);
                int cast      = EncryptionAlgorithmCount;

                foreach (var algorithm in supported)
                {
                    votes[(int)algorithm] += cast;
                    cast--;
                }
            }

            // Starting with S/MIME v3 (published in 1999), Triple-DES is a REQUIRED algorithm.
            // S/MIME v2.x and older only required RC2/40, but SUGGESTED Triple-DES.
            // Considering the fact that Bruce Schneier was able to write a
            // screensaver that could crack RC2/40 back in the late 90's, let's
            // not default to anything weaker than Triple-DES...
            EncryptionAlgorithm chosen = EncryptionAlgorithm.TripleDes;
            int nvotes = 0;

            // iterate through the algorithms, from strongest to weakest, keeping track
            // of the algorithm with the most amount of votes (between algorithms with
            // the same number of votes, choose the strongest of the 2 - i.e. the one
            // that we arrive at first).
            var algorithms = EncryptionAlgorithmRank;

            for (int i = 0; i < algorithms.Length; i++)
            {
                var algorithm = algorithms[i];

                if (!IsEnabled(algorithm))
                {
                    continue;
                }

                if (votes[(int)algorithm] > nvotes)
                {
                    nvotes = votes[(int)algorithm];
                    chosen = algorithm;
                }
            }

            return(chosen);
        }
Esempio n. 5
0
		/// <summary>
		/// Gets the X.509 certificate associated with the <see cref="MimeKit.MailboxAddress"/>.
		/// </summary>
		/// <remarks>
		/// Gets the X.509 certificate associated with the <see cref="MimeKit.MailboxAddress"/>.
		/// </remarks>
		/// <returns>The certificate.</returns>
		/// <param name="mailbox">The mailbox.</param>
		/// <exception cref="CertificateNotFoundException">
		/// A certificate for the specified <paramref name="mailbox"/> could not be found.
		/// </exception>
		protected override CmsRecipient GetCmsRecipient (MailboxAddress mailbox)
		{
			var certificate = GetCmsRecipientCertificate (mailbox);
			var cert = DotNetUtilities.FromX509Certificate (certificate);
			var recipient = new CmsRecipient (cert);

			foreach (var extension in certificate.Extensions) {
				if (extension.Oid.Value == "1.2.840.113549.1.9.15") {
					var algorithms = DecodeEncryptionAlgorithms (extension.RawData);

					if (algorithms != null)
						recipient.EncryptionAlgorithms = algorithms;

					break;
				}
			}

			return recipient;
		}
Esempio n. 6
0
        /// <summary>
        /// Gets the <see cref="CmsRecipient"/> for the specified mailbox.
        /// </summary>
        /// <remarks>
        /// <para>Constructs a <see cref="CmsRecipient"/> with the appropriate certificate and
        /// <see cref="CmsRecipient.EncryptionAlgorithms"/> 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.</para>
        /// </remarks>
        /// <returns>A <see cref="CmsRecipient"/>.</returns>
        /// <param name="mailbox">The mailbox.</param>
        /// <exception cref="CertificateNotFoundException">
        /// A certificate for the specified <paramref name="mailbox"/> could not be found.
        /// </exception>
        protected override CmsRecipient GetCmsRecipient(MailboxAddress mailbox)
        {
            X509Certificate certificate;

            if ((certificate = GetCmsRecipientCertificate(mailbox)) == null)
            {
                throw new CertificateNotFoundException(mailbox, "A valid certificate could not be found.");
            }

            var recipient = new CmsRecipient(certificate);

            EncryptionAlgorithm[] algorithms;

            if (capabilities.TryGetValue(certificate.GetFingerprint(), out algorithms))
            {
                recipient.EncryptionAlgorithms = algorithms;
            }

            return(recipient);
        }
Esempio n. 7
0
        /// <summary>
        /// Gets the <see cref="CmsRecipient"/> for the specified mailbox.
        /// </summary>
        /// <remarks>
        /// <para>Constructs a <see cref="CmsRecipient"/> with the appropriate certificate and
        /// <see cref="CmsRecipient.EncryptionAlgorithms"/> 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="CmsRecipient"/>.</returns>
        /// <param name="mailbox">The recipient's mailbox address.</param>
        /// <exception cref="CertificateNotFoundException">
        /// A certificate for the specified <paramref name="mailbox"/> could not be found.
        /// </exception>
        protected override CmsRecipient GetCmsRecipient(MailboxAddress mailbox)
        {
            foreach (var record in dbase.Find(mailbox, DateTime.UtcNow, false, CmsRecipientFields))
            {
                if (record.KeyUsage != 0 && (record.KeyUsage & X509KeyUsageFlags.KeyEncipherment) == 0)
                {
                    continue;
                }

                var recipient = new CmsRecipient(record.Certificate);

                if (record.Algorithms != null)
                {
                    recipient.EncryptionAlgorithms = record.Algorithms;
                }

                return(recipient);
            }

            throw new CertificateNotFoundException(mailbox, "A valid certificate could not be found.");
        }
Esempio n. 8
0
		public void TestDefaultValues ()
		{
			var path = Path.Combine ("..", "..", "TestData", "smime", "certificate-authority.crt");
			var recipient = new CmsRecipient (path);
			var certificate = recipient.Certificate;

			AssertDefaultValues (recipient, certificate);

			using (var stream = File.OpenRead (path))
				recipient = new CmsRecipient (stream);

			AssertDefaultValues (recipient, certificate);

			recipient = new CmsRecipient (certificate);

			AssertDefaultValues (recipient, certificate);

			recipient = new CmsRecipient (new X509Certificate2 (path));

			AssertDefaultValues (recipient, certificate);
		}
Esempio n. 9
0
		/// <summary>
		/// Gets the <see cref="CmsRecipient"/> for the specified mailbox.
		/// </summary>
		/// <returns>A <see cref="CmsRecipient"/>.</returns>
		/// <param name="mailbox">The mailbox.</param>
		/// <exception cref="CertificateNotFoundException">
		/// A certificate for the specified <paramref name="mailbox"/> could not be found.
		/// </exception>
		protected override CmsRecipient GetCmsRecipient (MailboxAddress mailbox)
		{
			var now = DateTime.Now;

			foreach (var certificate in certificates) {
				if (certificate.NotBefore > now || certificate.NotAfter < now)
					continue;

				var keyUsage = certificate.GetKeyUsageFlags ();
				if (keyUsage != 0 && (keyUsage & X509KeyUsageFlags.KeyEncipherment) == 0)
					continue;

				if (certificate.GetSubjectEmailAddress () == mailbox.Address) {
					var recipient = new CmsRecipient (certificate);
					EncryptionAlgorithm[] algorithms;

					if (capabilities.TryGetValue (certificate, out algorithms))
						recipient.EncryptionAlgorithms = algorithms;

					return recipient;
				}
			}

			throw new CertificateNotFoundException (mailbox, "A valid certificate could not be found.");
		}
		/// <summary>
		/// Gets the <see cref="CmsRecipient"/> for the specified mailbox.
		/// </summary>
		/// <remarks>
		/// <para>Constructs a <see cref="CmsRecipient"/> with the appropriate certificate and
		/// <see cref="CmsRecipient.EncryptionAlgorithms"/> 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="CmsRecipient"/>.</returns>
		/// <param name="mailbox">The mailbox.</param>
		/// <exception cref="CertificateNotFoundException">
		/// A certificate for the specified <paramref name="mailbox"/> could not be found.
		/// </exception>
		protected override CmsRecipient GetCmsRecipient (MailboxAddress mailbox)
		{
			foreach (var record in dbase.Find (mailbox, DateTime.UtcNow, false, CmsRecipientFields)) {
				if (record.KeyUsage != 0 && (record.KeyUsage & X509KeyUsageFlags.KeyEncipherment) == 0)
					continue;

				var recipient = new CmsRecipient (record.Certificate);
				if (record.Algorithms == null) {
					var capabilities = record.Certificate.GetExtensionValue (SmimeAttributes.SmimeCapabilities);
					if (capabilities != null) {
						var algorithms = DecodeEncryptionAlgorithms (capabilities.GetOctets ());

						if (algorithms != null)
							recipient.EncryptionAlgorithms = algorithms;
					}
				} else {
					recipient.EncryptionAlgorithms = record.Algorithms;
				}

				return recipient;
			}

			throw new CertificateNotFoundException (mailbox, "A valid certificate could not be found.");
		}