Skip to content

Commit b3c0a76

Browse files
committed
refactor: sm3 sf
1 parent 6625e45 commit b3c0a76

File tree

2 files changed

+45
-65
lines changed

2 files changed

+45
-65
lines changed

src/CryptoBase/Digests/SM3/SM3Digest.cs

Lines changed: 44 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@ namespace CryptoBase.Digests.SM3;
33
/// <summary>
44
/// https://www.oscca.gov.cn/sca/xxgk/2010-12/17/1002389/files/302a3ada057c4a73830536d03e683110.pdf
55
/// </summary>
6-
public class SM3Digest : IHash
6+
public sealed class SM3Digest : IHash
77
{
88
private const int BlockSizeOfInt = 16;
99
private const int SizeOfInt = sizeof(uint);
1010

1111
private static readonly uint[] T = new uint[64];
1212

13-
private static readonly Vector256<uint> Init = Vector256.Create(0x7380166FU, 0x4914B2B9U, 0x172442D7U, 0xDA8A0600U, 0xA96F30BCU, 0x163138AAU, 0xE38DEE4DU, 0xB0FB0E4EU);
13+
private static readonly uint[] Init = [0x7380166FU, 0x4914B2B9U, 0x172442D7U, 0xDA8A0600U, 0xA96F30BCU, 0x163138AAU, 0xE38DEE4DU, 0xB0FB0E4EU];
1414

15-
private Vector256<uint> V;
1615
private ulong _byteCount;
1716
private int _index;
1817
private int _bufferIndex;
1918

19+
private readonly uint[] _v;
2020
private readonly uint[] _w;
2121
private readonly byte[] _buffer;
2222

@@ -44,7 +44,6 @@ private static uint GG0(uint x, uint y, uint z)
4444
private static uint GG1(uint x, uint y, uint z)
4545
{
4646
return (y ^ z) & x ^ z;
47-
//return (x & y) | IntrinsicsUtils.AndNot(x, z);
4847
}
4948

5049
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -78,6 +77,7 @@ public SM3Digest()
7877
{
7978
_w = new uint[68];
8079
_buffer = new byte[SizeOfInt];
80+
_v = new uint[8];
8181
Reset();
8282
}
8383

@@ -96,6 +96,7 @@ public void UpdateFinal(ReadOnlySpan<byte> origin, Span<byte> destination)
9696
public void Update(ReadOnlySpan<byte> source)
9797
{
9898
_byteCount += (uint)source.Length;
99+
uint[] w = _w;
99100

100101
if (_bufferIndex != 0)
101102
{
@@ -108,22 +109,22 @@ public void Update(ReadOnlySpan<byte> source)
108109
return;
109110
}
110111

111-
source[..remain].CopyTo(_buffer.AsSpan(_bufferIndex));
112-
source = source[remain..];
113-
_w[_index++] = BinaryPrimitives.ReadUInt32BigEndian(_buffer);
112+
source.Slice(0, remain).CopyTo(_buffer.AsSpan(_bufferIndex));
113+
source = source.Slice(remain);
114+
w[_index++] = BinaryPrimitives.ReadUInt32BigEndian(_buffer);
114115
_bufferIndex = 0;
115116
}
116117

117118
while (source.Length >= SizeOfInt)
118119
{
119-
if (_index == BlockSizeOfInt)
120+
if (_index is BlockSizeOfInt)
120121
{
121122
Process();
122123
_index = 0;
123124
}
124125

125-
_w[_index++] = BinaryPrimitives.ReadUInt32BigEndian(source);
126-
source = source[SizeOfInt..];
126+
w[_index++] = BinaryPrimitives.ReadUInt32BigEndian(source);
127+
source = source.Slice(SizeOfInt);
127128
}
128129

129130
if (_index == BlockSizeOfInt)
@@ -139,7 +140,7 @@ public void Update(ReadOnlySpan<byte> source)
139140
}
140141
}
141142

142-
public unsafe void GetHash(Span<byte> destination)
143+
public void GetHash(Span<byte> destination)
143144
{
144145
try
145146
{
@@ -173,27 +174,14 @@ public unsafe void GetHash(Span<byte> destination)
173174
_w[15] = (uint)(_byteCount << 3 & 0xFFFFFFFF);
174175

175176
Process();
176-
177-
if (Avx.IsSupported && Avx2.IsSupported)
178-
{
179-
Vector256<byte> v = V.ReverseEndianness32().AsByte();
180-
181-
fixed (byte* p = destination)
182-
{
183-
Avx.Store(p, v);
184-
}
185-
}
186-
else
187-
{
188-
BinaryPrimitives.WriteUInt32BigEndian(destination, V.GetElement(0));
189-
BinaryPrimitives.WriteUInt32BigEndian(destination[4..], V.GetElement(1));
190-
BinaryPrimitives.WriteUInt32BigEndian(destination[8..], V.GetElement(2));
191-
BinaryPrimitives.WriteUInt32BigEndian(destination[12..], V.GetElement(3));
192-
BinaryPrimitives.WriteUInt32BigEndian(destination[16..], V.GetElement(4));
193-
BinaryPrimitives.WriteUInt32BigEndian(destination[20..], V.GetElement(5));
194-
BinaryPrimitives.WriteUInt32BigEndian(destination[24..], V.GetElement(6));
195-
BinaryPrimitives.WriteUInt32BigEndian(destination[28..], V.GetElement(7));
196-
}
177+
BinaryPrimitives.WriteUInt32BigEndian(destination, _v[0]);
178+
BinaryPrimitives.WriteUInt32BigEndian(destination.Slice(4), _v[1]);
179+
BinaryPrimitives.WriteUInt32BigEndian(destination.Slice(8), _v[2]);
180+
BinaryPrimitives.WriteUInt32BigEndian(destination.Slice(12), _v[3]);
181+
BinaryPrimitives.WriteUInt32BigEndian(destination.Slice(16), _v[4]);
182+
BinaryPrimitives.WriteUInt32BigEndian(destination.Slice(20), _v[5]);
183+
BinaryPrimitives.WriteUInt32BigEndian(destination.Slice(24), _v[6]);
184+
BinaryPrimitives.WriteUInt32BigEndian(destination.Slice(28), _v[7]);
197185
}
198186
finally
199187
{
@@ -203,47 +191,49 @@ public unsafe void GetHash(Span<byte> destination)
203191

204192
public void Reset()
205193
{
206-
V = Init;
194+
Init.AsSpan().CopyTo(_v);
207195
_byteCount = 0;
208196
_index = 0;
209197
_bufferIndex = 0;
210198
}
211199

212-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
213200
private void Process()
214201
{
202+
uint[] w = _w;
203+
uint[] v = _v;
204+
215205
for (int j = 16; j < 68; ++j)
216206
{
217-
_w[j] = P1(_w[j - 16] ^ _w[j - 9] ^ _w[j - 3].RotateLeft(15)) ^ _w[j - 13].RotateLeft(7) ^ _w[j - 6];
207+
w[j] = P1(w[j - 16] ^ w[j - 9] ^ w[j - 3].RotateLeft(15)) ^ w[j - 13].RotateLeft(7) ^ w[j - 6];
218208
}
219209

220-
uint a = V.GetElement(0);
221-
uint b = V.GetElement(1);
222-
uint c = V.GetElement(2);
223-
uint d = V.GetElement(3);
224-
uint e = V.GetElement(4);
225-
uint f = V.GetElement(5);
226-
uint g = V.GetElement(6);
227-
uint h = V.GetElement(7);
210+
uint a = v[0];
211+
uint b = v[1];
212+
uint c = v[2];
213+
uint d = v[3];
214+
uint e = v[4];
215+
uint f = v[5];
216+
uint g = v[6];
217+
uint h = v[7];
228218

229219
for (int j = 0; j < 64; ++j)
230220
{
231221
uint a12 = a.RotateLeft(12);
232222
uint ss1 = (a12 + e + T[j]).RotateLeft(7);
233223
uint ss2 = ss1 ^ a12;
234224

235-
uint w1 = _w[j] ^ _w[j + 4];
225+
uint w1 = w[j] ^ w[j + 4];
236226
uint tt1, tt2;
237227

238228
if (j < 16)
239229
{
240230
tt1 = FF0(a, b, c) + d + ss2 + w1;
241-
tt2 = GG0(e, f, g) + h + ss1 + _w[j];
231+
tt2 = GG0(e, f, g) + h + ss1 + w[j];
242232
}
243233
else
244234
{
245235
tt1 = FF1(a, b, c) + d + ss2 + w1;
246-
tt2 = GG1(e, f, g) + h + ss1 + _w[j];
236+
tt2 = GG1(e, f, g) + h + ss1 + w[j];
247237
}
248238

249239
d = c;
@@ -256,27 +246,17 @@ private void Process()
256246
e = P0(tt2);
257247
}
258248

259-
if (Avx2.IsSupported)
260-
{
261-
Vector256<uint> t = Vector256.Create(a, b, c, d, e, f, g, h);
262-
V = Avx2.Xor(V, t);
263-
}
264-
else
265-
{
266-
V = Vector256.Create(
267-
V.GetElement(0) ^ a,
268-
V.GetElement(1) ^ b,
269-
V.GetElement(2) ^ c,
270-
V.GetElement(3) ^ d,
271-
V.GetElement(4) ^ e,
272-
V.GetElement(5) ^ f,
273-
V.GetElement(6) ^ g,
274-
V.GetElement(7) ^ h);
275-
}
249+
v[0] ^= a;
250+
v[1] ^= b;
251+
v[2] ^= c;
252+
v[3] ^= d;
253+
v[4] ^= e;
254+
v[5] ^= f;
255+
v[6] ^= g;
256+
v[7] ^= h;
276257
}
277258

278259
public void Dispose()
279260
{
280-
GC.SuppressFinalize(this);
281261
}
282262
}

test/CryptoBase.Benchmark/SM3Benchmark.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public void Setup()
2020
_randombytes = RandomNumberGenerator.GetBytes(ByteLength);
2121
}
2222

23-
[Benchmark]
23+
[Benchmark(Baseline = true)]
2424
public void BouncyCastle()
2525
{
2626
Span<byte> hash = stackalloc byte[HashConstants.SM3Length];

0 commit comments

Comments
 (0)