Skip to content

Commit a4fa4b9

Browse files
Added non-allocating SHA1
1 parent 2cee9b0 commit a4fa4b9

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-0
lines changed

MLAPI/MLAPI.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
<Compile Include="NetworkingManagerComponents\Core\NetworkPoolManager.cs" />
105105
<Compile Include="NetworkingManagerComponents\Core\NetworkSceneManager.cs" />
106106
<Compile Include="NetworkingManagerComponents\Core\SpawnManager.cs" />
107+
<Compile Include="NetworkingManagerComponents\Cryptography\MessageDigest.cs" />
107108
<Compile Include="Properties\AssemblyInfo.cs" />
108109
<Compile Include="Data\NetId.cs" />
109110
<Compile Include="NetworkingManagerComponents\Binary\MessageChunker.cs" />
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace MLAPI.NetworkingManagerComponents.Cryptography
7+
{
8+
public static class MessageDigest
9+
{
10+
public struct SHA1Result
11+
{
12+
public uint i0, i1, i2, i3, i4;
13+
public byte Get(int idx) => (byte)((idx < 4 ? i0 : idx < 8 ? i1 : idx < 12 ? i2 : idx < 16 ? i3 : i4) >> (8 * (idx % 4)));
14+
}
15+
public static SHA1Result SHA1_Opt(byte[] message)
16+
{
17+
SHA1Result result = new SHA1Result
18+
{
19+
// Initialize buffers
20+
i0 = 0x67452301,
21+
i1 = 0xEFCDAB89,
22+
i2 = 0x98BADCFE,
23+
i3 = 0x10325476,
24+
i4 = 0xC3D2E1F0
25+
};
26+
27+
// Pad message
28+
long len = message.Length * 8;
29+
int
30+
ml = message.Length + 1,
31+
max = ml + ((960 - (ml * 8 % 512)) % 512) / 8 + 8;
32+
33+
// Replaces the allocation of a lot of bytes
34+
byte GetMsg(int idx)
35+
{
36+
if (idx < message.Length)
37+
return message[idx];
38+
else if (idx == message.Length)
39+
return 0x80;
40+
else if (max - idx <= 8)
41+
return (byte)((len >> ((max - 1 - idx) * 8)) & 255);
42+
return 0;
43+
}
44+
45+
int chunks = max / 64;
46+
47+
// Replaces the recurring allocation of 80 uints
48+
uint ComputeIndex(int block, int idx)
49+
{
50+
if (idx < 16)
51+
return (uint)((GetMsg(block * 64 + idx * 4) << 24) | (GetMsg(block * 64 + idx * 4 + 1) << 16) | (GetMsg(block * 64 + idx * 4 + 2) << 8) | (GetMsg(block * 64 + idx * 4 + 3) << 0));
52+
else
53+
return Rot(ComputeIndex(block, idx - 3) ^ ComputeIndex(block, idx - 8) ^ ComputeIndex(block, idx - 14) ^ ComputeIndex(block, idx - 16), 1);
54+
}
55+
56+
// Perform hashing for each 512-bit block
57+
for (int i = 0; i < chunks; ++i)
58+
{
59+
60+
// Initialize chunk-hash
61+
uint
62+
a = result.i0,
63+
b = result.i1,
64+
c = result.i2,
65+
d = result.i3,
66+
e = result.i4;
67+
68+
// Do hash rounds
69+
for (int t = 0; t < 80; ++t)
70+
{
71+
uint tmp = Rot(a, 5) + func(t, b, c, d) + e + K(t) + ComputeIndex(i, t);
72+
e = d;
73+
d = c;
74+
c = Rot(b, 30);
75+
b = a;
76+
a = tmp;
77+
}
78+
result.i0 += a;
79+
result.i1 += b;
80+
result.i2 += c;
81+
result.i3 += d;
82+
result.i4 += e;
83+
}
84+
result.i0 = Support.SwapEndian(result.i0);
85+
result.i1 = Support.SwapEndian(result.i1);
86+
result.i2 = Support.SwapEndian(result.i2);
87+
result.i3 = Support.SwapEndian(result.i3);
88+
result.i4 = Support.SwapEndian(result.i4);
89+
return result;
90+
}
91+
92+
private static uint func(int t, uint b, uint c, uint d) =>
93+
t < 20 ? (b & c) | ((~b) & d) :
94+
t < 40 ? b ^ c ^ d :
95+
t < 60 ? (b & c) | (b & d) | (c & d) :
96+
/*t<80*/ b ^ c ^ d;
97+
98+
private static uint K(int t) =>
99+
t < 20 ? 0x5A827999 :
100+
t < 40 ? 0x6ED9EBA1 :
101+
t < 60 ? 0x8F1BBCDC :
102+
/*t<80*/ 0xCA62C1D6;
103+
104+
private static uint Rot(uint val, int by) => (val << by) | (val >> (32 - by));
105+
}
106+
}

0 commit comments

Comments
 (0)