<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.1" />

HC256Engine

public class HC256Engine : IStreamCipher
using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Utilities; using System; namespace Org.BouncyCastle.Crypto.Engines { public class HC256Engine : IStreamCipher { private readonly uint[] p = new uint[1024]; private readonly uint[] q = new uint[1024]; private uint cnt; private byte[] key; private byte[] iv; private bool initialised; private readonly byte[] buf = new byte[4]; private int idx; public virtual string AlgorithmName => "HC-256"; private uint Step() { uint num = cnt & 1023; uint result; if (cnt < 1024) { uint num2 = p[(num - 3) & 1023]; uint num3 = p[(num - 1023) & 1023]; p[num] += p[(num - 10) & 1023] + (Integers.RotateRight(num2, 10) ^ Integers.RotateRight(num3, 23)) + q[(num2 ^ num3) & 1023]; num2 = p[(num - 12) & 1023]; result = ((q[num2 & 255] + q[((num2 >> 8) & 255) + 256] + q[((num2 >> 16) & 255) + 512] + q[((num2 >> 24) & 255) + 768]) ^ p[num]); } else { uint num4 = q[(num - 3) & 1023]; uint num5 = q[(num - 1023) & 1023]; q[num] += q[(num - 10) & 1023] + (Integers.RotateRight(num4, 10) ^ Integers.RotateRight(num5, 23)) + p[(num4 ^ num5) & 1023]; num4 = q[(num - 12) & 1023]; result = ((p[num4 & 255] + p[((num4 >> 8) & 255) + 256] + p[((num4 >> 16) & 255) + 512] + p[((num4 >> 24) & 255) + 768]) ^ q[num]); } cnt = ((cnt + 1) & 2047); return result; } private void Init() { if (key.Length != 32 && key.Length != 16) throw new ArgumentException("The key must be 128/256 bits long"); if (iv.Length < 16) throw new ArgumentException("The IV must be at least 128 bits long"); if (key.Length != 32) { byte[] destinationArray = new byte[32]; Array.Copy(key, 0, destinationArray, 0, key.Length); Array.Copy(key, 0, destinationArray, 16, key.Length); key = destinationArray; } if (iv.Length < 32) { byte[] array = new byte[32]; Array.Copy(iv, 0, array, 0, iv.Length); Array.Copy(iv, 0, array, iv.Length, array.Length - iv.Length); iv = array; } idx = 0; cnt = 0; uint[] array2 = new uint[2560]; Pack.LE_To_UInt32(key, 0, array2, 0, 8); Pack.LE_To_UInt32(iv, 0, array2, 8, 8); for (uint num = 16; num < 2560; num++) { uint num2 = array2[num - 2]; uint num3 = array2[num - 15]; array2[num] = (Integers.RotateRight(num2, 17) ^ Integers.RotateRight(num2, 19) ^ (num2 >> 10)) + array2[num - 7] + (Integers.RotateRight(num3, 7) ^ Integers.RotateRight(num3, 18) ^ (num3 >> 3)) + array2[num - 16] + num; } Array.Copy(array2, 512, p, 0, 1024); Array.Copy(array2, 1536, q, 0, 1024); for (int i = 0; i < 4096; i++) { Step(); } cnt = 0; } public virtual void Init(bool forEncryption, ICipherParameters parameters) { ParametersWithIV parametersWithIV = parameters as ParametersWithIV; if (parametersWithIV == null) throw new ArgumentException("HC-256 Init parameters must include an IV"); KeyParameter keyParameter = parametersWithIV.Parameters as KeyParameter; if (keyParameter == null) throw new ArgumentException("Invalid parameter passed to HC256 init - " + Platform.GetTypeName(parameters), "parameters"); key = keyParameter.GetKey(); iv = parametersWithIV.GetIV(); Init(); initialised = true; } 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()); } } }