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);
}
}