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

package org.bouncycastle.operator.jcajce;

import org.bouncycastle.operator.RawContentVerifier;
import java.security.SignatureException;
import org.bouncycastle.operator.RuntimeOperatorException;
import org.bouncycastle.asn1.ASN1BitString;
import org.bouncycastle.util.io.TeeOutputStream;
import org.bouncycastle.jcajce.io.OutputStreamFactory;
import java.io.OutputStream;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import java.util.List;
import org.bouncycastle.jcajce.CompositePublicKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.GeneralSecurityException;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.misc.MiscObjectIdentifiers;
import org.bouncycastle.operator.ContentVerifier;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import java.security.cert.CertificateEncodingException;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateException;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.ContentVerifierProvider;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.jcajce.util.NamedJcaJceHelper;
import org.bouncycastle.jcajce.util.ProviderJcaJceHelper;
import java.security.Provider;
import org.bouncycastle.jcajce.util.JcaJceHelper;
import org.bouncycastle.jcajce.util.DefaultJcaJceHelper;

public class JcaContentVerifierProviderBuilder
{
    private OperatorHelper helper;
    
    public JcaContentVerifierProviderBuilder() {
        this.helper = new OperatorHelper(new DefaultJcaJceHelper());
    }
    
    public JcaContentVerifierProviderBuilder setProvider(final Provider provider) {
        this.helper = new OperatorHelper(new ProviderJcaJceHelper(provider));
        return this;
    }
    
    public JcaContentVerifierProviderBuilder setProvider(final String s) {
        this.helper = new OperatorHelper(new NamedJcaJceHelper(s));
        return this;
    }
    
    public ContentVerifierProvider build(final X509CertificateHolder x509CertificateHolder) throws OperatorCreationException, CertificateException {
        return this.build(this.helper.convertCertificate(x509CertificateHolder));
    }
    
    public ContentVerifierProvider build(final X509Certificate x509Certificate) throws OperatorCreationException {
        JcaX509CertificateHolder jcaX509CertificateHolder;
        try {
            jcaX509CertificateHolder = new JcaX509CertificateHolder(x509Certificate);
        }
        catch (final CertificateEncodingException ex) {
            throw new OperatorCreationException("cannot process certificate: " + ex.getMessage(), ex);
        }
        return new ContentVerifierProvider() {
            @Override
            public boolean hasAssociatedCertificate() {
                return true;
            }
            
            @Override
            public X509CertificateHolder getAssociatedCertificate() {
                return jcaX509CertificateHolder;
            }
            
            @Override
            public ContentVerifier get(final AlgorithmIdentifier algorithmIdentifier) throws OperatorCreationException {
                if (algorithmIdentifier.getAlgorithm().equals(MiscObjectIdentifiers.id_alg_composite)) {
                    return JcaContentVerifierProviderBuilder.this.createCompositeVerifier(algorithmIdentifier, x509Certificate.getPublicKey());
                }
                Signature signature;
                try {
                    signature = JcaContentVerifierProviderBuilder.this.helper.createSignature(algorithmIdentifier);
                    signature.initVerify(x509Certificate.getPublicKey());
                }
                catch (final GeneralSecurityException obj) {
                    throw new OperatorCreationException("exception on setup: " + obj, obj);
                }
                final Signature access$200 = JcaContentVerifierProviderBuilder.this.createRawSig(algorithmIdentifier, x509Certificate.getPublicKey());
                if (access$200 != null) {
                    return new RawSigVerifier(algorithmIdentifier, signature, access$200);
                }
                return new SigVerifier(algorithmIdentifier, signature);
            }
        };
    }
    
    public ContentVerifierProvider build(final PublicKey publicKey) throws OperatorCreationException {
        return new ContentVerifierProvider() {
            @Override
            public boolean hasAssociatedCertificate() {
                return false;
            }
            
            @Override
            public X509CertificateHolder getAssociatedCertificate() {
                return null;
            }
            
            @Override
            public ContentVerifier get(final AlgorithmIdentifier algorithmIdentifier) throws OperatorCreationException {
                if (algorithmIdentifier.getAlgorithm().equals(MiscObjectIdentifiers.id_alg_composite)) {
                    return JcaContentVerifierProviderBuilder.this.createCompositeVerifier(algorithmIdentifier, publicKey);
                }
                if (publicKey instanceof CompositePublicKey && ((CompositePublicKey)publicKey).getAlgorithmIdentifier().getAlgorithm().equals(MiscObjectIdentifiers.id_composite_key)) {
                    final List<PublicKey> publicKeys = ((CompositePublicKey)publicKey).getPublicKeys();
                    int i = 0;
                    while (i != publicKeys.size()) {
                        try {
                            final Signature access$300 = JcaContentVerifierProviderBuilder.this.createSignature(algorithmIdentifier, publicKeys.get(i));
                            final Signature access$301 = JcaContentVerifierProviderBuilder.this.createRawSig(algorithmIdentifier, publicKeys.get(i));
                            if (access$301 != null) {
                                return new RawSigVerifier(algorithmIdentifier, access$300, access$301);
                            }
                            return new SigVerifier(algorithmIdentifier, access$300);
                        }
                        catch (final OperatorCreationException ex) {
                            ++i;
                            continue;
                        }
                        break;
                    }
                    throw new OperatorCreationException("no matching algorithm found for key");
                }
                final Signature access$302 = JcaContentVerifierProviderBuilder.this.createSignature(algorithmIdentifier, publicKey);
                final Signature access$303 = JcaContentVerifierProviderBuilder.this.createRawSig(algorithmIdentifier, publicKey);
                if (access$303 != null) {
                    return new RawSigVerifier(algorithmIdentifier, access$302, access$303);
                }
                return new SigVerifier(algorithmIdentifier, access$302);
            }
        };
    }
    
    public ContentVerifierProvider build(final SubjectPublicKeyInfo subjectPublicKeyInfo) throws OperatorCreationException {
        return this.build(this.helper.convertPublicKey(subjectPublicKeyInfo));
    }
    
    private ContentVerifier createCompositeVerifier(final AlgorithmIdentifier algorithmIdentifier, final PublicKey publicKey) throws OperatorCreationException {
        if (publicKey instanceof CompositePublicKey) {
            final List<PublicKey> publicKeys = ((CompositePublicKey)publicKey).getPublicKeys();
            final ASN1Sequence instance = ASN1Sequence.getInstance(algorithmIdentifier.getParameters());
            final Signature[] array = new Signature[instance.size()];
            for (int i = 0; i != instance.size(); ++i) {
                final AlgorithmIdentifier instance2 = AlgorithmIdentifier.getInstance(instance.getObjectAt(i));
                if (publicKeys.get(i) != null) {
                    array[i] = this.createSignature(instance2, publicKeys.get(i));
                }
                else {
                    array[i] = null;
                }
            }
            return new CompositeVerifier(array);
        }
        final ASN1Sequence instance3 = ASN1Sequence.getInstance(algorithmIdentifier.getParameters());
        final Signature[] array2 = new Signature[instance3.size()];
        for (int j = 0; j != instance3.size(); ++j) {
            final AlgorithmIdentifier instance4 = AlgorithmIdentifier.getInstance(instance3.getObjectAt(j));
            try {
                array2[j] = this.createSignature(instance4, publicKey);
            }
            catch (final Exception ex) {
                array2[j] = null;
            }
        }
        return new CompositeVerifier(array2);
    }
    
    private Signature createSignature(final AlgorithmIdentifier algorithmIdentifier, final PublicKey publicKey) throws OperatorCreationException {
        try {
            final Signature signature = this.helper.createSignature(algorithmIdentifier);
            signature.initVerify(publicKey);
            return signature;
        }
        catch (final GeneralSecurityException obj) {
            throw new OperatorCreationException("exception on setup: " + obj, obj);
        }
    }
    
    private Signature createRawSig(final AlgorithmIdentifier algorithmIdentifier, final PublicKey publicKey) {
        Signature rawSignature;
        try {
            rawSignature = this.helper.createRawSignature(algorithmIdentifier);
            if (rawSignature != null) {
                rawSignature.initVerify(publicKey);
            }
        }
        catch (final Exception ex) {
            rawSignature = null;
        }
        return rawSignature;
    }
    
    private static class CompositeVerifier implements ContentVerifier
    {
        private Signature[] sigs;
        private OutputStream stream;
        
        public CompositeVerifier(final Signature[] sigs) throws OperatorCreationException {
            this.sigs = sigs;
            int n;
            for (n = 0; n < sigs.length && sigs[n] == null; ++n) {}
            if (n == sigs.length) {
                throw new OperatorCreationException("no matching signature found in composite");
            }
            this.stream = OutputStreamFactory.createStream(sigs[n]);
            for (int i = n + 1; i != sigs.length; ++i) {
                if (sigs[i] != null) {
                    this.stream = new TeeOutputStream(this.stream, OutputStreamFactory.createStream(sigs[i]));
                }
            }
        }
        
        @Override
        public AlgorithmIdentifier getAlgorithmIdentifier() {
            return new AlgorithmIdentifier(MiscObjectIdentifiers.id_alg_composite);
        }
        
        @Override
        public OutputStream getOutputStream() {
            return this.stream;
        }
        
        @Override
        public boolean verify(final byte[] array) {
            try {
                final ASN1Sequence instance = ASN1Sequence.getInstance(array);
                boolean b = false;
                for (int i = 0; i != instance.size(); ++i) {
                    if (this.sigs[i] != null && !this.sigs[i].verify(ASN1BitString.getInstance(instance.getObjectAt(i)).getOctets())) {
                        b = true;
                    }
                }
                return !b;
            }
            catch (final SignatureException ex) {
                throw new RuntimeOperatorException("exception obtaining signature: " + ex.getMessage(), ex);
            }
        }
    }
    
    private static class RawSigVerifier extends SigVerifier implements RawContentVerifier
    {
        private Signature rawSignature;
        
        RawSigVerifier(final AlgorithmIdentifier algorithmIdentifier, final Signature signature, final Signature rawSignature) {
            super(algorithmIdentifier, signature);
            this.rawSignature = rawSignature;
        }
        
        @Override
        public boolean verify(final byte[] signature) {
            try {
                return super.verify(signature);
            }
            finally {
                try {
                    this.rawSignature.verify(signature);
                }
                catch (final Exception ex) {}
            }
        }
        
        @Override
        public boolean verify(final byte[] data, final byte[] array) {
            try {
                this.rawSignature.update(data);
                return this.rawSignature.verify(array);
            }
            catch (final SignatureException ex) {
                throw new RuntimeOperatorException("exception obtaining raw signature: " + ex.getMessage(), ex);
            }
            finally {
                try {
                    this.rawSignature.verify(array);
                }
                catch (final Exception ex2) {}
            }
        }
    }
    
    private static class SigVerifier implements ContentVerifier
    {
        private final AlgorithmIdentifier algorithm;
        private final Signature signature;
        protected final OutputStream stream;
        
        SigVerifier(final AlgorithmIdentifier algorithm, final Signature signature) {
            this.algorithm = algorithm;
            this.signature = signature;
            this.stream = OutputStreamFactory.createStream(signature);
        }
        
        @Override
        public AlgorithmIdentifier getAlgorithmIdentifier() {
            return this.algorithm;
        }
        
        @Override
        public OutputStream getOutputStream() {
            if (this.stream == null) {
                throw new IllegalStateException("verifier not initialised");
            }
            return this.stream;
        }
        
        @Override
        public boolean verify(final byte[] signature) {
            try {
                return this.signature.verify(signature);
            }
            catch (final SignatureException ex) {
                throw new RuntimeOperatorException("exception obtaining signature: " + ex.getMessage(), ex);
            }
        }
    }
}
