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

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

import java.util.HashSet;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import java.io.IOException;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import java.security.PublicKey;
import org.bouncycastle.pqc.crypto.mldsa.MLDSAParameters;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.pqc.crypto.mldsa.MLDSAPublicKeyParameters;
import org.bouncycastle.pqc.crypto.mldsa.MLDSAPrivateKeyParameters;
import java.security.PrivateKey;
import java.security.InvalidKeyException;
import java.security.spec.X509EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import org.bouncycastle.jcajce.spec.MLDSAPublicKeySpec;
import org.bouncycastle.jcajce.spec.MLDSAPrivateKeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.KeySpec;
import java.security.Key;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import java.util.Set;
import org.bouncycastle.pqc.jcajce.provider.util.BaseKeyFactorySpi;

public class MLDSAKeyFactorySpi extends BaseKeyFactorySpi
{
    private static final Set<ASN1ObjectIdentifier> pureKeyOids;
    private static final Set<ASN1ObjectIdentifier> hashKeyOids;
    private final boolean isHashOnly;
    
    public MLDSAKeyFactorySpi(final Set<ASN1ObjectIdentifier> set) {
        super(set);
        this.isHashOnly = false;
    }
    
    public MLDSAKeyFactorySpi(final ASN1ObjectIdentifier asn1ObjectIdentifier) {
        super(asn1ObjectIdentifier);
        this.isHashOnly = (asn1ObjectIdentifier.equals(NISTObjectIdentifiers.id_hash_ml_dsa_44_with_sha512) || asn1ObjectIdentifier.equals(NISTObjectIdentifiers.id_hash_ml_dsa_65_with_sha512) || asn1ObjectIdentifier.equals(NISTObjectIdentifiers.id_hash_ml_dsa_87_with_sha512));
    }
    
    public final KeySpec engineGetKeySpec(final Key key, final Class obj) throws InvalidKeySpecException {
        if (key instanceof BCMLDSAPrivateKey) {
            if (PKCS8EncodedKeySpec.class.isAssignableFrom(obj)) {
                return new PKCS8EncodedKeySpec(key.getEncoded());
            }
            if (MLDSAPrivateKeySpec.class.isAssignableFrom(obj)) {
                final BCMLDSAPrivateKey bcmldsaPrivateKey = (BCMLDSAPrivateKey)key;
                final byte[] seed = bcmldsaPrivateKey.getSeed();
                if (seed != null) {
                    return new MLDSAPrivateKeySpec(bcmldsaPrivateKey.getParameterSpec(), seed);
                }
                return new MLDSAPrivateKeySpec(bcmldsaPrivateKey.getParameterSpec(), bcmldsaPrivateKey.getPrivateData(), bcmldsaPrivateKey.getPublicKey().getPublicData());
            }
            else if (MLDSAPublicKeySpec.class.isAssignableFrom(obj)) {
                final BCMLDSAPrivateKey bcmldsaPrivateKey2 = (BCMLDSAPrivateKey)key;
                return new MLDSAPublicKeySpec(bcmldsaPrivateKey2.getParameterSpec(), bcmldsaPrivateKey2.getPublicKey().getPublicData());
            }
        }
        else {
            if (!(key instanceof BCMLDSAPublicKey)) {
                throw new InvalidKeySpecException("unsupported key type: " + key.getClass() + ".");
            }
            if (X509EncodedKeySpec.class.isAssignableFrom(obj)) {
                return new X509EncodedKeySpec(key.getEncoded());
            }
            if (MLDSAPublicKeySpec.class.isAssignableFrom(obj)) {
                final BCMLDSAPublicKey bcmldsaPublicKey = (BCMLDSAPublicKey)key;
                return new MLDSAPublicKeySpec(bcmldsaPublicKey.getParameterSpec(), bcmldsaPublicKey.getPublicData());
            }
        }
        throw new InvalidKeySpecException("unknown key specification: " + obj + ".");
    }
    
    public final Key engineTranslateKey(final Key key) throws InvalidKeyException {
        if (key instanceof BCMLDSAPrivateKey || key instanceof BCMLDSAPublicKey) {
            return key;
        }
        throw new InvalidKeyException("unsupported key type");
    }
    
    @Override
    public PrivateKey engineGeneratePrivate(final KeySpec keySpec) throws InvalidKeySpecException {
        if (keySpec instanceof MLDSAPrivateKeySpec) {
            final MLDSAPrivateKeySpec mldsaPrivateKeySpec = (MLDSAPrivateKeySpec)keySpec;
            final MLDSAParameters parameters = Utils.getParameters(mldsaPrivateKeySpec.getParameterSpec().getName());
            MLDSAPrivateKeyParameters mldsaPrivateKeyParameters;
            if (mldsaPrivateKeySpec.isSeed()) {
                mldsaPrivateKeyParameters = new MLDSAPrivateKeyParameters(parameters, mldsaPrivateKeySpec.getSeed());
            }
            else {
                mldsaPrivateKeyParameters = new MLDSAPrivateKeyParameters(parameters, mldsaPrivateKeySpec.getPrivateData(), null);
                final byte[] publicData = mldsaPrivateKeySpec.getPublicData();
                if (publicData != null && !Arrays.constantTimeAreEqual(publicData, mldsaPrivateKeyParameters.getPublicKey())) {
                    throw new InvalidKeySpecException("public key data does not match private key data");
                }
            }
            return new BCMLDSAPrivateKey(mldsaPrivateKeyParameters);
        }
        return super.engineGeneratePrivate(keySpec);
    }
    
    @Override
    public PublicKey engineGeneratePublic(final KeySpec keySpec) throws InvalidKeySpecException {
        if (keySpec instanceof MLDSAPublicKeySpec) {
            final MLDSAPublicKeySpec mldsaPublicKeySpec = (MLDSAPublicKeySpec)keySpec;
            return new BCMLDSAPublicKey(new MLDSAPublicKeyParameters(Utils.getParameters(mldsaPublicKeySpec.getParameterSpec().getName()), mldsaPublicKeySpec.getPublicData()));
        }
        return super.engineGeneratePublic(keySpec);
    }
    
    @Override
    public PrivateKey generatePrivate(final PrivateKeyInfo privateKeyInfo) throws IOException {
        final BCMLDSAPrivateKey bcmldsaPrivateKey = new BCMLDSAPrivateKey(privateKeyInfo);
        if (!this.isHashOnly || bcmldsaPrivateKey.getAlgorithm().indexOf("WITH") > 0) {
            return bcmldsaPrivateKey;
        }
        final MLDSAPrivateKeyParameters keyParams = bcmldsaPrivateKey.getKeyParams();
        MLDSAParameters mldsaParameters;
        if (keyParams.getParameters().equals(MLDSAParameters.ml_dsa_44)) {
            mldsaParameters = MLDSAParameters.ml_dsa_44_with_sha512;
        }
        else if (keyParams.getParameters().equals(MLDSAParameters.ml_dsa_65)) {
            mldsaParameters = MLDSAParameters.ml_dsa_65_with_sha512;
        }
        else {
            if (!keyParams.getParameters().equals(MLDSAParameters.ml_dsa_87)) {
                throw new IllegalStateException("unknown ML-DSA parameters");
            }
            mldsaParameters = MLDSAParameters.ml_dsa_87_with_sha512;
        }
        return new BCMLDSAPrivateKey(new MLDSAPrivateKeyParameters(mldsaParameters, keyParams.getRho(), keyParams.getK(), keyParams.getTr(), keyParams.getS1(), keyParams.getS2(), keyParams.getT0(), keyParams.getT1(), keyParams.getSeed()));
    }
    
    @Override
    public PublicKey generatePublic(final SubjectPublicKeyInfo subjectPublicKeyInfo) throws IOException {
        return new BCMLDSAPublicKey(subjectPublicKeyInfo);
    }
    
    static {
        pureKeyOids = new HashSet<ASN1ObjectIdentifier>();
        hashKeyOids = new HashSet<ASN1ObjectIdentifier>();
        MLDSAKeyFactorySpi.pureKeyOids.add(NISTObjectIdentifiers.id_ml_dsa_44);
        MLDSAKeyFactorySpi.pureKeyOids.add(NISTObjectIdentifiers.id_ml_dsa_65);
        MLDSAKeyFactorySpi.pureKeyOids.add(NISTObjectIdentifiers.id_ml_dsa_87);
        MLDSAKeyFactorySpi.hashKeyOids.add(NISTObjectIdentifiers.id_ml_dsa_44);
        MLDSAKeyFactorySpi.hashKeyOids.add(NISTObjectIdentifiers.id_ml_dsa_65);
        MLDSAKeyFactorySpi.hashKeyOids.add(NISTObjectIdentifiers.id_ml_dsa_87);
        MLDSAKeyFactorySpi.hashKeyOids.add(NISTObjectIdentifiers.id_hash_ml_dsa_44_with_sha512);
        MLDSAKeyFactorySpi.hashKeyOids.add(NISTObjectIdentifiers.id_hash_ml_dsa_65_with_sha512);
        MLDSAKeyFactorySpi.hashKeyOids.add(NISTObjectIdentifiers.id_hash_ml_dsa_87_with_sha512);
    }
    
    public static class Hash extends MLDSAKeyFactorySpi
    {
        public Hash() {
            super(MLDSAKeyFactorySpi.hashKeyOids);
        }
    }
    
    public static class HashMLDSA44 extends MLDSAKeyFactorySpi
    {
        public HashMLDSA44() {
            super(NISTObjectIdentifiers.id_hash_ml_dsa_44_with_sha512);
        }
    }
    
    public static class HashMLDSA65 extends MLDSAKeyFactorySpi
    {
        public HashMLDSA65() {
            super(NISTObjectIdentifiers.id_hash_ml_dsa_65_with_sha512);
        }
    }
    
    public static class HashMLDSA87 extends MLDSAKeyFactorySpi
    {
        public HashMLDSA87() {
            super(NISTObjectIdentifiers.id_hash_ml_dsa_87_with_sha512);
        }
    }
    
    public static class MLDSA44 extends MLDSAKeyFactorySpi
    {
        public MLDSA44() {
            super(NISTObjectIdentifiers.id_ml_dsa_44);
        }
    }
    
    public static class MLDSA65 extends MLDSAKeyFactorySpi
    {
        public MLDSA65() {
            super(NISTObjectIdentifiers.id_ml_dsa_65);
        }
    }
    
    public static class MLDSA87 extends MLDSAKeyFactorySpi
    {
        public MLDSA87() {
            super(NISTObjectIdentifiers.id_ml_dsa_87);
        }
    }
    
    public static class Pure extends MLDSAKeyFactorySpi
    {
        public Pure() {
            super(MLDSAKeyFactorySpi.pureKeyOids);
        }
    }
}
