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

package org.bouncycastle.its.jcajce;

import org.bouncycastle.jcajce.util.NamedJcaJceHelper;
import org.bouncycastle.jcajce.util.ProviderJcaJceHelper;
import java.security.Provider;
import org.bouncycastle.jcajce.util.DefaultJcaJceHelper;
import org.bouncycastle.operator.DigestCalculatorProvider;
import org.bouncycastle.util.Arrays;
import java.security.PublicKey;
import java.security.Signature;
import org.bouncycastle.operator.DigestCalculator;
import java.io.OutputStream;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.oer.OEREncoder;
import org.bouncycastle.oer.its.template.ieee1609dot2.IEEE1609dot2;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.ContentVerifier;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.its.ITSPublicVerificationKey;
import org.bouncycastle.oer.its.ieee1609dot2.VerificationKeyIndicator;
import org.bouncycastle.oer.its.ieee1609dot2.basetypes.PublicVerificationKey;
import java.io.IOException;
import java.security.interfaces.ECPublicKey;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.jcajce.util.JcaJceHelper;
import org.bouncycastle.its.ITSCertificate;
import org.bouncycastle.its.operator.ITSContentVerifierProvider;

public class JcaITSContentVerifierProvider implements ITSContentVerifierProvider
{
    private final ITSCertificate issuer;
    private final byte[] parentData;
    private final JcaJceHelper helper;
    private AlgorithmIdentifier digestAlgo;
    private ECPublicKey pubParams;
    private int sigChoice;
    
    private JcaITSContentVerifierProvider(final ITSCertificate issuer, final JcaJceHelper helper) {
        this.issuer = issuer;
        this.helper = helper;
        try {
            this.parentData = issuer.getEncoded();
        }
        catch (final IOException ex) {
            throw new IllegalStateException("unable to extract parent data: " + ex.getMessage());
        }
        final VerificationKeyIndicator verifyKeyIndicator = issuer.toASN1Structure().getToBeSigned().getVerifyKeyIndicator();
        if (verifyKeyIndicator.getVerificationKeyIndicator() instanceof PublicVerificationKey) {
            this.initForPvi(PublicVerificationKey.getInstance(verifyKeyIndicator.getVerificationKeyIndicator()), helper);
            return;
        }
        throw new IllegalArgumentException("not public verification key");
    }
    
    private JcaITSContentVerifierProvider(final ITSPublicVerificationKey itsPublicVerificationKey, final JcaJceHelper helper) {
        this.issuer = null;
        this.parentData = null;
        this.helper = helper;
        this.initForPvi(itsPublicVerificationKey.toASN1Structure(), helper);
    }
    
    private void initForPvi(final PublicVerificationKey publicVerificationKey, final JcaJceHelper jcaJceHelper) {
        this.sigChoice = publicVerificationKey.getChoice();
        switch (publicVerificationKey.getChoice()) {
            case 0: {
                this.digestAlgo = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256);
                break;
            }
            case 1: {
                this.digestAlgo = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256);
                break;
            }
            case 2: {
                this.digestAlgo = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha384);
                break;
            }
            default: {
                throw new IllegalArgumentException("unknown key type");
            }
        }
        this.pubParams = (ECPublicKey)new JcaITSPublicVerificationKey(publicVerificationKey, jcaJceHelper).getKey();
    }
    
    @Override
    public boolean hasAssociatedCertificate() {
        return this.issuer != null;
    }
    
    @Override
    public ITSCertificate getAssociatedCertificate() {
        return this.issuer;
    }
    
    @Override
    public ContentVerifier get(final int i) throws OperatorCreationException {
        if (this.sigChoice != i) {
            throw new OperatorCreationException("wrong verifier for algorithm: " + i);
        }
        DigestCalculatorProvider build;
        try {
            build = new JcaDigestCalculatorProviderBuilder().setHelper(this.helper).build();
        }
        catch (final Exception cause) {
            throw new IllegalStateException(cause.getMessage(), cause);
        }
        final DigestCalculator value = build.get(this.digestAlgo);
        try {
            final OutputStream outputStream = value.getOutputStream();
            if (this.parentData != null) {
                outputStream.write(this.parentData, 0, this.parentData.length);
            }
            final byte[] digest = value.getDigest();
            byte[] digest2;
            if (this.issuer != null && this.issuer.getIssuer().isSelf()) {
                final byte[] byteArray = OEREncoder.toByteArray(this.issuer.toASN1Structure().getToBeSigned(), IEEE1609dot2.ToBeSignedCertificate.build());
                outputStream.write(byteArray, 0, byteArray.length);
                digest2 = value.getDigest();
            }
            else {
                digest2 = null;
            }
            Signature signature = null;
            switch (this.sigChoice) {
                case 0:
                case 1: {
                    signature = this.helper.createSignature("SHA256withECDSA");
                    break;
                }
                case 2: {
                    signature = this.helper.createSignature("SHA384withECDSA");
                    break;
                }
                default: {
                    throw new IllegalArgumentException("choice " + this.sigChoice + " not supported");
                }
            }
            return new ContentVerifier() {
                @Override
                public AlgorithmIdentifier getAlgorithmIdentifier() {
                    return null;
                }
                
                @Override
                public OutputStream getOutputStream() {
                    return outputStream;
                }
                
                @Override
                public boolean verify(final byte[] signature) {
                    final byte[] digest = value.getDigest();
                    try {
                        signature.initVerify(JcaITSContentVerifierProvider.this.pubParams);
                        signature.update(digest);
                        if (digest2 != null && Arrays.areEqual(digest, digest2)) {
                            signature.update(value.getDigest());
                        }
                        else {
                            signature.update(digest);
                        }
                        return signature.verify(signature);
                    }
                    catch (final Exception cause) {
                        throw new RuntimeException(cause.getMessage(), cause);
                    }
                }
            };
        }
        catch (final Exception cause2) {
            throw new IllegalStateException(cause2.getMessage(), cause2);
        }
    }
    
    public static class Builder
    {
        private JcaJceHelper helper;
        
        public Builder() {
            this.helper = new DefaultJcaJceHelper();
        }
        
        public Builder setProvider(final Provider provider) {
            this.helper = new ProviderJcaJceHelper(provider);
            return this;
        }
        
        public Builder setProvider(final String s) {
            this.helper = new NamedJcaJceHelper(s);
            return this;
        }
        
        public JcaITSContentVerifierProvider build(final ITSCertificate itsCertificate) {
            return new JcaITSContentVerifierProvider(itsCertificate, this.helper, null);
        }
        
        public JcaITSContentVerifierProvider build(final ITSPublicVerificationKey itsPublicVerificationKey) {
            return new JcaITSContentVerifierProvider(itsPublicVerificationKey, this.helper, null);
        }
    }
}
