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

package org.bouncycastle.jcajce;

import java.security.Security;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.pqc.crypto.util.SubjectPublicKeyInfoFactory;
import org.bouncycastle.pqc.crypto.util.PublicKeyFactory;
import org.bouncycastle.internal.asn1.iana.IANAObjectIdentifiers;
import java.io.IOException;
import org.bouncycastle.jcajce.provider.asymmetric.compositesignatures.KeyFactorySpi;
import org.bouncycastle.jcajce.provider.asymmetric.compositesignatures.CompositeIndex;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import java.util.Collections;
import java.util.ArrayList;
import org.bouncycastle.internal.asn1.misc.MiscObjectIdentifiers;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import java.security.Provider;
import java.util.List;
import java.security.PublicKey;

public class CompositePublicKey implements PublicKey
{
    private final List<PublicKey> keys;
    private final List<Provider> providers;
    private final AlgorithmIdentifier algorithmIdentifier;
    
    public static Builder builder(final ASN1ObjectIdentifier asn1ObjectIdentifier) {
        return new Builder(new AlgorithmIdentifier(asn1ObjectIdentifier));
    }
    
    public static Builder builder(final String s) {
        return builder(CompositeUtil.getOid(s));
    }
    
    public CompositePublicKey(final PublicKey... array) {
        this(MiscObjectIdentifiers.id_composite_key, array);
    }
    
    public CompositePublicKey(final ASN1ObjectIdentifier asn1ObjectIdentifier, final PublicKey... array) {
        this(new AlgorithmIdentifier(asn1ObjectIdentifier), array);
    }
    
    public CompositePublicKey(final AlgorithmIdentifier algorithmIdentifier, final PublicKey... array) {
        this.algorithmIdentifier = algorithmIdentifier;
        if (array == null || array.length == 0) {
            throw new IllegalArgumentException("at least one public key must be provided for the composite public key");
        }
        final ArrayList list = new ArrayList(array.length);
        for (int i = 0; i < array.length; ++i) {
            list.add(array[i]);
        }
        this.keys = (List<PublicKey>)Collections.unmodifiableList((List<?>)list);
        this.providers = null;
    }
    
    public CompositePublicKey(final SubjectPublicKeyInfo subjectPublicKeyInfo) {
        final ASN1ObjectIdentifier algorithm = subjectPublicKeyInfo.getAlgorithm().getAlgorithm();
        CompositePublicKey compositePublicKey;
        try {
            if (!CompositeIndex.isAlgorithmSupported(algorithm)) {
                throw new IllegalStateException("unable to create CompositePublicKey from SubjectPublicKeyInfo");
            }
            compositePublicKey = (CompositePublicKey)new KeyFactorySpi().generatePublic(subjectPublicKeyInfo);
            if (compositePublicKey == null) {
                throw new IllegalStateException("unable to create CompositePublicKey from SubjectPublicKeyInfo");
            }
        }
        catch (final IOException cause) {
            throw new IllegalStateException(cause.getMessage(), cause);
        }
        this.keys = compositePublicKey.getPublicKeys();
        this.algorithmIdentifier = compositePublicKey.getAlgorithmIdentifier();
        this.providers = null;
    }
    
    private CompositePublicKey(final AlgorithmIdentifier algorithmIdentifier, final PublicKey[] array, final Provider[] array2) {
        this.algorithmIdentifier = algorithmIdentifier;
        if (array.length != 2) {
            throw new IllegalArgumentException("two keys required for composite private key");
        }
        final ArrayList list = new ArrayList(array.length);
        if (array2 == null) {
            for (int i = 0; i < array.length; ++i) {
                list.add(array[i]);
            }
            this.providers = null;
        }
        else {
            final ArrayList list2 = new ArrayList(array2.length);
            for (int j = 0; j < array.length; ++j) {
                list2.add(array2[j]);
                list.add(array[j]);
            }
            this.providers = (List<Provider>)Collections.unmodifiableList((List<?>)list2);
        }
        this.keys = (List<PublicKey>)Collections.unmodifiableList((List<?>)list);
    }
    
    public List<PublicKey> getPublicKeys() {
        return this.keys;
    }
    
    public List<Provider> getProviders() {
        return this.providers;
    }
    
    @Override
    public String getAlgorithm() {
        return CompositeIndex.getAlgorithmName(this.algorithmIdentifier.getAlgorithm());
    }
    
    public AlgorithmIdentifier getAlgorithmIdentifier() {
        return this.algorithmIdentifier;
    }
    
    @Override
    public String getFormat() {
        return "X.509";
    }
    
    @Override
    public byte[] getEncoded() {
        if (this.algorithmIdentifier.getAlgorithm().on(IANAObjectIdentifiers.id_alg)) {
            try {
                return new SubjectPublicKeyInfo(this.getAlgorithmIdentifier(), Arrays.concatenate(SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(PublicKeyFactory.createKey(this.keys.get(0).getEncoded())).getPublicKeyData().getBytes(), org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(org.bouncycastle.crypto.util.PublicKeyFactory.createKey(this.keys.get(1).getEncoded())).getPublicKeyData().getBytes())).getEncoded();
            }
            catch (final IOException ex) {
                throw new IllegalStateException("unable to encode composite public key: " + ex.getMessage());
            }
        }
        final ASN1EncodableVector asn1EncodableVector = new ASN1EncodableVector();
        for (int i = 0; i < this.keys.size(); ++i) {
            if (this.algorithmIdentifier.getAlgorithm().equals(MiscObjectIdentifiers.id_composite_key)) {
                asn1EncodableVector.add(SubjectPublicKeyInfo.getInstance(this.keys.get(i).getEncoded()));
            }
            else {
                asn1EncodableVector.add(SubjectPublicKeyInfo.getInstance(this.keys.get(i).getEncoded()).getPublicKeyData());
            }
        }
        try {
            return new SubjectPublicKeyInfo(this.algorithmIdentifier, new DERSequence(asn1EncodableVector)).getEncoded("DER");
        }
        catch (final IOException ex2) {
            throw new IllegalStateException("unable to encode composite public key: " + ex2.getMessage());
        }
    }
    
    @Override
    public int hashCode() {
        return this.keys.hashCode();
    }
    
    @Override
    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        }
        if (o instanceof CompositePublicKey) {
            boolean b = true;
            final CompositePublicKey compositePublicKey = (CompositePublicKey)o;
            if (!compositePublicKey.getAlgorithmIdentifier().equals(this.algorithmIdentifier) || !this.keys.equals(compositePublicKey.keys)) {
                b = false;
            }
            return b;
        }
        return false;
    }
    
    public static class Builder
    {
        private final AlgorithmIdentifier algorithmIdentifier;
        private final PublicKey[] keys;
        private final Provider[] providers;
        private int count;
        
        private Builder(final AlgorithmIdentifier algorithmIdentifier) {
            this.keys = new PublicKey[2];
            this.providers = new Provider[2];
            this.count = 0;
            this.algorithmIdentifier = algorithmIdentifier;
        }
        
        public Builder addPublicKey(final PublicKey publicKey) {
            return this.addPublicKey(publicKey, (Provider)null);
        }
        
        public Builder addPublicKey(final PublicKey publicKey, final String name) {
            return this.addPublicKey(publicKey, Security.getProvider(name));
        }
        
        public Builder addPublicKey(final PublicKey publicKey, final Provider provider) {
            if (this.count == this.keys.length) {
                throw new IllegalStateException("only " + this.keys.length + " allowed in composite");
            }
            this.keys[this.count] = publicKey;
            this.providers[this.count++] = provider;
            return this;
        }
        
        public CompositePublicKey build() {
            if (this.providers[0] == null && this.providers[1] == null) {
                return new CompositePublicKey(this.algorithmIdentifier, this.keys, null, null);
            }
            return new CompositePublicKey(this.algorithmIdentifier, this.keys, this.providers, null);
        }
    }
}
