/// <summary>
        /// Decrypts the given encrypted text with an AEAD encryption algorithm
        /// </summary>
        /// <param name="symmetricBlockAlgorithm">string SymmetricBlockAlgorithm enum, symmetric block algorithm name</param>
        /// <param name="symmetricBlockMode">string SymmetricBlockModes enum, symmetric block mode name</param>
        /// <param name="key">string Hexa key for the algorithm excecution</param>
        /// <param name="macSize">int macSize in bits for MAC length for AEAD Encryption algorithm</param>
        /// <param name="nonce">string Hexa nonce for MAC length for AEAD Encryption algorithm</param>
        /// <param name="encryptedInput">string Base64 text to decrypt</param>
        /// <returns></returns>
        public string DoAEADDecrypt(string symmetricBlockAlgorithm, string symmetricBlockMode,
                                    string key, int macSize, string nonce, string encryptedInput)
        {
            this.error.cleanError();
            SymmetricBlockAlgorithm algorithm = SymmetricBlockAlgorithmUtils.getSymmetricBlockAlgorithm(symmetricBlockAlgorithm, this.error);
            SymmetricBlockMode      mode      = SymmetricBlockModeUtils.getSymmetricBlockMode(symmetricBlockMode, this.error);

            if (this.error.existsError())
            {
                return("");
            }

            IBlockCipher     engine = getCipherEngine(algorithm);
            IAeadBlockCipher bbc    = getAEADCipherMode(engine, mode);

            if (this.error.existsError() && !(string.Compare(this.error.Code, "SB016", true) == 0))
            {
                return("");
            }
            byte[] nonceBytes = SecurityUtils.GetHexa(nonce, "SB025", this.error);
            byte[] keyBytes   = SecurityUtils.GetHexa(key, "SB025", this.error);
            if (this.HasError())
            {
                return("");
            }
            KeyParameter keyParam = new KeyParameter(keyBytes);

            AeadParameters AEADparams = new AeadParameters(keyParam, macSize, nonceBytes);

            try
            {
                bbc.Init(false, AEADparams);
            }catch (Exception e)
            {
                this.error.setError("SB030", e.Message);
                return("");
            }
            byte[] out2            = Base64.Decode(encryptedInput);
            byte[] comparisonBytes = new byte[bbc.GetOutputSize(out2.Length)];
            int    length          = bbc.ProcessBytes(out2, 0, out2.Length, comparisonBytes, 0);

            try
            {
                bbc.DoFinal(comparisonBytes, length);
            }
            catch (Exception)
            {
                this.error.setError("SB012", "AEAD decryption exception");
                return("");
            }
            this.error.cleanError();
            // return System.Text.Encoding.UTF8.GetString(comparisonBytes).Trim();
            EncodingUtil eu = new EncodingUtil();

            this.error = eu.GetError();

            return(eu.getString(comparisonBytes));
        }
        private bool isValidAlgorithm(string algorithm)
        {
            SymmetricBlockAlgorithm symmetricBlockAlgorithm = SymmetricBlockAlgorithmUtils.getSymmetricBlockAlgorithm(algorithm,
                                                                                                                      this.error);
            int blockSize = SymmetricBlockAlgorithmUtils.getBlockSize(symmetricBlockAlgorithm, this.error);

            if (this.HasError())
            {
                return(false);
            }
            if (blockSize != 64 && blockSize != 128)
            {
                return(false);
            }

            return(true);
        }
        /********EXTERNAL OBJECT PUBLIC METHODS  - BEGIN ********/



        /// <summary>
        /// Encrypts the given text with an AEAD encryption algorithm
        /// </summary>
        /// <param name="symmetricBlockAlgorithm">string SymmetricBlockAlgorithm enum, symmetric block algorithm name</param>
        /// <param name="symmetricBlockMode">string SymmetricBlockModes enum, symmetric block mode name</param>
        /// <param name="key">string Hexa key for the algorithm excecution</param>
        /// <param name="macSize">int macSize in bits for MAC length for AEAD Encryption algorithm</param>
        /// <param name="nonce">string Hexa nonce for MAC length for AEAD Encryption algorithm</param>
        /// <param name="plainText"> string UTF-8 plain text to encrypt</param>
        /// <returns></returns>
        public string DoAEADEncrypt(string symmetricBlockAlgorithm, string symmetricBlockMode,
                                    string key, int macSize, string nonce, string plainText)
        {
            this.error.cleanError();
            SymmetricBlockAlgorithm algorithm = SymmetricBlockAlgorithmUtils.getSymmetricBlockAlgorithm(symmetricBlockAlgorithm, this.error);
            SymmetricBlockMode      mode      = SymmetricBlockModeUtils.getSymmetricBlockMode(symmetricBlockMode, this.error);

            if (this.error.existsError())
            {
                return("");
            }

            IBlockCipher     engine = getCipherEngine(algorithm);
            IAeadBlockCipher bbc    = getAEADCipherMode(engine, mode);

            if (this.error.existsError() && !(string.Compare(this.error.Code, "SB016", true) == 0))
            {
                return("");
            }
            byte[] nonceBytes = SecurityUtils.GetHexa(nonce, "SB024", this.error);
            byte[] keyBytes   = SecurityUtils.GetHexa(key, "SB024", this.error);
            if (this.HasError())
            {
                return("");
            }

            KeyParameter keyParam = new KeyParameter(keyBytes);

            AeadParameters AEADparams = new AeadParameters(keyParam, macSize, nonceBytes);

            try
            {
                bbc.Init(true, AEADparams);
            }catch (Exception e)
            {
                this.error.setError("SB029", e.Message);
                return("");
            }
            EncodingUtil eu = new EncodingUtil();

            byte[] inputBytes = eu.getBytes(plainText);
            if (eu.GetError().existsError())
            {
                this.error = eu.GetError();
                return("");
            }
            byte[] outputBytes = new byte[bbc.GetOutputSize(inputBytes.Length)];
            int    length      = bbc.ProcessBytes(inputBytes, 0, inputBytes.Length, outputBytes, 0);

            try
            {
                bbc.DoFinal(outputBytes, length);
            }
            catch (Exception)
            {
                this.error.setError("SB010", "AEAD encryption exception");
                return("");
            }
            string result = Base64.ToBase64String(outputBytes);

            if (result == null || result.Length == 0)
            {
                this.error.setError("SB011", "Error encoding base64");
                return("");
            }
            this.error.cleanError();
            return(result);
        }
        public string DoDecrypt(string symmetricBlockAlgorithm, string symmetricBlockMode,
                                string symmetricBlockPadding, string key, string IV, string encryptedInput)
        {
            this.error.cleanError();
            SymmetricBlockAlgorithm algorithm = SymmetricBlockAlgorithmUtils.getSymmetricBlockAlgorithm(symmetricBlockAlgorithm, this.error);
            SymmetricBlockMode      mode      = SymmetricBlockModeUtils.getSymmetricBlockMode(symmetricBlockMode, this.error);
            SymmetricBlockPadding   padding   = SymmetricBlockPaddingUtils.getSymmetricBlockPadding(symmetricBlockPadding, this.error);

            if (this.error.existsError())
            {
                return("");
            }

            BufferedBlockCipher bbc = getCipher(algorithm, mode, padding);

            if (this.error.existsError() && !(string.Compare(this.error.Code, "SB016", true) == 0))
            {
                return("");
            }
            byte[] bytesKey = SecurityUtils.GetHexa(key, "SB023", this.error);
            byte[] bytesIV  = SecurityUtils.GetHexa(IV, "SB023", this.error);
            if (this.HasError())
            {
                return("");
            }

            KeyParameter keyParam = new KeyParameter(bytesKey);

            if (SymmetricBlockMode.ECB != mode && SymmetricBlockMode.OPENPGPCFB != mode)
            {
                ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, bytesIV);
                try
                {
                    bbc.Init(false, keyParamWithIV);
                }catch (Exception e)
                {
                    this.error.setError("SB027", e.Message);
                    return("");
                }
            }
            else
            {
                try
                {
                    bbc.Init(false, keyParam);
                }catch (Exception e)
                {
                    this.error.setError("SB028", e.Message);
                    return("");
                }
            }

            byte[] out2            = Base64.Decode(encryptedInput);
            byte[] comparisonBytes = new byte[bbc.GetOutputSize(out2.Length)];
            int    length          = bbc.ProcessBytes(out2, 0, out2.Length, comparisonBytes, 0);

            try
            {
                bbc.DoFinal(comparisonBytes, length);
            }
            catch (Exception)
            {
                this.error.setError("SB015", "Block decryption exception");
                return("");
            }
            this.error.cleanError();

            EncodingUtil eu = new EncodingUtil();

            this.error = eu.GetError();
            return(eu.getString(comparisonBytes));
        }
        public string DoEncrypt(string symmetricBlockAlgorithm, string symmetricBlockMode,
                                string symmetricBlockPadding, string key, string IV, string plainText)
        {
            this.error.cleanError();
            SymmetricBlockAlgorithm algorithm = SymmetricBlockAlgorithmUtils.getSymmetricBlockAlgorithm(symmetricBlockAlgorithm, this.error);
            SymmetricBlockMode      mode      = SymmetricBlockModeUtils.getSymmetricBlockMode(symmetricBlockMode, this.error);
            SymmetricBlockPadding   padding   = SymmetricBlockPaddingUtils.getSymmetricBlockPadding(symmetricBlockPadding, this.error);

            if (this.error.existsError())
            {
                return("");
            }

            BufferedBlockCipher bbc = getCipher(algorithm, mode, padding);

            if (this.error.existsError() && !(string.Compare(this.error.Code, "SB016", true) == 0))
            {
                return("");
            }
            byte[] byteIV  = SecurityUtils.GetHexa(IV, "SB022", this.error);
            byte[] byteKey = SecurityUtils.GetHexa(key, "SB022", this.error);
            if (this.HasError())
            {
                return("");
            }
            KeyParameter keyParam = new KeyParameter(byteKey);

            if (SymmetricBlockMode.ECB != mode && SymmetricBlockMode.OPENPGPCFB != mode)
            {
                ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, byteIV);
                try{
                    bbc.Init(true, keyParamWithIV);
                }catch (Exception e)
                {
                    this.error.setError("SB025", e.Message);
                    return("");
                }
            }
            else
            {
                try
                {
                    bbc.Init(true, keyParam);
                }catch (Exception e)
                {
                    this.error.setError("SB026", e.Message);
                    return("");
                }
            }

            EncodingUtil eu = new EncodingUtil();

            byte[] inputBytes = eu.getBytes(plainText);
            if (eu.GetError().existsError())
            {
                this.error = eu.GetError();
                return("");
            }
            byte[] outputBytes = new byte[bbc.GetOutputSize(inputBytes.Length)];
            int    length      = bbc.ProcessBytes(inputBytes, 0, inputBytes.Length, outputBytes, 0);

            try
            {
                bbc.DoFinal(outputBytes, length);
            }
            catch (Exception)
            {
                this.error.setError("SB013", "Block encryption exception");
                return("");
            }
            string result = Base64.ToBase64String(outputBytes);

            if (result == null || result.Length == 0)
            {
                this.error.setError("SB014", "Error encoding base64");
                return("");
            }
            this.error.cleanError();
            return(result);
        }
        public string calculate(string plainText, string key, string algorithm, int macSize)
        {
            if (!isValidAlgorithm(algorithm))
            {
                this.error.setError("CM001", "Invalid Symmetric block algorithm for CMAC");
                return("");
            }
            SymmetricBlockAlgorithm symmetricBlockAlgorithm = SymmetricBlockAlgorithmUtils.getSymmetricBlockAlgorithm(algorithm,
                                                                                                                      this.error);
            SymmetricBlockCipher symCipher   = new SymmetricBlockCipher();
            IBlockCipher         blockCipher = symCipher.getCipherEngine(symmetricBlockAlgorithm);

            if (symCipher.HasError())
            {
                this.error = symCipher.GetError();
                return("");
            }
            if (macSize > blockCipher.GetBlockSize() * 8)
            {
                this.error.setError("CM002", "The mac length must be less or equal than the algorithm block size.");
                return("");
            }
            byte[] byteKey = SecurityUtils.GetHexa(key, "CM003", this.error);
            if (this.HasError())
            {
                return("");
            }

            EncodingUtil eu = new EncodingUtil();

            byte[] byteInput = eu.getBytes(plainText);

            ICipherParameters parms = new KeyParameter(byteKey);

            CMac mac = null;

            if (macSize != 0)
            {
                mac = new CMac(blockCipher, macSize);
            }
            else
            {
                mac = new CMac(blockCipher);
            }
            try
            {
                mac.Init(parms);
            }catch (Exception e)
            {
                this.error.setError("CM004", e.Message);
                return("");
            }
            byte[] resBytes = new byte[mac.GetMacSize()];
            mac.BlockUpdate(byteInput, 0, byteInput.Length);
            mac.DoFinal(resBytes, 0);
            string result = toHexastring(resBytes);

            if (!this.error.existsError())
            {
                return(result);
            }
            return("");
        }