using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;

namespace NFC.Crypto
{
    public class AES : ICipher
    {
        public uint BlockSize { get; } = 16;

        public uint KeySize { get; } = 16;

        public byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
        {
            AesEngine engine = new AesEngine();
            CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
            BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher);
            KeyParameter keyParam = new KeyParameter(key);
            ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv);

            // Encrypt
            cipher.Init(true, keyParamWithIV);
            byte[] outputBytes = new byte[cipher.GetOutputSize(data.Length)];
            int length = cipher.ProcessBytes(data, outputBytes, 0);
            cipher.DoFinal(outputBytes, length);

            return outputBytes;
        }

        public byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
        {
            AesEngine engine = new AesEngine();
            CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
            BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher);
            KeyParameter keyParam = new KeyParameter(key);
            ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv);

            // Decrypt
            cipher.Init(false, keyParamWithIV);
            byte[] outputBytes = new byte[cipher.GetOutputSize(data.Length)];
            int length = cipher.ProcessBytes(data, outputBytes, 0);
            cipher.DoFinal(outputBytes, length);

            return outputBytes;
        }
    }
}