BlockCipher
Base class for block cipher implementations.
            
                using Org.BouncyCastle.Crypto.Paddings;
using Renci.SshNet.Common;
using Renci.SshNet.Security.Cryptography.Ciphers;
using Renci.SshNet.Security.Cryptography.Ciphers.Modes;
using System;
namespace Renci.SshNet.Security.Cryptography
{
    public abstract class BlockCipher : SymmetricCipher
    {
        private readonly CipherMode _mode;
        private readonly IBlockCipherPadding _padding;
        private readonly byte _blockSize;
        public override byte MinimumSize => BlockSize;
        public byte BlockSize => _blockSize;
        protected BlockCipher(byte[] key, byte blockSize, CipherMode mode, IBlockCipherPadding padding)
            : base(key)
        {
            _blockSize = blockSize;
            _mode = mode;
            _padding = padding;
            _mode?.Init(this);
        }
        public override byte[] Encrypt(byte[] input, int offset, int length)
        {
            int num = 0;
            if (_padding != null) {
                num = _blockSize - length % (int)_blockSize;
                input = input.Take(offset, length);
                Array.Resize(ref input, length + num);
                _padding.AddPadding(input, length);
                length += num;
                offset = 0;
            } else if (length % (int)_blockSize > 0) {
                CipherMode mode = _mode;
                if ((!(mode is CfbCipherMode) && !(mode is OfbCipherMode) && !(mode is CtrCipherMode)) || 1 == 0)
                    throw new ArgumentException($"""{GetType().Name}""", "data");
                num = _blockSize - length % (int)_blockSize;
                input = input.Take(offset, length);
                length += num;
                Array.Resize(ref input, length);
                offset = 0;
            }
            byte[] array = new byte[length];
            int num2 = 0;
            for (int i = 0; i < length / (int)_blockSize; i++) {
                num2 = ((_mode != null) ? (num2 + _mode.EncryptBlock(input, offset + i * _blockSize, _blockSize, array, i * _blockSize)) : (num2 + EncryptBlock(input, offset + i * _blockSize, _blockSize, array, i * _blockSize)));
            }
            if (num2 < length)
                throw new InvalidOperationException("Encryption error.");
            if (_padding == null && num > 0)
                Array.Resize(ref array, array.Length - num);
            return array;
        }
        public override byte[] Decrypt(byte[] input, int offset, int length)
        {
            int num = 0;
            if (length % (int)_blockSize > 0) {
                bool flag = _padding == null;
                if (flag) {
                    CipherMode mode = _mode;
                    bool flag2 = (mode is CfbCipherMode || mode is OfbCipherMode || mode is CtrCipherMode) ? true : false;
                    flag = flag2;
                }
                if (!flag)
                    throw new ArgumentException($"""{GetType().Name}""", "data");
                num = _blockSize - length % (int)_blockSize;
                input = input.Take(offset, length);
                length += num;
                Array.Resize(ref input, length);
                offset = 0;
            }
            byte[] array = new byte[length];
            int num2 = 0;
            for (int i = 0; i < length / (int)_blockSize; i++) {
                num2 = ((_mode != null) ? (num2 + _mode.DecryptBlock(input, offset + i * _blockSize, _blockSize, array, i * _blockSize)) : (num2 + DecryptBlock(input, offset + i * _blockSize, _blockSize, array, i * _blockSize)));
            }
            if (num2 < length)
                throw new InvalidOperationException("Encryption error.");
            if (_padding != null)
                num = _padding.PadCount(array);
            if (num > 0)
                Array.Resize(ref array, array.Length - num);
            return array;
        }
        public abstract int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
        public abstract int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
    }
}