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

SicBlockCipher

using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Utilities; using System; namespace Org.BouncyCastle.Crypto.Modes { public class SicBlockCipher : IBlockCipherMode, IBlockCipher { private readonly IBlockCipher cipher; private readonly int blockSize; private readonly byte[] counter; private readonly byte[] counterOut; private byte[] IV; public IBlockCipher UnderlyingCipher => cipher; public virtual string AlgorithmName => cipher.AlgorithmName + "/SIC"; public virtual bool IsPartialBlockOkay => true; public SicBlockCipher(IBlockCipher cipher) { this.cipher = cipher; blockSize = cipher.GetBlockSize(); counter = new byte[blockSize]; counterOut = new byte[blockSize]; IV = new byte[blockSize]; } public virtual void Init(bool forEncryption, ICipherParameters parameters) { ParametersWithIV parametersWithIV = parameters as ParametersWithIV; if (parametersWithIV == null) throw new ArgumentException("CTR/SIC mode requires ParametersWithIV", "parameters"); IV = Arrays.Clone(parametersWithIV.GetIV()); if (blockSize < IV.Length) throw new ArgumentException("CTR/SIC mode requires IV no greater than: " + blockSize.ToString() + " bytes."); int num = System.Math.Min(8, blockSize / 2); if (blockSize - IV.Length > num) throw new ArgumentException("CTR/SIC mode requires IV of at least: " + (blockSize - num).ToString() + " bytes."); Reset(); if (parametersWithIV.Parameters != null) cipher.Init(true, parametersWithIV.Parameters); } public virtual int GetBlockSize() { return cipher.GetBlockSize(); } public virtual int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff) { cipher.ProcessBlock(counter, 0, counterOut, 0); for (int i = 0; i < counterOut.Length; i++) { output[outOff + i] = (byte)(counterOut[i] ^ input[inOff + i]); } int num = counter.Length; while (--num >= 0 && ++counter[num] == 0) { } return counter.Length; } public virtual int ProcessBlock(ReadOnlySpan<byte> input, Span<byte> output) { cipher.ProcessBlock(counter, 0, counterOut, 0); for (int i = 0; i < counterOut.Length; i++) { output[i] = (byte)(counterOut[i] ^ input[i]); } int num = counter.Length; while (--num >= 0 && ++counter[num] == 0) { } return counter.Length; } public virtual void Reset() { Arrays.Fill(counter, 0); Array.Copy(IV, 0, counter, 0, IV.Length); } } }