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

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"); if (inLen >= 1) { int num = 8 - m_bufPos; if (inLen < num) { Array.Copy(input, inOff, m_buf, m_bufPos, inLen); m_bufPos += inLen; } else { int num2 = 0; if (m_bufPos > 0) { Array.Copy(input, inOff, m_buf, m_bufPos, num); num2 += num; S0 ^= Pack.LE_To_UInt64(m_buf, 0); P12(); } int num3; while ((num3 = inLen - num2) >= 8) { S0 ^= Pack.LE_To_UInt64(input, inOff + num2); P12(); num2 += 8; } Array.Copy(input, inOff + num2, m_buf, 0, num3); m_bufPos = num3; } } } public int DoFinal(byte[] output, int outOff) { Check.OutputLength(output, outOff, 32, "output buffer too short"); PadAndAbsorb(); Pack.UInt64_To_LE(S0, output, outOff); for (int i = 0; i < 3; i++) { outOff += 8; P12(); Pack.UInt64_To_LE(S0, output, outOff); } 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)); } } }