FNV1aX.cs

FNV1a 128…1024Bit Hashing BigInteger

using System;
using System.Numerics;
using System.Security.Cryptography;
using static System.Globalization.CultureInfo;
using static System.Globalization.NumberStyles;
using static System.Numerics.BigInteger;
[Serializable]
public class FNV1aX : HashAlgorithm
{
private static int _bitWidth;
private BigInteger _h1;
public BigInteger _mod;
public BigInteger _offset;
private BigInteger _prime;
public FNV1aX(int bitWidth = 128)
{
_bitWidth = bitWidth;
SetBitWidthPom(bitWidth);
_h1 = _offset;
}
public override int HashSize => _bitWidth;
private void SetBitWidthPom(int bitWidth)
{
switch (bitWidth)
{
//case 32:
// _prime = Parse("1000193", AllowHexSpecifier, InvariantCulture);
// _offset = Parse("811c9dc5", AllowHexSpecifier, InvariantCulture);
// _mod = Parse("10000000", AllowHexSpecifier, InvariantCulture);
// break;
//case 64:
// _prime = Parse("100000001B3", AllowHexSpecifier, InvariantCulture);
// _offset = Parse("CBF29CE484222325", AllowHexSpecifier, InvariantCulture);
// _mod = Parse("1000000000000000", AllowHexSpecifier, InvariantCulture);
// break;
case 128:
_prime = Parse("0000000001000000000000000000013B", AllowHexSpecifier, InvariantCulture);
_offset = Parse("6c62272e07bb014262b821756295c58d", AllowHexSpecifier, InvariantCulture);
_mod = Parse("10000000000000000000000000000000", AllowHexSpecifier, InvariantCulture);
break;
case 256:
_prime = Parse("0000000000000000000001000000000000000000000000000000000000000163", AllowHexSpecifier, InvariantCulture);
_offset = Parse("dd268dbcaac550362d98c384c4e576ccc8b1536847b6bbb31023b4c8caee0535", AllowHexSpecifier, InvariantCulture);
_mod = Parse("1000000000000000000000000000000000000000000000000000000000000000", AllowHexSpecifier, InvariantCulture);
break;
case 512:
_prime = Parse("00000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000157",
AllowHexSpecifier, InvariantCulture);
_offset = Parse("b86db0b1171f4416dca1e50f309990acac87d059c90000000000000000000d21e948f68a34c192f62ea79bc942dbe7ce182036415f56e34bac982aac4afe9fd9",
AllowHexSpecifier, InvariantCulture);
_mod = Parse("10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", AllowHexSpecifier,
InvariantCulture);
break;
case 1024:
_prime = Parse(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018D",
AllowHexSpecifier, InvariantCulture);
_offset = Parse(
"0000000000000000005f7a76758ecc4d32e56d5a591028b74b29fc4223fdada16c3bf34eda3674da9a21d9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c6d7eb6e73802734510a555f256cc005ae556bde8cc9c6a93b21aff4b16c71ee90b3",
AllowHexSpecifier, InvariantCulture);
_mod = Parse(
"1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
AllowHexSpecifier, InvariantCulture);
break;
}
}
public override void Initialize()
{
_h1 = _offset;
}
protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
{
Hash(bytes, ibStart, cbSize);
}
private unsafe void Hash(byte[] bytes, int ibStart, int cbSize)
{
if (bytes == null)
return;
if (ibStart >= bytes.Length || cbSize > bytes.Length)
return;
fixed (byte* pb = bytes)
{
var nb = pb + ibStart;
while (cbSize >= 8)
{
_h1 ^= *(ulong*) nb;
_h1 *= _prime;
_h1 %= _mod;
nb += 8;
cbSize -= 8;
}
switch (cbSize & 7)
{
case 7:
_h1 ^= *(ulong*) (nb + 6);
_h1 *= _prime;
_h1 %= _mod;
goto case 6;
case 6:
_h1 ^= *(ulong*) (nb + 5);
_h1 *= _prime;
_h1 %= _mod;
goto case 5;
case 5:
_h1 ^= *(ulong*) (nb + 4);
_h1 *= _prime;
_h1 %= _mod;
goto case 4;
case 4:
_h1 ^= *(ulong*) (nb + 3);
_h1 *= _prime;
_h1 %= _mod;
goto case 3;
case 3:
_h1 ^= *(ulong*) (nb + 2);
_h1 *= _prime;
_h1 %= _mod;
goto case 2;
case 2:
_h1 ^= *(ulong*) (nb + 1);
_h1 *= _prime;
_h1 %= _mod;
goto case 1;
case 1:
_h1 ^= *nb;
_h1 *= _prime;
_h1 %= _mod;
break;
}
}
}
protected override byte[] HashFinal()
{
return _h1.ToByteArray();
}
}
using System; using System.Numerics; using System.Security.Cryptography; using static System.Globalization.CultureInfo; using static System.Globalization.NumberStyles; using static System.Numerics.BigInteger; [Serializable] public class FNV1aX : HashAlgorithm { private static int _bitWidth; private BigInteger _h1; public BigInteger _mod; public BigInteger _offset; private BigInteger _prime; public FNV1aX(int bitWidth = 128) { _bitWidth = bitWidth; SetBitWidthPom(bitWidth); _h1 = _offset; } public override int HashSize => _bitWidth; private void SetBitWidthPom(int bitWidth) { switch (bitWidth) { //case 32: // _prime = Parse("1000193", AllowHexSpecifier, InvariantCulture); // _offset = Parse("811c9dc5", AllowHexSpecifier, InvariantCulture); // _mod = Parse("10000000", AllowHexSpecifier, InvariantCulture); // break; //case 64: // _prime = Parse("100000001B3", AllowHexSpecifier, InvariantCulture); // _offset = Parse("CBF29CE484222325", AllowHexSpecifier, InvariantCulture); // _mod = Parse("1000000000000000", AllowHexSpecifier, InvariantCulture); // break; case 128: _prime = Parse("0000000001000000000000000000013B", AllowHexSpecifier, InvariantCulture); _offset = Parse("6c62272e07bb014262b821756295c58d", AllowHexSpecifier, InvariantCulture); _mod = Parse("10000000000000000000000000000000", AllowHexSpecifier, InvariantCulture); break; case 256: _prime = Parse("0000000000000000000001000000000000000000000000000000000000000163", AllowHexSpecifier, InvariantCulture); _offset = Parse("dd268dbcaac550362d98c384c4e576ccc8b1536847b6bbb31023b4c8caee0535", AllowHexSpecifier, InvariantCulture); _mod = Parse("1000000000000000000000000000000000000000000000000000000000000000", AllowHexSpecifier, InvariantCulture); break; case 512: _prime = Parse("00000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000157", AllowHexSpecifier, InvariantCulture); _offset = Parse("b86db0b1171f4416dca1e50f309990acac87d059c90000000000000000000d21e948f68a34c192f62ea79bc942dbe7ce182036415f56e34bac982aac4afe9fd9", AllowHexSpecifier, InvariantCulture); _mod = Parse("10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", AllowHexSpecifier, InvariantCulture); break; case 1024: _prime = Parse( "000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018D", AllowHexSpecifier, InvariantCulture); _offset = Parse( "0000000000000000005f7a76758ecc4d32e56d5a591028b74b29fc4223fdada16c3bf34eda3674da9a21d9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c6d7eb6e73802734510a555f256cc005ae556bde8cc9c6a93b21aff4b16c71ee90b3", AllowHexSpecifier, InvariantCulture); _mod = Parse( "1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", AllowHexSpecifier, InvariantCulture); break; } } public override void Initialize() { _h1 = _offset; } protected override void HashCore(byte[] bytes, int ibStart, int cbSize) { Hash(bytes, ibStart, cbSize); } private unsafe void Hash(byte[] bytes, int ibStart, int cbSize) { if (bytes == null) return; if (ibStart >= bytes.Length || cbSize > bytes.Length) return; fixed (byte* pb = bytes) { var nb = pb + ibStart; while (cbSize >= 8) { _h1 ^= *(ulong*) nb; _h1 *= _prime; _h1 %= _mod; nb += 8; cbSize -= 8; } switch (cbSize & 7) { case 7: _h1 ^= *(ulong*) (nb + 6); _h1 *= _prime; _h1 %= _mod; goto case 6; case 6: _h1 ^= *(ulong*) (nb + 5); _h1 *= _prime; _h1 %= _mod; goto case 5; case 5: _h1 ^= *(ulong*) (nb + 4); _h1 *= _prime; _h1 %= _mod; goto case 4; case 4: _h1 ^= *(ulong*) (nb + 3); _h1 *= _prime; _h1 %= _mod; goto case 3; case 3: _h1 ^= *(ulong*) (nb + 2); _h1 *= _prime; _h1 %= _mod; goto case 2; case 2: _h1 ^= *(ulong*) (nb + 1); _h1 *= _prime; _h1 %= _mod; goto case 1; case 1: _h1 ^= *nb; _h1 *= _prime; _h1 %= _mod; break; } } } protected override byte[] HashFinal() { return _h1.ToByteArray(); } }
using System;
using System.Numerics;
using System.Security.Cryptography;
using static System.Globalization.CultureInfo;
using static System.Globalization.NumberStyles;
using static System.Numerics.BigInteger;
[Serializable]
public class FNV1aX : HashAlgorithm
{
    private static int        _bitWidth;
    private        BigInteger _h1;
    public         BigInteger _mod;
    public         BigInteger _offset;
    private        BigInteger _prime;
    public FNV1aX(int bitWidth = 128)
    {
        _bitWidth = bitWidth;
        SetBitWidthPom(bitWidth);
        _h1 = _offset;
    }
    public override int HashSize => _bitWidth;
    private void SetBitWidthPom(int bitWidth)
    {
        switch (bitWidth)
        {
            //case 32:
            //    _prime  = Parse("1000193", AllowHexSpecifier, InvariantCulture);
            //    _offset = Parse("811c9dc5", AllowHexSpecifier, InvariantCulture);
            //    _mod    = Parse("10000000", AllowHexSpecifier, InvariantCulture);
            //    break;
            //case 64:
            //    _prime  = Parse("100000001B3", AllowHexSpecifier, InvariantCulture);
            //    _offset = Parse("CBF29CE484222325", AllowHexSpecifier, InvariantCulture);
            //    _mod    = Parse("1000000000000000", AllowHexSpecifier, InvariantCulture);
            //    break;
            case 128:
                _prime = Parse("0000000001000000000000000000013B", AllowHexSpecifier, InvariantCulture);
                _offset = Parse("6c62272e07bb014262b821756295c58d", AllowHexSpecifier, InvariantCulture);
                _mod = Parse("10000000000000000000000000000000", AllowHexSpecifier, InvariantCulture);
                break;
            case 256:
                _prime  = Parse("0000000000000000000001000000000000000000000000000000000000000163", AllowHexSpecifier, InvariantCulture);
                _offset = Parse("dd268dbcaac550362d98c384c4e576ccc8b1536847b6bbb31023b4c8caee0535", AllowHexSpecifier, InvariantCulture);
                _mod    = Parse("1000000000000000000000000000000000000000000000000000000000000000", AllowHexSpecifier, InvariantCulture);
                break;
            case 512:
                _prime = Parse("00000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000157",
                    AllowHexSpecifier, InvariantCulture);
                _offset = Parse("b86db0b1171f4416dca1e50f309990acac87d059c90000000000000000000d21e948f68a34c192f62ea79bc942dbe7ce182036415f56e34bac982aac4afe9fd9",
                    AllowHexSpecifier, InvariantCulture);
                _mod = Parse("10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", AllowHexSpecifier,
                    InvariantCulture);
                break;
            case 1024:
                _prime = Parse(
                    "000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018D",
                    AllowHexSpecifier, InvariantCulture);
                _offset = Parse(
                    "0000000000000000005f7a76758ecc4d32e56d5a591028b74b29fc4223fdada16c3bf34eda3674da9a21d9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c6d7eb6e73802734510a555f256cc005ae556bde8cc9c6a93b21aff4b16c71ee90b3",
                    AllowHexSpecifier, InvariantCulture);
                _mod = Parse(
                    "1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
                    AllowHexSpecifier, InvariantCulture);
                break;
        }
    }
    public override void Initialize()
    {
        _h1 = _offset;
    }
    protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
    {
        Hash(bytes, ibStart, cbSize);
    }
    private unsafe void Hash(byte[] bytes, int ibStart, int cbSize)
    {
        if (bytes == null)
            return;
        if (ibStart >= bytes.Length || cbSize > bytes.Length)
            return;
        fixed (byte* pb = bytes)
        {
            var nb = pb + ibStart;
            while (cbSize >= 8)
            {
                _h1    ^= *(ulong*) nb;
                _h1    *= _prime;
                _h1    %= _mod;
                nb     += 8;
                cbSize -= 8;
            }
            switch (cbSize & 7)
            {
                case 7:
                    _h1 ^= *(ulong*) (nb + 6);
                    _h1 *= _prime;
                    _h1 %= _mod;
                    goto case 6;
                case 6:
                    _h1 ^= *(ulong*) (nb + 5);
                    _h1 *= _prime;
                    _h1 %= _mod;
                    goto case 5;
                case 5:
                    _h1 ^= *(ulong*) (nb + 4);
                    _h1 *= _prime;
                    _h1 %= _mod;
                    goto case 4;
                case 4:
                    _h1 ^= *(ulong*) (nb + 3);
                    _h1 *= _prime;
                    _h1 %= _mod;
                    goto case 3;
                case 3:
                    _h1 ^= *(ulong*) (nb + 2);
                    _h1 *= _prime;
                    _h1 %= _mod;
                    goto case 2;
                case 2:
                    _h1 ^= *(ulong*) (nb + 1);
                    _h1 *= _prime;
                    _h1 %= _mod;
                    goto case 1;
                case 1:
                    _h1 ^= *nb;
                    _h1 *= _prime;
                    _h1 %= _mod;
                    break;
            }
        }
    }
    protected override byte[] HashFinal()
    {
        return _h1.ToByteArray();
    }
}

FNV1a128b.cs

FNV1a Patterned 128Bit Hashing Algorithm using BigInteger

using System.Numerics;
using System.Security.Cryptography;
public class FNV1a128b : HashAlgorithm
{
private readonly BigInteger K = "309485009821345068724781371".BigIntegerBase10();
private readonly BigInteger M = "340282366920938463463374607431768211456".BigIntegerBase10();
private BigInteger _hash;
private readonly BigInteger Seed = "144066263297769815596495629667062367629".BigIntegerBase10();
public FNV1a128b()
{
_hash = Seed;
}
public FNV1a128b(BigInteger seed)
{
Seed = seed;
_hash = Seed;
}
public override int HashSize => 128;
public override void Initialize()
{
_hash = Seed;
}
protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
{
Hash128(bytes, ibStart, cbSize);
}
protected override byte[] HashFinal()
{
return _hash.ToByteArray();
}
private unsafe void Hash128(byte[] bytes, int ibStart, int cbSize)
{
fixed (byte* pb = bytes)
{
var np = pb + ibStart;
for (; cbSize > 0; --cbSize, np++)
_hash = ((_hash ^ *np) * K) % M;
}
}
}
using System.Numerics; using System.Security.Cryptography; public class FNV1a128b : HashAlgorithm { private readonly BigInteger K = "309485009821345068724781371".BigIntegerBase10(); private readonly BigInteger M = "340282366920938463463374607431768211456".BigIntegerBase10(); private BigInteger _hash; private readonly BigInteger Seed = "144066263297769815596495629667062367629".BigIntegerBase10(); public FNV1a128b() { _hash = Seed; } public FNV1a128b(BigInteger seed) { Seed = seed; _hash = Seed; } public override int HashSize => 128; public override void Initialize() { _hash = Seed; } protected override void HashCore(byte[] bytes, int ibStart, int cbSize) { Hash128(bytes, ibStart, cbSize); } protected override byte[] HashFinal() { return _hash.ToByteArray(); } private unsafe void Hash128(byte[] bytes, int ibStart, int cbSize) { fixed (byte* pb = bytes) { var np = pb + ibStart; for (; cbSize > 0; --cbSize, np++) _hash = ((_hash ^ *np) * K) % M; } } }
using System.Numerics;
using System.Security.Cryptography;
public class FNV1a128b : HashAlgorithm
{
    private readonly BigInteger K = "309485009821345068724781371".BigIntegerBase10();
    private readonly BigInteger M = "340282366920938463463374607431768211456".BigIntegerBase10();
    private          BigInteger _hash;
    private readonly BigInteger Seed = "144066263297769815596495629667062367629".BigIntegerBase10();
    public FNV1a128b()
    {
        _hash = Seed;
    }
    public FNV1a128b(BigInteger seed)
    {
        Seed  = seed;
        _hash = Seed;
    }
    public override int HashSize => 128;
    public override void Initialize()
    {
        _hash = Seed;
    }
    protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
    {
        Hash128(bytes, ibStart, cbSize);
    }
    protected override byte[] HashFinal()
    {
        return _hash.ToByteArray();
    }
    private unsafe void Hash128(byte[] bytes, int ibStart, int cbSize)
    {
        fixed (byte* pb = bytes)
        {
            var np = pb + ibStart;
            for (; cbSize > 0; --cbSize, np++)
                _hash = ((_hash ^ *np) * K) % M;
        }
    }
}

KSM128.cs

Re-Work of the Sha3 Keccak Sponge for 128 Bit Hashing

using System;
using System.Runtime.CompilerServices;
public class KSM128 : HashAlgorithmEx
{
private readonly int _outputLength;
private readonly int _rateBytes;
private readonly ulong[] _roundConstants =
{
0x0000000000000001,
0x0000000000008082,
0x800000000000808A,
0x8000000080008000,
0x000000000000808B,
0x0000000080000001,
0x8000000080008081,
0x8000000000008009,
0x000000000000008A,
0x0000000000000088,
0x0000000080008009,
0x000000008000000A,
0x000000008000808B,
0x800000000000008B,
0x8000000000008089,
0x8000000000008003,
0x8000000000008002,
0x8000000000000080,
0x000000000000800A,
0x800000008000000A,
0x8000000080008081,
0x8000000000008080,
0x0000000080000001,
0x8000000080008008
};
private readonly ulong[] _seed;
private int _blockSize;
private int _input;
private int _output;
private byte[] _result;
private ulong[] _state;
public int HashLength;
public int Rounds = 24;
public KSM128(int size, int rounds = 24, ulong[] seed = null)
{
if (rounds > 24)
throw new Exception($"Maximum rounds allowed is {24}");
var MaxBR = (64 >> 3) * 5;
var sizeBytes = size >> 3;
var rateBytes = MaxBR - (sizeBytes << 1);
var MaxSize = ((MaxBR - 8) >> 1) << 3;
if (rateBytes < 8)
throw new Exception($"Maximum size allowed is {MaxSize} Bits with {128} bit Width specified. Specified Size is {size} Bits.");
var outputLength = size >> 3;
_rateBytes = rateBytes;
_outputLength = outputLength;
HashLength = outputLength;
_seed = seed;
}
public override void Initialize()
{
_blockSize = 0;
_input = 0;
_output = 0;
_state = new ulong[5];
_result = new byte[_outputLength];
if (_seed != null && _seed[0] != 0)
{
for (var i = 0; i < _seed.Length && i < _state.Length; ++i)
_state[i] = _seed[i];
Permute(_state);
}
}
public void Absorb(byte[] array, int start, int size)
{
while (size > 0)
{
_blockSize = Math.Min(size, _rateBytes);
for (var index = start; index < _blockSize; ++index)
{
var num = Convert.ToByte(Buffer.GetByte(_state, index) ^ array[index + _input]);
Buffer.SetByte(_state, index, num);
}
_input += _blockSize;
size -= _blockSize;
if (_blockSize == _rateBytes)
{
Permute(_state);
_blockSize = 0;
}
}
}
public byte[] Squeeze()
{
Buffer.SetByte(_state, _blockSize, Convert.ToByte(Buffer.GetByte(_state, _blockSize) ^ 6));
Buffer.SetByte(_state, _rateBytes - 1, Convert.ToByte(Buffer.GetByte(_state, _rateBytes - 1) ^ 128));
Permute(_state);
var outputLength = _outputLength;
while (outputLength > 0)
{
_blockSize = Math.Min(outputLength, _rateBytes);
Buffer.BlockCopy(_state, 0, _result, _output, _blockSize);
_output += _blockSize;
outputLength -= _blockSize;
if (outputLength > 0)
Permute(_state);
}
return _result;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Permute(ulong[] state)
{
for (var round = 0; round < Rounds; ++round)
{
Theta(out var C0, state, out var C1, out var C2, out var C3, out var C4);
RhoPi(state);
Chi(ref C0, state, ref C1, ref C2, ref C3, ref C4);
Iota(round, state);
}
}
private static void Theta(out ulong C0, ulong[] state, out ulong C1, out ulong C2, out ulong C3, out ulong C4)
{
C0 = state[0] ^ state[4];
C1 = state[1] ^ state[0];
C2 = state[2] ^ state[1];
C3 = state[3] ^ state[2];
C4 = state[4] ^ state[3];
var D0 = Rol(C1, 1) ^ C4;
var D1 = Rol(C2, 1) ^ C0;
var D2 = Rol(C3, 1) ^ C1;
var D3 = Rol(C4, 1) ^ C2;
var D4 = Rol(C0, 1) ^ C3;
state[0] ^= D0;
state[1] ^= D1;
state[2] ^= D2;
state[3] ^= D3;
state[4] ^= D4;
}
private static void RhoPi(ulong[] state)
{
var a = Rol(state[1], 1);
state[1] = Rol(state[4], 44);
state[4] = Rol(state[3], 43);
state[3] = Rol(state[2], 14);
state[4] = Rol(state[1], 21);
state[2] = a;
}
private void Iota(int round, ulong[] state)
{
state[0] ^= _roundConstants[round];
}
private static void Chi(ref ulong C0, ulong[] state, ref ulong C1, ref ulong C2, ref ulong C3, ref ulong C4)
{
C0 = state[0] ^ (~state[1] & state[2]);
C1 = state[1] ^ (~state[2] & state[3]);
C2 = state[2] ^ (~state[3] & state[4]);
C3 = state[3] ^ (~state[4] & state[0]);
C4 = state[4] ^ (~state[0] & state[1]);
state[0] = C0;
state[1] = C1;
state[2] = C2;
state[3] = C3;
state[4] = C4;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong Rol(ulong x, byte y)
{
return (x << y) | (x >> (64 - y));
}
protected override void HashCore(byte[] array, int ibStart, int cbSize)
{
Initialize();
Absorb(array, ibStart, cbSize);
}
protected override byte[] HashFinal()
{
return Squeeze();
}
}
using System; using System.Runtime.CompilerServices; public class KSM128 : HashAlgorithmEx { private readonly int _outputLength; private readonly int _rateBytes; private readonly ulong[] _roundConstants = { 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000, 0x000000000000808B, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009, 0x000000000000008A, 0x0000000000000088, 0x0000000080008009, 0x000000008000000A, 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, 0x000000000000800A, 0x800000008000000A, 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 }; private readonly ulong[] _seed; private int _blockSize; private int _input; private int _output; private byte[] _result; private ulong[] _state; public int HashLength; public int Rounds = 24; public KSM128(int size, int rounds = 24, ulong[] seed = null) { if (rounds > 24) throw new Exception($"Maximum rounds allowed is {24}"); var MaxBR = (64 >> 3) * 5; var sizeBytes = size >> 3; var rateBytes = MaxBR - (sizeBytes << 1); var MaxSize = ((MaxBR - 8) >> 1) << 3; if (rateBytes < 8) throw new Exception($"Maximum size allowed is {MaxSize} Bits with {128} bit Width specified. Specified Size is {size} Bits."); var outputLength = size >> 3; _rateBytes = rateBytes; _outputLength = outputLength; HashLength = outputLength; _seed = seed; } public override void Initialize() { _blockSize = 0; _input = 0; _output = 0; _state = new ulong[5]; _result = new byte[_outputLength]; if (_seed != null && _seed[0] != 0) { for (var i = 0; i < _seed.Length && i < _state.Length; ++i) _state[i] = _seed[i]; Permute(_state); } } public void Absorb(byte[] array, int start, int size) { while (size > 0) { _blockSize = Math.Min(size, _rateBytes); for (var index = start; index < _blockSize; ++index) { var num = Convert.ToByte(Buffer.GetByte(_state, index) ^ array[index + _input]); Buffer.SetByte(_state, index, num); } _input += _blockSize; size -= _blockSize; if (_blockSize == _rateBytes) { Permute(_state); _blockSize = 0; } } } public byte[] Squeeze() { Buffer.SetByte(_state, _blockSize, Convert.ToByte(Buffer.GetByte(_state, _blockSize) ^ 6)); Buffer.SetByte(_state, _rateBytes - 1, Convert.ToByte(Buffer.GetByte(_state, _rateBytes - 1) ^ 128)); Permute(_state); var outputLength = _outputLength; while (outputLength > 0) { _blockSize = Math.Min(outputLength, _rateBytes); Buffer.BlockCopy(_state, 0, _result, _output, _blockSize); _output += _blockSize; outputLength -= _blockSize; if (outputLength > 0) Permute(_state); } return _result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void Permute(ulong[] state) { for (var round = 0; round < Rounds; ++round) { Theta(out var C0, state, out var C1, out var C2, out var C3, out var C4); RhoPi(state); Chi(ref C0, state, ref C1, ref C2, ref C3, ref C4); Iota(round, state); } } private static void Theta(out ulong C0, ulong[] state, out ulong C1, out ulong C2, out ulong C3, out ulong C4) { C0 = state[0] ^ state[4]; C1 = state[1] ^ state[0]; C2 = state[2] ^ state[1]; C3 = state[3] ^ state[2]; C4 = state[4] ^ state[3]; var D0 = Rol(C1, 1) ^ C4; var D1 = Rol(C2, 1) ^ C0; var D2 = Rol(C3, 1) ^ C1; var D3 = Rol(C4, 1) ^ C2; var D4 = Rol(C0, 1) ^ C3; state[0] ^= D0; state[1] ^= D1; state[2] ^= D2; state[3] ^= D3; state[4] ^= D4; } private static void RhoPi(ulong[] state) { var a = Rol(state[1], 1); state[1] = Rol(state[4], 44); state[4] = Rol(state[3], 43); state[3] = Rol(state[2], 14); state[4] = Rol(state[1], 21); state[2] = a; } private void Iota(int round, ulong[] state) { state[0] ^= _roundConstants[round]; } private static void Chi(ref ulong C0, ulong[] state, ref ulong C1, ref ulong C2, ref ulong C3, ref ulong C4) { C0 = state[0] ^ (~state[1] & state[2]); C1 = state[1] ^ (~state[2] & state[3]); C2 = state[2] ^ (~state[3] & state[4]); C3 = state[3] ^ (~state[4] & state[0]); C4 = state[4] ^ (~state[0] & state[1]); state[0] = C0; state[1] = C1; state[2] = C2; state[3] = C3; state[4] = C4; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static ulong Rol(ulong x, byte y) { return (x << y) | (x >> (64 - y)); } protected override void HashCore(byte[] array, int ibStart, int cbSize) { Initialize(); Absorb(array, ibStart, cbSize); } protected override byte[] HashFinal() { return Squeeze(); } }
using System;
using System.Runtime.CompilerServices;
public class KSM128 : HashAlgorithmEx
{
    private readonly int _outputLength;
    private readonly int _rateBytes;
    private readonly ulong[] _roundConstants =
    {
        0x0000000000000001,
        0x0000000000008082,
        0x800000000000808A,
        0x8000000080008000,
        0x000000000000808B,
        0x0000000080000001,
        0x8000000080008081,
        0x8000000000008009,
        0x000000000000008A,
        0x0000000000000088,
        0x0000000080008009,
        0x000000008000000A,
        0x000000008000808B,
        0x800000000000008B,
        0x8000000000008089,
        0x8000000000008003,
        0x8000000000008002,
        0x8000000000000080,
        0x000000000000800A,
        0x800000008000000A,
        0x8000000080008081,
        0x8000000000008080,
        0x0000000080000001,
        0x8000000080008008
    };
    private readonly ulong[] _seed;
    private          int     _blockSize;
    private          int     _input;
    private          int     _output;
    private          byte[]  _result;
    private          ulong[] _state;
    public           int     HashLength;
    public           int     Rounds = 24;
    public KSM128(int size, int rounds = 24, ulong[] seed = null)
    {
        if (rounds > 24)
            throw new Exception($"Maximum rounds allowed is {24}");
        var MaxBR     = (64 >> 3) * 5;
        var sizeBytes = size >> 3;
        var rateBytes = MaxBR - (sizeBytes << 1);
        var MaxSize   = ((MaxBR - 8)       >> 1) << 3;
        if (rateBytes < 8)
            throw new Exception($"Maximum size allowed is {MaxSize} Bits with {128} bit Width specified. Specified Size is {size} Bits.");
        var outputLength = size >> 3;
        _rateBytes    = rateBytes;
        _outputLength = outputLength;
        HashLength    = outputLength;
        _seed         = seed;
    }
    public override void Initialize()
    {
        _blockSize = 0;
        _input     = 0;
        _output    = 0;
        _state     = new ulong[5];
        _result    = new byte[_outputLength];
        if (_seed != null && _seed[0] != 0)
        {
            for (var i = 0; i < _seed.Length && i < _state.Length; ++i)
                _state[i] = _seed[i];
            Permute(_state);
        }
    }
    public void Absorb(byte[] array, int start, int size)
    {
        while (size > 0)
        {
            _blockSize = Math.Min(size, _rateBytes);
            for (var index = start; index < _blockSize; ++index)
            {
                var num = Convert.ToByte(Buffer.GetByte(_state, index) ^ array[index + _input]);
                Buffer.SetByte(_state, index, num);
            }
            _input += _blockSize;
            size   -= _blockSize;
            if (_blockSize == _rateBytes)
            {
                Permute(_state);
                _blockSize = 0;
            }
        }
    }
    public byte[] Squeeze()
    {
        Buffer.SetByte(_state, _blockSize,     Convert.ToByte(Buffer.GetByte(_state, _blockSize)     ^ 6));
        Buffer.SetByte(_state, _rateBytes - 1, Convert.ToByte(Buffer.GetByte(_state, _rateBytes - 1) ^ 128));
        Permute(_state);
        var outputLength = _outputLength;
        while (outputLength > 0)
        {
            _blockSize = Math.Min(outputLength, _rateBytes);
            Buffer.BlockCopy(_state, 0, _result, _output, _blockSize);
            _output      += _blockSize;
            outputLength -= _blockSize;
            if (outputLength > 0)
                Permute(_state);
        }
        return _result;
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private void Permute(ulong[] state)
    {
        for (var round = 0; round < Rounds; ++round)
        {
            Theta(out var C0, state, out var C1, out var C2, out var C3, out var C4);
            RhoPi(state);
            Chi(ref C0, state, ref C1, ref C2, ref C3, ref C4);
            Iota(round, state);
        }
    }
    private static void Theta(out ulong C0, ulong[] state, out ulong C1, out ulong C2, out ulong C3, out ulong C4)
    {
        C0 = state[0] ^ state[4];
        C1 = state[1] ^ state[0];
        C2 = state[2] ^ state[1];
        C3 = state[3] ^ state[2];
        C4 = state[4] ^ state[3];
        var D0 = Rol(C1, 1) ^ C4;
        var D1 = Rol(C2, 1) ^ C0;
        var D2 = Rol(C3, 1) ^ C1;
        var D3 = Rol(C4, 1) ^ C2;
        var D4 = Rol(C0, 1) ^ C3;
        state[0] ^= D0;
        state[1] ^= D1;
        state[2] ^= D2;
        state[3] ^= D3;
        state[4] ^= D4;
    }
    private static void RhoPi(ulong[] state)
    {
        var a = Rol(state[1], 1);
        state[1] = Rol(state[4], 44);
        state[4] = Rol(state[3], 43);
        state[3] = Rol(state[2], 14);
        state[4] = Rol(state[1], 21);
        state[2] = a;
    }
    private void Iota(int round, ulong[] state)
    {
        state[0] ^= _roundConstants[round];
    }
    private static void Chi(ref ulong C0, ulong[] state, ref ulong C1, ref ulong C2, ref ulong C3, ref ulong C4)
    {
        C0       = state[0] ^ (~state[1] & state[2]);
        C1       = state[1] ^ (~state[2] & state[3]);
        C2       = state[2] ^ (~state[3] & state[4]);
        C3       = state[3] ^ (~state[4] & state[0]);
        C4       = state[4] ^ (~state[0] & state[1]);
        state[0] = C0;
        state[1] = C1;
        state[2] = C2;
        state[3] = C3;
        state[4] = C4;
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static ulong Rol(ulong x, byte y)
    {
        return (x << y) | (x >> (64 - y));
    }
    protected override void HashCore(byte[] array, int ibStart, int cbSize)
    {
        Initialize();
        Absorb(array, ibStart, cbSize);
    }
    protected override byte[] HashFinal()
    {
        return Squeeze();
    }
}