当前位置:   article > 正文

国密算法(SM3)在C#里面的简单封装_c# sm3

c# sm3

前言

接上一篇SM2,现奉上SM3的简单封装


一、SM3是什么?

SM3是一款国产哈希算法,中华人民共和国政府采用的一种密码散列函数标准,由国家密码管理局于2010年12月17日发布。相关标准为“GM/T 0004-2012 《SM3密码杂凑算法》”。在商用密码体系中,SM3主要用于数字签名及验证、消息认证码生成及验证、随机数生成等,其算法公开。据国家密码管理局表示,其安全性及效率与SHA-256相当。


二、C#具体代码

1.引入库

using Org.BouncyCastle.Crypto;
  • 1

2.具体工具代码



/// <summary>
/// SM3工具类
/// </summary>
public class SM3Util
{
    public string secretKey = "";

    public string 加密(string data)
    {
        byte[] msg1 = Encoding.Default.GetBytes(data);
        //byte[] key1 = Encoding.Default.GetBytes(secretKey);

        //var keyParameter = new KeyParameter(key1);
        var sm3 = new SM3Digest();

        //HMac mac = new HMac(sm3); // 带密钥的杂凑算法
        //mac.Init(keyParameter);
        sm3.BlockUpdate(msg1, 0, msg1.Length);
        // byte[] result = new byte[sm3.GetMacSize()];
        byte[] result = new byte[sm3.GetDigestSize()];
        sm3.DoFinal(result, 0);
        return Encoding.ASCII.GetString(Hex.Encode(result));
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26


public abstract class GeneralDigest : IDigest
{
    private const int BYTE_LENGTH = 64;

    private readonly byte[] xBuf;
    private int xBufOff;

    private long byteCount;

    internal GeneralDigest()
    {
        xBuf = new byte[4];
    }

    internal GeneralDigest(GeneralDigest t)
    {
        xBuf = new byte[t.xBuf.Length];
        Array.Copy(t.xBuf, 0, xBuf, 0, t.xBuf.Length);

        xBufOff = t.xBufOff;
        byteCount = t.byteCount;
    }

    public void Update(byte input)
    {
        xBuf[xBufOff++] = input;

        if (xBufOff == xBuf.Length)
        {
            ProcessWord(xBuf, 0);
            xBufOff = 0;
        }

        byteCount++;
    }

    public void BlockUpdate(byte[] input, int inOff, int length)
    {
        //
        // fill the current word
        //
        while ((xBufOff != 0) && (length > 0))
        {
            Update(input[inOff]);
            inOff++;
            length--;
        }

        //
        // process whole words.
        //
        while (length > xBuf.Length)
        {
            ProcessWord(input, inOff);

            inOff += xBuf.Length;
            length -= xBuf.Length;
            byteCount += xBuf.Length;
        }

        //
        // load in the remainder.
        //
        while (length > 0)
        {
            Update(input[inOff]);

            inOff++;
            length--;
        }
    }

    public void Finish()
    {
        long bitLength = (byteCount << 3);

        //
        // add the pad bytes.
        //
        Update(unchecked((byte)128));

        while (xBufOff != 0) Update(unchecked((byte)0));
        ProcessLength(bitLength);
        ProcessBlock();
    }

    public virtual void Reset()
    {
        byteCount = 0;
        xBufOff = 0;
        Array.Clear(xBuf, 0, xBuf.Length);
    }

    public int GetByteLength()
    {
        return BYTE_LENGTH;
    }

    internal abstract void ProcessWord(byte[] input, int inOff);

    internal abstract void ProcessLength(long bitLength);

    internal abstract void ProcessBlock();

    public abstract string AlgorithmName { get; }

    public abstract int GetDigestSize();

    public abstract void BlockUpdate(ReadOnlySpan<byte> input);

    public abstract int DoFinal(byte[] output, int outOff);

    public abstract int DoFinal(Span<byte> output);
}

public class SupportClass
{
    /// <summary>
    /// Performs an unsigned bitwise right shift with the specified number
    /// </summary>
    /// <param name="number">Number to operate on</param>
    /// <param name="bits">Ammount of bits to shift</param>
    /// <returns>The resulting number from the shift operation</returns>
    public static int URShift(int number, int bits)
    {
        if (number >= 0)
            return number >> bits;
        else
            return (number >> bits) + (2 << ~bits);
    }

    /// <summary>
    /// Performs an unsigned bitwise right shift with the specified number
    /// </summary>
    /// <param name="number">Number to operate on</param>
    /// <param name="bits">Ammount of bits to shift</param>
    /// <returns>The resulting number from the shift operation</returns>
    public static int URShift(int number, long bits)
    {
        return URShift(number, (int)bits);
    }

    /// <summary>
    /// Performs an unsigned bitwise right shift with the specified number
    /// </summary>
    /// <param name="number">Number to operate on</param>
    /// <param name="bits">Ammount of bits to shift</param>
    /// <returns>The resulting number from the shift operation</returns>
    public static long URShift(long number, int bits)
    {
        if (number >= 0)
            return number >> bits;
        else
            return (number >> bits) + (2L << ~bits);
    }

    /// <summary>
    /// Performs an unsigned bitwise right shift with the specified number
    /// </summary>
    /// <param name="number">Number to operate on</param>
    /// <param name="bits">Ammount of bits to shift</param>
    /// <returns>The resulting number from the shift operation</returns>
    public static long URShift(long number, long bits)
    {
        return URShift(number, (int)bits);
    }
}

public class SM3Digest : GeneralDigest
{
    public override string AlgorithmName
    {
        get
        {
            return "SM3";
        }
    }

    public override int GetDigestSize()
    {
        return DIGEST_LENGTH;
    }

    private const int DIGEST_LENGTH = 32;

    private static readonly int[] v0 = new int[] { 0x7380166f, 0x4914b2b9, 0x172442d7, unchecked((int)0xda8a0600), unchecked((int)0xa96f30bc), 0x163138aa, unchecked((int)0xe38dee4d), unchecked((int)0xb0fb0e4e) };

    private readonly int[] v = new int[8];
    private readonly int[] v_ = new int[8];

    private static readonly int[] X0 = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

    private readonly int[] X = new int[68];
    private int xOff;

    private readonly int T_00_15 = 0x79cc4519;
    private readonly int T_16_63 = 0x7a879d8a;

    public SM3Digest()
    {
        Reset();
    }

    public SM3Digest(SM3Digest t) : base(t)
    {
        Array.Copy(t.X, 0, X, 0, t.X.Length);
        xOff = t.xOff;

        Array.Copy(t.v, 0, v, 0, t.v.Length);
    }

    public override void Reset()
    {
        base.Reset();

        Array.Copy(v0, 0, v, 0, v0.Length);

        xOff = 0;
        Array.Copy(X0, 0, X, 0, X0.Length);
    }

    internal override void ProcessBlock()
    {
        int i;

        int[] ww = X;
        int[] ww_ = new int[64];

        for (i = 16; i < 68; i++)
        {
            ww[i] = P1(ww[i - 16] ^ ww[i - 9] ^ (ROTATE(ww[i - 3], 15))) ^ (ROTATE(ww[i - 13], 7)) ^ ww[i - 6];
        }

        for (i = 0; i < 64; i++)
        {
            ww_[i] = ww[i] ^ ww[i + 4];
        }

        int[] vv = v;
        int[] vv_ = v_;

        Array.Copy(vv, 0, vv_, 0, v0.Length);

        int SS1, SS2, TT1, TT2, aaa;
        for (i = 0; i < 16; i++)
        {
            aaa = ROTATE(vv_[0], 12);
            SS1 = aaa + vv_[4] + ROTATE(T_00_15, i);
            SS1 = ROTATE(SS1, 7);
            SS2 = SS1 ^ aaa;

            TT1 = FF_00_15(vv_[0], vv_[1], vv_[2]) + vv_[3] + SS2 + ww_[i];
            TT2 = GG_00_15(vv_[4], vv_[5], vv_[6]) + vv_[7] + SS1 + ww[i];
            vv_[3] = vv_[2];
            vv_[2] = ROTATE(vv_[1], 9);
            vv_[1] = vv_[0];
            vv_[0] = TT1;
            vv_[7] = vv_[6];
            vv_[6] = ROTATE(vv_[5], 19);
            vv_[5] = vv_[4];
            vv_[4] = P0(TT2);
        }
        for (i = 16; i < 64; i++)
        {
            aaa = ROTATE(vv_[0], 12);
            SS1 = aaa + vv_[4] + ROTATE(T_16_63, i);
            SS1 = ROTATE(SS1, 7);
            SS2 = SS1 ^ aaa;

            TT1 = FF_16_63(vv_[0], vv_[1], vv_[2]) + vv_[3] + SS2 + ww_[i];
            TT2 = GG_16_63(vv_[4], vv_[5], vv_[6]) + vv_[7] + SS1 + ww[i];
            vv_[3] = vv_[2];
            vv_[2] = ROTATE(vv_[1], 9);
            vv_[1] = vv_[0];
            vv_[0] = TT1;
            vv_[7] = vv_[6];
            vv_[6] = ROTATE(vv_[5], 19);
            vv_[5] = vv_[4];
            vv_[4] = P0(TT2);
        }
        for (i = 0; i < 8; i++)
        {
            vv[i] ^= vv_[i];
        }

        // Reset
        xOff = 0;
        Array.Copy(X0, 0, X, 0, X0.Length);
    }

    internal override void ProcessWord(byte[] in_Renamed, int inOff)
    {
        int n = in_Renamed[inOff] << 24;
        n |= (in_Renamed[++inOff] & 0xff) << 16;
        n |= (in_Renamed[++inOff] & 0xff) << 8;
        n |= (in_Renamed[++inOff] & 0xff);
        X[xOff] = n;

        if (++xOff == 16)
        {
            ProcessBlock();
        }
    }

    internal override void ProcessLength(long bitLength)
    {
        if (xOff > 14)
        {
            ProcessBlock();
        }

        X[14] = (int)(SupportClass.URShift(bitLength, 32));
        X[15] = (int)(bitLength & unchecked((int)0xffffffff));
    }

    public static void IntToBigEndian(int n, byte[] bs, int off)
    {
        bs[off] = (byte)(SupportClass.URShift(n, 24));
        bs[++off] = (byte)(SupportClass.URShift(n, 16));
        bs[++off] = (byte)(SupportClass.URShift(n, 8));
        bs[++off] = (byte)(n);
    }

    public override int DoFinal(byte[] out_Renamed, int outOff)
    {
        Finish();

        for (int i = 0; i < 8; i++)
        {
            IntToBigEndian(v[i], out_Renamed, outOff + i * 4);
        }

        Reset();

        return DIGEST_LENGTH;
    }

    private static int ROTATE(int x, int n)
    {
        return (x << n) | (SupportClass.URShift(x, (32 - n)));
    }

    private static int P0(int X)
    {
        return ((X) ^ ROTATE((X), 9) ^ ROTATE((X), 17));
    }

    private static int P1(int X)
    {
        return ((X) ^ ROTATE((X), 15) ^ ROTATE((X), 23));
    }

    private static int FF_00_15(int X, int Y, int Z)
    {
        return (X ^ Y ^ Z);
    }

    private static int FF_16_63(int X, int Y, int Z)
    {
        return ((X & Y) | (X & Z) | (Y & Z));
    }

    private static int GG_00_15(int X, int Y, int Z)
    {
        return (X ^ Y ^ Z);
    }

    private static int GG_16_63(int X, int Y, int Z)
    {
        return ((X & Y) | (~X & Z));
    }

    public override void BlockUpdate(ReadOnlySpan<byte> input)
    {
    }

    public override int DoFinal(Span<byte> output)
    {
        return DIGEST_LENGTH;
    }

    //[STAThread]
    //public static void  Main()
    //{
    //    byte[] md = new byte[32];
    //    byte[] msg1 = Encoding.Default.GetBytes("ererfeiisgod");
    //    SM3Digest sm3 = new SM3Digest();
    //    sm3.BlockUpdate(msg1, 0, msg1.Length);
    //    sm3.DoFinal(md, 0);
    //    System.String s = new UTF8Encoding().GetString(Hex.Encode(md));
    //    System.Console.Out.WriteLine(s.ToUpper());

    //    Console.ReadLine();
    //}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/139543
推荐阅读