Files
SuperVPN/output/Libraries/BouncyCastle.Crypto/Org/BouncyCastle/Crypto/Macs/SipHash.cs
2025-10-09 09:57:24 +09:00

185 lines
3.3 KiB
C#

using System;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Utilities;
namespace Org.BouncyCastle.Crypto.Macs;
public class SipHash : IMac
{
protected readonly int c;
protected readonly int d;
protected long k0;
protected long k1;
protected long v0;
protected long v1;
protected long v2;
protected long v3;
protected long m = 0L;
protected int wordPos = 0;
protected int wordCount = 0;
public virtual string AlgorithmName => "SipHash-" + c + "-" + d;
public SipHash()
: this(2, 4)
{
}
public SipHash(int c, int d)
{
this.c = c;
this.d = d;
}
public virtual int GetMacSize()
{
return 8;
}
public virtual void Init(ICipherParameters parameters)
{
if (!(parameters is KeyParameter keyParameter))
{
throw new ArgumentException("must be an instance of KeyParameter", "parameters");
}
byte[] key = keyParameter.GetKey();
if (key.Length != 16)
{
throw new ArgumentException("must be a 128-bit key", "parameters");
}
k0 = (long)Pack.LE_To_UInt64(key, 0);
k1 = (long)Pack.LE_To_UInt64(key, 8);
Reset();
}
public virtual void Update(byte input)
{
m = (m >>> 8) | (long)((ulong)input << 56);
if (++wordPos == 8)
{
ProcessMessageWord();
wordPos = 0;
}
}
public virtual void BlockUpdate(byte[] input, int offset, int length)
{
int i = 0;
int num = length & -8;
if (wordPos == 0)
{
for (; i < num; i += 8)
{
m = (long)Pack.LE_To_UInt64(input, offset + i);
ProcessMessageWord();
}
for (; i < length; i++)
{
m = (m >>> 8) | (long)((ulong)input[offset + i] << 56);
}
wordPos = length - num;
return;
}
int num2 = wordPos << 3;
for (; i < num; i += 8)
{
ulong num3 = Pack.LE_To_UInt64(input, offset + i);
m = (long)(num3 << num2) | (m >>> -num2);
ProcessMessageWord();
m = (long)num3;
}
for (; i < length; i++)
{
m = (m >>> 8) | (long)((ulong)input[offset + i] << 56);
if (++wordPos == 8)
{
ProcessMessageWord();
wordPos = 0;
}
}
}
public virtual long DoFinal()
{
m >>>= 7 - wordPos << 3;
m >>>= 8;
m |= (long)((wordCount << 3) + wordPos) << 56;
ProcessMessageWord();
v2 ^= 255L;
ApplySipRounds(d);
long result = v0 ^ v1 ^ v2 ^ v3;
Reset();
return result;
}
public virtual int DoFinal(byte[] output, int outOff)
{
long n = DoFinal();
Pack.UInt64_To_LE((ulong)n, output, outOff);
return 8;
}
public virtual void Reset()
{
v0 = k0 ^ 0x736F6D6570736575L;
v1 = k1 ^ 0x646F72616E646F6DL;
v2 = k0 ^ 0x6C7967656E657261L;
v3 = k1 ^ 0x7465646279746573L;
m = 0L;
wordPos = 0;
wordCount = 0;
}
protected virtual void ProcessMessageWord()
{
wordCount++;
v3 ^= m;
ApplySipRounds(c);
v0 ^= m;
}
protected virtual void ApplySipRounds(int n)
{
long num = v0;
long num2 = v1;
long num3 = v2;
long num4 = v3;
for (int i = 0; i < n; i++)
{
num += num2;
num3 += num4;
num2 = RotateLeft(num2, 13);
num4 = RotateLeft(num4, 16);
num2 ^= num;
num4 ^= num3;
num = RotateLeft(num, 32);
num3 += num2;
num += num4;
num2 = RotateLeft(num2, 17);
num4 = RotateLeft(num4, 21);
num2 ^= num3;
num4 ^= num;
num3 = RotateLeft(num3, 32);
}
v0 = num;
v1 = num2;
v2 = num3;
v3 = num4;
}
protected static long RotateLeft(long x, int n)
{
return (x << n) | (x >>> -n);
}
}