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

IsapDigest

public sealed class IsapDigest : IDigest
using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Utilities; using System; using System.Runtime.CompilerServices; namespace Org.BouncyCastle.Crypto.Digests { public sealed class IsapDigest : IDigest { private readonly byte[] m_buf = new byte[8]; private int m_bufPos; private ulong x0 = 17191252062196199485; private ulong x1 = 10066134719181819906; private ulong x2 = 13009371945472744034; private ulong x3 = 4834782570098516968; private ulong x4 = 3787428097924915520; public string AlgorithmName => "ISAP Hash"; public int GetDigestSize() { return 32; } public int GetByteLength() { return 8; } public void Update(byte input) { m_buf[m_bufPos] = input; if (++m_bufPos == 8) { x0 ^= Pack.BE_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)); x0 ^= Pack.BE_To_UInt64(m_buf); P12(); int num2 = num; input = input.Slice(num2, input.Length - num2); } while (input.Length >= 8) { x0 ^= Pack.BE_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"); FinishAbsorbing(); for (int i = 0; i < 4; i++) { P12(); ulong n = x0; int num = i << 3; Pack.UInt64_To_BE(n, output.Slice(num, output.Length - num)); } Reset(); return 32; } public void Reset() { Array.Clear(m_buf, 0, m_buf.Length); m_bufPos = 0; x0 = 17191252062196199485; x1 = 10066134719181819906; x2 = 13009371945472744034; x3 = 4834782570098516968; x4 = 3787428097924915520; } private void FinishAbsorbing() { m_buf[m_bufPos] = 128; x0 ^= (ulong)((long)Pack.BE_To_UInt64(m_buf, 0) & (-1 << 56 - (m_bufPos << 3))); } 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 = x0 ^ x1 ^ x2 ^ x3 ^ c ^ (x1 & (x0 ^ x2 ^ x4 ^ c)); ulong num2 = x0 ^ x2 ^ x3 ^ x4 ^ c ^ ((x1 ^ x2 ^ c) & (x1 ^ x3)); ulong num3 = x1 ^ x2 ^ x4 ^ c ^ (x3 & x4); ulong num4 = x0 ^ x1 ^ x2 ^ c ^ (~x0 & (x3 ^ x4)); ulong num5 = x1 ^ x3 ^ x4 ^ ((x0 ^ x4) & x1); x0 = (num ^ Longs.RotateRight(num, 19) ^ Longs.RotateRight(num, 28)); x1 = (num2 ^ Longs.RotateRight(num2, 39) ^ Longs.RotateRight(num2, 61)); x2 = ~(num3 ^ Longs.RotateRight(num3, 1) ^ Longs.RotateRight(num3, 6)); x3 = (num4 ^ Longs.RotateRight(num4, 10) ^ Longs.RotateRight(num4, 17)); x4 = (num5 ^ Longs.RotateRight(num5, 7) ^ Longs.RotateRight(num5, 41)); } } }