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

Haraka256Digest

public sealed class Haraka256Digest : HarakaBase
using Org.BouncyCastle.Utilities; using System; namespace Org.BouncyCastle.Crypto.Digests { public sealed class Haraka256Digest : HarakaBase { private readonly byte[] m_buf; private int m_bufPos; public override string AlgorithmName => "Haraka-256"; public Haraka256Digest() { m_buf = new byte[32]; m_bufPos = 0; } public override int GetByteLength() { return 32; } public override void Update(byte input) { if (m_bufPos > 31) throw new ArgumentException("total input cannot be more than 32 bytes"); m_buf[m_bufPos++] = input; } public override void BlockUpdate(byte[] input, int inOff, int len) { if (m_bufPos > 32 - len) throw new ArgumentException("total input cannot be more than 32 bytes"); Array.Copy(input, inOff, m_buf, m_bufPos, len); m_bufPos += len; } public override void BlockUpdate(ReadOnlySpan<byte> input) { if (m_bufPos > 32 - input.Length) throw new ArgumentException("total input cannot be more than 32 bytes"); input.CopyTo(m_buf.AsSpan(m_bufPos)); m_bufPos += input.Length; } public override int DoFinal(byte[] output, int outOff) { return DoFinal(output.AsSpan(outOff)); } public override int DoFinal(Span<byte> output) { if (m_bufPos != 32) throw new ArgumentException("input must be exactly 32 bytes"); if (output.Length < 32) throw new ArgumentException("output too short to receive digest"); if (Haraka256_X86.IsSupported) { Haraka256_X86.Hash(m_buf, output); Reset(); return 32; } int result = Haraka256256(m_buf, output); Reset(); return result; } public override void Reset() { m_bufPos = 0; Array.Clear(m_buf, 0, 32); } private static int Haraka256256(ReadOnlySpan<byte> msg, Span<byte> output) { byte[][] array = new byte[2][] { new byte[16], new byte[16] }; byte[][] array2 = new byte[2][] { new byte[16], new byte[16] }; ReadOnlySpan<byte> readOnlySpan = msg.Slice(0, 16); readOnlySpan.CopyTo(array[0]); readOnlySpan = msg.Slice(16, 16); readOnlySpan.CopyTo(array[1]); array[0] = HarakaBase.AesEnc(array[0], HarakaBase.RC[0]); array[1] = HarakaBase.AesEnc(array[1], HarakaBase.RC[1]); array[0] = HarakaBase.AesEnc(array[0], HarakaBase.RC[2]); array[1] = HarakaBase.AesEnc(array[1], HarakaBase.RC[3]); Mix256(array, array2); array[0] = HarakaBase.AesEnc(array2[0], HarakaBase.RC[4]); array[1] = HarakaBase.AesEnc(array2[1], HarakaBase.RC[5]); array[0] = HarakaBase.AesEnc(array[0], HarakaBase.RC[6]); array[1] = HarakaBase.AesEnc(array[1], HarakaBase.RC[7]); Mix256(array, array2); array[0] = HarakaBase.AesEnc(array2[0], HarakaBase.RC[8]); array[1] = HarakaBase.AesEnc(array2[1], HarakaBase.RC[9]); array[0] = HarakaBase.AesEnc(array[0], HarakaBase.RC[10]); array[1] = HarakaBase.AesEnc(array[1], HarakaBase.RC[11]); Mix256(array, array2); array[0] = HarakaBase.AesEnc(array2[0], HarakaBase.RC[12]); array[1] = HarakaBase.AesEnc(array2[1], HarakaBase.RC[13]); array[0] = HarakaBase.AesEnc(array[0], HarakaBase.RC[14]); array[1] = HarakaBase.AesEnc(array[1], HarakaBase.RC[15]); Mix256(array, array2); array[0] = HarakaBase.AesEnc(array2[0], HarakaBase.RC[16]); array[1] = HarakaBase.AesEnc(array2[1], HarakaBase.RC[17]); array[0] = HarakaBase.AesEnc(array[0], HarakaBase.RC[18]); array[1] = HarakaBase.AesEnc(array[1], HarakaBase.RC[19]); Mix256(array, array2); Bytes.Xor(16, array2[0], msg, output); Bytes.Xor(16, array2[1], msg.Slice(16, msg.Length - 16), output.Slice(16, output.Length - 16)); return HarakaBase.DIGEST_SIZE; } private static void Mix256(byte[][] s1, byte[][] s2) { Array.Copy(s1[0], 0, s2[0], 0, 4); Array.Copy(s1[1], 0, s2[0], 4, 4); Array.Copy(s1[0], 4, s2[0], 8, 4); Array.Copy(s1[1], 4, s2[0], 12, 4); Array.Copy(s1[0], 8, s2[1], 0, 4); Array.Copy(s1[1], 8, s2[1], 4, 4); Array.Copy(s1[0], 12, s2[1], 8, 4); Array.Copy(s1[1], 12, s2[1], 12, 4); } } }