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());
int num;
if (blockSize < IV.Length) {
num = blockSize;
throw new ArgumentException("CTR/SIC mode requires IV no greater than: " + num.ToString() + " bytes.");
}
int num2 = System.Math.Min(8, blockSize / 2);
if (blockSize - IV.Length > num2) {
num = blockSize - num2;
throw new ArgumentException("CTR/SIC mode requires IV of at least: " + 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 void Reset()
{
Arrays.Fill(counter, 0);
Array.Copy(IV, 0, counter, 0, IV.Length);
}
}
}