Created
July 27, 2020 04:39
-
-
Save mjs3339/618932005aae8e6af75e3ed1b8850343 to your computer and use it in GitHub Desktop.
Uses Sha3 to Shuffle Primitive Arrays
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
public class ArrayMixer | |
{ | |
private readonly SHA3ModInt _alg; | |
private readonly int _moveSize; | |
public ArrayMixer(int hashSize = 256) | |
{ | |
_alg = new SHA3ModInt(hashSize); | |
_moveSize = _alg.ComputeHash(2.GetBytes()).Length; | |
} | |
public byte[] Mix(byte[] buf, int times = 1) | |
{ | |
var bufferSize = buf.Length; | |
var lBuffer = new byte[_moveSize]; | |
var oBuffer = new byte[bufferSize]; | |
for (var i = 0; i < times; ++i) | |
{ | |
var bytesSuffled = 0; | |
var moveSize = _moveSize; | |
var p = 0; | |
while (true) | |
{ | |
var rBytesShuffle = bufferSize - bytesSuffled; | |
if (rBytesShuffle < moveSize) | |
moveSize = rBytesShuffle; | |
if (rBytesShuffle <= 0) | |
break; | |
Buffer.BlockCopy(buf, p, lBuffer, 0, moveSize); | |
lBuffer = _alg.ComputeHash(lBuffer); | |
Buffer.BlockCopy(lBuffer, 0, oBuffer, p, moveSize); | |
p += moveSize; | |
bytesSuffled += moveSize; | |
} | |
Buffer.BlockCopy(oBuffer, 0, buf, 0, bufferSize); | |
} | |
lBuffer.Fill(0); | |
oBuffer.Fill(0); | |
return buf; | |
} | |
public ushort[] Mix(ushort[] buf, int times = 1) | |
{ | |
var bb = buf.GetBytes(); | |
return Mix(bb, times).ToUShortArray(); | |
} | |
public uint[] Mix(uint[] buf, int times = 1) | |
{ | |
var bb = buf.GetBytes(); | |
return Mix(bb, times).ToUIntArray(); | |
} | |
public ulong[] Mix(ulong[] buf, int times = 1) | |
{ | |
var bb = buf.GetBytes(); | |
return Mix(bb, times).ToULongArray(); | |
} | |
private static ulong[] ByteArrayToULongArray(byte[] ba, int finalSize) | |
{ | |
var minSize = ba.Length / 8; | |
if (finalSize < minSize) | |
finalSize = minSize; | |
ba = PadULong(ba); | |
var result = new ulong[finalSize]; | |
for (var i = 0; i < ba.Length; i += 8) | |
Buffer.BlockCopy(ba, i, result, i, 8); | |
return result; | |
} | |
private static byte[] PadULong(byte[] ba) | |
{ | |
var s = ba.Length % 8; | |
switch (s) | |
{ | |
case 0: | |
break; | |
case 1: | |
Array.Resize(ref ba, ba.Length + 7); | |
ba[ba.Length - 1] = 0x80; | |
ba[ba.Length - 2] = 0x80; | |
ba[ba.Length - 3] = 0x80; | |
ba[ba.Length - 4] = 0x80; | |
ba[ba.Length - 5] = 0x80; | |
ba[ba.Length - 6] = 0x80; | |
ba[ba.Length - 7] = 0x80; | |
break; | |
case 2: | |
Array.Resize(ref ba, ba.Length + 6); | |
ba[ba.Length - 1] = 0x80; | |
ba[ba.Length - 2] = 0x80; | |
ba[ba.Length - 3] = 0x80; | |
ba[ba.Length - 4] = 0x80; | |
ba[ba.Length - 5] = 0x80; | |
ba[ba.Length - 6] = 0x80; | |
break; | |
case 3: | |
Array.Resize(ref ba, ba.Length + 5); | |
ba[ba.Length - 1] = 0x80; | |
ba[ba.Length - 2] = 0x80; | |
ba[ba.Length - 3] = 0x80; | |
ba[ba.Length - 4] = 0x80; | |
ba[ba.Length - 5] = 0x80; | |
break; | |
case 4: | |
Array.Resize(ref ba, ba.Length + 4); | |
ba[ba.Length - 1] = 0x80; | |
ba[ba.Length - 2] = 0x80; | |
ba[ba.Length - 3] = 0x80; | |
ba[ba.Length - 4] = 0x80; | |
break; | |
case 5: | |
Array.Resize(ref ba, ba.Length + 3); | |
ba[ba.Length - 1] = 0x80; | |
ba[ba.Length - 2] = 0x80; | |
ba[ba.Length - 3] = 0x80; | |
break; | |
case 6: | |
Array.Resize(ref ba, ba.Length + 2); | |
ba[ba.Length - 1] = 0x80; | |
ba[ba.Length - 2] = 0x80; | |
break; | |
case 7: | |
Array.Resize(ref ba, ba.Length + 1); | |
ba[ba.Length - 1] = 0x80; | |
break; | |
} | |
return ba; | |
} | |
private static void Extrude(ulong[] x) | |
{ | |
var size = x.Length; | |
for (var i = 0; i < size; i++) | |
{ | |
ulong n = 0; | |
var j = 0; | |
while (j < size) | |
{ | |
n ^= x[j]; | |
++j; | |
} | |
x[i] = (n << 1) | (n >> 56); | |
} | |
} | |
/// <summary> | |
/// ExpandAndMixArray resizes the array by extrusion then mixes the array using a Sha3 one way hash | |
/// </summary> | |
/// <param name="ba">The buffer</param> | |
/// <param name="size">The final desired size</param> | |
/// <param name="times">The number of times to mix the final array</param> | |
public byte[] ExpandAndMixArray(byte[] ba, int size, int times = 1) | |
{ | |
var ula = ByteArrayToULongArray(ba, size); | |
Extrude(ula); | |
var array = ula.GetBytes(); | |
return Mix(array, times); | |
} | |
public ushort[] ExpandAndMixArray(ushort[] ba, int size, int times = 1) | |
{ | |
var bb = ba.GetBytes(); | |
return ExpandAndMixArray(bb, size, times).ToUShortArray(); | |
} | |
public uint[] ExpandAndMixArray(uint[] ba, int size, int times = 1) | |
{ | |
var bb = ba.GetBytes(); | |
return ExpandAndMixArray(bb, size, times).ToUIntArray(); | |
} | |
public ulong[] ExpandAndMixArray(ulong[] ba, int size, int times = 1) | |
{ | |
var bb = ba.GetBytes(); | |
return ExpandAndMixArray(bb, size, times).ToULongArray(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment