// 
// Decompiled by Procyon v0.6.0
// 

package org.bouncycastle.jcajce.provider.asymmetric.x509;

import org.bouncycastle.asn1.ASN1OctetString;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.security.cert.Certificate;
import java.util.Iterator;
import org.bouncycastle.asn1.util.ASN1Dump;
import org.bouncycastle.asn1.x509.CRLDistPoint;
import org.bouncycastle.asn1.x509.IssuingDistributionPoint;
import org.bouncycastle.asn1.x509.CRLNumber;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.util.Strings;
import org.bouncycastle.util.Arrays;
import java.util.Collections;
import java.security.cert.X509CRLEntry;
import java.math.BigInteger;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.asn1.x509.TBSCertList;
import org.bouncycastle.asn1.x509.Time;
import java.util.Date;
import javax.security.auth.x500.X500Principal;
import org.bouncycastle.jce.X509Principal;
import org.bouncycastle.asn1.x500.X500Name;
import java.security.Principal;
import java.io.OutputStream;
import java.io.BufferedOutputStream;
import org.bouncycastle.jcajce.io.OutputStreamFactory;
import java.util.List;
import java.io.IOException;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1BitString;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.jcajce.CompositePublicKey;
import java.security.Provider;
import java.security.SignatureException;
import java.security.InvalidKeyException;
import java.security.cert.CRLException;
import java.security.NoSuchProviderException;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.PublicKey;
import java.util.HashSet;
import java.util.Set;
import java.util.Enumeration;
import org.bouncycastle.asn1.x509.Extensions;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x509.CertificateList;
import org.bouncycastle.jcajce.util.JcaJceHelper;
import java.security.cert.X509CRL;

abstract class X509CRLImpl extends X509CRL
{
    protected JcaJceHelper bcHelper;
    protected CertificateList c;
    protected String sigAlgName;
    protected byte[] sigAlgParams;
    protected boolean isIndirect;
    
    X509CRLImpl(final JcaJceHelper bcHelper, final CertificateList c, final String sigAlgName, final byte[] sigAlgParams, final boolean isIndirect) {
        this.bcHelper = bcHelper;
        this.c = c;
        this.sigAlgName = sigAlgName;
        this.sigAlgParams = sigAlgParams;
        this.isIndirect = isIndirect;
    }
    
    @Override
    public boolean hasUnsupportedCriticalExtension() {
        if (this.getVersion() == 2) {
            final Extensions extensions = this.c.getExtensions();
            if (extensions != null) {
                final Enumeration oids = extensions.oids();
                while (oids.hasMoreElements()) {
                    final ASN1ObjectIdentifier asn1ObjectIdentifier = oids.nextElement();
                    if (!Extension.issuingDistributionPoint.equals(asn1ObjectIdentifier)) {
                        if (Extension.deltaCRLIndicator.equals(asn1ObjectIdentifier)) {
                            continue;
                        }
                        if (extensions.getExtension(asn1ObjectIdentifier).isCritical()) {
                            return true;
                        }
                        continue;
                    }
                }
            }
        }
        return false;
    }
    
    private Set getExtensionOIDs(final boolean b) {
        if (this.getVersion() == 2) {
            final Extensions extensions = this.c.getExtensions();
            if (extensions != null) {
                final HashSet set = new HashSet();
                final Enumeration oids = extensions.oids();
                while (oids.hasMoreElements()) {
                    final ASN1ObjectIdentifier asn1ObjectIdentifier = oids.nextElement();
                    if (b == extensions.getExtension(asn1ObjectIdentifier).isCritical()) {
                        set.add(asn1ObjectIdentifier.getId());
                    }
                }
                return set;
            }
        }
        return null;
    }
    
    @Override
    public Set getCriticalExtensionOIDs() {
        return this.getExtensionOIDs(true);
    }
    
    @Override
    public Set getNonCriticalExtensionOIDs() {
        return this.getExtensionOIDs(false);
    }
    
    @Override
    public byte[] getExtensionValue(final String s) {
        return X509SignatureUtil.getExtensionValue(this.c.getExtensions(), s);
    }
    
    @Override
    public void verify(final PublicKey publicKey) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException {
        this.doVerify(publicKey, new SignatureCreator() {
            @Override
            public Signature createSignature(final String algorithm) throws NoSuchAlgorithmException, NoSuchProviderException {
                try {
                    return X509CRLImpl.this.bcHelper.createSignature(algorithm);
                }
                catch (final Exception ex) {
                    return Signature.getInstance(algorithm);
                }
            }
        });
    }
    
    @Override
    public void verify(final PublicKey publicKey, final String s) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException {
        this.doVerify(publicKey, new SignatureCreator() {
            @Override
            public Signature createSignature(final String s) throws NoSuchAlgorithmException, NoSuchProviderException {
                if (s != null) {
                    return Signature.getInstance(s, s);
                }
                return Signature.getInstance(s);
            }
        });
    }
    
    @Override
    public void verify(final PublicKey publicKey, final Provider provider) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
        try {
            this.doVerify(publicKey, new SignatureCreator() {
                @Override
                public Signature createSignature(final String s) throws NoSuchAlgorithmException, NoSuchProviderException {
                    if (provider != null) {
                        return Signature.getInstance(X509CRLImpl.this.getSigAlgName(), provider);
                    }
                    return Signature.getInstance(X509CRLImpl.this.getSigAlgName());
                }
            });
        }
        catch (final NoSuchProviderException ex) {
            throw new NoSuchAlgorithmException("provider issue: " + ex.getMessage());
        }
    }
    
    private void doVerify(final PublicKey publicKey, final SignatureCreator signatureCreator) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, SignatureException, NoSuchProviderException {
        if (!this.c.getSignatureAlgorithm().equals(this.c.getTBSCertList().getSignature())) {
            throw new CRLException("Signature algorithm on CertificateList does not match TBSCertList.");
        }
        if (publicKey instanceof CompositePublicKey && X509SignatureUtil.isCompositeAlgorithm(this.c.getSignatureAlgorithm())) {
            final List<PublicKey> publicKeys = ((CompositePublicKey)publicKey).getPublicKeys();
            final ASN1Sequence instance = ASN1Sequence.getInstance(this.c.getSignatureAlgorithm().getParameters());
            final ASN1Sequence instance2 = ASN1Sequence.getInstance(this.c.getSignature().getOctets());
            boolean b = false;
            for (int i = 0; i != publicKeys.size(); ++i) {
                if (publicKeys.get(i) != null) {
                    final AlgorithmIdentifier instance3 = AlgorithmIdentifier.getInstance(instance.getObjectAt(i));
                    final Signature signature = signatureCreator.createSignature(X509SignatureUtil.getSignatureName(instance3));
                    SignatureException ex = null;
                    try {
                        this.checkSignature(publicKeys.get(i), signature, instance3.getParameters(), ASN1BitString.getInstance(instance2.getObjectAt(i)).getOctets());
                        b = true;
                    }
                    catch (final SignatureException ex2) {
                        ex = ex2;
                    }
                    if (ex != null) {
                        throw ex;
                    }
                }
            }
            if (!b) {
                throw new InvalidKeyException("no matching key found");
            }
        }
        else if (X509SignatureUtil.isCompositeAlgorithm(this.c.getSignatureAlgorithm())) {
            final ASN1Sequence instance4 = ASN1Sequence.getInstance(this.c.getSignatureAlgorithm().getParameters());
            final ASN1Sequence instance5 = ASN1Sequence.getInstance(this.c.getSignature().getOctets());
            boolean b2 = false;
            for (int j = 0; j != instance5.size(); ++j) {
                final AlgorithmIdentifier instance6 = AlgorithmIdentifier.getInstance(instance4.getObjectAt(j));
                final String signatureName = X509SignatureUtil.getSignatureName(instance6);
                SignatureException ex3 = null;
                try {
                    this.checkSignature(publicKey, signatureCreator.createSignature(signatureName), instance6.getParameters(), ASN1BitString.getInstance(instance5.getObjectAt(j)).getOctets());
                    b2 = true;
                }
                catch (final InvalidKeyException ex4) {}
                catch (final NoSuchAlgorithmException ex5) {}
                catch (final SignatureException ex6) {
                    ex3 = ex6;
                }
                if (ex3 != null) {
                    throw ex3;
                }
            }
            if (!b2) {
                throw new InvalidKeyException("no matching key found");
            }
        }
        else {
            final Signature signature2 = signatureCreator.createSignature(this.getSigAlgName());
            if (this.sigAlgParams == null) {
                this.checkSignature(publicKey, signature2, null, this.getSignature());
            }
            else {
                try {
                    this.checkSignature(publicKey, signature2, ASN1Primitive.fromByteArray(this.sigAlgParams), this.getSignature());
                }
                catch (final IOException ex7) {
                    throw new SignatureException("cannot decode signature parameters: " + ex7.getMessage());
                }
            }
        }
    }
    
    private void checkSignature(final PublicKey publicKey, final Signature signature, final ASN1Encodable asn1Encodable, final byte[] signature2) throws CRLException, InvalidKeyException, NoSuchAlgorithmException, SignatureException {
        if (!X509SignatureUtil.areEquivalentAlgorithms(this.c.getSignatureAlgorithm(), this.c.getTBSCertList().getSignature())) {
            throw new CRLException("Signature algorithm on CertificateList does not match TbsCertList.");
        }
        X509SignatureUtil.setSignatureParameters(signature, asn1Encodable);
        signature.initVerify(publicKey);
        try {
            final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(OutputStreamFactory.createStream(signature), 512);
            this.c.getTBSCertList().encodeTo(bufferedOutputStream, "DER");
            bufferedOutputStream.close();
        }
        catch (final IOException ex) {
            throw new CRLException(ex.toString());
        }
        if (!signature.verify(signature2)) {
            throw new SignatureException("CRL does not verify with supplied public key.");
        }
    }
    
    @Override
    public int getVersion() {
        return this.c.getVersionNumber();
    }
    
    @Override
    public Principal getIssuerDN() {
        return new X509Principal(X500Name.getInstance(this.c.getIssuer().toASN1Primitive()));
    }
    
    @Override
    public X500Principal getIssuerX500Principal() {
        try {
            return new X500Principal(this.c.getIssuer().getEncoded());
        }
        catch (final IOException ex) {
            throw new IllegalStateException("can't encode issuer DN");
        }
    }
    
    @Override
    public Date getThisUpdate() {
        return this.c.getThisUpdate().getDate();
    }
    
    @Override
    public Date getNextUpdate() {
        final Time nextUpdate = this.c.getNextUpdate();
        return (null == nextUpdate) ? null : nextUpdate.getDate();
    }
    
    private Set loadCRLEntries() {
        final HashSet set = new HashSet();
        final Enumeration revokedCertificateEnumeration = this.c.getRevokedCertificateEnumeration();
        X500Name instance = null;
        while (revokedCertificateEnumeration.hasMoreElements()) {
            final TBSCertList.CRLEntry crlEntry = revokedCertificateEnumeration.nextElement();
            set.add(new X509CRLEntryObject(crlEntry, this.isIndirect, instance));
            if (this.isIndirect && crlEntry.hasExtensions()) {
                final Extension extension = crlEntry.getExtensions().getExtension(Extension.certificateIssuer);
                if (extension == null) {
                    continue;
                }
                instance = X500Name.getInstance(GeneralNames.getInstance(extension.getParsedValue()).getNames()[0].getName());
            }
        }
        return set;
    }
    
    @Override
    public X509CRLEntry getRevokedCertificate(final BigInteger bigInteger) {
        final Enumeration revokedCertificateEnumeration = this.c.getRevokedCertificateEnumeration();
        X500Name instance = null;
        while (revokedCertificateEnumeration.hasMoreElements()) {
            final TBSCertList.CRLEntry crlEntry = revokedCertificateEnumeration.nextElement();
            if (crlEntry.getUserCertificate().hasValue(bigInteger)) {
                return new X509CRLEntryObject(crlEntry, this.isIndirect, instance);
            }
            if (!this.isIndirect || !crlEntry.hasExtensions()) {
                continue;
            }
            final Extension extension = crlEntry.getExtensions().getExtension(Extension.certificateIssuer);
            if (extension == null) {
                continue;
            }
            instance = X500Name.getInstance(GeneralNames.getInstance(extension.getParsedValue()).getNames()[0].getName());
        }
        return null;
    }
    
    @Override
    public Set getRevokedCertificates() {
        final Set loadCRLEntries = this.loadCRLEntries();
        if (!loadCRLEntries.isEmpty()) {
            return Collections.unmodifiableSet((Set<?>)loadCRLEntries);
        }
        return null;
    }
    
    @Override
    public byte[] getTBSCertList() throws CRLException {
        try {
            return this.c.getTBSCertList().getEncoded("DER");
        }
        catch (final IOException ex) {
            throw new CRLException(ex.toString());
        }
    }
    
    @Override
    public byte[] getSignature() {
        return this.c.getSignature().getOctets();
    }
    
    @Override
    public String getSigAlgName() {
        return this.sigAlgName;
    }
    
    @Override
    public String getSigAlgOID() {
        return this.c.getSignatureAlgorithm().getAlgorithm().getId();
    }
    
    @Override
    public byte[] getSigAlgParams() {
        return Arrays.clone(this.sigAlgParams);
    }
    
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        final String lineSeparator = Strings.lineSeparator();
        sb.append("              Version: ").append(this.getVersion()).append(lineSeparator);
        sb.append("             IssuerDN: ").append(this.getIssuerDN()).append(lineSeparator);
        sb.append("          This update: ").append(this.getThisUpdate()).append(lineSeparator);
        sb.append("          Next update: ").append(this.getNextUpdate()).append(lineSeparator);
        sb.append("  Signature Algorithm: ").append(this.getSigAlgName()).append(lineSeparator);
        X509SignatureUtil.prettyPrintSignature(this.getSignature(), sb, lineSeparator);
        final Extensions extensions = this.c.getExtensions();
        if (extensions != null) {
            final Enumeration oids = extensions.oids();
            if (oids.hasMoreElements()) {
                sb.append("           Extensions: ").append(lineSeparator);
            }
            while (oids.hasMoreElements()) {
                final ASN1ObjectIdentifier asn1ObjectIdentifier = oids.nextElement();
                final Extension extension = extensions.getExtension(asn1ObjectIdentifier);
                if (extension.getExtnValue() != null) {
                    final ASN1InputStream asn1InputStream = new ASN1InputStream(extension.getExtnValue().getOctets());
                    sb.append("                       critical(").append(extension.isCritical()).append(") ");
                    try {
                        if (asn1ObjectIdentifier.equals(Extension.cRLNumber)) {
                            sb.append(new CRLNumber(ASN1Integer.getInstance(asn1InputStream.readObject()).getPositiveValue())).append(lineSeparator);
                        }
                        else if (asn1ObjectIdentifier.equals(Extension.deltaCRLIndicator)) {
                            sb.append("Base CRL: " + new CRLNumber(ASN1Integer.getInstance(asn1InputStream.readObject()).getPositiveValue())).append(lineSeparator);
                        }
                        else if (asn1ObjectIdentifier.equals(Extension.issuingDistributionPoint)) {
                            sb.append(IssuingDistributionPoint.getInstance(asn1InputStream.readObject())).append(lineSeparator);
                        }
                        else if (asn1ObjectIdentifier.equals(Extension.cRLDistributionPoints)) {
                            sb.append(CRLDistPoint.getInstance(asn1InputStream.readObject())).append(lineSeparator);
                        }
                        else if (asn1ObjectIdentifier.equals(Extension.freshestCRL)) {
                            sb.append(CRLDistPoint.getInstance(asn1InputStream.readObject())).append(lineSeparator);
                        }
                        else {
                            sb.append(asn1ObjectIdentifier.getId());
                            sb.append(" value = ").append(ASN1Dump.dumpAsString(asn1InputStream.readObject())).append(lineSeparator);
                        }
                    }
                    catch (final Exception ex) {
                        sb.append(asn1ObjectIdentifier.getId());
                        sb.append(" value = ").append("*****").append(lineSeparator);
                    }
                }
                else {
                    sb.append(lineSeparator);
                }
            }
        }
        final Set revokedCertificates = this.getRevokedCertificates();
        if (revokedCertificates != null) {
            final Iterator iterator = revokedCertificates.iterator();
            while (iterator.hasNext()) {
                sb.append(iterator.next());
                sb.append(lineSeparator);
            }
        }
        return sb.toString();
    }
    
    @Override
    public boolean isRevoked(final Certificate certificate) {
        if (!certificate.getType().equals("X.509")) {
            throw new IllegalArgumentException("X.509 CRL used with non X.509 Cert");
        }
        final Enumeration revokedCertificateEnumeration = this.c.getRevokedCertificateEnumeration();
        X500Name x500Name = this.c.getIssuer();
        if (revokedCertificateEnumeration.hasMoreElements()) {
            final BigInteger serialNumber = ((X509Certificate)certificate).getSerialNumber();
            while (revokedCertificateEnumeration.hasMoreElements()) {
                final TBSCertList.CRLEntry instance = TBSCertList.CRLEntry.getInstance(revokedCertificateEnumeration.nextElement());
                if (this.isIndirect && instance.hasExtensions()) {
                    final Extension extension = instance.getExtensions().getExtension(Extension.certificateIssuer);
                    if (extension != null) {
                        x500Name = X500Name.getInstance(GeneralNames.getInstance(extension.getParsedValue()).getNames()[0].getName());
                    }
                }
                if (instance.getUserCertificate().hasValue(serialNumber)) {
                    X500Name x500Name2;
                    if (certificate instanceof X509Certificate) {
                        x500Name2 = X500Name.getInstance(((X509Certificate)certificate).getIssuerX500Principal().getEncoded());
                    }
                    else {
                        try {
                            x500Name2 = org.bouncycastle.asn1.x509.Certificate.getInstance(certificate.getEncoded()).getIssuer();
                        }
                        catch (final CertificateEncodingException ex) {
                            throw new IllegalArgumentException("Cannot process certificate: " + ex.getMessage());
                        }
                    }
                    return x500Name.equals(x500Name2);
                }
            }
        }
        return false;
    }
    
    static byte[] getExtensionOctets(final CertificateList list, final ASN1ObjectIdentifier asn1ObjectIdentifier) {
        final ASN1OctetString extensionValue = Extensions.getExtensionValue(list.getExtensions(), asn1ObjectIdentifier);
        return (byte[])((extensionValue == null) ? null : extensionValue.getOctets());
    }
}
