init commit
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Crypto.Utilities;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Engines;
|
||||
|
||||
public class HC128Engine : IStreamCipher
|
||||
{
|
||||
private uint[] p = new uint[512];
|
||||
|
||||
private uint[] q = new uint[512];
|
||||
|
||||
private uint cnt = 0u;
|
||||
|
||||
private byte[] key;
|
||||
|
||||
private byte[] iv;
|
||||
|
||||
private bool initialised;
|
||||
|
||||
private byte[] buf = new byte[4];
|
||||
|
||||
private int idx = 0;
|
||||
|
||||
public virtual string AlgorithmName => "HC-128";
|
||||
|
||||
private static uint F1(uint x)
|
||||
{
|
||||
return RotateRight(x, 7) ^ RotateRight(x, 18) ^ (x >> 3);
|
||||
}
|
||||
|
||||
private static uint F2(uint x)
|
||||
{
|
||||
return RotateRight(x, 17) ^ RotateRight(x, 19) ^ (x >> 10);
|
||||
}
|
||||
|
||||
private uint G1(uint x, uint y, uint z)
|
||||
{
|
||||
return (RotateRight(x, 10) ^ RotateRight(z, 23)) + RotateRight(y, 8);
|
||||
}
|
||||
|
||||
private uint G2(uint x, uint y, uint z)
|
||||
{
|
||||
return (RotateLeft(x, 10) ^ RotateLeft(z, 23)) + RotateLeft(y, 8);
|
||||
}
|
||||
|
||||
private static uint RotateLeft(uint x, int bits)
|
||||
{
|
||||
return (x << bits) | (x >> -bits);
|
||||
}
|
||||
|
||||
private static uint RotateRight(uint x, int bits)
|
||||
{
|
||||
return (x >> bits) | (x << -bits);
|
||||
}
|
||||
|
||||
private uint H1(uint x)
|
||||
{
|
||||
return q[x & 0xFF] + q[((x >> 16) & 0xFF) + 256];
|
||||
}
|
||||
|
||||
private uint H2(uint x)
|
||||
{
|
||||
return p[x & 0xFF] + p[((x >> 16) & 0xFF) + 256];
|
||||
}
|
||||
|
||||
private static uint Mod1024(uint x)
|
||||
{
|
||||
return x & 0x3FF;
|
||||
}
|
||||
|
||||
private static uint Mod512(uint x)
|
||||
{
|
||||
return x & 0x1FF;
|
||||
}
|
||||
|
||||
private static uint Dim(uint x, uint y)
|
||||
{
|
||||
return Mod512(x - y);
|
||||
}
|
||||
|
||||
private uint Step()
|
||||
{
|
||||
uint num = Mod512(cnt);
|
||||
uint result;
|
||||
if (cnt < 512)
|
||||
{
|
||||
uint[] array;
|
||||
nint num2;
|
||||
(array = p)[num2 = (nint)num] = array[num2] + G1(p[Dim(num, 3u)], p[Dim(num, 10u)], p[Dim(num, 511u)]);
|
||||
result = H1(p[Dim(num, 12u)]) ^ p[num];
|
||||
}
|
||||
else
|
||||
{
|
||||
uint[] array;
|
||||
nint num2;
|
||||
(array = q)[num2 = (nint)num] = array[num2] + G2(q[Dim(num, 3u)], q[Dim(num, 10u)], q[Dim(num, 511u)]);
|
||||
result = H2(q[Dim(num, 12u)]) ^ q[num];
|
||||
}
|
||||
cnt = Mod1024(cnt + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void Init()
|
||||
{
|
||||
if (key.Length != 16)
|
||||
{
|
||||
throw new ArgumentException("The key must be 128 bits long");
|
||||
}
|
||||
idx = 0;
|
||||
cnt = 0u;
|
||||
uint[] array = new uint[1280];
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
uint[] array3;
|
||||
uint[] array2 = (array3 = array);
|
||||
int num = i >> 2;
|
||||
nint num2 = num;
|
||||
array2[num] = array3[num2] | (uint)(key[i] << 8 * (i & 3));
|
||||
}
|
||||
Array.Copy(array, 0, array, 4, 4);
|
||||
for (int j = 0; j < iv.Length && j < 16; j++)
|
||||
{
|
||||
uint[] array3;
|
||||
uint[] array4 = (array3 = array);
|
||||
int num3 = (j >> 2) + 8;
|
||||
nint num2 = num3;
|
||||
array4[num3] = array3[num2] | (uint)(iv[j] << 8 * (j & 3));
|
||||
}
|
||||
Array.Copy(array, 8, array, 12, 4);
|
||||
for (uint num4 = 16u; num4 < 1280; num4++)
|
||||
{
|
||||
array[num4] = F2(array[num4 - 2]) + array[num4 - 7] + F1(array[num4 - 15]) + array[num4 - 16] + num4;
|
||||
}
|
||||
Array.Copy(array, 256, p, 0, 512);
|
||||
Array.Copy(array, 768, q, 0, 512);
|
||||
for (int k = 0; k < 512; k++)
|
||||
{
|
||||
p[k] = Step();
|
||||
}
|
||||
for (int l = 0; l < 512; l++)
|
||||
{
|
||||
q[l] = Step();
|
||||
}
|
||||
cnt = 0u;
|
||||
}
|
||||
|
||||
public virtual void Init(bool forEncryption, ICipherParameters parameters)
|
||||
{
|
||||
ICipherParameters cipherParameters = parameters;
|
||||
if (parameters is ParametersWithIV)
|
||||
{
|
||||
iv = ((ParametersWithIV)parameters).GetIV();
|
||||
cipherParameters = ((ParametersWithIV)parameters).Parameters;
|
||||
}
|
||||
else
|
||||
{
|
||||
iv = new byte[0];
|
||||
}
|
||||
if (cipherParameters is KeyParameter)
|
||||
{
|
||||
key = ((KeyParameter)cipherParameters).GetKey();
|
||||
Init();
|
||||
initialised = true;
|
||||
return;
|
||||
}
|
||||
throw new ArgumentException("Invalid parameter passed to HC128 init - " + Platform.GetTypeName(parameters), "parameters");
|
||||
}
|
||||
|
||||
private byte GetByte()
|
||||
{
|
||||
if (idx == 0)
|
||||
{
|
||||
Pack.UInt32_To_LE(Step(), buf);
|
||||
}
|
||||
byte result = buf[idx];
|
||||
idx = (idx + 1) & 3;
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual void ProcessBytes(byte[] input, int inOff, int len, byte[] output, int outOff)
|
||||
{
|
||||
if (!initialised)
|
||||
{
|
||||
throw new InvalidOperationException(AlgorithmName + " not initialised");
|
||||
}
|
||||
Check.DataLength(input, inOff, len, "input buffer too short");
|
||||
Check.OutputLength(output, outOff, len, "output buffer too short");
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
output[outOff + i] = (byte)(input[inOff + i] ^ GetByte());
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Reset()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
public virtual byte ReturnByte(byte input)
|
||||
{
|
||||
return (byte)(input ^ GetByte());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user