94 lines
2.2 KiB
C#
94 lines
2.2 KiB
C#
using System;
|
|
using Org.BouncyCastle.Crypto.Parameters;
|
|
using Org.BouncyCastle.Utilities;
|
|
|
|
namespace Org.BouncyCastle.Crypto.Modes;
|
|
|
|
public class SicBlockCipher : IBlockCipher
|
|
{
|
|
private readonly IBlockCipher cipher;
|
|
|
|
private readonly int blockSize;
|
|
|
|
private readonly byte[] counter;
|
|
|
|
private readonly byte[] counterOut;
|
|
|
|
private byte[] IV;
|
|
|
|
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 IBlockCipher GetUnderlyingCipher()
|
|
{
|
|
return cipher;
|
|
}
|
|
|
|
public virtual void Init(bool forEncryption, ICipherParameters parameters)
|
|
{
|
|
if (!(parameters is ParametersWithIV parametersWithIV))
|
|
{
|
|
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 + " 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) + " bytes.");
|
|
}
|
|
if (parametersWithIV.Parameters != null)
|
|
{
|
|
cipher.Init(forEncryption: true, parametersWithIV.Parameters);
|
|
}
|
|
Reset();
|
|
}
|
|
|
|
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)
|
|
{
|
|
byte[] array2;
|
|
byte[] array = (array2 = counter);
|
|
int num2 = num;
|
|
nint num3 = num2;
|
|
if ((array[num2] = (byte)(array2[num3] + 1)) != 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
return counter.Length;
|
|
}
|
|
|
|
public virtual void Reset()
|
|
{
|
|
Arrays.Fill(counter, 0);
|
|
Array.Copy(IV, 0, counter, 0, IV.Length);
|
|
cipher.Reset();
|
|
}
|
|
}
|