/// <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."); }
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); }
/// <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; }
/// <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); }
/// <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."); }
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); }
/// <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."); }