MimeKit/MimeKit.Cryptography/BouncyCastleSecureMimeContext.cs
Decompiler Source FileMimeKit.BouncyCastleSecureMimeContextDecompiled Source
Interpretation
- Decompiled source file. Use method/event registrations and call-site extraction to connect back to DialogMethod, QBMEvent, and API layers.
Relations
- Generate: 1.2.840.113533.7.66.10 at line 965
- UnitOfWork.Generate: 1.2.840.113533.7.66.10 at line 965
- Generate: 1.3.6.1.4.1.188.7.1.1.2 at line 967
- UnitOfWork.Generate: 1.3.6.1.4.1.188.7.1.1.2 at line 967
Typed Edges
- No typed edges extracted for this source.
References
- No direct source references extracted.
Referenced By
- No direct source references extracted.
C# source-derived context
Generated by pattern extraction from the decompiled C# source and decompile index. This is factual source evidence, not inferred behavior.
None extracted.
Summary: classes BouncyCastleSecureMimeContext, RsaOaepAwareRecipientInfoGenerator; methods CreateWrapper, GenerateWrappedKey, Generate, CanSign, CanEncrypt, GetCertificate
Classes
BouncyCastleSecureMimeContext RsaOaepAwareRecipientInfoGeneratorMethods
- CreateWrapper
- GenerateWrappedKey
- Generate
- CanSign
- CanEncrypt
- GetCertificate
- GetPrivateKey
- GetTrustedAnchors
- GetIntermediateCertificates
- GetCertificateRevocationLists
- GetNextCertificateRevocationListUpdate
- GetCmsRecipient
- GetCmsRecipients
- GetCmsSigner
- UpdateSecureMimeCapabilities
- AddSecureMimeCapabilities
- CreateSignedDataGenerator
- Sign
- SignAsync
- EncapsulatedSign
- EncapsulatedSignAsync
- BuildCertificateChain
- BuildCertPath
- TryGetDigestAlgorithm
- TryGetEncryptionAlgorithm
- DownloadCrlOverHttp
- DownloadCrlOverHttpAsync
- EnumerateCrlDistributionPointUrls
- DownloadCrls
- DownloadCrlsAsync
- GetDigitalSignatures
- GetDigitalSignaturesAsync
- Verify
- VerifyAsync
- CmsEnvelopeAddEllipticCurve
- AddRecipient
- ValidateRecipientCertificate
- ValidateRecipientCertificateAsync
- Envelope
- AddCmsRecipients
- AddCmsRecipientsAsync
- EnvelopeAsync
- Encrypt
- EncryptAsync
- GetDecryptedContent
- Decrypt
- DecryptAsync
- DecryptTo
- DecryptToAsync
- Export
- ExportAsync
DB/Dialog object references
None extracted.
OIM key/entity markers
None extracted.API/entity calls
None extracted.Registrations / handlers
None extracted.
Complete Source
1using System;2using System.Collections.Generic;3using System.IO;4using System.Net.Http;5using System.Threading;6using System.Threading.Tasks;7using MimeKit.IO;8using Org.BouncyCastle.Asn1;9using Org.BouncyCastle.Asn1.Cms;10using Org.BouncyCastle.Asn1.Pkcs;11using Org.BouncyCastle.Asn1.Smime;12using Org.BouncyCastle.Asn1.X509;13using Org.BouncyCastle.Cms;14using Org.BouncyCastle.Crypto;15using Org.BouncyCastle.Crypto.Generators;16using Org.BouncyCastle.Crypto.Parameters;17using Org.BouncyCastle.Pkix;18using Org.BouncyCastle.Security;19using Org.BouncyCastle.Utilities.Collections;20using Org.BouncyCastle.X509;21using Org.BouncyCastle.X509.Extension;22using Org.BouncyCastle.X509.Store;2324namespace MimeKit.Cryptography;2526public abstract class BouncyCastleSecureMimeContext : SecureMimeContext27{28 private class RsaOaepAwareRecipientInfoGenerator : RecipientInfoGenerator29 {30 private readonly CmsRecipient recipient;3132 public RsaOaepAwareRecipientInfoGenerator(CmsRecipient recipient)33 {34 this.recipient = recipient;35 }3637 private static IWrapper CreateWrapper(AlgorithmIdentifier keyExchangeAlgorithm)38 {39 string algorithm;40 if (!keyExchangeAlgorithm.Algorithm.Id.Equals(PkcsObjectIdentifiers.IdRsaesOaep.Id, StringComparison.Ordinal))41 {42 algorithm = ((!keyExchangeAlgorithm.Algorithm.Id.Equals(PkcsObjectIdentifiers.RsaEncryption.Id, StringComparison.Ordinal)) ? keyExchangeAlgorithm.Algorithm.Id : "RSA//PKCS1Padding");43 }44 else45 {46 RsaesOaepParameters instance = RsaesOaepParameters.GetInstance(keyExchangeAlgorithm.Parameters);47 algorithm = "RSA//OAEPWITH" + DigestUtilities.GetAlgorithmName(instance.HashAlgorithm.Algorithm) + "ANDMGF1Padding";48 }49 return WrapperUtilities.GetWrapper(algorithm);50 }5152 private static byte[] GenerateWrappedKey(KeyParameter contentEncryptionKey, AlgorithmIdentifier keyEncryptionAlgorithm, AsymmetricKeyParameter publicKey, SecureRandom random)53 {54 IWrapper wrapper = CreateWrapper(keyEncryptionAlgorithm);55 byte[] key = contentEncryptionKey.GetKey();56 wrapper.Init(forWrapping: true, new ParametersWithRandom(publicKey, random));57 return wrapper.Wrap(key, 0, key.Length);58 }5960 public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random)61 {62 TbsCertificateStructure tbsCertificate = recipient.Certificate.TbsCertificate;63 AsymmetricKeyParameter publicKey = recipient.Certificate.GetPublicKey();64 SubjectPublicKeyInfo subjectPublicKeyInfo = tbsCertificate.SubjectPublicKeyInfo;65 AlgorithmIdentifier keyEncryptionAlgorithm;66 if (publicKey is RsaKeyParameters)67 {68 RsaEncryptionPadding rsaEncryptionPadding = recipient.RsaEncryptionPadding;69 if ((object)rsaEncryptionPadding != null && rsaEncryptionPadding.Scheme == RsaEncryptionPaddingScheme.Oaep)70 {71 keyEncryptionAlgorithm = recipient.RsaEncryptionPadding.GetAlgorithmIdentifier();72 goto IL_0067;73 }74 }75 keyEncryptionAlgorithm = subjectPublicKeyInfo.Algorithm;76 goto IL_0067;77 IL_0067:78 byte[] contents = GenerateWrappedKey(contentEncryptionKey, keyEncryptionAlgorithm, publicKey, random);79 RecipientIdentifier rid;80 if (recipient.RecipientIdentifierType == SubjectIdentifierType.SubjectKeyIdentifier)81 {82 SubjectKeyIdentifier subjectKeyIdentifier = X509ExtensionUtilities.GetSubjectKeyIdentifier(recipient.Certificate);83 rid = new RecipientIdentifier(subjectKeyIdentifier);84 }85 else86 {87 Org.BouncyCastle.Asn1.Cms.IssuerAndSerialNumber id = new Org.BouncyCastle.Asn1.Cms.IssuerAndSerialNumber(tbsCertificate.Issuer, tbsCertificate.SerialNumber.Value);88 rid = new RecipientIdentifier(id);89 }90 return new RecipientInfo(new KeyTransRecipientInfo(rid, keyEncryptionAlgorithm, new DerOctetString(contents)));91 }92 }9394 private static readonly X509CertStoreSelector MatchAllCertificates = new X509CertStoreSelector();9596 private static readonly string RsassaPssOid = PkcsObjectIdentifiers.IdRsassaPss.Id;9798 private static readonly HttpClient SharedHttpClient = new HttpClient();99100 protected SecureRandom RandomNumberGenerator { get; private set; }101102 public bool CheckCertificateRevocation { get; set; }103104 protected virtual HttpClient HttpClient => SharedHttpClient;105106 protected BouncyCastleSecureMimeContext()107 : this(new SecureRandom())108 {109 }110111 protected BouncyCastleSecureMimeContext(SecureRandom random)112 {113 if (random == null)114 {115 throw new ArgumentNullException("random");116 }117 RandomNumberGenerator = random;118 }119120 internal static bool CanSign(X509KeyUsageFlags keyUsage)121 {122 if (keyUsage != X509KeyUsageFlags.None)123 {124 return (keyUsage & X509KeyUsageFlags.DigitalSignature) != 0;125 }126 return true;127 }128129 internal static bool CanEncrypt(X509KeyUsageFlags keyUsage)130 {131 return true;132 }133134 protected abstract X509Certificate GetCertificate(ISelector<X509Certificate> selector);135136 protected abstract AsymmetricKeyParameter GetPrivateKey(ISelector<X509Certificate> selector);137138 protected abstract ISet<TrustAnchor> GetTrustedAnchors();139140 protected abstract IStore<X509Certificate> GetIntermediateCertificates();141142 protected abstract IStore<X509Crl> GetCertificateRevocationLists();143144 protected abstract DateTime GetNextCertificateRevocationListUpdate(X509Name issuer);145146 protected abstract CmsRecipient GetCmsRecipient(MailboxAddress mailbox);147148 protected CmsRecipientCollection GetCmsRecipients(IEnumerable<MailboxAddress> mailboxes)149 {150 if (mailboxes == null)151 {152 throw new ArgumentNullException("mailboxes");153 }154 CmsRecipientCollection cmsRecipientCollection = new CmsRecipientCollection();155 foreach (MailboxAddress mailbox in mailboxes)156 {157 cmsRecipientCollection.Add(GetCmsRecipient(mailbox));158 }159 return cmsRecipientCollection;160 }161162 protected abstract CmsSigner GetCmsSigner(MailboxAddress mailbox, DigestAlgorithm digestAlgo);163164 protected abstract void UpdateSecureMimeCapabilities(X509Certificate certificate, EncryptionAlgorithm[] algorithms, DateTime timestamp);165166 private CmsAttributeTableGenerator AddSecureMimeCapabilities(Org.BouncyCastle.Asn1.Cms.AttributeTable signedAttributes)167 {168 SmimeCapabilitiesAttribute secureMimeCapabilitiesAttribute = GetSecureMimeCapabilitiesAttribute(includeRsaesOaep: true);169 return new DefaultSignedAttributeTableGenerator(signedAttributes.Add(secureMimeCapabilitiesAttribute.AttrType, secureMimeCapabilitiesAttribute.AttrValues[0]));170 }171172 private CmsSignedDataStreamGenerator CreateSignedDataGenerator(CmsSigner signer)173 {174 SimpleAttributeTableGenerator unsignedAttrGenerator = new SimpleAttributeTableGenerator(signer.UnsignedAttributes);175 CmsAttributeTableGenerator signedAttrGenerator = AddSecureMimeCapabilities(signer.SignedAttributes);176 CmsSignedDataStreamGenerator cmsSignedDataStreamGenerator = new CmsSignedDataStreamGenerator(RandomNumberGenerator);177 string digestOid = SecureMimeContext.GetDigestOid(signer.DigestAlgorithm);178 byte[] array = null;179 if (signer.SignerIdentifierType == SubjectIdentifierType.SubjectKeyIdentifier)180 {181 array = X509ExtensionUtilities.GetSubjectKeyIdentifier(signer.Certificate)?.GetKeyIdentifier();182 }183 if (signer.PrivateKey is RsaKeyParameters && signer.RsaSignaturePadding == RsaSignaturePadding.Pss)184 {185 if (array == null)186 {187 cmsSignedDataStreamGenerator.AddSigner(signer.PrivateKey, signer.Certificate, RsassaPssOid, digestOid, signedAttrGenerator, unsignedAttrGenerator);188 }189 else190 {191 cmsSignedDataStreamGenerator.AddSigner(signer.PrivateKey, array, RsassaPssOid, digestOid, signedAttrGenerator, unsignedAttrGenerator);192 }193 }194 else if (array == null)195 {196 cmsSignedDataStreamGenerator.AddSigner(signer.PrivateKey, signer.Certificate, digestOid, signedAttrGenerator, unsignedAttrGenerator);197 }198 else199 {200 cmsSignedDataStreamGenerator.AddSigner(signer.PrivateKey, array, digestOid, signedAttrGenerator, unsignedAttrGenerator);201 }202 cmsSignedDataStreamGenerator.AddCertificates(signer.CertificateChain);203 return cmsSignedDataStreamGenerator;204 }205206 private Stream Sign(CmsSigner signer, Stream content, bool encapsulate, CancellationToken cancellationToken)207 {208 CmsSignedDataStreamGenerator cmsSignedDataStreamGenerator = CreateSignedDataGenerator(signer);209 MemoryBlockStream memoryBlockStream = new MemoryBlockStream();210 using (Stream destination = cmsSignedDataStreamGenerator.Open(memoryBlockStream, encapsulate))211 {212 content.CopyTo(destination, 4096);213 }214 memoryBlockStream.Position = 0L;215 return memoryBlockStream;216 }217218 private async Task<Stream> SignAsync(CmsSigner signer, Stream content, bool encapsulate, CancellationToken cancellationToken)219 {220 CmsSignedDataStreamGenerator cmsSignedDataStreamGenerator = CreateSignedDataGenerator(signer);221 MemoryBlockStream memory = new MemoryBlockStream();222 using (Stream stream = cmsSignedDataStreamGenerator.Open(memory, encapsulate))223 {224 await content.CopyToAsync(stream, 4096, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);225 }226 memory.Position = 0L;227 return memory;228 }229230 public override ApplicationPkcs7Mime EncapsulatedSign(CmsSigner signer, Stream content, CancellationToken cancellationToken = default(CancellationToken))231 {232 if (signer == null)233 {234 throw new ArgumentNullException("signer");235 }236 if (content == null)237 {238 throw new ArgumentNullException("content");239 }240 Stream stream = Sign(signer, content, encapsulate: true, cancellationToken);241 return new ApplicationPkcs7Mime(SecureMimeType.SignedData, stream);242 }243244 public override async Task<ApplicationPkcs7Mime> EncapsulatedSignAsync(CmsSigner signer, Stream content, CancellationToken cancellationToken = default(CancellationToken))245 {246 if (signer == null)247 {248 throw new ArgumentNullException("signer");249 }250 if (content == null)251 {252 throw new ArgumentNullException("content");253 }254 return new ApplicationPkcs7Mime(SecureMimeType.SignedData, await SignAsync(signer, content, encapsulate: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false));255 }256257 public override ApplicationPkcs7Mime EncapsulatedSign(MailboxAddress signer, DigestAlgorithm digestAlgo, Stream content, CancellationToken cancellationToken = default(CancellationToken))258 {259 if (signer == null)260 {261 throw new ArgumentNullException("signer");262 }263 if (content == null)264 {265 throw new ArgumentNullException("content");266 }267 CmsSigner cmsSigner = GetCmsSigner(signer, digestAlgo);268 return EncapsulatedSign(cmsSigner, content, cancellationToken);269 }270271 public override Task<ApplicationPkcs7Mime> EncapsulatedSignAsync(MailboxAddress signer, DigestAlgorithm digestAlgo, Stream content, CancellationToken cancellationToken = default(CancellationToken))272 {273 if (signer == null)274 {275 throw new ArgumentNullException("signer");276 }277 if (content == null)278 {279 throw new ArgumentNullException("content");280 }281 CmsSigner cmsSigner = GetCmsSigner(signer, digestAlgo);282 return EncapsulatedSignAsync(cmsSigner, content, cancellationToken);283 }284285 public override ApplicationPkcs7Signature Sign(CmsSigner signer, Stream content, CancellationToken cancellationToken = default(CancellationToken))286 {287 if (signer == null)288 {289 throw new ArgumentNullException("signer");290 }291 if (content == null)292 {293 throw new ArgumentNullException("content");294 }295 Stream stream = Sign(signer, content, encapsulate: false, cancellationToken);296 return new ApplicationPkcs7Signature(stream);297 }298299 public override async Task<ApplicationPkcs7Signature> SignAsync(CmsSigner signer, Stream content, CancellationToken cancellationToken = default(CancellationToken))300 {301 if (signer == null)302 {303 throw new ArgumentNullException("signer");304 }305 if (content == null)306 {307 throw new ArgumentNullException("content");308 }309 return new ApplicationPkcs7Signature(await SignAsync(signer, content, encapsulate: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false));310 }311312 public override MimePart Sign(MailboxAddress signer, DigestAlgorithm digestAlgo, Stream content, CancellationToken cancellationToken = default(CancellationToken))313 {314 if (signer == null)315 {316 throw new ArgumentNullException("signer");317 }318 if (content == null)319 {320 throw new ArgumentNullException("content");321 }322 CmsSigner cmsSigner = GetCmsSigner(signer, digestAlgo);323 return Sign(cmsSigner, content, cancellationToken);324 }325326 public override async Task<MimePart> SignAsync(MailboxAddress signer, DigestAlgorithm digestAlgo, Stream content, CancellationToken cancellationToken = default(CancellationToken))327 {328 if (signer == null)329 {330 throw new ArgumentNullException("signer");331 }332 if (content == null)333 {334 throw new ArgumentNullException("content");335 }336 CmsSigner cmsSigner = GetCmsSigner(signer, digestAlgo);337 return await SignAsync(cmsSigner, content, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);338 }339340 private X509Certificate GetCertificate(IStore<X509Certificate> store, SignerID signer)341 {342 if (signer.Certificate != null)343 {344 return signer.Certificate;345 }346 IEnumerable<X509Certificate> enumerable = store.EnumerateMatches(signer);347 using (IEnumerator<X509Certificate> enumerator = enumerable.GetEnumerator())348 {349 if (enumerator.MoveNext())350 {351 return enumerator.Current;352 }353 }354 return GetCertificate(signer);355 }356357 protected IList<X509Certificate> BuildCertificateChain(X509Certificate certificate)358 {359 X509CertStoreSelector targetConstraintsCert = new X509CertStoreSelector();360 X509CertificateStore x509CertificateStore = new X509CertificateStore();361 x509CertificateStore.Add(certificate);362 ISet<TrustAnchor> trustedAnchors = GetTrustedAnchors();363 X509CertificateStore x509CertificateStore2 = new X509CertificateStore();364 foreach (TrustAnchor item in trustedAnchors)365 {366 x509CertificateStore2.Add(item.TrustedCert);367 }368 PkixBuilderParameters pkixBuilderParameters = new PkixBuilderParameters(trustedAnchors, targetConstraintsCert)369 {370 ValidityModel = 0,371 IsRevocationEnabled = false,372 Date = DateTime.UtcNow373 };374 pkixBuilderParameters.AddStoreCert(x509CertificateStore);375 IStore<X509Certificate> intermediateCertificates = GetIntermediateCertificates();376 foreach (X509Certificate item2 in intermediateCertificates.EnumerateMatches(MatchAllCertificates))377 {378 x509CertificateStore2.Add(item2);379 }380 pkixBuilderParameters.AddStoreCert(x509CertificateStore2);381 PkixCertPathBuilder pkixCertPathBuilder = new PkixCertPathBuilder();382 PkixCertPathBuilderResult pkixCertPathBuilderResult = pkixCertPathBuilder.Build(pkixBuilderParameters);383 X509Certificate[] array = new X509Certificate[pkixCertPathBuilderResult.CertPath.Certificates.Count];384 for (int i = 0; i < array.Length; i++)385 {386 array[i] = pkixCertPathBuilderResult.CertPath.Certificates[i];387 }388 return array;389 }390391 private PkixCertPath BuildCertPath(ISelector<X509Certificate> selector, ISet<TrustAnchor> anchors, IStore<X509Certificate> certificates, IStore<X509Crl> crls, X509Certificate certificate, DateTime signingTime)392 {393 X509CertificateStore x509CertificateStore = new X509CertificateStore();394 if (certificate != null)395 {396 x509CertificateStore.Add(certificate);397 }398 foreach (X509Certificate item in certificates.EnumerateMatches(null))399 {400 x509CertificateStore.Add(item);401 }402 PkixBuilderParameters pkixBuilderParameters = new PkixBuilderParameters(anchors, selector)403 {404 ValidityModel = 0,405 IsRevocationEnabled = CheckCertificateRevocation406 };407 pkixBuilderParameters.AddStoreCert(x509CertificateStore);408 pkixBuilderParameters.AddStoreCrl(crls);409 pkixBuilderParameters.AddStoreCert(GetIntermediateCertificates());410 if (CheckCertificateRevocation)411 {412 pkixBuilderParameters.AddStoreCrl(GetCertificateRevocationLists());413 }414 if (signingTime != default(DateTime))415 {416 pkixBuilderParameters.Date = signingTime;417 }418 PkixCertPathBuilder pkixCertPathBuilder = new PkixCertPathBuilder();419 PkixCertPathBuilderResult pkixCertPathBuilderResult = pkixCertPathBuilder.Build(pkixBuilderParameters);420 return pkixCertPathBuilderResult.CertPath;421 }422423 protected internal static bool TryGetDigestAlgorithm(AlgorithmIdentifier identifier, out DigestAlgorithm algorithm)424 {425 if (identifier == null)426 {427 throw new ArgumentNullException("identifier");428 }429 return SecureMimeContext.TryGetDigestAlgorithm(identifier.Algorithm.Id, out algorithm);430 }431432 protected internal static bool TryGetEncryptionAlgorithm(AlgorithmIdentifier identifier, out EncryptionAlgorithm algorithm)433 {434 if (identifier == null)435 {436 throw new ArgumentNullException("identifier");437 }438 if (identifier.Algorithm.Id == CmsEnvelopedGenerator.Aes256Cbc)439 {440 algorithm = EncryptionAlgorithm.Aes256;441 return true;442 }443 if (identifier.Algorithm.Id == CmsEnvelopedGenerator.Aes192Cbc)444 {445 algorithm = EncryptionAlgorithm.Aes192;446 return true;447 }448 if (identifier.Algorithm.Id == CmsEnvelopedGenerator.Aes128Cbc)449 {450 algorithm = EncryptionAlgorithm.Aes128;451 return true;452 }453 if (identifier.Algorithm.Id == CmsEnvelopedGenerator.Camellia256Cbc)454 {455 algorithm = EncryptionAlgorithm.Camellia256;456 return true;457 }458 if (identifier.Algorithm.Id == CmsEnvelopedGenerator.Camellia192Cbc)459 {460 algorithm = EncryptionAlgorithm.Camellia192;461 return true;462 }463 if (identifier.Algorithm.Id == CmsEnvelopedGenerator.Camellia128Cbc)464 {465 algorithm = EncryptionAlgorithm.Camellia128;466 return true;467 }468 if (identifier.Algorithm.Id == "1.2.840.113533.7.66.10")469 {470 algorithm = EncryptionAlgorithm.Cast5;471 return true;472 }473 if (identifier.Algorithm.Id == CmsEnvelopedGenerator.DesEde3Cbc)474 {475 algorithm = EncryptionAlgorithm.TripleDes;476 return true;477 }478 if (identifier.Algorithm.Id == SecureMimeContext.Blowfish.Id)479 {480 algorithm = EncryptionAlgorithm.Blowfish;481 return true;482 }483 if (identifier.Algorithm.Id == SecureMimeContext.Twofish.Id)484 {485 algorithm = EncryptionAlgorithm.Twofish;486 return true;487 }488 if (identifier.Algorithm.Id == CmsEnvelopedGenerator.SeedCbc)489 {490 algorithm = EncryptionAlgorithm.Seed;491 return true;492 }493 if (identifier.Algorithm.Id == SmimeCapability.DesCbc.Id)494 {495 algorithm = EncryptionAlgorithm.Des;496 return true;497 }498 if (identifier.Algorithm.Id == "1.3.6.1.4.1.188.7.1.1.2")499 {500 algorithm = EncryptionAlgorithm.Idea;501 return true;502 }503 if (identifier.Algorithm.Id == CmsEnvelopedGenerator.RC2Cbc)504 {505 if (identifier.Parameters is DerSequence derSequence)506 {507 DerInteger derInteger = (DerInteger)derSequence[0];508 switch (derInteger.Value.IntValue)509 {510 case 58:511 algorithm = EncryptionAlgorithm.RC2128;512 return true;513 case 120:514 algorithm = EncryptionAlgorithm.RC264;515 return true;516 case 160:517 algorithm = EncryptionAlgorithm.RC240;518 return true;519 }520 }521 else if (identifier.Parameters is DerInteger derInteger2)522 {523 switch (derInteger2.Value.IntValue)524 {525 case 128:526 algorithm = EncryptionAlgorithm.RC2128;527 return true;528 case 64:529 algorithm = EncryptionAlgorithm.RC264;530 return true;531 case 40:532 algorithm = EncryptionAlgorithm.RC240;533 return true;534 }535 }536 }537 algorithm = EncryptionAlgorithm.RC240;538 return false;539 }540541 private bool DownloadCrlOverHttp(string location, Stream stream, CancellationToken cancellationToken)542 {543 try544 {545 using (HttpResponseMessage httpResponseMessage = HttpClient.GetAsync(location, cancellationToken).GetAwaiter().GetResult())546 {547 httpResponseMessage.Content.CopyToAsync(stream, cancellationToken).GetAwaiter().GetResult();548 }549 return true;550 }551 catch552 {553 return false;554 }555 }556557 private async Task<bool> DownloadCrlOverHttpAsync(string location, Stream stream, CancellationToken cancellationToken)558 {559 _ = 1;560 try561 {562 using (HttpResponseMessage response = await HttpClient.GetAsync(location, cancellationToken).ConfigureAwait(continueOnCapturedContext: false))563 {564 await response.Content.CopyToAsync(stream, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);565 }566 return true;567 }568 catch569 {570 return false;571 }572 }573574 private static IEnumerable<string> EnumerateCrlDistributionPointUrls(X509Certificate certificate)575 {576 Asn1OctetString extensionValue = certificate.GetExtensionValue(X509Extensions.CrlDistributionPoints);577 if (extensionValue == null)578 {579 yield break;580 }581 DistributionPoint[] points = CrlDistPoint.GetInstance(extensionValue.GetOctets()).GetDistributionPoints();582 for (int i = 0; i < points.Length; i++)583 {584 GeneralName[] generalNames = GeneralNames.GetInstance(points[i].DistributionPointName.Name).GetNames();585 for (int j = 0; j < generalNames.Length; j++)586 {587 if (generalNames[j].TagNo == 6)588 {589 yield return DerIA5String.GetInstance(generalNames[j].Name).GetString();590 }591 }592 }593 }594595 private void DownloadCrls(X509Certificate certificate, CancellationToken cancellationToken)596 {597 DateTime nextCertificateRevocationListUpdate = GetNextCertificateRevocationListUpdate(certificate.IssuerDN);598 DateTime utcNow = DateTime.UtcNow;599 if (nextCertificateRevocationListUpdate > utcNow)600 {601 return;602 }603 using MemoryBlockStream memoryBlockStream = new MemoryBlockStream();604 bool flag = false;605 foreach (string item in EnumerateCrlDistributionPointUrls(certificate))606 {607 if ((item.StartsWith("https://", StringComparison.OrdinalIgnoreCase) || item.StartsWith("http://", StringComparison.OrdinalIgnoreCase)) && DownloadCrlOverHttp(item, memoryBlockStream, cancellationToken))608 {609 flag = true;610 break;611 }612 }613 if (!flag)614 {615 return;616 }617 memoryBlockStream.Position = 0L;618 X509CrlParser x509CrlParser = new X509CrlParser();619 foreach (X509Crl item2 in x509CrlParser.ReadCrls(memoryBlockStream))620 {621 Import(item2, cancellationToken);622 }623 }624625 private async Task DownloadCrlsAsync(X509Certificate certificate, CancellationToken cancellationToken)626 {627 DateTime nextCertificateRevocationListUpdate = GetNextCertificateRevocationListUpdate(certificate.IssuerDN);628 DateTime utcNow = DateTime.UtcNow;629 if (nextCertificateRevocationListUpdate > utcNow)630 {631 return;632 }633 using MemoryBlockStream stream = new MemoryBlockStream();634 bool downloaded = false;635 foreach (string item in EnumerateCrlDistributionPointUrls(certificate))636 {637 if ((item.StartsWith("https://", StringComparison.OrdinalIgnoreCase) || item.StartsWith("http://", StringComparison.OrdinalIgnoreCase)) && await DownloadCrlOverHttpAsync(item, stream, cancellationToken).ConfigureAwait(continueOnCapturedContext: false))638 {639 downloaded = true;640 break;641 }642 }643 if (!downloaded)644 {645 return;646 }647 stream.Position = 0L;648 X509CrlParser x509CrlParser = new X509CrlParser();649 foreach (X509Crl item2 in x509CrlParser.ReadCrls(stream))650 {651 await ImportAsync(item2, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);652 }653 }654655 private DigitalSignatureCollection GetDigitalSignatures(CmsSignedDataParser parser, CancellationToken cancellationToken)656 {657 IStore<X509Certificate> certificates = parser.GetCertificates();658 List<IDigitalSignature> list = new List<IDigitalSignature>();659 IStore<X509Crl> crls = parser.GetCrls();660 SignerInformationStore signerInfos = parser.GetSignerInfos();661 foreach (SignerInformation signer in signerInfos.GetSigners())662 {663 X509Certificate certificate = GetCertificate(certificates, signer.SignerID);664 SecureMimeDigitalSignature secureMimeDigitalSignature = new SecureMimeDigitalSignature(signer, certificate);665 if (CheckCertificateRevocation)666 {667 foreach (X509Certificate item in certificates.EnumerateMatches(null))668 {669 DownloadCrls(item, cancellationToken);670 }671 }672 if (certificate != null)673 {674 Import(certificate, cancellationToken);675 if (secureMimeDigitalSignature.EncryptionAlgorithms.Length != 0 && secureMimeDigitalSignature.CreationDate != default(DateTime))676 {677 UpdateSecureMimeCapabilities(certificate, secureMimeDigitalSignature.EncryptionAlgorithms, secureMimeDigitalSignature.CreationDate);678 }679 }680 ISet<TrustAnchor> trustedAnchors = GetTrustedAnchors();681 IStore<X509Certificate> intermediateCertificates = GetIntermediateCertificates();682 if (CheckCertificateRevocation)683 {684 foreach (TrustAnchor item2 in trustedAnchors)685 {686 DownloadCrls(item2.TrustedCert, cancellationToken);687 }688 foreach (X509Certificate item3 in intermediateCertificates.EnumerateMatches(MatchAllCertificates))689 {690 DownloadCrls(item3, cancellationToken);691 }692 }693 try694 {695 secureMimeDigitalSignature.Chain = BuildCertPath(signer.SignerID, trustedAnchors, certificates, crls, certificate, secureMimeDigitalSignature.CreationDate);696 }697 catch (Exception chainException)698 {699 secureMimeDigitalSignature.ChainException = chainException;700 }701 list.Add(secureMimeDigitalSignature);702 }703 return new DigitalSignatureCollection(list);704 }705706 private async Task<DigitalSignatureCollection> GetDigitalSignaturesAsync(CmsSignedDataParser parser, CancellationToken cancellationToken)707 {708 IStore<X509Certificate> certificates = parser.GetCertificates();709 List<IDigitalSignature> signatures = new List<IDigitalSignature>();710 IStore<X509Crl> crls = parser.GetCrls();711 SignerInformationStore signerInfos = parser.GetSignerInfos();712 foreach (SignerInformation signerInfo in signerInfos.GetSigners())713 {714 X509Certificate certificate = GetCertificate(certificates, signerInfo.SignerID);715 SecureMimeDigitalSignature signature = new SecureMimeDigitalSignature(signerInfo, certificate);716 if (CheckCertificateRevocation)717 {718 foreach (X509Certificate item in certificates.EnumerateMatches(null))719 {720 await DownloadCrlsAsync(item, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);721 }722 }723 if (certificate != null)724 {725 await ImportAsync(certificate, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);726 if (signature.EncryptionAlgorithms.Length != 0 && signature.CreationDate != default(DateTime))727 {728 UpdateSecureMimeCapabilities(certificate, signature.EncryptionAlgorithms, signature.CreationDate);729 }730 }731 ISet<TrustAnchor> anchors = GetTrustedAnchors();732 IStore<X509Certificate> intermediates = GetIntermediateCertificates();733 if (CheckCertificateRevocation)734 {735 foreach (TrustAnchor item2 in anchors)736 {737 await DownloadCrlsAsync(item2.TrustedCert, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);738 }739 foreach (X509Certificate item3 in intermediates.EnumerateMatches(MatchAllCertificates))740 {741 await DownloadCrlsAsync(item3, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);742 }743 }744 try745 {746 signature.Chain = BuildCertPath(signerInfo.SignerID, anchors, certificates, crls, certificate, signature.CreationDate);747 }748 catch (Exception chainException)749 {750 signature.ChainException = chainException;751 }752 signatures.Add(signature);753 }754 return new DigitalSignatureCollection(signatures);755 }756757 public override DigitalSignatureCollection Verify(Stream content, Stream signatureData, CancellationToken cancellationToken = default(CancellationToken))758 {759 if (content == null)760 {761 throw new ArgumentNullException("content");762 }763 if (signatureData == null)764 {765 throw new ArgumentNullException("signatureData");766 }767 using CmsSignedDataParser cmsSignedDataParser = new CmsSignedDataParser(new CmsTypedStream(content), signatureData);768 CmsTypedStream signedContent = cmsSignedDataParser.GetSignedContent();769 try770 {771 signedContent.ContentStream.CopyTo(Stream.Null, 4096);772 }773 finally774 {775 signedContent.ContentStream.Dispose();776 }777 return GetDigitalSignatures(cmsSignedDataParser, cancellationToken);778 }779780 public override async Task<DigitalSignatureCollection> VerifyAsync(Stream content, Stream signatureData, CancellationToken cancellationToken = default(CancellationToken))781 {782 if (content == null)783 {784 throw new ArgumentNullException("content");785 }786 if (signatureData == null)787 {788 throw new ArgumentNullException("signatureData");789 }790 using CmsSignedDataParser parser = new CmsSignedDataParser(new CmsTypedStream(content), signatureData);791 CmsTypedStream signed = parser.GetSignedContent();792 try793 {794 await signed.ContentStream.CopyToAsync(Stream.Null, 4096, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);795 }796 finally797 {798 signed.ContentStream.Dispose();799 }800 return await GetDigitalSignaturesAsync(parser, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);801 }802803 public override DigitalSignatureCollection Verify(Stream signedData, out MimeEntity entity, CancellationToken cancellationToken = default(CancellationToken))804 {805 if (signedData == null)806 {807 throw new ArgumentNullException("signedData");808 }809 using CmsSignedDataParser cmsSignedDataParser = new CmsSignedDataParser(signedData);810 CmsTypedStream signedContent = cmsSignedDataParser.GetSignedContent();811 try812 {813 entity = MimeEntity.Load(signedContent.ContentStream, cancellationToken);814 signedContent.ContentStream.CopyTo(Stream.Null, 4096);815 }816 finally817 {818 signedContent.ContentStream.Dispose();819 }820 return GetDigitalSignatures(cmsSignedDataParser, cancellationToken);821 }822823 public override Stream Verify(Stream signedData, out DigitalSignatureCollection signatures, CancellationToken cancellationToken = default(CancellationToken))824 {825 if (signedData == null)826 {827 throw new ArgumentNullException("signedData");828 }829 using CmsSignedDataParser cmsSignedDataParser = new CmsSignedDataParser(signedData);830 CmsTypedStream signedContent = cmsSignedDataParser.GetSignedContent();831 MemoryBlockStream memoryBlockStream = new MemoryBlockStream();832 try833 {834 signedContent.ContentStream.CopyTo(memoryBlockStream, 4096);835 memoryBlockStream.Position = 0L;836 }837 catch838 {839 memoryBlockStream.Dispose();840 }841 finally842 {843 signedContent.ContentStream.Dispose();844 }845 signatures = GetDigitalSignatures(cmsSignedDataParser, cancellationToken);846 return memoryBlockStream;847 }848849 private void CmsEnvelopeAddEllipticCurve(CmsEnvelopedGenerator cms, CmsRecipient recipient, X509Certificate certificate, ECKeyParameters publicKey)850 {851 ECKeyPairGenerator eCKeyPairGenerator = new ECKeyPairGenerator();852 eCKeyPairGenerator.Init(new ECKeyGenerationParameters(publicKey.Parameters, RandomNumberGenerator));853 AsymmetricCipherKeyPair asymmetricCipherKeyPair = eCKeyPairGenerator.GenerateKeyPair();854 if (recipient.RecipientIdentifierType == SubjectIdentifierType.SubjectKeyIdentifier)855 {856 SubjectKeyIdentifier subjectKeyIdentifier = X509ExtensionUtilities.GetSubjectKeyIdentifier(recipient.Certificate);857 cms.AddKeyAgreementRecipient(CmsEnvelopedGenerator.ECDHSha1Kdf, asymmetricCipherKeyPair.Private, asymmetricCipherKeyPair.Public, subjectKeyIdentifier.GetKeyIdentifier(), publicKey, CmsEnvelopedGenerator.Aes128Wrap);858 }859 else860 {861 cms.AddKeyAgreementRecipient(CmsEnvelopedGenerator.ECDHSha1Kdf, asymmetricCipherKeyPair.Private, asymmetricCipherKeyPair.Public, certificate, CmsEnvelopedGenerator.Aes128Wrap);862 }863 }864865 private void AddRecipient(CmsEnvelopedGenerator cms, CmsRecipient recipient)866 {867 X509Certificate certificate = recipient.Certificate;868 AsymmetricKeyParameter publicKey = certificate.GetPublicKey();869 if (publicKey is RsaKeyParameters)870 {871 cms.AddRecipientInfoGenerator(new RsaOaepAwareRecipientInfoGenerator(recipient));872 return;873 }874 if (publicKey is ECKeyParameters publicKey2)875 {876 CmsEnvelopeAddEllipticCurve(cms, recipient, certificate, publicKey2);877 return;878 }879 string value = certificate.SubjectPublicKeyInfo.Algorithm.Algorithm.ToString();880 throw new NotSupportedException($"Unsupported type of recipient certificate: {publicKey.GetType().Name} (SubjectPublicKeyInfo OID = {value})");881 }882883 private void ValidateRecipientCertificate(X509Certificate certificate, CancellationToken cancellationToken = default(CancellationToken))884 {885 DownloadCrls(certificate, cancellationToken);886 X509CertStoreSelector targetConstraintsCert = new X509CertStoreSelector887 {888 Certificate = certificate889 };890 X509CertificateStore x509CertificateStore = new X509CertificateStore();891 x509CertificateStore.Add(certificate);892 ISet<TrustAnchor> trustedAnchors = GetTrustedAnchors();893 X509CertificateStore x509CertificateStore2 = new X509CertificateStore();894 foreach (TrustAnchor item in trustedAnchors)895 {896 DownloadCrls(item.TrustedCert, cancellationToken);897 x509CertificateStore2.Add(item.TrustedCert);898 }899 IStore<X509Certificate> intermediateCertificates = GetIntermediateCertificates();900 foreach (X509Certificate item2 in intermediateCertificates.EnumerateMatches(MatchAllCertificates))901 {902 DownloadCrls(item2, cancellationToken);903 }904 PkixBuilderParameters pkixBuilderParameters = new PkixBuilderParameters(trustedAnchors, targetConstraintsCert)905 {906 ValidityModel = 0,907 IsRevocationEnabled = true,908 Date = DateTime.UtcNow909 };910 pkixBuilderParameters.AddStoreCert(x509CertificateStore);911 pkixBuilderParameters.AddStoreCert(intermediateCertificates);912 pkixBuilderParameters.AddStoreCert(x509CertificateStore2);913 pkixBuilderParameters.AddStoreCrl(GetCertificateRevocationLists());914 PkixCertPathBuilder pkixCertPathBuilder = new PkixCertPathBuilder();915 pkixCertPathBuilder.Build(pkixBuilderParameters);916 }917918 private async Task ValidateRecipientCertificateAsync(X509Certificate certificate, CancellationToken cancellationToken = default(CancellationToken))919 {920 await DownloadCrlsAsync(certificate, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);921 X509CertStoreSelector selector = new X509CertStoreSelector922 {923 Certificate = certificate924 };925 X509CertificateStore userCertificateStore = new X509CertificateStore();926 userCertificateStore.Add(certificate);927 ISet<TrustAnchor> trustedAnchors = GetTrustedAnchors();928 X509CertificateStore anchorStore = new X509CertificateStore();929 foreach (TrustAnchor anchor in trustedAnchors)930 {931 await DownloadCrlsAsync(anchor.TrustedCert, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);932 anchorStore.Add(anchor.TrustedCert);933 }934 IStore<X509Certificate> intermediateStore = GetIntermediateCertificates();935 foreach (X509Certificate item in intermediateStore.EnumerateMatches(MatchAllCertificates))936 {937 await DownloadCrlsAsync(item, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);938 }939 PkixBuilderParameters pkixBuilderParameters = new PkixBuilderParameters(trustedAnchors, selector)940 {941 ValidityModel = 0,942 IsRevocationEnabled = true,943 Date = DateTime.UtcNow944 };945 pkixBuilderParameters.AddStoreCert(userCertificateStore);946 pkixBuilderParameters.AddStoreCert(intermediateStore);947 pkixBuilderParameters.AddStoreCert(anchorStore);948 pkixBuilderParameters.AddStoreCrl(GetCertificateRevocationLists());949 PkixCertPathBuilder pkixCertPathBuilder = new PkixCertPathBuilder();950 pkixCertPathBuilder.Build(pkixBuilderParameters);951 }952953 private Stream Envelope(CmsEnvelopedDataGenerator cms, EncryptionAlgorithm algorithm, Stream content, CancellationToken cancellationToken)954 {955 CmsProcessableInputStream content2 = new CmsProcessableInputStream(content);956 return new MemoryStream((algorithm switch957 {958 EncryptionAlgorithm.Aes128 => cms.Generate(content2, CmsEnvelopedGenerator.Aes128Cbc), 959 EncryptionAlgorithm.Aes192 => cms.Generate(content2, CmsEnvelopedGenerator.Aes192Cbc), 960 EncryptionAlgorithm.Aes256 => cms.Generate(content2, CmsEnvelopedGenerator.Aes256Cbc), 961 EncryptionAlgorithm.Blowfish => cms.Generate(content2, SecureMimeContext.Blowfish.Id), 962 EncryptionAlgorithm.Camellia128 => cms.Generate(content2, CmsEnvelopedGenerator.Camellia128Cbc), 963 EncryptionAlgorithm.Camellia192 => cms.Generate(content2, CmsEnvelopedGenerator.Camellia192Cbc), 964 EncryptionAlgorithm.Camellia256 => cms.Generate(content2, CmsEnvelopedGenerator.Camellia256Cbc), 965 EncryptionAlgorithm.Cast5 => cms.Generate(content2, "1.2.840.113533.7.66.10"), 966 EncryptionAlgorithm.Des => cms.Generate(content2, SmimeCapability.DesCbc.Id), 967 EncryptionAlgorithm.Idea => cms.Generate(content2, "1.3.6.1.4.1.188.7.1.1.2"), 968 EncryptionAlgorithm.RC240 => cms.Generate(content2, CmsEnvelopedGenerator.RC2Cbc, 40), 969 EncryptionAlgorithm.RC264 => cms.Generate(content2, CmsEnvelopedGenerator.RC2Cbc, 64), 970 EncryptionAlgorithm.RC2128 => cms.Generate(content2, CmsEnvelopedGenerator.RC2Cbc, 128), 971 EncryptionAlgorithm.Seed => cms.Generate(content2, CmsEnvelopedGenerator.SeedCbc), 972 EncryptionAlgorithm.TripleDes => cms.Generate(content2, CmsEnvelopedGenerator.DesEde3Cbc), 973 _ => throw new NotSupportedException($"The {algorithm} encryption algorithm is not supported by the {GetType().Name}."), 974 }).GetEncoded(), writable: false);975 }976977 private void AddCmsRecipients(CmsEnvelopedGenerator cms, CmsRecipientCollection recipients, CancellationToken cancellationToken)978 {979 HashSet<X509Certificate> hashSet = new HashSet<X509Certificate>();980 foreach (CmsRecipient recipient in recipients)981 {982 if (hashSet.Add(recipient.Certificate))983 {984 if (CheckCertificateRevocation)985 {986 ValidateRecipientCertificate(recipient.Certificate, cancellationToken);987 }988 AddRecipient(cms, recipient);989 }990 }991 }992993 private async Task AddCmsRecipientsAsync(CmsEnvelopedGenerator cms, CmsRecipientCollection recipients, CancellationToken cancellationToken)994 {995 HashSet<X509Certificate> unique = new HashSet<X509Certificate>();996 foreach (CmsRecipient recipient in recipients)997 {998 if (unique.Add(recipient.Certificate))999 {1000 if (CheckCertificateRevocation)1001 {1002 await ValidateRecipientCertificateAsync(recipient.Certificate, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);1003 }1004 AddRecipient(cms, recipient);1005 }1006 }1007 }10081009 private ApplicationPkcs7Mime Envelope(CmsRecipientCollection recipients, Stream content, CancellationToken cancellationToken)1010 {1011 EncryptionAlgorithm preferredEncryptionAlgorithm = GetPreferredEncryptionAlgorithm(recipients);1012 CmsEnvelopedDataGenerator cms = new CmsEnvelopedDataGenerator(RandomNumberGenerator);1013 AddCmsRecipients(cms, recipients, cancellationToken);1014 Stream stream = Envelope(cms, preferredEncryptionAlgorithm, content, cancellationToken);1015 return new ApplicationPkcs7Mime(SecureMimeType.EnvelopedData, stream);1016 }10171018 private async Task<ApplicationPkcs7Mime> EnvelopeAsync(CmsRecipientCollection recipients, Stream content, CancellationToken cancellationToken)1019 {1020 EncryptionAlgorithm algorithm = GetPreferredEncryptionAlgorithm(recipients);1021 MemoryBlockStream memory = null;1022 if ((!(content is MemoryBlockStream) && !(content is MemoryStream)) || 1 == 0)1023 {1024 memory = new MemoryBlockStream();1025 try1026 {1027 await content.CopyToAsync(memory, 4096, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);1028 memory.Position = 0L;1029 }1030 catch1031 {1032 memory.Dispose();1033 throw;1034 }1035 content = memory;1036 }1037 try1038 {1039 CmsEnvelopedDataGenerator cms = new CmsEnvelopedDataGenerator(RandomNumberGenerator);1040 await AddCmsRecipientsAsync(cms, recipients, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);1041 Stream stream = Envelope(cms, algorithm, content, cancellationToken);1042 return new ApplicationPkcs7Mime(SecureMimeType.EnvelopedData, stream);1043 }1044 finally1045 {1046 memory?.Dispose();1047 }1048 }10491050 public override ApplicationPkcs7Mime Encrypt(CmsRecipientCollection recipients, Stream content, CancellationToken cancellationToken = default(CancellationToken))1051 {1052 if (recipients == null)1053 {1054 throw new ArgumentNullException("recipients");1055 }1056 if (recipients.Count == 0)1057 {1058 throw new ArgumentException("No recipients specified.", "recipients");1059 }1060 if (content == null)1061 {1062 throw new ArgumentNullException("content");1063 }1064 return Envelope(recipients, content, cancellationToken);1065 }10661067 public override Task<ApplicationPkcs7Mime> EncryptAsync(CmsRecipientCollection recipients, Stream content, CancellationToken cancellationToken = default(CancellationToken))1068 {1069 if (recipients == null)1070 {1071 throw new ArgumentNullException("recipients");1072 }1073 if (recipients.Count == 0)1074 {1075 throw new ArgumentException("No recipients specified.", "recipients");1076 }1077 if (content == null)1078 {1079 throw new ArgumentNullException("content");1080 }1081 return EnvelopeAsync(recipients, content, cancellationToken);1082 }10831084 public override MimePart Encrypt(IEnumerable<MailboxAddress> recipients, Stream content, CancellationToken cancellationToken = default(CancellationToken))1085 {1086 if (recipients == null)1087 {1088 throw new ArgumentNullException("recipients");1089 }1090 if (content == null)1091 {1092 throw new ArgumentNullException("content");1093 }1094 return Encrypt(GetCmsRecipients(recipients), content, cancellationToken);1095 }10961097 public override async Task<MimePart> EncryptAsync(IEnumerable<MailboxAddress> recipients, Stream content, CancellationToken cancellationToken = default(CancellationToken))1098 {1099 if (recipients == null)1100 {1101 throw new ArgumentNullException("recipients");1102 }1103 if (content == null)1104 {1105 throw new ArgumentNullException("content");1106 }1107 return await EncryptAsync(GetCmsRecipients(recipients), content, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);1108 }11091110 private CmsTypedStream GetDecryptedContent(CmsEnvelopedDataParser parser)1111 {1112 RecipientInformationStore recipientInfos = parser.GetRecipientInfos();1113 foreach (RecipientInformation recipient in recipientInfos.GetRecipients())1114 {1115 AsymmetricKeyParameter privateKey;1116 if ((privateKey = GetPrivateKey(recipient.RecipientID)) != null)1117 {1118 return recipient.GetContentStream(privateKey);1119 }1120 }1121 throw new CmsException("A suitable private key could not be found for decrypting.");1122 }11231124 public override MimeEntity Decrypt(Stream encryptedData, CancellationToken cancellationToken = default(CancellationToken))1125 {1126 if (encryptedData == null)1127 {1128 throw new ArgumentNullException("encryptedData");1129 }1130 using CmsEnvelopedDataParser parser = new CmsEnvelopedDataParser(encryptedData);1131 CmsTypedStream decryptedContent = GetDecryptedContent(parser);1132 try1133 {1134 return MimeEntity.Load(decryptedContent.ContentStream, persistent: false, cancellationToken);1135 }1136 finally1137 {1138 decryptedContent.ContentStream.Dispose();1139 }1140 }11411142 public override async Task<MimeEntity> DecryptAsync(Stream encryptedData, CancellationToken cancellationToken = default(CancellationToken))1143 {1144 if (encryptedData == null)1145 {1146 throw new ArgumentNullException("encryptedData");1147 }1148 using CmsEnvelopedDataParser parser = new CmsEnvelopedDataParser(encryptedData);1149 CmsTypedStream decrypted = GetDecryptedContent(parser);1150 try1151 {1152 return await MimeEntity.LoadAsync(decrypted.ContentStream, persistent: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);1153 }1154 finally1155 {1156 decrypted.ContentStream.Dispose();1157 }1158 }11591160 public override void DecryptTo(Stream encryptedData, Stream decryptedData, CancellationToken cancellationToken = default(CancellationToken))1161 {1162 if (encryptedData == null)1163 {1164 throw new ArgumentNullException("encryptedData");1165 }1166 if (decryptedData == null)1167 {1168 throw new ArgumentNullException("decryptedData");1169 }1170 using CmsEnvelopedDataParser parser = new CmsEnvelopedDataParser(encryptedData);1171 CmsTypedStream decryptedContent = GetDecryptedContent(parser);1172 try1173 {1174 decryptedContent.ContentStream.CopyTo(decryptedData, 4096);1175 }1176 finally1177 {1178 decryptedContent.ContentStream.Dispose();1179 }1180 }11811182 public override async Task DecryptToAsync(Stream encryptedData, Stream decryptedData, CancellationToken cancellationToken = default(CancellationToken))1183 {1184 if (encryptedData == null)1185 {1186 throw new ArgumentNullException("encryptedData");1187 }1188 if (decryptedData == null)1189 {1190 throw new ArgumentNullException("decryptedData");1191 }1192 using CmsEnvelopedDataParser parser = new CmsEnvelopedDataParser(encryptedData);1193 CmsTypedStream decrypted = GetDecryptedContent(parser);1194 try1195 {1196 await decrypted.ContentStream.CopyToAsync(decryptedData, 4096, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);1197 }1198 finally1199 {1200 decrypted.ContentStream.Dispose();1201 }1202 }12031204 public override MimePart Export(IEnumerable<MailboxAddress> mailboxes, CancellationToken cancellationToken = default(CancellationToken))1205 {1206 if (mailboxes == null)1207 {1208 throw new ArgumentNullException("mailboxes");1209 }1210 X509CertificateStore x509CertificateStore = new X509CertificateStore();1211 int num = 0;1212 foreach (MailboxAddress mailbox in mailboxes)1213 {1214 CmsRecipient cmsRecipient = GetCmsRecipient(mailbox);1215 x509CertificateStore.Add(cmsRecipient.Certificate);1216 num++;1217 }1218 if (num == 0)1219 {1220 throw new ArgumentException("No mailboxes specified.", "mailboxes");1221 }1222 CmsSignedDataStreamGenerator cmsSignedDataStreamGenerator = new CmsSignedDataStreamGenerator(RandomNumberGenerator);1223 cmsSignedDataStreamGenerator.AddCertificates(x509CertificateStore);1224 MemoryBlockStream memoryBlockStream = new MemoryBlockStream();1225 cmsSignedDataStreamGenerator.Open(memoryBlockStream).Dispose();1226 memoryBlockStream.Position = 0L;1227 return new ApplicationPkcs7Mime(SecureMimeType.CertsOnly, memoryBlockStream);1228 }12291230 public override Task<MimePart> ExportAsync(IEnumerable<MailboxAddress> mailboxes, CancellationToken cancellationToken = default(CancellationToken))1231 {1232 return Task.FromResult(Export(mailboxes, cancellationToken));1233 }1234}1235