<PackageReference Include="BouncyCastle.Cryptography" Version="2.7.0-beta.98" />

PaddedBufferedBlockCipher

using Org.BouncyCastle.Crypto.Modes; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; using System; namespace Org.BouncyCastle.Crypto.Paddings { public class PaddedBufferedBlockCipher : BufferedBlockCipher { private readonly IBlockCipherPadding m_padding; public PaddedBufferedBlockCipher(IBlockCipher cipher, IBlockCipherPadding padding) : this(EcbBlockCipher.GetBlockCipherMode(cipher), padding) { } public PaddedBufferedBlockCipher(IBlockCipherMode cipherMode, IBlockCipherPadding padding) : base(cipherMode) { m_padding = padding; } public PaddedBufferedBlockCipher(IBlockCipherMode cipherMode) : this(cipherMode, new Pkcs7Padding()) { } public override void Init(bool forEncryption, ICipherParameters parameters) { base.forEncryption = forEncryption; parameters = ParameterUtilities.GetRandom(parameters, out SecureRandom random); Reset(); m_padding.Init(random); m_cipherMode.Init(forEncryption, parameters); } public override int GetOutputSize(int length) { int num = bufOff + length; int num2 = buf.Length; if (!forEncryption) return BufferedCipherBase.GetFullBlocksSize(num + num2 - 1, num2); return BufferedCipherBase.GetFullBlocksSize(num, num2) + num2; } public override int GetUpdateOutputSize(int length) { return BufferedCipherBase.GetFullBlocksSize(bufOff + length - 1, buf.Length); } public override int ProcessByte(byte input, byte[] output, int outOff) { int result = 0; if (bufOff == buf.Length) { Check.OutputLength(output, outOff, buf.Length, "output buffer too short"); result = m_cipherMode.ProcessBlock(buf, 0, output, outOff); bufOff = 0; } buf[bufOff++] = input; return result; } public override int ProcessBytes(byte[] input, int inOff, int length, byte[] output, int outOff) { if (length < 1) { if (length < 0) throw new ArgumentException("Can't have a negative input length!"); return 0; } int num = 0; int num2 = buf.Length; int num3 = num2 - bufOff; if (length > num3) { int updateOutputSize = GetUpdateOutputSize(length); Check.OutputLength(output, outOff, updateOutputSize, "output buffer too short"); Array.Copy(input, inOff, buf, bufOff, num3); inOff += num3; length -= num3; if (output == input && Arrays.SegmentsOverlap(outOff, num2, inOff, length)) { input = new byte[length]; Array.Copy(output, inOff, input, 0, length); inOff = 0; } num = m_cipherMode.ProcessBlock(buf, 0, output, outOff); bufOff = 0; while (length > num2) { num += m_cipherMode.ProcessBlock(input, inOff, output, outOff + num); inOff += num2; length -= num2; } } Array.Copy(input, inOff, buf, bufOff, length); bufOff += length; return num; } public override int DoFinal(byte[] output, int outOff) { try { int num = 0; int num2 = buf.Length; if (forEncryption) { if (bufOff == num2) { Check.OutputLength(output, outOff, num2 * 2, "output buffer too short"); num = m_cipherMode.ProcessBlock(buf, 0, output, outOff); bufOff = 0; } else Check.OutputLength(output, outOff, num2, "output buffer too short"); m_padding.AddPadding(buf, bufOff); num += m_cipherMode.ProcessBlock(buf, 0, output, outOff + num); } else { Check.DataLength(bufOff != num2, "last block incomplete in decryption"); num = m_cipherMode.ProcessBlock(buf, 0, buf, 0); num -= m_padding.PadCount(buf); Check.OutputLength(output, outOff, num, "output buffer too short"); Array.Copy(buf, 0, output, outOff, num); } return num; } finally { Reset(); } } } }