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

package org.bouncycastle.jcajce.provider.asymmetric.ec;

import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.asn1.x9.X9ECParameters;
import java.math.BigInteger;
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import java.security.KeyPair;
import org.bouncycastle.crypto.KeyGenerationParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import java.security.spec.ECGenParameterSpec;
import org.bouncycastle.jce.spec.ECParameterSpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.InvalidParameterException;
import org.bouncycastle.util.Integers;
import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import java.util.Hashtable;
import org.bouncycastle.jcajce.provider.config.ProviderConfiguration;
import java.security.SecureRandom;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import java.security.KeyPairGenerator;

public abstract class GMKeyPairGeneratorSpi extends KeyPairGenerator
{
    public GMKeyPairGeneratorSpi(final String algorithm) {
        super(algorithm);
    }
    
    public static class BaseSM2 extends GMKeyPairGeneratorSpi
    {
        ECKeyGenerationParameters param;
        ECKeyPairGenerator engine;
        Object ecParams;
        int strength;
        SecureRandom random;
        boolean initialised;
        String algorithm;
        ProviderConfiguration configuration;
        private static Hashtable ecParameters;
        
        public BaseSM2() {
            super("EC");
            this.engine = new ECKeyPairGenerator();
            this.ecParams = null;
            this.strength = 239;
            this.random = CryptoServicesRegistrar.getSecureRandom();
            this.initialised = false;
            this.algorithm = "EC";
            this.configuration = BouncyCastleProvider.CONFIGURATION;
        }
        
        public BaseSM2(final String algorithm, final ProviderConfiguration configuration) {
            super(algorithm);
            this.engine = new ECKeyPairGenerator();
            this.ecParams = null;
            this.strength = 239;
            this.random = CryptoServicesRegistrar.getSecureRandom();
            this.initialised = false;
            this.algorithm = algorithm;
            this.configuration = configuration;
        }
        
        @Override
        public void initialize(final int strength, final SecureRandom random) {
            this.strength = strength;
            this.random = random;
            final ECNamedCurveGenParameterSpec ecNamedCurveGenParameterSpec = BaseSM2.ecParameters.get(Integers.valueOf(strength));
            if (ecNamedCurveGenParameterSpec == null) {
                throw new InvalidParameterException("unknown key size.");
            }
            try {
                this.initialize(ecNamedCurveGenParameterSpec, random);
            }
            catch (final InvalidAlgorithmParameterException ex) {
                throw new InvalidParameterException("key size not configurable.");
            }
        }
        
        @Override
        public void initialize(final AlgorithmParameterSpec obj, final SecureRandom secureRandom) throws InvalidAlgorithmParameterException {
            if (obj == null) {
                final ECParameterSpec ecImplicitlyCa = this.configuration.getEcImplicitlyCa();
                if (ecImplicitlyCa == null) {
                    throw new InvalidAlgorithmParameterException("null parameter passed but no implicitCA set");
                }
                this.ecParams = null;
                this.param = this.createKeyGenParamsBC(ecImplicitlyCa, secureRandom);
            }
            else if (obj instanceof ECParameterSpec) {
                this.ecParams = obj;
                this.param = this.createKeyGenParamsBC((ECParameterSpec)obj, secureRandom);
            }
            else if (obj instanceof java.security.spec.ECParameterSpec) {
                this.ecParams = obj;
                this.param = this.createKeyGenParamsJCE((java.security.spec.ECParameterSpec)obj, secureRandom);
            }
            else if (obj instanceof ECGenParameterSpec) {
                this.initializeNamedCurve(((ECGenParameterSpec)obj).getName(), secureRandom);
            }
            else if (obj instanceof ECNamedCurveGenParameterSpec) {
                this.initializeNamedCurve(((ECNamedCurveGenParameterSpec)obj).getName(), secureRandom);
            }
            else {
                final String name = ECUtil.getNameFrom(obj);
                if (name == null) {
                    throw new InvalidAlgorithmParameterException("invalid parameterSpec: " + obj);
                }
                this.initializeNamedCurve(name, secureRandom);
            }
            this.engine.init(this.param);
            this.initialised = true;
        }
        
        @Override
        public KeyPair generateKeyPair() {
            if (!this.initialised) {
                this.initialize(this.strength, new SecureRandom());
            }
            final AsymmetricCipherKeyPair generateKeyPair = this.engine.generateKeyPair();
            final ECPublicKeyParameters ecPublicKeyParameters = (ECPublicKeyParameters)generateKeyPair.getPublic();
            final ECPrivateKeyParameters ecPrivateKeyParameters = (ECPrivateKeyParameters)generateKeyPair.getPrivate();
            if (this.ecParams instanceof ECParameterSpec) {
                final ECParameterSpec ecParameterSpec = (ECParameterSpec)this.ecParams;
                final BCECPublicKey publicKey = new BCECPublicKey(this.algorithm, ecPublicKeyParameters, ecParameterSpec, this.configuration);
                return new KeyPair(publicKey, new BCECPrivateKey(this.algorithm, ecPrivateKeyParameters, publicKey, ecParameterSpec, this.configuration));
            }
            if (this.ecParams == null) {
                return new KeyPair(new BCECPublicKey(this.algorithm, ecPublicKeyParameters, this.configuration), new BCECPrivateKey(this.algorithm, ecPrivateKeyParameters, this.configuration));
            }
            final java.security.spec.ECParameterSpec ecParameterSpec2 = (java.security.spec.ECParameterSpec)this.ecParams;
            final BCECPublicKey publicKey2 = new BCECPublicKey(this.algorithm, ecPublicKeyParameters, ecParameterSpec2, this.configuration);
            return new KeyPair(publicKey2, new BCECPrivateKey(this.algorithm, ecPrivateKeyParameters, publicKey2, ecParameterSpec2, this.configuration));
        }
        
        protected ECKeyGenerationParameters createKeyGenParamsBC(final ECParameterSpec ecParameterSpec, final SecureRandom secureRandom) {
            return new ECKeyGenerationParameters(new ECDomainParameters(ecParameterSpec.getCurve(), ecParameterSpec.getG(), ecParameterSpec.getN(), ecParameterSpec.getH()), secureRandom);
        }
        
        protected ECKeyGenerationParameters createKeyGenParamsJCE(final java.security.spec.ECParameterSpec ecParameterSpec, final SecureRandom secureRandom) {
            if (ecParameterSpec instanceof ECNamedCurveSpec) {
                final X9ECParameters domainParametersFromName = ECUtils.getDomainParametersFromName(((ECNamedCurveSpec)ecParameterSpec).getName(), this.configuration);
                if (null != domainParametersFromName) {
                    return this.createKeyGenParamsJCE(domainParametersFromName, secureRandom);
                }
            }
            final ECCurve convertCurve = EC5Util.convertCurve(ecParameterSpec.getCurve());
            return new ECKeyGenerationParameters(new ECDomainParameters(convertCurve, EC5Util.convertPoint(convertCurve, ecParameterSpec.getGenerator()), ecParameterSpec.getOrder(), BigInteger.valueOf(ecParameterSpec.getCofactor())), secureRandom);
        }
        
        protected ECKeyGenerationParameters createKeyGenParamsJCE(final X9ECParameters x9ECParameters, final SecureRandom secureRandom) {
            return new ECKeyGenerationParameters(new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN(), x9ECParameters.getH()), secureRandom);
        }
        
        protected void initializeNamedCurve(final String str, final SecureRandom secureRandom) throws InvalidAlgorithmParameterException {
            final X9ECParameters domainParametersFromName = ECUtils.getDomainParametersFromName(str, this.configuration);
            if (null == domainParametersFromName) {
                throw new InvalidAlgorithmParameterException("unknown curve name: " + str);
            }
            this.ecParams = new ECNamedCurveSpec(str, domainParametersFromName.getCurve(), domainParametersFromName.getG(), domainParametersFromName.getN(), domainParametersFromName.getH(), null);
            this.param = this.createKeyGenParamsJCE(domainParametersFromName, secureRandom);
        }
        
        static {
            (BaseSM2.ecParameters = new Hashtable()).put(Integers.valueOf(192), new ECNamedCurveGenParameterSpec("prime192v1"));
            BaseSM2.ecParameters.put(Integers.valueOf(239), new ECNamedCurveGenParameterSpec("prime239v1"));
            BaseSM2.ecParameters.put(Integers.valueOf(256), new ECNamedCurveGenParameterSpec("prime256v1"));
            BaseSM2.ecParameters.put(Integers.valueOf(224), new ECNamedCurveGenParameterSpec("P-224"));
            BaseSM2.ecParameters.put(Integers.valueOf(384), new ECNamedCurveGenParameterSpec("P-384"));
            BaseSM2.ecParameters.put(Integers.valueOf(521), new ECNamedCurveGenParameterSpec("P-521"));
        }
    }
    
    public static class SM2 extends BaseSM2
    {
        public SM2() {
            super("SM2", BouncyCastleProvider.CONFIGURATION);
        }
    }
}
