RC564Engine
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Utilities;
using Org.BouncyCastle.Utilities;
using System;
namespace Org.BouncyCastle.Crypto.Engines
{
public class RC564Engine : IBlockCipher
{
private int _noRounds;
private long[] _S;
private static readonly long P64 = -5196783011329398165;
private static readonly long Q64 = -7046029254386353131;
private bool forEncryption;
public virtual string AlgorithmName => "RC5-64";
public RC564Engine()
{
_noRounds = 12;
}
public virtual int GetBlockSize()
{
return 16;
}
public virtual void Init(bool forEncryption, ICipherParameters parameters)
{
RC5Parameters rC5Parameters = parameters as RC5Parameters;
if (rC5Parameters == null)
throw new ArgumentException("invalid parameter passed to RC564 init - " + Platform.GetTypeName(parameters));
this.forEncryption = forEncryption;
_noRounds = rC5Parameters.Rounds;
SetKey(rC5Parameters.GetKey());
}
public virtual int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff)
{
if (!forEncryption)
return DecryptBlock(input, inOff, output, outOff);
return EncryptBlock(input, inOff, output, outOff);
}
private void SetKey(byte[] key)
{
long[] array = new long[(key.Length + 7) / 8];
for (int i = 0; i != key.Length; i++) {
array[i / 8] += (long)(key[i] & 255) << 8 * (i % 8);
}
_S = new long[2 * (_noRounds + 1)];
_S[0] = P64;
for (int j = 1; j < _S.Length; j++) {
_S[j] = _S[j - 1] + Q64;
}
int num = (array.Length <= _S.Length) ? (3 * _S.Length) : (3 * array.Length);
long num2 = 0;
long num3 = 0;
int num4 = 0;
int num5 = 0;
for (int k = 0; k < num; k++) {
num2 = (_S[num4] = Longs.RotateLeft(_S[num4] + num2 + num3, 3));
num3 = (array[num5] = Longs.RotateLeft(array[num5] + num2 + num3, (int)(num2 + num3)));
num4 = (num4 + 1) % _S.Length;
num5 = (num5 + 1) % array.Length;
}
}
private int EncryptBlock(byte[] input, int inOff, byte[] outBytes, int outOff)
{
long num = (long)Pack.LE_To_UInt64(input, inOff) + _S[0];
long num2 = (long)Pack.LE_To_UInt64(input, inOff + 8) + _S[1];
for (int i = 1; i <= _noRounds; i++) {
num = Longs.RotateLeft(num ^ num2, (int)num2) + _S[2 * i];
num2 = Longs.RotateLeft(num2 ^ num, (int)num) + _S[2 * i + 1];
}
Pack.UInt64_To_LE((ulong)num, outBytes, outOff);
Pack.UInt64_To_LE((ulong)num2, outBytes, outOff + 8);
return 16;
}
private int DecryptBlock(byte[] input, int inOff, byte[] outBytes, int outOff)
{
long num = (long)Pack.LE_To_UInt64(input, inOff);
long num2 = (long)Pack.LE_To_UInt64(input, inOff + 8);
for (int num3 = _noRounds; num3 >= 1; num3--) {
num2 = (Longs.RotateRight(num2 - _S[2 * num3 + 1], (int)num) ^ num);
num = (Longs.RotateRight(num - _S[2 * num3], (int)num2) ^ num2);
}
Pack.UInt64_To_LE((ulong)(num - _S[0]), outBytes, outOff);
Pack.UInt64_To_LE((ulong)(num2 - _S[1]), outBytes, outOff + 8);
return 16;
}
}
}