@@ -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}
0 commit comments