Files
SuperVPN/output/Libraries/BouncyCastle.Crypto/Org/BouncyCastle/Crypto/Engines/HC128Engine.cs
2025-10-09 09:57:24 +09:00

206 lines
4.3 KiB
C#

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());
}
}