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

package org.bouncycastle.operator.jcajce;

import java.util.HashSet;
import org.bouncycastle.asn1.ASN1Integer;
import java.security.spec.MGF1ParameterSpec;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
import org.bouncycastle.asn1.pkcs.RSASSAPSSparams;
import java.util.List;
import java.io.IOException;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.util.io.TeeOutputStream;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.util.Strings;
import java.security.GeneralSecurityException;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.ExtendedContentSigner;
import java.security.SignatureException;
import org.bouncycastle.operator.RuntimeOperatorException;
import org.bouncycastle.jcajce.io.OutputStreamFactory;
import java.security.Signature;
import java.io.OutputStream;
import org.bouncycastle.jcajce.CompositePrivateKey;
import org.bouncycastle.operator.ContentSigner;
import java.security.PrivateKey;
import org.bouncycastle.jcajce.util.NamedJcaJceHelper;
import org.bouncycastle.jcajce.util.ProviderJcaJceHelper;
import java.security.Provider;
import org.bouncycastle.asn1.misc.MiscObjectIdentifiers;
import org.bouncycastle.jcajce.spec.CompositeAlgorithmSpec;
import org.bouncycastle.asn1.ASN1Encodable;
import java.security.spec.PSSParameterSpec;
import org.bouncycastle.jcajce.util.JcaJceHelper;
import org.bouncycastle.jcajce.util.DefaultJcaJceHelper;
import org.bouncycastle.pqc.crypto.lms.LMSigParameters;
import org.bouncycastle.util.Pack;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import java.security.PublicKey;
import java.security.spec.AlgorithmParameterSpec;
import java.security.SecureRandom;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
import java.util.Set;

public class JcaContentSignerBuilder
{
    private static final Set isAlgIdFromPrivate;
    private static final DefaultSignatureAlgorithmIdentifierFinder SIGNATURE_ALGORITHM_IDENTIFIER_FINDER;
    private final String signatureAlgorithm;
    private final AlgorithmIdentifier signatureDigestAlgorithm;
    private OperatorHelper helper;
    private SecureRandom random;
    private AlgorithmIdentifier sigAlgId;
    private AlgorithmParameterSpec sigAlgSpec;
    
    public JcaContentSignerBuilder(final String s) {
        this(s, (AlgorithmIdentifier)null);
    }
    
    private static AlgorithmIdentifier getSigDigAlgId(final PublicKey publicKey) {
        final SubjectPublicKeyInfo instance = SubjectPublicKeyInfo.getInstance(publicKey.getEncoded());
        if (instance.getAlgorithm().getAlgorithm().equals(PKCSObjectIdentifiers.id_alg_hss_lms_hashsig)) {
            return new AlgorithmIdentifier(LMSigParameters.getParametersForType(Pack.bigEndianToInt(instance.getPublicKeyData().getOctets(), 4)).getDigestOID());
        }
        return null;
    }
    
    public JcaContentSignerBuilder(final String s, final PublicKey publicKey) {
        this(s, getSigDigAlgId(publicKey));
    }
    
    public JcaContentSignerBuilder(final String signatureAlgorithm, final AlgorithmIdentifier signatureDigestAlgorithm) {
        this.helper = new OperatorHelper(new DefaultJcaJceHelper());
        this.signatureAlgorithm = signatureAlgorithm;
        this.signatureDigestAlgorithm = signatureDigestAlgorithm;
    }
    
    public JcaContentSignerBuilder(final String s, final AlgorithmParameterSpec algorithmParameterSpec) {
        this(s, algorithmParameterSpec, null);
    }
    
    public JcaContentSignerBuilder(final String signatureAlgorithm, final AlgorithmParameterSpec algorithmParameterSpec, final AlgorithmIdentifier signatureDigestAlgorithm) {
        this.helper = new OperatorHelper(new DefaultJcaJceHelper());
        this.signatureAlgorithm = signatureAlgorithm;
        this.signatureDigestAlgorithm = signatureDigestAlgorithm;
        if (algorithmParameterSpec instanceof PSSParameterSpec) {
            final PSSParameterSpec sigAlgSpec = (PSSParameterSpec)algorithmParameterSpec;
            this.sigAlgSpec = sigAlgSpec;
            this.sigAlgId = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_RSASSA_PSS, createPSSParams(sigAlgSpec));
        }
        else {
            if (!(algorithmParameterSpec instanceof CompositeAlgorithmSpec)) {
                throw new IllegalArgumentException("unknown sigParamSpec: " + ((algorithmParameterSpec == null) ? "null" : algorithmParameterSpec.getClass().getName()));
            }
            final CompositeAlgorithmSpec sigAlgSpec2 = (CompositeAlgorithmSpec)algorithmParameterSpec;
            this.sigAlgSpec = sigAlgSpec2;
            this.sigAlgId = new AlgorithmIdentifier(MiscObjectIdentifiers.id_alg_composite, createCompParams(sigAlgSpec2));
        }
    }
    
    public JcaContentSignerBuilder setProvider(final Provider provider) {
        this.helper = new OperatorHelper(new ProviderJcaJceHelper(provider));
        return this;
    }
    
    public JcaContentSignerBuilder setProvider(final String s) {
        this.helper = new OperatorHelper(new NamedJcaJceHelper(s));
        return this;
    }
    
    public JcaContentSignerBuilder setSecureRandom(final SecureRandom random) {
        this.random = random;
        return this;
    }
    
    public ContentSigner build(final PrivateKey privateKey) throws OperatorCreationException {
        if (privateKey instanceof CompositePrivateKey && ((CompositePrivateKey)privateKey).getAlgorithmIdentifier().getAlgorithm().equals(MiscObjectIdentifiers.id_composite_key)) {
            return this.buildComposite((CompositePrivateKey)privateKey);
        }
        try {
            if (this.sigAlgSpec == null) {
                this.sigAlgId = this.getSigAlgId(privateKey);
            }
            final AlgorithmIdentifier sigAlgId = this.sigAlgId;
            final Signature signature = this.helper.createSignature(this.sigAlgId);
            if (this.random != null) {
                signature.initSign(privateKey, this.random);
            }
            else {
                signature.initSign(privateKey);
            }
            final ContentSigner contentSigner = new ContentSigner() {
                private OutputStream stream = OutputStreamFactory.createStream(signature);
                
                @Override
                public AlgorithmIdentifier getAlgorithmIdentifier() {
                    return sigAlgId;
                }
                
                @Override
                public OutputStream getOutputStream() {
                    return this.stream;
                }
                
                @Override
                public byte[] getSignature() {
                    try {
                        return signature.sign();
                    }
                    catch (final SignatureException ex) {
                        throw new RuntimeOperatorException("exception obtaining signature: " + ex.getMessage(), ex);
                    }
                }
            };
            if (this.signatureDigestAlgorithm != null) {
                return new ExtendedContentSigner() {
                    private final AlgorithmIdentifier digestAlgorithm = JcaContentSignerBuilder.this.signatureDigestAlgorithm;
                    private final ContentSigner signer = contentSigner;
                    
                    @Override
                    public AlgorithmIdentifier getDigestAlgorithmIdentifier() {
                        return this.digestAlgorithm;
                    }
                    
                    @Override
                    public AlgorithmIdentifier getAlgorithmIdentifier() {
                        return this.signer.getAlgorithmIdentifier();
                    }
                    
                    @Override
                    public OutputStream getOutputStream() {
                        return this.signer.getOutputStream();
                    }
                    
                    @Override
                    public byte[] getSignature() {
                        return this.signer.getSignature();
                    }
                };
            }
            return contentSigner;
        }
        catch (final GeneralSecurityException ex) {
            throw new OperatorCreationException("cannot create signer: " + ex.getMessage(), ex);
        }
    }
    
    private AlgorithmIdentifier getSigAlgId(final PrivateKey privateKey) {
        if (!JcaContentSignerBuilder.isAlgIdFromPrivate.contains(Strings.toUpperCase(this.signatureAlgorithm))) {
            return JcaContentSignerBuilder.SIGNATURE_ALGORITHM_IDENTIFIER_FINDER.find(this.signatureAlgorithm);
        }
        final AlgorithmIdentifier find = JcaContentSignerBuilder.SIGNATURE_ALGORITHM_IDENTIFIER_FINDER.find(privateKey.getAlgorithm());
        if (find == null) {
            return PrivateKeyInfo.getInstance(privateKey.getEncoded()).getPrivateKeyAlgorithm();
        }
        return find;
    }
    
    private ContentSigner buildComposite(final CompositePrivateKey compositePrivateKey) throws OperatorCreationException {
        try {
            final List<PrivateKey> privateKeys = compositePrivateKey.getPrivateKeys();
            final ASN1Sequence instance = ASN1Sequence.getInstance(this.sigAlgId.getParameters());
            final Signature[] array = new Signature[instance.size()];
            for (int i = 0; i != instance.size(); ++i) {
                array[i] = this.helper.createSignature(AlgorithmIdentifier.getInstance(instance.getObjectAt(i)));
                if (this.random != null) {
                    array[i].initSign(privateKeys.get(i), this.random);
                }
                else {
                    array[i].initSign(privateKeys.get(i));
                }
            }
            OutputStream stream = OutputStreamFactory.createStream(array[0]);
            for (int j = 1; j != array.length; ++j) {
                stream = new TeeOutputStream(stream, OutputStreamFactory.createStream(array[j]));
            }
            return new ContentSigner() {
                OutputStream stream = stream;
                
                @Override
                public AlgorithmIdentifier getAlgorithmIdentifier() {
                    return JcaContentSignerBuilder.this.sigAlgId;
                }
                
                @Override
                public OutputStream getOutputStream() {
                    return this.stream;
                }
                
                @Override
                public byte[] getSignature() {
                    try {
                        final ASN1EncodableVector asn1EncodableVector = new ASN1EncodableVector();
                        for (int i = 0; i != array.length; ++i) {
                            asn1EncodableVector.add(new DERBitString(array[i].sign()));
                        }
                        return new DERSequence(asn1EncodableVector).getEncoded("DER");
                    }
                    catch (final IOException ex) {
                        throw new RuntimeOperatorException("exception encoding signature: " + ex.getMessage(), ex);
                    }
                    catch (final SignatureException ex2) {
                        throw new RuntimeOperatorException("exception obtaining signature: " + ex2.getMessage(), ex2);
                    }
                }
            };
        }
        catch (final GeneralSecurityException ex) {
            throw new OperatorCreationException("cannot create signer: " + ex.getMessage(), ex);
        }
    }
    
    private static RSASSAPSSparams createPSSParams(final PSSParameterSpec pssParameterSpec) {
        final DefaultDigestAlgorithmIdentifierFinder defaultDigestAlgorithmIdentifierFinder = new DefaultDigestAlgorithmIdentifierFinder();
        AlgorithmIdentifier find = defaultDigestAlgorithmIdentifierFinder.find(pssParameterSpec.getDigestAlgorithm());
        if (find.getParameters() == null) {
            find = new AlgorithmIdentifier(find.getAlgorithm(), DERNull.INSTANCE);
        }
        AlgorithmIdentifier find2 = defaultDigestAlgorithmIdentifierFinder.find(((MGF1ParameterSpec)pssParameterSpec.getMGFParameters()).getDigestAlgorithm());
        if (find2.getParameters() == null) {
            find2 = new AlgorithmIdentifier(find2.getAlgorithm(), DERNull.INSTANCE);
        }
        return new RSASSAPSSparams(find, new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, find2), new ASN1Integer(pssParameterSpec.getSaltLength()), new ASN1Integer(pssParameterSpec.getTrailerField()));
    }
    
    private static ASN1Sequence createCompParams(final CompositeAlgorithmSpec compositeAlgorithmSpec) {
        final DefaultSignatureAlgorithmIdentifierFinder defaultSignatureAlgorithmIdentifierFinder = new DefaultSignatureAlgorithmIdentifierFinder();
        final ASN1EncodableVector asn1EncodableVector = new ASN1EncodableVector();
        final List<String> algorithmNames = compositeAlgorithmSpec.getAlgorithmNames();
        final List<AlgorithmParameterSpec> parameterSpecs = compositeAlgorithmSpec.getParameterSpecs();
        for (int i = 0; i != algorithmNames.size(); ++i) {
            final AlgorithmParameterSpec algorithmParameterSpec = parameterSpecs.get(i);
            if (algorithmParameterSpec == null) {
                asn1EncodableVector.add(defaultSignatureAlgorithmIdentifierFinder.find((String)algorithmNames.get(i)));
            }
            else {
                if (!(algorithmParameterSpec instanceof PSSParameterSpec)) {
                    throw new IllegalArgumentException("unrecognized parameterSpec");
                }
                asn1EncodableVector.add(new AlgorithmIdentifier(PKCSObjectIdentifiers.id_RSASSA_PSS, createPSSParams((PSSParameterSpec)algorithmParameterSpec)));
            }
        }
        return new DERSequence(asn1EncodableVector);
    }
    
    static {
        isAlgIdFromPrivate = new HashSet();
        SIGNATURE_ALGORITHM_IDENTIFIER_FINDER = new DefaultSignatureAlgorithmIdentifierFinder();
        JcaContentSignerBuilder.isAlgIdFromPrivate.add("COMPOSITE");
        JcaContentSignerBuilder.isAlgIdFromPrivate.add("DILITHIUM");
        JcaContentSignerBuilder.isAlgIdFromPrivate.add("SPHINCS+");
        JcaContentSignerBuilder.isAlgIdFromPrivate.add("SPHINCSPlus");
        JcaContentSignerBuilder.isAlgIdFromPrivate.add("ML-DSA");
        JcaContentSignerBuilder.isAlgIdFromPrivate.add("SLH-DSA");
        JcaContentSignerBuilder.isAlgIdFromPrivate.add("HASH-ML-DSA");
        JcaContentSignerBuilder.isAlgIdFromPrivate.add("HASH-SLH-DSA");
    }
}
