XoodyakDigest
using Org.BouncyCastle.Crypto.Utilities;
using Org.BouncyCastle.Utilities;
using System;
namespace Org.BouncyCastle.Crypto.Digests
{
public sealed class XoodyakDigest : IDigest
{
private static readonly uint[] RC = new uint[12] {
88,
56,
960,
208,
288,
20,
96,
44,
896,
240,
416,
18
};
private const int f_bPrime = 48;
private const int MAXROUNDS = 12;
private const int TAGLEN = 16;
private const int Rabsorb = 16;
private readonly byte[] m_state = new byte[48];
private readonly byte[] m_buf = new byte[16];
private int m_bufPos;
private bool m_updated;
public string AlgorithmName => "Xoodyak Hash";
public XoodyakDigest()
{
Reset();
}
public int GetDigestSize()
{
return 32;
}
public int GetByteLength()
{
return 16;
}
public void Update(byte input)
{
m_buf[m_bufPos] = input;
if (++m_bufPos == 16) {
Down(m_buf, 0, 16);
Up();
m_updated = true;
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 = 16 - 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;
Down(m_buf, 0, 16);
Up();
m_updated = true;
}
int num3;
while ((num3 = inLen - num2) >= 16) {
Down(input, inOff + num2, 16);
Up();
m_updated = true;
num2 += 16;
}
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");
if (m_bufPos > 0 || !m_updated) {
Down(m_buf, 0, m_bufPos);
Up();
}
Array.Copy(m_state, 0, output, outOff, 16);
m_state[0] ^= 1;
Up();
Array.Copy(m_state, 0, output, outOff + 16, 16);
Reset();
return 32;
}
public void Reset()
{
Arrays.Fill(m_state, 0);
Arrays.Fill(m_buf, 0);
m_bufPos = 0;
m_updated = false;
m_state[47] ^= 1;
}
private void Up()
{
uint num = Pack.LE_To_UInt32(m_state, 0);
uint num2 = Pack.LE_To_UInt32(m_state, 4);
uint num3 = Pack.LE_To_UInt32(m_state, 8);
uint num4 = Pack.LE_To_UInt32(m_state, 12);
uint num5 = Pack.LE_To_UInt32(m_state, 16);
uint num6 = Pack.LE_To_UInt32(m_state, 20);
uint num7 = Pack.LE_To_UInt32(m_state, 24);
uint num8 = Pack.LE_To_UInt32(m_state, 28);
uint num9 = Pack.LE_To_UInt32(m_state, 32);
uint num10 = Pack.LE_To_UInt32(m_state, 36);
uint num11 = Pack.LE_To_UInt32(m_state, 40);
uint num12 = Pack.LE_To_UInt32(m_state, 44);
for (int i = 0; i < 12; i++) {
uint i2 = num ^ num5 ^ num9;
uint i3 = num2 ^ num6 ^ num10;
uint i4 = num3 ^ num7 ^ num11;
uint i5 = num4 ^ num8 ^ num12;
uint num13 = Integers.RotateLeft(i5, 5) ^ Integers.RotateLeft(i5, 14);
uint num14 = Integers.RotateLeft(i2, 5) ^ Integers.RotateLeft(i2, 14);
uint num15 = Integers.RotateLeft(i3, 5) ^ Integers.RotateLeft(i3, 14);
uint num16 = Integers.RotateLeft(i4, 5) ^ Integers.RotateLeft(i4, 14);
num ^= num13;
num5 ^= num13;
num9 ^= num13;
num2 ^= num14;
num6 ^= num14;
num10 ^= num14;
num3 ^= num15;
num7 ^= num15;
num11 ^= num15;
num4 ^= num16;
num8 ^= num16;
num12 ^= num16;
uint num17 = num;
uint num18 = num2;
uint num19 = num3;
uint num20 = num4;
uint num21 = num8;
uint num22 = num5;
uint num23 = num6;
uint num24 = num7;
uint num25 = Integers.RotateLeft(num9, 11);
uint num26 = Integers.RotateLeft(num10, 11);
uint num27 = Integers.RotateLeft(num11, 11);
uint num28 = Integers.RotateLeft(num12, 11);
num17 ^= RC[i];
num = (num17 ^ (~num21 & num25));
num2 = (num18 ^ (~num22 & num26));
num3 = (num19 ^ (~num23 & num27));
num4 = (num20 ^ (~num24 & num28));
num5 = (num21 ^ (~num25 & num17));
num6 = (num22 ^ (~num26 & num18));
num7 = (num23 ^ (~num27 & num19));
num8 = (num24 ^ (~num28 & num20));
num25 ^= (~num17 & num21);
num26 ^= (~num18 & num22);
num27 ^= (~num19 & num23);
num28 ^= (~num20 & num24);
num5 = Integers.RotateLeft(num5, 1);
num6 = Integers.RotateLeft(num6, 1);
num7 = Integers.RotateLeft(num7, 1);
num8 = Integers.RotateLeft(num8, 1);
num9 = Integers.RotateLeft(num27, 8);
num10 = Integers.RotateLeft(num28, 8);
num11 = Integers.RotateLeft(num25, 8);
num12 = Integers.RotateLeft(num26, 8);
}
Pack.UInt32_To_LE(num, m_state, 0);
Pack.UInt32_To_LE(num2, m_state, 4);
Pack.UInt32_To_LE(num3, m_state, 8);
Pack.UInt32_To_LE(num4, m_state, 12);
Pack.UInt32_To_LE(num5, m_state, 16);
Pack.UInt32_To_LE(num6, m_state, 20);
Pack.UInt32_To_LE(num7, m_state, 24);
Pack.UInt32_To_LE(num8, m_state, 28);
Pack.UInt32_To_LE(num9, m_state, 32);
Pack.UInt32_To_LE(num10, m_state, 36);
Pack.UInt32_To_LE(num11, m_state, 40);
Pack.UInt32_To_LE(num12, m_state, 44);
}
private void Down(byte[] Xi, int XiOff, int XiLen)
{
for (int i = 0; i < XiLen; i++) {
m_state[i] ^= Xi[XiOff++];
}
m_state[XiLen] ^= 1;
}
}
}