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

Haraka512Digest

public sealed class Haraka512Digest : HarakaBase
using Org.BouncyCastle.Utilities; using System; namespace Org.BouncyCastle.Crypto.Digests { public sealed class Haraka512Digest : HarakaBase { private readonly byte[] m_buf; private int m_bufPos; public override string AlgorithmName => "Haraka-512"; public Haraka512Digest() { m_buf = new byte[64]; m_bufPos = 0; } public override int GetByteLength() { return 64; } public override void Update(byte input) { if (m_bufPos > 63) throw new ArgumentException("total input cannot be more than 64 bytes"); m_buf[m_bufPos++] = input; } public override void BlockUpdate(byte[] input, int inOff, int len) { if (m_bufPos > 64 - len) throw new ArgumentException("total input cannot be more than 64 bytes"); Array.Copy(input, inOff, m_buf, m_bufPos, len); m_bufPos += len; } public override void BlockUpdate(ReadOnlySpan<byte> input) { if (m_bufPos > 64 - input.Length) throw new ArgumentException("total input cannot be more than 64 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 != 64) throw new ArgumentException("input must be exactly 64 bytes"); if (output.Length < 32) throw new ArgumentException("output too short to receive digest"); if (Haraka512_X86.IsSupported) { Haraka512_X86.Hash(m_buf, output); Reset(); return 32; } int result = Haraka512256(m_buf, output); Reset(); return result; } public override void Reset() { m_bufPos = 0; Array.Clear(m_buf, 0, 64); } private static int Haraka512256(ReadOnlySpan<byte> msg, Span<byte> output) { byte[][] array = new byte[4][] { new byte[16], new byte[16], new byte[16], new byte[16] }; byte[][] array2 = new byte[4][] { new byte[16], new byte[16], 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]); readOnlySpan = msg.Slice(32, 16); readOnlySpan.CopyTo(array[2]); readOnlySpan = msg.Slice(48, 16); readOnlySpan.CopyTo(array[3]); array[0] = HarakaBase.AesEnc(array[0], HarakaBase.RC[0]); array[1] = HarakaBase.AesEnc(array[1], HarakaBase.RC[1]); array[2] = HarakaBase.AesEnc(array[2], HarakaBase.RC[2]); array[3] = HarakaBase.AesEnc(array[3], HarakaBase.RC[3]); array[0] = HarakaBase.AesEnc(array[0], HarakaBase.RC[4]); array[1] = HarakaBase.AesEnc(array[1], HarakaBase.RC[5]); array[2] = HarakaBase.AesEnc(array[2], HarakaBase.RC[6]); array[3] = HarakaBase.AesEnc(array[3], HarakaBase.RC[7]); Mix512(array, array2); array[0] = HarakaBase.AesEnc(array2[0], HarakaBase.RC[8]); array[1] = HarakaBase.AesEnc(array2[1], HarakaBase.RC[9]); array[2] = HarakaBase.AesEnc(array2[2], HarakaBase.RC[10]); array[3] = HarakaBase.AesEnc(array2[3], HarakaBase.RC[11]); array[0] = HarakaBase.AesEnc(array[0], HarakaBase.RC[12]); array[1] = HarakaBase.AesEnc(array[1], HarakaBase.RC[13]); array[2] = HarakaBase.AesEnc(array[2], HarakaBase.RC[14]); array[3] = HarakaBase.AesEnc(array[3], HarakaBase.RC[15]); Mix512(array, array2); array[0] = HarakaBase.AesEnc(array2[0], HarakaBase.RC[16]); array[1] = HarakaBase.AesEnc(array2[1], HarakaBase.RC[17]); array[2] = HarakaBase.AesEnc(array2[2], HarakaBase.RC[18]); array[3] = HarakaBase.AesEnc(array2[3], HarakaBase.RC[19]); array[0] = HarakaBase.AesEnc(array[0], HarakaBase.RC[20]); array[1] = HarakaBase.AesEnc(array[1], HarakaBase.RC[21]); array[2] = HarakaBase.AesEnc(array[2], HarakaBase.RC[22]); array[3] = HarakaBase.AesEnc(array[3], HarakaBase.RC[23]); Mix512(array, array2); array[0] = HarakaBase.AesEnc(array2[0], HarakaBase.RC[24]); array[1] = HarakaBase.AesEnc(array2[1], HarakaBase.RC[25]); array[2] = HarakaBase.AesEnc(array2[2], HarakaBase.RC[26]); array[3] = HarakaBase.AesEnc(array2[3], HarakaBase.RC[27]); array[0] = HarakaBase.AesEnc(array[0], HarakaBase.RC[28]); array[1] = HarakaBase.AesEnc(array[1], HarakaBase.RC[29]); array[2] = HarakaBase.AesEnc(array[2], HarakaBase.RC[30]); array[3] = HarakaBase.AesEnc(array[3], HarakaBase.RC[31]); Mix512(array, array2); array[0] = HarakaBase.AesEnc(array2[0], HarakaBase.RC[32]); array[1] = HarakaBase.AesEnc(array2[1], HarakaBase.RC[33]); array[2] = HarakaBase.AesEnc(array2[2], HarakaBase.RC[34]); array[3] = HarakaBase.AesEnc(array2[3], HarakaBase.RC[35]); array[0] = HarakaBase.AesEnc(array[0], HarakaBase.RC[36]); array[1] = HarakaBase.AesEnc(array[1], HarakaBase.RC[37]); array[2] = HarakaBase.AesEnc(array[2], HarakaBase.RC[38]); array[3] = HarakaBase.AesEnc(array[3], HarakaBase.RC[39]); Mix512(array, array2); Bytes.Xor(16, array2[0], msg, array[0]); Bytes.Xor(16, array2[1], msg.Slice(16, msg.Length - 16), array[1]); Bytes.Xor(16, array2[2], msg.Slice(32, msg.Length - 32), array[2]); Bytes.Xor(16, array2[3], msg.Slice(48, msg.Length - 48), array[3]); Span<byte> span = array[0].AsSpan(8, 8); span.CopyTo(output); span = array[1].AsSpan(8, 8); span.CopyTo(output.Slice(8, output.Length - 8)); span = array[2].AsSpan(0, 8); span.CopyTo(output.Slice(16, output.Length - 16)); span = array[3].AsSpan(0, 8); span.CopyTo(output.Slice(24, output.Length - 24)); return HarakaBase.DIGEST_SIZE; } private static void Mix512(byte[][] s1, byte[][] s2) { Array.Copy(s1[0], 12, s2[0], 0, 4); Array.Copy(s1[2], 12, s2[0], 4, 4); Array.Copy(s1[1], 12, s2[0], 8, 4); Array.Copy(s1[3], 12, s2[0], 12, 4); Array.Copy(s1[2], 0, s2[1], 0, 4); Array.Copy(s1[0], 0, s2[1], 4, 4); Array.Copy(s1[3], 0, s2[1], 8, 4); Array.Copy(s1[1], 0, s2[1], 12, 4); Array.Copy(s1[2], 4, s2[2], 0, 4); Array.Copy(s1[0], 4, s2[2], 4, 4); Array.Copy(s1[3], 4, s2[2], 8, 4); Array.Copy(s1[1], 4, s2[2], 12, 4); Array.Copy(s1[0], 8, s2[3], 0, 4); Array.Copy(s1[2], 8, s2[3], 4, 4); Array.Copy(s1[1], 8, s2[3], 8, 4); Array.Copy(s1[3], 8, s2[3], 12, 4); } } }