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

AsconHash256

public sealed class AsconHash256 : IDigest
Ascon-Hash256 was introduced in NIST Special Publication (SP) 800-232 (Initial Public Draft).
using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Utilities; using System; using System.Runtime.CompilerServices; namespace Org.BouncyCastle.Crypto.Digests { public sealed class AsconHash256 : IDigest { private const int Rate = 8; private readonly byte[] m_buf = new byte[8]; private ulong S0; private ulong S1; private ulong S2; private ulong S3; private ulong S4; private int m_bufPos; public string AlgorithmName => "Ascon-Hash256"; public AsconHash256() { Reset(); } public int GetDigestSize() { return 32; } public int GetByteLength() { return 8; } public void Update(byte input) { m_buf[m_bufPos] = input; if (++m_bufPos == 8) { S0 ^= Pack.LE_To_UInt64(m_buf, 0); P12(); m_bufPos = 0; } } public void BlockUpdate(byte[] input, int inOff, int inLen) { Check.DataLength(input, inOff, inLen, "input buffer too short"); BlockUpdate(input.AsSpan(inOff, inLen)); } public void BlockUpdate(ReadOnlySpan<byte> input) { int num = 8 - m_bufPos; if (input.Length < num) { input.CopyTo(m_buf.AsSpan(m_bufPos)); m_bufPos += input.Length; } else { if (m_bufPos > 0) { input.Slice(0, num).CopyTo(m_buf.AsSpan(m_bufPos)); S0 ^= Pack.LE_To_UInt64(m_buf); P12(); int num2 = num; input = input.Slice(num2, input.Length - num2); } while (input.Length >= 8) { S0 ^= Pack.LE_To_UInt64(input); P12(); input = input.Slice(8, input.Length - 8); } input.CopyTo(m_buf); m_bufPos = input.Length; } } public int DoFinal(byte[] output, int outOff) { return DoFinal(output.AsSpan(outOff)); } public int DoFinal(Span<byte> output) { Check.OutputLength(output, 32, "output buffer too short"); PadAndAbsorb(); Pack.UInt64_To_LE(S0, output); for (int i = 0; i < 3; i++) { output = output.Slice(8, output.Length - 8); P12(); Pack.UInt64_To_LE(S0, output); } Reset(); return 32; } public void Reset() { S0 = 11177464323724596865; S1 = 5459383224871899602; S2 = 12566513473065105434; S3 = 4359436768738168243; S4 = 1899470422303676269; Array.Clear(m_buf, 0, m_buf.Length); m_bufPos = 0; } private void PadAndAbsorb() { int num = m_bufPos << 3; S0 ^= (Pack.LE_To_UInt64(m_buf, 0) & (72057594037927935 >> 56 - num)); S0 ^= (ulong)(1 << num); P12(); } private void P12() { Round(240); Round(225); Round(210); Round(195); Round(180); Round(165); Round(150); Round(135); Round(120); Round(105); Round(90); Round(75); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void Round(ulong c) { ulong num = S2 ^ c; ulong num2 = S0 ^ S1 ^ num ^ S3 ^ (S1 & (S0 ^ num ^ S4)); ulong num3 = S0 ^ num ^ S3 ^ S4 ^ ((S1 ^ num) & (S1 ^ S3)); ulong num4 = S1 ^ num ^ S4 ^ (S3 & S4); ulong num5 = S0 ^ S1 ^ num ^ (~S0 & (S3 ^ S4)); ulong num6 = S1 ^ S3 ^ S4 ^ ((S0 ^ S4) & S1); S0 = (num2 ^ Longs.RotateRight(num2, 19) ^ Longs.RotateRight(num2, 28)); S1 = (num3 ^ Longs.RotateRight(num3, 39) ^ Longs.RotateRight(num3, 61)); S2 = ~(num4 ^ Longs.RotateRight(num4, 1) ^ Longs.RotateRight(num4, 6)); S3 = (num5 ^ Longs.RotateRight(num5, 10) ^ Longs.RotateRight(num5, 17)); S4 = (num6 ^ Longs.RotateRight(num6, 7) ^ Longs.RotateRight(num6, 41)); } } }