C# 实现国密SM3加解密封装

2023-05-16

1.Portable.BouncyCastle 引入

右键解决方案的引用,选择管理NuGet程序包

 在浏览的搜索框中搜索:“Portable.BouncyCastle”

 选择第一个,在右侧点击安装即可完成程序包的引入。

2.SM3

2.1.公共方法

 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);
        }
    }

2.2.GeneralDigest

    /// <summary>
    /// General
    /// </summary>
    public abstract class GeneralDigest : IDigest
    {
        private const int BYTE_LENGTH = 64;

        private 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 int DoFinal(byte[] output, int outOff);
    }

2.3.SM3Digest

    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 int[] v = new int[8];
        private 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 int[] X = new int[68];
        private int xOff;

        private int T_00_15 = 0x79cc4519;
        private 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 int ROTATE(int x, int n)
        {
            return (x << n) | (SupportClass.URShift(x, (32 - n)));
        }

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

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

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

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

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

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

2.4.加解密方法封装

public static class Sm3Crypto
    {
        /// <summary>
        /// sm3加密(使用自定义密钥)
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static byte[] ToSM3byte(string data, string key)
        {
            byte[] msg1 = Encoding.Default.GetBytes(data);
            byte[] key1 = Encoding.Default.GetBytes(key);

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

            HMac mac = new HMac(sm3);//带密钥的杂凑算法
            mac.Init(keyParameter);
            mac.BlockUpdate(msg1, 0, msg1.Length);
            byte[] result = new byte[mac.GetMacSize()];

            mac.DoFinal(result, 0);
            return Hex.Encode(result);
        }

        /// <summary>
        /// sm3加密
        /// </summary>
        /// <param name="data"></param>
        /// <returns>二进制数组</returns>
        public static byte[] ToSM3byte(string data)
        {
            var msg = Encoding.Default.GetBytes(data);//把字符串转成16进制的ASCII码 
            SM3Digest sm3 = new SM3Digest();
            sm3.BlockUpdate(msg, 0, msg.Length);
            byte[] md = new byte[sm3.GetDigestSize()];//SM3算法产生的哈希值大小
            sm3.DoFinal(md, 0);
            return Hex.Encode(md);
        }

        /// <summary>
        /// sm3加密
        /// </summary>
        /// <param name="data"></param>
        /// <returns>16进制字符串</returns>
        public static string ToSM3HexStr(string data)
        {
            var msg = Encoding.Default.GetBytes(data);//把字符串转成16进制的ASCII码 
            SM3Digest sm3 = new SM3Digest();
            sm3.BlockUpdate(msg, 0, msg.Length);
            byte[] md = new byte[sm3.GetDigestSize()];//SM3算法产生的哈希值大小
            sm3.DoFinal(md, 0);
            return new UTF8Encoding().GetString(Hex.Encode(md));
        }

        /// <summary>
        /// sm3加密(使用自定义Hex密钥)
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string ToSM3HexStr(string data, string key)
        {
            byte[] msg1 = Encoding.Default.GetBytes(data);
            byte[] key1 = HexStringToBytes(key);

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

            HMac mac = new HMac(sm3);//带密钥的杂凑算法
            mac.Init(keyParameter);
            mac.BlockUpdate(msg1, 0, msg1.Length);
            byte[] result = new byte[mac.GetMacSize()];

            mac.DoFinal(result, 0);
            return new UTF8Encoding().GetString(Hex.Encode(result));
        }

        /// <summary>
        /// 16进制格式字符串转字节数组
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        public static byte[] HexStringToBytes(string hexString)
        {
            hexString = Regex.Replace(hexString, @".{2}", "$0 ");
            //以 ' ' 分割字符串,并去掉空字符
            string[] chars = hexString.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            byte[] returnBytes = new byte[chars.Length];
            //逐个字符变为16进制字节数据
            for (int i = 0; i < chars.Length; i++)
            {
                returnBytes[i] = Convert.ToByte(chars[i], 16);
            }
            return returnBytes;
        }
    }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 实现国密SM3加解密封装 的相关文章

  • 时间序列预测——ARIMA模型

    文章链接 xff1a 时间序列预测 Prophet模型 https blog csdn net beiye article details 123353123 spm 61 1001 2014 3001 5502 SPSS软件实操 ARIM
  • 基本矩阵F和本质矩阵E的详细推导

    基本矩阵F E在计算机视觉中是提纯匹配点 恢复相机位姿的一个法宝 但是它是如何得到的 下面笔者做其简单的推导 如图下图 xff0c 两视几何图 其中C和C 分别代表左 右摄影中心 xff0c x和x 代表同名像点 xff0c e和e 代表极
  • [ubuntu]安装并使用python 3.6及与2.7的切换

    当前使用ubuntu14 04 1 添加python3 6安装包 xff0c 并安装 xff08 也可以去官网下载安装包 xff09 linux 报错E Unable To Locate Package Software propertie
  • Python + Requests 模拟登陆(含验证码)

    其实模拟登陆非常简单 xff0c 只要在打开网站的同时提交数据就可以了 下面通过登陆超星网来举例说明如何一步步实现模拟登陆 1 获取需要提交的数据 使用chrome的Network或者fiddler可以很轻易的得到我们想要的数据 xff0c
  • Cmake实现递归cpp和h

    为解决获取编译链所有C 43 43 源文件和头文件 Cmake实现递归目录 编程心得 拾随小笺
  • 鉴权 前后端常见的几种鉴权方式

    https juejin cn post 6844903927100473357 鉴权 xff08 authentication xff09 是指验证用户是否拥有访问系统的权利 传统的鉴权是通过密码来验证的 这种方式的前提是 xff0c 每
  • curl指令模拟postman发json数据,发本地文件

    菜鸟curl指令介绍 xff1a https www coonote com linux linux cmd curl html post formdata多个参数 多个参数可以使用 F进行串接 curl span class token
  • 最全的HTTP(get post)请求示例, 包括post模拟get请求

    public class HttpRequest private static SimpleDateFormat sdf 61 new SimpleDateFormat 34 yyyyMMddHHmmss 34 private static
  • python爬虫——模拟登陆

    参考链接 xff1a https blog csdn net weixin 39875941 article details 109878457 模拟登陆 Python网络爬虫应用十分广泛 xff0c 但是有些网页需要用户登陆后才能获取到信
  • vector数组 传递 引用 指针 参数

    一 一维 span class hljs stl container span class hljs built in vector span lt span class hljs keyword int span gt span vec
  • Oracle # 字符串匹配函数(Oracle、SQLSERVER、Excel)

    引言 xff1a 当数据库设置字段的时候 xff0c 会设置1表XXX xff1b 0表示XXX 查询的时候怎么显示汉字呢 xff1f Oracle数据库 xff1a 普通查询数据 xff1a select from U ORANGEZAT
  • 时间序列预测——Prophet模型

    文章链接 xff1a 时间序列预测 ARIMA模型 https blog csdn net beiye article details 123317316 spm 61 1001 2014 3001 5502 1 Propht模型概述 Pr
  • 机器人导航——路径跟踪

    要完成一套完整的机器人路径规划 xff0c 并完成其物理实验并非一件简单的事情 参考 xff1a http wenku baidu com link url 61 n11mP6EDlM78NZYZ4yQYXzmzPeBV6BeLNOUjIv
  • python 读取txt出现\xef\xbb\xbf…的问题

    用python读取txt文件 xff0c 文件的内容是一列数如下 xff1a 1883 1886 1900 1900 1897 1897 1897 1897 1906 1917 1910 1910 但是读取的时候第一个元素为 xef xbb
  • (算法)判断两个区间是否重叠

    题目 xff1a 判断两个区间是否重叠 思路 xff1a 假设区间表示为 start end xff0c 先存在两个区间A B 两个区间的关系有两种 xff1a 重叠与不重叠 重叠的情况有4种 xff0c 两种相交 xff0c 两种包含 x
  • python ctrl+c 退出while True:

    写了一个死循环 xff0c 类似 xff1a def function while True my code 程序运行后想用ctrl 43 c按键停止程序 xff0c 可是终止不了 以下为解决办法 xff1a 第一步 xff1a 加入sys
  • python二维字典

    感谢原文 xff1a http www jb51 net article 83108 htm 本文实例讲述了Python的 二维 字典 two dimension dictionary 定义与实现方法 分享给大家供大家参考 xff0c 具体
  • ros安装出现依赖问题

    http www liuxiao org 2015 10 ros E5 9C A8 ubuntu 14 04 E7 B3 BB E7 BB 9F E4 B8 8A E5 AE 89 E8 A3 85 ros indigo 0 安装环境 xf
  • KMP算法介绍

    参考 xff1a https www cnblogs com c cloud p 3224788 html 前言 之前对kmp算法虽然了解它的原理 xff0c 即求出P0 Pi的最大相同前后缀长度k xff1b 但是问题在于如何求出这个最大
  • 【python】*与** 参数问题

    原文地址 xff1a https www cnblogs com paulwinflo p 5764748 html 可变参数 在Python函数中 xff0c 还可以定义可变参数 顾名思义 xff0c 可变参数就是传入的参数个数是可变的

随机推荐