<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.1" />

SM3Digest

public class SM3Digest : GeneralDigest
Implementation of Chinese SM3 digest as described at http://tools.ietf.org/html/draft-shen-sm3-hash-00 and at .... ( Chinese PDF )
using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Utilities; using System; namespace Org.BouncyCastle.Crypto.Digests { public class SM3Digest : GeneralDigest { private const int DIGEST_LENGTH = 32; private const int BLOCK_SIZE = 16; private uint[] V = new uint[8]; private uint[] inwords = new uint[16]; private int xOff; private uint[] W = new uint[68]; private static readonly uint[] T; public override string AlgorithmName => "SM3"; static SM3Digest() { T = new uint[64]; for (int i = 0; i < 16; i++) { uint num = 2043430169; T[i] = ((num << i) | (num >> 32 - i)); } for (int j = 16; j < 64; j++) { int num2 = j % 32; uint num3 = 2055708042; T[j] = ((num3 << num2) | (num3 >> 32 - num2)); } } public SM3Digest() { Reset(); } public SM3Digest(SM3Digest t) : base(t) { CopyIn(t); } private void CopyIn(SM3Digest t) { Array.Copy(t.V, 0, V, 0, V.Length); Array.Copy(t.inwords, 0, inwords, 0, inwords.Length); xOff = t.xOff; } public override int GetDigestSize() { return 32; } public override IMemoable Copy() { return new SM3Digest(this); } public override void Reset(IMemoable other) { SM3Digest t = (SM3Digest)other; CopyIn((GeneralDigest)t); CopyIn(t); } public override void Reset() { base.Reset(); V[0] = 1937774191; V[1] = 1226093241; V[2] = 388252375; V[3] = 3666478592; V[4] = 2842636476; V[5] = 372324522; V[6] = 3817729613; V[7] = 2969243214; xOff = 0; } public override int DoFinal(byte[] output, int outOff) { Finish(); Pack.UInt32_To_BE(V, output, outOff); Reset(); return 32; } internal override void ProcessWord(byte[] input, int inOff) { inwords[xOff++] = Pack.BE_To_UInt32(input, inOff); if (xOff >= 16) ProcessBlock(); } internal override void ProcessLength(long bitLength) { if (xOff > 14) { inwords[xOff] = 0; xOff++; ProcessBlock(); } while (xOff < 14) { inwords[xOff] = 0; xOff++; } inwords[xOff++] = (uint)(bitLength >> 32); inwords[xOff++] = (uint)bitLength; } private uint P0(uint x) { uint num = (x << 9) | (x >> 23); uint num2 = (x << 17) | (x >> 15); return x ^ num ^ num2; } private uint P1(uint x) { uint num = (x << 15) | (x >> 17); uint num2 = (x << 23) | (x >> 9); return x ^ num ^ num2; } private uint FF0(uint x, uint y, uint z) { return x ^ y ^ z; } private uint FF1(uint x, uint y, uint z) { return (x & y) | (x & z) | (y & z); } private uint GG0(uint x, uint y, uint z) { return x ^ y ^ z; } private uint GG1(uint x, uint y, uint z) { return (x & y) | (~x & z); } internal override void ProcessBlock() { for (int i = 0; i < 16; i++) { W[i] = inwords[i]; } for (int j = 16; j < 68; j++) { uint num = W[j - 3]; uint num2 = (num << 15) | (num >> 17); uint num3 = W[j - 13]; uint num4 = (num3 << 7) | (num3 >> 25); W[j] = (P1(W[j - 16] ^ W[j - 9] ^ num2) ^ num4 ^ W[j - 6]); } uint num5 = V[0]; uint num6 = V[1]; uint num7 = V[2]; uint num8 = V[3]; uint num9 = V[4]; uint num10 = V[5]; uint num11 = V[6]; uint num12 = V[7]; for (int k = 0; k < 16; k++) { uint num13 = (num5 << 12) | (num5 >> 20); uint num14 = num13 + num9 + T[k]; uint num15 = (num14 << 7) | (num14 >> 25); uint num16 = num15 ^ num13; uint num17 = W[k]; uint num18 = num17 ^ W[k + 4]; uint num19 = FF0(num5, num6, num7) + num8 + num16 + num18; uint x = GG0(num9, num10, num11) + num12 + num15 + num17; num8 = num7; num7 = ((num6 << 9) | (num6 >> 23)); num6 = num5; num5 = num19; num12 = num11; num11 = ((num10 << 19) | (num10 >> 13)); num10 = num9; num9 = P0(x); } for (int l = 16; l < 64; l++) { uint num20 = (num5 << 12) | (num5 >> 20); uint num21 = num20 + num9 + T[l]; uint num22 = (num21 << 7) | (num21 >> 25); uint num23 = num22 ^ num20; uint num24 = W[l]; uint num25 = num24 ^ W[l + 4]; uint num26 = FF1(num5, num6, num7) + num8 + num23 + num25; uint x2 = GG1(num9, num10, num11) + num12 + num22 + num24; num8 = num7; num7 = ((num6 << 9) | (num6 >> 23)); num6 = num5; num5 = num26; num12 = num11; num11 = ((num10 << 19) | (num10 >> 13)); num10 = num9; num9 = P0(x2); } V[0] ^= num5; V[1] ^= num6; V[2] ^= num7; V[3] ^= num8; V[4] ^= num9; V[5] ^= num10; V[6] ^= num11; V[7] ^= num12; xOff = 0; } } }