IsapDigest
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));
}
}
}