// 
// 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.util.Arrays;
import java.security.Signature;
import java.security.PrivateKey;
import java.io.OutputStream;
import org.bouncycastle.operator.DigestCalculatorProvider;
import java.io.IOException;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.sec.SECObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.jcajce.util.JcaJceHelper;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.operator.DigestCalculator;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.its.ITSCertificate;
import java.security.interfaces.ECPrivateKey;
import org.bouncycastle.its.operator.ITSContentSigner;

public class JcaITSContentSigner implements ITSContentSigner
{
    private final ECPrivateKey privateKey;
    private final ITSCertificate signerCert;
    private final AlgorithmIdentifier digestAlgo;
    private final DigestCalculator digest;
    private final byte[] parentData;
    private final ASN1ObjectIdentifier curveID;
    private final byte[] parentDigest;
    private final String signer;
    private final JcaJceHelper helper;
    
    private JcaITSContentSigner(final ECPrivateKey privateKey, final ITSCertificate signerCert, final JcaJceHelper jcaJceHelper) {
        this.privateKey = privateKey;
        this.signerCert = signerCert;
        this.helper = jcaJceHelper;
        this.curveID = ASN1ObjectIdentifier.getInstance(PrivateKeyInfo.getInstance(privateKey.getEncoded()).getPrivateKeyAlgorithm().getParameters());
        if (this.curveID.equals(SECObjectIdentifiers.secp256r1)) {
            this.digestAlgo = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256);
            this.signer = "SHA256withECDSA";
        }
        else if (this.curveID.equals(TeleTrusTObjectIdentifiers.brainpoolP256r1)) {
            this.digestAlgo = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256);
            this.signer = "SHA256withECDSA";
        }
        else {
            if (!this.curveID.equals(TeleTrusTObjectIdentifiers.brainpoolP384r1)) {
                throw new IllegalArgumentException("unknown key type");
            }
            this.digestAlgo = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha384);
            this.signer = "SHA384withECDSA";
        }
        DigestCalculatorProvider build;
        try {
            build = new JcaDigestCalculatorProviderBuilder().setHelper(jcaJceHelper).build();
        }
        catch (final Exception cause) {
            throw new IllegalStateException(cause.getMessage(), cause);
        }
        try {
            this.digest = build.get(this.digestAlgo);
        }
        catch (final OperatorCreationException cause2) {
            throw new IllegalStateException("cannot recognise digest type: " + this.digestAlgo.getAlgorithm(), cause2);
        }
        if (signerCert != null) {
            try {
                this.parentData = signerCert.getEncoded();
                final OutputStream outputStream = this.digest.getOutputStream();
                outputStream.write(this.parentData, 0, this.parentData.length);
                outputStream.close();
                this.parentDigest = this.digest.getDigest();
                return;
            }
            catch (final IOException ex) {
                throw new IllegalStateException("signer certificate encoding failed: " + ex.getMessage());
            }
        }
        this.parentData = null;
        this.parentDigest = this.digest.getDigest();
    }
    
    @Override
    public OutputStream getOutputStream() {
        return this.digest.getOutputStream();
    }
    
    @Override
    public byte[] getSignature() {
        final byte[] digest = this.digest.getDigest();
        try {
            final Signature signature = this.helper.createSignature(this.signer);
            signature.initSign(this.privateKey);
            signature.update(digest, 0, digest.length);
            signature.update(this.parentDigest, 0, this.parentDigest.length);
            return signature.sign();
        }
        catch (final Exception cause) {
            throw new RuntimeException(cause.getMessage(), cause);
        }
    }
    
    @Override
    public ITSCertificate getAssociatedCertificate() {
        return this.signerCert;
    }
    
    @Override
    public byte[] getAssociatedCertificateDigest() {
        return Arrays.clone(this.parentDigest);
    }
    
    @Override
    public AlgorithmIdentifier getDigestAlgorithm() {
        return this.digestAlgo;
    }
    
    @Override
    public ASN1ObjectIdentifier getCurveID() {
        return this.curveID;
    }
    
    @Override
    public boolean isForSelfSigning() {
        return this.parentData == null;
    }
    
    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 JcaITSContentSigner build(final PrivateKey privateKey) {
            return new JcaITSContentSigner((ECPrivateKey)privateKey, null, this.helper, null);
        }
        
        public JcaITSContentSigner build(final PrivateKey privateKey, final ITSCertificate itsCertificate) {
            return new JcaITSContentSigner((ECPrivateKey)privateKey, itsCertificate, this.helper, null);
        }
    }
}
