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

IsapDigest

public sealed class IsapDigest : IDigest
using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Utilities; using System; using System.IO; using System.Runtime.CompilerServices; namespace Org.BouncyCastle.Crypto.Digests { public sealed class IsapDigest : IDigest { private readonly MemoryStream buffer = new MemoryStream(); private ulong x0; private ulong x1; private ulong x2; private ulong x3; private ulong x4; public string AlgorithmName => "ISAP Hash"; public int GetDigestSize() { return 32; } public int GetByteLength() { return 8; } public void Update(byte input) { buffer.WriteByte(input); } public void BlockUpdate(byte[] input, int inOff, int inLen) { Check.DataLength(input, inOff, inLen, "input buffer too short"); buffer.Write(input, inOff, inLen); } public void BlockUpdate(ReadOnlySpan<byte> input) { buffer.Write(input); } 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"); x0 = 17191252062196199485; x1 = 10066134719181819906; x2 = 13009371945472744034; x3 = 4834782570098516968; x4 = 3787428097924915520; if (!buffer.TryGetBuffer(out ArraySegment<byte> segment)) throw new UnauthorizedAccessException(); Span<byte> span = segment.AsSpan(); while (span.Length >= 8) { x0 ^= Pack.BE_To_UInt64(span); span = span.Slice(8, span.Length - 8); P12(); } x0 ^= (ulong)(128 << (7 - span.Length << 3)); if (!span.IsEmpty) x0 ^= Pack.BE_To_UInt64_High(span); 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)); } return 32; } public void Reset() { buffer.SetLength(0); } 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)); } } }