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

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

import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import java.util.HashSet;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import java.io.IOException;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.pqc.crypto.mlkem.MLKEMPublicKeyParameters;
import java.security.PublicKey;
import org.bouncycastle.pqc.crypto.mlkem.MLKEMParameters;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.pqc.crypto.mlkem.MLKEMPrivateKeyParameters;
import java.security.PrivateKey;
import java.security.InvalidKeyException;
import java.security.spec.X509EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import org.bouncycastle.jcajce.spec.MLKEMPublicKeySpec;
import org.bouncycastle.jcajce.spec.MLKEMPrivateKeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.KeySpec;
import java.security.Key;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import java.util.Set;
import org.bouncycastle.pqc.jcajce.provider.util.BaseKeyFactorySpi;

public class MLKEMKeyFactorySpi extends BaseKeyFactorySpi
{
    private static final Set<ASN1ObjectIdentifier> keyOids;
    
    public MLKEMKeyFactorySpi() {
        super(MLKEMKeyFactorySpi.keyOids);
    }
    
    public MLKEMKeyFactorySpi(final ASN1ObjectIdentifier asn1ObjectIdentifier) {
        super(asn1ObjectIdentifier);
    }
    
    public final KeySpec engineGetKeySpec(final Key key, final Class obj) throws InvalidKeySpecException {
        if (key instanceof BCMLKEMPrivateKey) {
            if (PKCS8EncodedKeySpec.class.isAssignableFrom(obj)) {
                return new PKCS8EncodedKeySpec(key.getEncoded());
            }
            if (MLKEMPrivateKeySpec.class.isAssignableFrom(obj)) {
                final BCMLKEMPrivateKey bcmlkemPrivateKey = (BCMLKEMPrivateKey)key;
                final byte[] seed = bcmlkemPrivateKey.getSeed();
                if (seed != null) {
                    return new MLKEMPrivateKeySpec(bcmlkemPrivateKey.getParameterSpec(), seed);
                }
                return new MLKEMPrivateKeySpec(bcmlkemPrivateKey.getParameterSpec(), bcmlkemPrivateKey.getPrivateData(), bcmlkemPrivateKey.getPublicKey().getPublicData());
            }
            else if (MLKEMPublicKeySpec.class.isAssignableFrom(obj)) {
                final BCMLKEMPrivateKey bcmlkemPrivateKey2 = (BCMLKEMPrivateKey)key;
                return new MLKEMPublicKeySpec(bcmlkemPrivateKey2.getParameterSpec(), bcmlkemPrivateKey2.getPublicKey().getPublicData());
            }
        }
        else {
            if (!(key instanceof BCMLKEMPublicKey)) {
                throw new InvalidKeySpecException("Unsupported key type: " + key.getClass() + ".");
            }
            if (X509EncodedKeySpec.class.isAssignableFrom(obj)) {
                return new X509EncodedKeySpec(key.getEncoded());
            }
            if (MLKEMPublicKeySpec.class.isAssignableFrom(obj)) {
                final BCMLKEMPublicKey bcmlkemPublicKey = (BCMLKEMPublicKey)key;
                return new MLKEMPublicKeySpec(bcmlkemPublicKey.getParameterSpec(), bcmlkemPublicKey.getPublicData());
            }
        }
        throw new InvalidKeySpecException("unknown key specification: " + obj + ".");
    }
    
    public final Key engineTranslateKey(final Key key) throws InvalidKeyException {
        if (key instanceof BCMLKEMPrivateKey || key instanceof BCMLKEMPublicKey) {
            return key;
        }
        throw new InvalidKeyException("unsupported key type");
    }
    
    @Override
    public PrivateKey engineGeneratePrivate(final KeySpec keySpec) throws InvalidKeySpecException {
        if (keySpec instanceof MLKEMPrivateKeySpec) {
            final MLKEMPrivateKeySpec mlkemPrivateKeySpec = (MLKEMPrivateKeySpec)keySpec;
            final MLKEMParameters parameters = Utils.getParameters(mlkemPrivateKeySpec.getParameterSpec().getName());
            MLKEMPrivateKeyParameters mlkemPrivateKeyParameters;
            if (mlkemPrivateKeySpec.isSeed()) {
                mlkemPrivateKeyParameters = new MLKEMPrivateKeyParameters(parameters, mlkemPrivateKeySpec.getSeed());
            }
            else {
                mlkemPrivateKeyParameters = new MLKEMPrivateKeyParameters(parameters, mlkemPrivateKeySpec.getPrivateData());
                final byte[] publicData = mlkemPrivateKeySpec.getPublicData();
                if (publicData != null && !Arrays.constantTimeAreEqual(publicData, mlkemPrivateKeyParameters.getPublicKey())) {
                    throw new InvalidKeySpecException("public key data does not match private key data");
                }
            }
            return new BCMLKEMPrivateKey(mlkemPrivateKeyParameters);
        }
        return super.engineGeneratePrivate(keySpec);
    }
    
    @Override
    public PublicKey engineGeneratePublic(final KeySpec keySpec) throws InvalidKeySpecException {
        if (keySpec instanceof MLKEMPublicKeySpec) {
            final MLKEMPublicKeySpec mlkemPublicKeySpec = (MLKEMPublicKeySpec)keySpec;
            return new BCMLKEMPublicKey(new MLKEMPublicKeyParameters(Utils.getParameters(mlkemPublicKeySpec.getParameterSpec().getName()), mlkemPublicKeySpec.getPublicData()));
        }
        return super.engineGeneratePublic(keySpec);
    }
    
    @Override
    public PrivateKey generatePrivate(final PrivateKeyInfo privateKeyInfo) throws IOException {
        return new BCMLKEMPrivateKey(privateKeyInfo);
    }
    
    @Override
    public PublicKey generatePublic(final SubjectPublicKeyInfo subjectPublicKeyInfo) throws IOException {
        return new BCMLKEMPublicKey(subjectPublicKeyInfo);
    }
    
    static {
        (keyOids = new HashSet<ASN1ObjectIdentifier>()).add(NISTObjectIdentifiers.id_alg_ml_kem_512);
        MLKEMKeyFactorySpi.keyOids.add(NISTObjectIdentifiers.id_alg_ml_kem_768);
        MLKEMKeyFactorySpi.keyOids.add(NISTObjectIdentifiers.id_alg_ml_kem_1024);
    }
    
    public static class MLKEM1024 extends MLKEMKeyFactorySpi
    {
        public MLKEM1024() {
            super(NISTObjectIdentifiers.id_alg_ml_kem_1024);
        }
    }
    
    public static class MLKEM512 extends MLKEMKeyFactorySpi
    {
        public MLKEM512() {
            super(NISTObjectIdentifiers.id_alg_ml_kem_512);
        }
    }
    
    public static class MLKEM768 extends MLKEMKeyFactorySpi
    {
        public MLKEM768() {
            super(NISTObjectIdentifiers.id_alg_ml_kem_768);
        }
    }
}
