public virtual ISet FindCrls(X509CrlStoreSelector crlselect, PkixParameters paramsPkix, DateTime currentDate)
		{
			ISet initialSet = new HashSet();

			// get complete CRL(s)
			try
			{
				initialSet.AddAll(FindCrls(crlselect, paramsPkix.GetAdditionalStores()));
				initialSet.AddAll(FindCrls(crlselect, paramsPkix.GetStores()));
			}
			catch (Exception e)
			{
				throw new Exception("Exception obtaining complete CRLs.", e);
			}

			ISet finalSet = new HashSet();
			DateTime validityDate = currentDate;

			if (paramsPkix.Date != null)
			{
				validityDate = paramsPkix.Date.Value;
			}

			// based on RFC 5280 6.3.3
			foreach (X509Crl crl in initialSet)
			{
				if (crl.NextUpdate.Value.CompareTo(validityDate) > 0)
				{
					X509Certificate cert = crlselect.CertificateChecking;

					if (cert != null)
					{
						if (crl.ThisUpdate.CompareTo(cert.NotAfter) < 0)
						{
							finalSet.Add(crl);
						}
					}
					else
					{
						finalSet.Add(crl);
					}
				}
			}

			return finalSet;
		}
		/**
		 * Build and validate a CertPath using the given parameter.
		 *
		 * @param params PKIXBuilderParameters object containing all information to
		 *            build the CertPath
		 */
		public virtual PkixCertPathBuilderResult Build(
			PkixBuilderParameters pkixParams)
		{
			// search target certificates

			IX509Selector certSelect = pkixParams.GetTargetCertConstraints();
			if (!(certSelect is X509CertStoreSelector))
			{
				throw new PkixCertPathBuilderException(
					"TargetConstraints must be an instance of "
					+ typeof(X509CertStoreSelector).FullName + " for "
					+ this.GetType() + " class.");
			}

			ISet targets = new HashSet();
			try
			{
				targets.AddAll(PkixCertPathValidatorUtilities.FindCertificates((X509CertStoreSelector)certSelect, pkixParams.GetStores()));
				// TODO Should this include an entry for pkixParams.GetAdditionalStores() too?
			}
			catch (Exception e)
			{
				throw new PkixCertPathBuilderException(
					"Error finding target certificate.", e);
			}

			if (targets.IsEmpty)
				throw new PkixCertPathBuilderException("No certificate found matching targetContraints.");

			PkixCertPathBuilderResult result = null;
			IList certPathList = Platform.CreateArrayList();

			// check all potential target certificates
			foreach (X509Certificate cert in targets)
			{
				result = Build(cert, pkixParams, certPathList);

				if (result != null)
					break;
			}

			if (result == null && certPathException != null)
			{
				throw new PkixCertPathBuilderException(certPathException.Message, certPathException.InnerException);
			}

			if (result == null && certPathException == null)
			{
				throw new PkixCertPathBuilderException("Unable to find certificate chain.");
			}

			return result;
		}
		public virtual ISet FindCrls(X509CrlStoreSelector crlselect, PkixParameters paramsPkix)
		{
			ISet completeSet = new HashSet();

			// get complete CRL(s)
			try
			{
				completeSet.AddAll(FindCrls(crlselect, paramsPkix.GetStores()));
			}
			catch (Exception e)
			{
				throw new Exception("Exception obtaining complete CRLs.", e);
			}

			return completeSet;
		}
        /**
         * Returns the union of the excluded IP ranges in <code>excluded</code>
         * with <code>ip</code>.
         *
         * @param excluded A <code>Set</code> of excluded IP addresses with their
         *                 subnet mask as byte arrays.
         * @param ip       The IP address with its subnet mask.
         * @return The <code>Set</code> of excluded IP ranges unified with
         *         <code>ip</code> as byte arrays.
         */
        private ISet UnionIP(ISet excluded, byte[] ip)
        {
            if (excluded.IsEmpty)
            {
                if (ip == null)
                {
                    return excluded;
                }
                excluded.Add(ip);

                return excluded;
            }
            else
            {
                ISet union = new HashSet();

                IEnumerator it = excluded.GetEnumerator();
                while (it.MoveNext())
                {
                    byte[] _excluded = (byte[])it.Current;
                    union.AddAll(UnionIPRange(_excluded, ip));
                }

                return union;
            }
        }
 /**
  * Returns the intersection of the permitted IP ranges in
  * <code>permitted</code> with <code>ip</code>.
  *
  * @param permitted A <code>Set</code> of permitted IP addresses with
  *                  their subnet mask as byte arrays.
  * @param ips       The IP address with its subnet mask.
  * @return The <code>Set</code> of permitted IP ranges intersected with
  *         <code>ip</code>.
  */
 private ISet IntersectIP(ISet permitted, ISet ips)
 {
     ISet intersect = new HashSet();
     for (IEnumerator it = ips.GetEnumerator(); it.MoveNext(); )
     {
         byte[] ip = Asn1OctetString.GetInstance(
             ((GeneralSubtree)it.Current).Base.Name).GetOctets();
         if (permitted == null)
         {
             if (ip != null)
             {
                 intersect.Add(ip);
             }
         }
         else
         {
             IEnumerator it2 = permitted.GetEnumerator();
             while (it2.MoveNext())
             {
                 byte[] _permitted = (byte[])it2.Current;
                 intersect.AddAll(IntersectIPRange(_permitted, ip));
             }
         }
     }
     return intersect;
 }
		/**
		* Build and validate a CertPath using the given parameter.
		*
		* @param params PKIXBuilderParameters object containing all information to
		*            build the CertPath
		*/
		public virtual PkixCertPathBuilderResult Build(
			PkixBuilderParameters pkixParams)
		{
			// search target certificates

			IX509Selector certSelect = pkixParams.GetTargetConstraints();
			if (!(certSelect is X509AttrCertStoreSelector))
			{
				throw new PkixCertPathBuilderException(
					"TargetConstraints must be an instance of "
					+ typeof(X509AttrCertStoreSelector).FullName
					+ " for "
					+ typeof(PkixAttrCertPathBuilder).FullName + " class.");
			}

			ICollection targets;
			try
			{
				targets = PkixCertPathValidatorUtilities.FindCertificates(
					(X509AttrCertStoreSelector)certSelect, pkixParams.GetStores());
			}
			catch (Exception e)
			{
				throw new PkixCertPathBuilderException("Error finding target attribute certificate.", e);
			}

			if (targets.Count == 0)
			{
				throw new PkixCertPathBuilderException(
					"No attribute certificate found matching targetContraints.");
			}

			PkixCertPathBuilderResult result = null;

			// check all potential target certificates
			foreach (IX509AttributeCertificate cert in targets)
			{
				X509CertStoreSelector selector = new X509CertStoreSelector();
				X509Name[] principals = cert.Issuer.GetPrincipals();
				ISet issuers = new HashSet();
				for (int i = 0; i < principals.Length; i++)
				{
					try
					{
						selector.Subject = principals[i];

						issuers.AddAll(PkixCertPathValidatorUtilities.FindCertificates(selector, pkixParams.GetStores()));
					}
					catch (Exception e)
					{
						throw new PkixCertPathBuilderException(
							"Public key certificate for attribute certificate cannot be searched.",
							e);
					}
				}

				if (issuers.IsEmpty)
					throw new PkixCertPathBuilderException("Public key certificate for attribute certificate cannot be found.");

                IList certPathList = Platform.CreateArrayList();

				foreach (X509Certificate issuer in issuers)
				{
					result = Build(cert, issuer, pkixParams, certPathList);

					if (result != null)
						break;
				}

				if (result != null)
					break;
			}

			if (result == null && certPathException != null)
			{
				throw new PkixCertPathBuilderException(
					"Possible certificate chain could not be validated.",
					certPathException);
			}

			if (result == null && certPathException == null)
			{
				throw new PkixCertPathBuilderException(
					"Unable to find certificate chain.");
			}

			return result;
		}
		private PkixCertPathBuilderResult Build(
			IX509AttributeCertificate	attrCert,
			X509Certificate				tbvCert,
			PkixBuilderParameters		pkixParams,
			IList						tbvPath)
		{
			// If tbvCert is readily present in tbvPath, it indicates having run
			// into a cycle in the
			// PKI graph.
			if (tbvPath.Contains(tbvCert))
				return null;

			// step out, the certificate is not allowed to appear in a certification
			// chain
			if (pkixParams.GetExcludedCerts().Contains(tbvCert))
				return null;

			// test if certificate path exceeds maximum length
			if (pkixParams.MaxPathLength != -1)
			{
				if (tbvPath.Count - 1 > pkixParams.MaxPathLength)
					return null;
			}

			tbvPath.Add(tbvCert);

			PkixCertPathBuilderResult builderResult = null;

//			X509CertificateParser certParser = new X509CertificateParser();
			PkixAttrCertPathValidator validator = new PkixAttrCertPathValidator();

			try
			{
				// check whether the issuer of <tbvCert> is a TrustAnchor
				if (PkixCertPathValidatorUtilities.FindTrustAnchor(tbvCert, pkixParams.GetTrustAnchors()) != null)
				{
					PkixCertPath certPath = new PkixCertPath(tbvPath);
					PkixCertPathValidatorResult result;

					try
					{
						result = validator.Validate(certPath, pkixParams);
					}
					catch (Exception e)
					{
						throw new Exception("Certification path could not be validated.", e);
					}

					return new PkixCertPathBuilderResult(certPath, result.TrustAnchor,
						result.PolicyTree, result.SubjectPublicKey);
				}
				else
				{
					// add additional X.509 stores from locations in certificate
					try
					{
						PkixCertPathValidatorUtilities.AddAdditionalStoresFromAltNames(tbvCert, pkixParams);
					}
					catch (CertificateParsingException e)
					{
						throw new Exception("No additional X.509 stores can be added from certificate locations.", e);
					}

					// try to get the issuer certificate from one of the stores
					ISet issuers = new HashSet();
					try
					{
						issuers.AddAll(PkixCertPathValidatorUtilities.FindIssuerCerts(tbvCert, pkixParams));
					}
					catch (Exception e)
					{
						throw new Exception("Cannot find issuer certificate for certificate in certification path.", e);
					}

					if (issuers.IsEmpty)
						throw new Exception("No issuer certificate for certificate in certification path found.");

					foreach (X509Certificate issuer in issuers)
					{
						// if untrusted self signed certificate continue
						if (PkixCertPathValidatorUtilities.IsSelfIssued(issuer))
							continue;

						builderResult = Build(attrCert, issuer, pkixParams, tbvPath);

						if (builderResult != null)
							break;
					}
				}
			}
			catch (Exception e)
			{
				certPathException = new Exception("No valid certification path could be build.", e);
			}

			if (builderResult == null)
			{
				tbvPath.Remove(tbvCert);
			}

			return builderResult;
		}
		internal static ISet ProcessCrlA1i(
			DateTime		currentDate,
			PkixParameters	paramsPKIX,
			X509Certificate	cert,
			X509Crl			crl)
		{
			ISet deltaSet = new HashSet();
			if (paramsPKIX.IsUseDeltasEnabled)
			{
				CrlDistPoint freshestCRL = null;
				try
				{
					freshestCRL = CrlDistPoint.GetInstance(
						PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.FreshestCrl));
				}
				catch (Exception e)
				{
					throw new Exception("Freshest CRL extension could not be decoded from certificate.", e);
				}

				if (freshestCRL == null)
				{
					try
					{
						freshestCRL = CrlDistPoint.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(crl, X509Extensions.FreshestCrl));
					}
					catch (Exception e)
					{
						throw new Exception("Freshest CRL extension could not be decoded from CRL.", e);
					}
				}
				if (freshestCRL != null)
				{
					try
					{
						PkixCertPathValidatorUtilities.AddAdditionalStoresFromCrlDistributionPoint(freshestCRL, paramsPKIX);
					}
					catch (Exception e)
					{
						throw new Exception(
							"No new delta CRL locations could be added from Freshest CRL extension.", e);
					}
					// get delta CRL(s)
					try
					{
						deltaSet.AddAll(PkixCertPathValidatorUtilities.GetDeltaCrls(currentDate, paramsPKIX, crl));
					}
					catch (Exception e)
					{
						throw new Exception("Exception obtaining delta CRLs.", e);
					}
				}
			}
			return deltaSet;
		}
		internal static ISet[] ProcessCrlA1ii(
			DateTime		currentDate,
			PkixParameters	paramsPKIX,
			X509Certificate	cert,
			X509Crl			crl)
		{
			ISet deltaSet = new HashSet();
			X509CrlStoreSelector crlselect = new X509CrlStoreSelector();
			crlselect.CertificateChecking = cert;

			try
			{
				IList issuer = Platform.CreateArrayList();
				issuer.Add(crl.IssuerDN);
				crlselect.Issuers = issuer;
			}
			catch (IOException e)
			{
				throw new Exception("Cannot extract issuer from CRL." + e, e);
			}

			crlselect.CompleteCrlEnabled = true;
			ISet completeSet = CrlUtilities.FindCrls(crlselect, paramsPKIX, currentDate);

			if (paramsPKIX.IsUseDeltasEnabled)
			{
				// get delta CRL(s)
				try
				{
					deltaSet.AddAll(PkixCertPathValidatorUtilities.GetDeltaCrls(currentDate, paramsPKIX, crl));
				}
				catch (Exception e)
				{
					throw new Exception("Exception obtaining delta CRLs.", e);
				}
			}

			return new ISet[]{ completeSet, deltaSet };
		}
		/**
		* Searches for a holder public key certificate and verifies its
		* certification path.
		* 
		* @param attrCert the attribute certificate.
		* @param pkixParams The PKIX parameters.
		* @return The certificate path of the holder certificate.
		* @throws Exception if
		*             <ul>
		*             <li>no public key certificate can be found although holder
		*             information is given by an entity name or a base certificate
		*             ID</li>
		*             <li>support classes cannot be created</li>
		*             <li>no certification path for the public key certificate can
		*             be built</li>
		*             </ul>
		*/
		internal static PkixCertPath ProcessAttrCert1(
			IX509AttributeCertificate	attrCert,
			PkixParameters				pkixParams)
		{
			PkixCertPathBuilderResult result = null;
			// find holder PKCs
			ISet holderPKCs = new HashSet();
			if (attrCert.Holder.GetIssuer() != null)
			{
				X509CertStoreSelector selector = new X509CertStoreSelector();
				selector.SerialNumber = attrCert.Holder.SerialNumber;
				X509Name[] principals = attrCert.Holder.GetIssuer();
				for (int i = 0; i < principals.Length; i++)
				{
					try
					{
//						if (principals[i] is X500Principal)
						{
							selector.Issuer = principals[i];
						}
						holderPKCs.AddAll(PkixCertPathValidatorUtilities
							.FindCertificates(selector, pkixParams.GetStores()));
					}
					catch (Exception e)
					{
						throw new PkixCertPathValidatorException(
							"Public key certificate for attribute certificate cannot be searched.",
							e);
					}
				}
				if (holderPKCs.IsEmpty)
				{
					throw new PkixCertPathValidatorException(
						"Public key certificate specified in base certificate ID for attribute certificate cannot be found.");
				}
			}
			if (attrCert.Holder.GetEntityNames() != null)
			{
				X509CertStoreSelector selector = new X509CertStoreSelector();
				X509Name[] principals = attrCert.Holder.GetEntityNames();
				for (int i = 0; i < principals.Length; i++)
				{
					try
					{
//						if (principals[i] is X500Principal)
						{
							selector.Issuer = principals[i];
						}
						holderPKCs.AddAll(PkixCertPathValidatorUtilities
							.FindCertificates(selector, pkixParams.GetStores()));
					}
					catch (Exception e)
					{
						throw new PkixCertPathValidatorException(
							"Public key certificate for attribute certificate cannot be searched.",
							e);
					}
				}
				if (holderPKCs.IsEmpty)
				{
					throw new PkixCertPathValidatorException(
						"Public key certificate specified in entity name for attribute certificate cannot be found.");
				}
			}

			// verify cert paths for PKCs
			PkixBuilderParameters parameters = (PkixBuilderParameters)
				PkixBuilderParameters.GetInstance(pkixParams);

			PkixCertPathValidatorException lastException = null;
			foreach (X509Certificate cert in holderPKCs)
			{
				X509CertStoreSelector selector = new X509CertStoreSelector();
				selector.Certificate = cert;
				parameters.SetTargetConstraints(selector);

				PkixCertPathBuilder builder = new PkixCertPathBuilder();

				try
				{
					result = builder.Build(PkixBuilderParameters.GetInstance(parameters));
				}
				catch (PkixCertPathBuilderException e)
				{
					lastException = new PkixCertPathValidatorException(
						"Certification path for public key certificate of attribute certificate could not be build.",
						e);
				}
			}
			if (lastException != null)
			{
				throw lastException;
			}
			return result.CertPath;
		}
		/**
		* Find the issuer certificates of a given certificate.
		*
		* @param cert
		*            The certificate for which an issuer should be found.
		* @param pkixParams
		* @return A <code>Collection</code> object containing the issuer
		*         <code>X509Certificate</code>s. Never <code>null</code>.
		*
		* @exception Exception
		*                if an error occurs.
		*/
		internal static ICollection FindIssuerCerts(
			X509Certificate			cert,
			PkixBuilderParameters	pkixParams)
		{
			X509CertStoreSelector certSelect = new X509CertStoreSelector();
			ISet certs = new HashSet();
			try
			{
				certSelect.Subject = cert.IssuerDN;
			}
			catch (IOException ex)
			{
				throw new Exception(
					"Subject criteria for certificate selector to find issuer certificate could not be set.", ex);
			}

			try
			{
                certs.AddAll(PkixCertPathValidatorUtilities.FindCertificates(certSelect, pkixParams.GetStores()));
                certs.AddAll(PkixCertPathValidatorUtilities.FindCertificates(certSelect, pkixParams.GetAdditionalStores()));
			}
			catch (Exception e)
			{
				throw new Exception("Issuer certificate cannot be searched.", e);
			}

			return certs;
		}
		/// <summary>
		/// crl checking
		/// Return a Collection of all CRLs found in the X509Store's that are
		/// matching the crlSelect criteriums.
		/// </summary>
		/// <param name="crlSelect">a {@link X509CRLStoreSelector} object that will be used
		/// to select the CRLs</param>
		/// <param name="crlStores">a List containing only {@link org.bouncycastle.x509.X509Store
		/// X509Store} objects. These are used to search for CRLs</param>
		/// <returns>a Collection of all found {@link X509CRL X509CRL} objects. May be
		/// empty but never <code>null</code>.
		/// </returns>
		private ICollection FindCrls(X509CrlStoreSelector crlSelect, IList crlStores)
		{
			ISet crls = new HashSet();

			Exception lastException = null;
			bool foundValidStore = false;

			foreach (IX509Store store in crlStores)
			{
				try
				{
					crls.AddAll(store.GetMatches(crlSelect));
					foundValidStore = true;
				}
				catch (X509StoreException e)
				{
					lastException = new Exception("Exception searching in X.509 CRL store.", e);
				}
			}

	        if (!foundValidStore && lastException != null)
	            throw lastException;

			return crls;
		}