BcTlsMLKemDomain
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System;
namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
{
    public class BcTlsMLKemDomain : TlsKemDomain
    {
        protected readonly BcTlsCrypto m_crypto;
        protected readonly TlsKemConfig m_config;
        protected readonly MLKemParameters m_domainParameters;
        protected readonly bool m_isServer;
        public virtual bool IsServer => m_isServer;
        public static MLKemParameters GetDomainParameters(TlsKemConfig kemConfig)
        {
            switch (kemConfig.NamedGroup) {
            case 1298:
                return MLKemParameters.ml_kem_512;
            case 1896:
                return MLKemParameters.ml_kem_768;
            case 4132:
                return MLKemParameters.ml_kem_1024;
            default:
                throw new ArgumentException("No ML-KEM configuration provided", "kemConfig");
            }
        }
        public BcTlsMLKemDomain(BcTlsCrypto crypto, TlsKemConfig kemConfig)
        {
            m_crypto = crypto;
            m_config = kemConfig;
            m_domainParameters = GetDomainParameters(kemConfig);
            m_isServer = kemConfig.IsServer;
        }
        public virtual TlsAgreement CreateKem()
        {
            return new BcTlsMLKem(this);
        }
        public virtual BcTlsSecret Decapsulate(MLKemPrivateKeyParameters privateKey, byte[] ciphertext)
        {
            IKemDecapsulator decapsulator = KemUtilities.GetDecapsulator(m_domainParameters.Oid);
            decapsulator.Init(privateKey);
            byte[] data = KemUtilities.Decapsulate(decapsulator, ciphertext, 0, ciphertext.Length);
            return m_crypto.AdoptLocalSecret(data);
        }
        public virtual MLKemPublicKeyParameters DecodePublicKey(byte[] encoding)
        {
            return MLKemPublicKeyParameters.FromEncoding(m_domainParameters, encoding);
        }
        public virtual byte[] Encapsulate(MLKemPublicKeyParameters publicKey, out TlsSecret secret)
        {
            IKemEncapsulator encapsulator = KemUtilities.GetEncapsulator(m_domainParameters.Oid);
            encapsulator.Init(new ParametersWithRandom(publicKey, m_crypto.SecureRandom));
            Tuple<byte[], byte[]> tuple = KemUtilities.Encapsulate(encapsulator);
            secret = m_crypto.AdoptLocalSecret(tuple.Item2);
            return tuple.Item1;
        }
        public virtual byte[] EncodePublicKey(MLKemPublicKeyParameters publicKey)
        {
            return publicKey.GetEncoded();
        }
        public virtual AsymmetricCipherKeyPair GenerateKeyPair()
        {
            MLKemKeyPairGenerator mLKemKeyPairGenerator = new MLKemKeyPairGenerator();
            mLKemKeyPairGenerator.Init(new MLKemKeyGenerationParameters(m_crypto.SecureRandom, m_domainParameters));
            return mLKemKeyPairGenerator.GenerateKeyPair();
        }
    }
}