<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.0" />

CfbBlockCipherMac

public class CfbBlockCipherMac : IMac
using Org.BouncyCastle.Crypto.Paddings; using System; namespace Org.BouncyCastle.Crypto.Macs { public class CfbBlockCipherMac : IMac { private byte[] mac; private byte[] Buffer; private int bufOff; private MacCfbBlockCipher cipher; private IBlockCipherPadding padding; private int macSize; public string AlgorithmName => cipher.AlgorithmName; public CfbBlockCipherMac(IBlockCipher cipher) : this(cipher, 8, cipher.GetBlockSize() * 8 / 2, null) { } public CfbBlockCipherMac(IBlockCipher cipher, IBlockCipherPadding padding) : this(cipher, 8, cipher.GetBlockSize() * 8 / 2, padding) { } public CfbBlockCipherMac(IBlockCipher cipher, int cfbBitSize, int macSizeInBits) : this(cipher, cfbBitSize, macSizeInBits, null) { } public CfbBlockCipherMac(IBlockCipher cipher, int cfbBitSize, int macSizeInBits, IBlockCipherPadding padding) { if (macSizeInBits % 8 != 0) throw new ArgumentException("MAC size must be multiple of 8"); mac = new byte[cipher.GetBlockSize()]; this.cipher = new MacCfbBlockCipher(cipher, cfbBitSize); this.padding = padding; macSize = macSizeInBits / 8; Buffer = new byte[this.cipher.GetBlockSize()]; bufOff = 0; } public void Init(ICipherParameters parameters) { Reset(); cipher.Init(true, parameters); } public int GetMacSize() { return macSize; } public void Update(byte input) { if (bufOff == Buffer.Length) { cipher.ProcessBlock(Buffer, 0, mac, 0); bufOff = 0; } Buffer[bufOff++] = input; } public void BlockUpdate(byte[] input, int inOff, int len) { if (len < 0) throw new ArgumentException("Can't have a negative input length!"); BlockUpdate(input.AsSpan(inOff, len)); } public void BlockUpdate(ReadOnlySpan<byte> input) { int blockSize = cipher.GetBlockSize(); int num = 0; int num2 = blockSize - bufOff; if (input.Length > num2) { input.Slice(0, num2).CopyTo(Buffer.AsSpan(bufOff)); num += cipher.ProcessBlock(Buffer, mac); bufOff = 0; int num3 = num2; input = input.Slice(num3, input.Length - num3); while (input.Length > blockSize) { num += cipher.ProcessBlock(input, mac); num3 = blockSize; input = input.Slice(num3, input.Length - num3); } } input.CopyTo(Buffer.AsSpan(bufOff)); bufOff += input.Length; } public int DoFinal(byte[] output, int outOff) { return DoFinal(output.AsSpan(outOff)); } public int DoFinal(Span<byte> output) { int blockSize = cipher.GetBlockSize(); if (padding == null) { while (bufOff < blockSize) { Buffer[bufOff++] = 0; } } else padding.AddPadding(Buffer, bufOff); cipher.ProcessBlock(Buffer, 0, mac, 0); cipher.GetMacBlock(mac); mac.AsSpan(0, macSize).CopyTo(output); Reset(); return macSize; } public void Reset() { Array.Clear(Buffer, 0, Buffer.Length); bufOff = 0; cipher.Reset(); } } }