精华内容
下载资源
问答
  • 若依框架将vue前端参数sm4加密,后端sm4解密的解决办法
    2022-02-18 10:47:18

    1、修改com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter

    LoginUser loginUser = tokenService.getLoginUser(request);
    if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication()))
    {
        tokenService.verifyToken(loginUser);
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
        authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
    }
    if (request.getHeader("Authorization")!=null){
        /*业务逻辑:前端在request.js中拦截了所有请求,并加密了除了login以外的所有请求,将其参数加密。
        * 在后端就需要一个地方将所有参数解密,此过滤器完成参数注入之前的解密工作。
        * 需要说明的几点:
        * 1、加密方式采用SM4_ECB方式,所以解密需要对应使用ECB解密
        * 2、加密盐16位。使用截取token后16位字符串替换-和_符号之后的字符串作为加密盐
        * 3、由于request.getInputStream()流中的参数只能读一次,读第二次就会报Required request body is missing的错误,
        *    所以这里将读取过程转移到RepeatedlyRequestWrapper里面去了。*/
        //            ServletInputStream inputStream=request.getInputStream();
        //            BufferedReader streamReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        //            StringBuilder responseStrBuilder = new StringBuilder();
        //            String inputStr;
        //            while ((inputStr = streamReader.readLine()) != null)
        //                responseStrBuilder.append(inputStr);
        //            String str = responseStrBuilder.toString();
        RepeatedlyRequestWrapper requestWrapper = new RepeatedlyRequestWrapper(request);
        chain.doFilter(requestWrapper, response);
    }else {
        //没有登录的情况下,没有票据,不用管。
        chain.doFilter(request, response);
    }

    2、添加com.ruoyi.framework.web.wrapper.RepeatedlyRequestWrapper

    import com.alibaba.fastjson.JSONObject;
    import com.ruoyi.common.utils.StringUtils;
    import com.ruoyi.common.utils.sm4.SM4Utils;
    
    import javax.servlet.ReadListener;
    import javax.servlet.ServletInputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import java.io.BufferedReader;
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.nio.charset.Charset;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    
    /***
     * 此类完成vue客户端的解密工作
     */
    public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper {
        
    private final byte[] body;
    private final Map<String, String[]> parameterMap;
    
    
    
    public RepeatedlyRequestWrapper(HttpServletRequest request,String inputToken )
            throws IOException {
        super(request);
        String path = request.getRequestURI();
        String sm4secretKey = inputToken.substring(inputToken.length()-16);
        sm4secretKey=sm4secretKey.replace("-","a");
        sm4secretKey=sm4secretKey.replace("_","a");
    
        Map<String, String[]> newParas = new HashMap<>();
        SM4Utils sm4 = new SM4Utils(sm4secretKey);
        ServletInputStream inputStream = request.getInputStream();
        BufferedReader streamReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        StringBuilder responseStrBuilder = new StringBuilder();
        String inputStr;
        while ((inputStr = streamReader.readLine()) != null)
            responseStrBuilder.append(inputStr);
        String str = responseStrBuilder.toString();
        JSONObject newObject = new JSONObject();
        if(str.equals("")){
    
        }else {
            JSONObject jsonObject = JSONObject.parseObject(str);
            //解密之前判断一下数据完整性
            Object paraEndCheck=jsonObject.get("paraEndCheck");
            if(paraEndCheck==null||paraEndCheck.toString().equals("")){
                throw new IOException("数据传输错误,数据不完整");
            }else{
                if(paraEndCheck.equals(sm4secretKey)){
                    jsonObject.remove("paraEndCheck");
                }else{
                    throw new IOException("数据传输错误,数据不完整");
                }
            }
    
            //解密数据
            Set<String> keys = jsonObject.keySet();
            for (String key : keys) {
                String value = jsonObject.getString(key);
                if (value == null) {
                    newObject.put(key, value);
                } else {
                    if (path.equals("/login")) {
                        newObject.put(key, value);
                    } else {
                        value = sm4.decryptData_CBC(value);
                        Locale defloc = Locale.getDefault();
                        String valueStrTemp = value.trim().toLowerCase(defloc);
                        //如果解密出来是数字、数组、bool,则需要转换为相应的东西
                        if(valueStrTemp.equals("true")){
                            newObject.put(key, true);
                        }else if(valueStrTemp.equals("false")){
                            newObject.put(key, true);
                        }else if(StringUtils.isArray(value)){
                            newObject.put(key, JSONArray.parse(value));
                        }else if(value.trim().startsWith("{")){
                            newObject.put(key, JSONObject.parse(value));
                        }else if(value.trim().startsWith("[")){
                            newObject.put(key, JSONArray.parse(value));
                        }else if(StringUtils.isNumeric(value)){
                            if(value.contains(".")){
                                newObject.put(key, Float.parseFloat(value));
                            }else{
                                newObject.put(key, Integer.parseInt(value));
                            }
                        }else if(value.contains("T")&&value.contains("Z")){
                                //有可能是时间
                                String str2=value.replace("\"","");
                                newObject.put(key,str2);
                        }else{
                            newObject.put(key, value);
                        }
                    }
                }
            }
    
        }
    
        body = newObject.toJSONString().getBytes("utf-8");
    
        //看看request.getParameterMap里面有没有参数,有参数的话可能是get方法传过来的,一并处理掉
        Map<String,String[]> paras=request.getParameterMap();
        Map<String,String[]> newparas=new HashMap<>();
        if(paras.size()>0) {
            Set<Map.Entry<String, String[]>> parasSet = paras.entrySet();
            for (Map.Entry<String, String[]> item : parasSet) {
                String value = item.getValue()[0];
                String key = item.getKey();
    
                //对于paraEndCheck不处理。
                if("paraEndCheck".equals(key)){
                    continue;
                }
    
                if (value == null) {
                    newparas.put(key, new String[]{""});
                } else {
                    if (path.equals("/login")) {
                        newparas.put(key, new String[]{value});
                    } else {
                        value = sm4.decryptData_CBC(value);
                        newparas.put(key, new String[]{value});
                    }
                }
            }
    
            this.parameterMap = newparas;
        }else{
            this.parameterMap=new HashMap<>();
        }
    }
    
    /**
     * 获取所有参数名
     *
     * @return 返回所有参数名
     */
    @Override
    public Enumeration<String> getParameterNames() {
        Vector<String> vector = new Vector<String>(parameterMap.keySet());
        return vector.elements();
    }
    
    /**
     * 获取指定参数名的值,如果有重复的参数名,则返回第一个的值 接收一般变量 ,如text类型
     *
     * @param name 指定参数名
     * @return 指定参数名的值
     */
    @Override
    public String getParameter(String name) {
        if(parameterMap.get(name)==null){
            return null;
        }
        String[] results = parameterMap.get(name);
        return results[0];
    }
    
    
    /**
     * 获取指定参数名的所有值的数组,如:checkbox的所有数据
     * 接收数组变量 ,如checkobx类型
     */
    @Override
    public String[] getParameterValues(String name) {
        return parameterMap.get(name);
    }
    
    @Override
    public Map<String, String[]> getParameterMap() {
        return parameterMap;
    }
    
    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }
    
    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream() {
    
            @Override
            public boolean isFinished() {
                return false;
            }
    
            @Override
            public boolean isReady() {
                return false;
            }
    
            @Override
            public void setReadListener(ReadListener listener) {
    
            }
    
            @Override
            public int read() throws IOException {
                return bais.read();
            }
        };
    }
    
    /**
     * 通过BufferedReader和字符编码集转换成byte数组
     *
     * @param br
     * @param encoding
     * @return
     * @throws IOException
     */
    private byte[] readBytes(BufferedReader br, String encoding) throws IOException {
        String str = null, retStr = "";
        while ((str = br.readLine()) != null) {
            retStr += str;
        }
        if (StringUtils.isNotBlank(retStr)) {
            return retStr.getBytes(Charset.forName(encoding));
        }
        return null;
    }
    }
    

    3、前端request.js中加密参数:

    var sm4Util = new SM4Util();
    
    
    // request拦截器
    service.interceptors.request.use(config => {
      // 是否需要设置 token
      const isToken = (config.headers || {}).isToken === false
      if (getToken() && !isToken) {
        config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
      }
    
      //拿一下秘钥
      if (config.headers['Authorization'] != undefined) {
        var Authorization = config.headers['Authorization'];
        sm4Util.secretKey = Authorization.substr(Authorization.length - 16, 16)
          .replace(/-/g, 'a')
          .replace(/_/g, 'a');
        sm4Util.iv = sm4Util.secretKey;
      }
    
      // get请求映射params参数
      if (config.method === 'get' && config.params) {
        //console.log("canshu:",config.params);
        let url = config.url + '?';
        for (const propName of Object.keys(config.params)) {
          var value = config.params[propName];
          var part = encodeURIComponent(propName) + "=";
          if (value !== null && typeof (value) !== "undefined") {
            if (typeof value === 'object') {
              for (const key of Object.keys(value)) {
                let params = propName + '[' + key + ']';
                var subPart = encodeURIComponent(params) + "=";
    
                //只要请求路径不是login,全部加密  //李昭 20220216
                if (config.url == "/login") {
                  url += subPart + encodeURIComponent(value[key]) + "&";
                } else {
                  let sm4Para = "";
                  if (key == "url") {
                    sm4Para = encodeURIComponent(value[key]);
                  } else {
                    sm4Para = encodeURIComponent(sm4Util.encryptData_ECB(value[key]));
                  }
                  url += subPart + sm4Para + "&";
                }
              }
            } else {
              //url += part + encodeURIComponent(value) + "&";
              //只要请求路径不是login,全部加密  //李昭 20220216
              if (config.url == "/login") {
                url += part + encodeURIComponent(value) + "&";
              } else {
                let sm4Para = "";
                if (propName == "url") {
                  sm4Para = encodeURIComponent(value);
                } else {
                  sm4Para = sm4Util.encryptData_CBC(value);
                  sm4Para = encodeURIComponent(sm4Util.encryptData_CBC(value));
                }
                url += part + sm4Para + "&";
              }
            }
          }
        }
        url = url.slice(0, -1);
        config.params = {};
        config.url = url;
      } else {
        //post也需要将参数都加密
        //console.log("canshu:",config.params);console.log("canshu2:",config.data);
        //只要请求路径不是login,全部加密  //李昭 20220216
        if (config.url == "/login") {
    
        } else {
          //将params里面的数据和data里面的数据都加密
          if (config.params != undefined) {
            for (let propName in config.params) {
              var value = config.params[propName];
              if (value !== null && value != undefined) {
                if (typeof value === 'object') {
                  value = JSON.stringify(value);
                  let sm4Para = "";
                  sm4Para = sm4Util.encryptData_CBC(value);
                  config.params[propName] = sm4Para;
                } else {
                  let sm4Para = "";
                  if (propName == "url") {
                    sm4Para = config.params[propName];
                  } else {
                    sm4Para = sm4Util.encryptData_CBC(config.params[propName]);
                  }
                  config.params[propName] = sm4Para;
                }
              }
            }
    
            //数据完整性:
            config.params["paraEndCheck"]=sm4Util.secretKey;
          }
          if (config.data != undefined) {
            for (let propName in config.data) {
              var value = config.data[propName];
              if (value !== null && value != undefined) {
                if (typeof value === 'object') {
                  value = JSON.stringify(value);
                  let sm4Para = "";
                  sm4Para = sm4Util.encryptData_CBC(value);
                  config.data[propName] = sm4Para;
                } else {
                  let sm4Para = "";
                  if (propName == "url") {
                    sm4Para = config.data[propName];
                  } else {
                    sm4Para = sm4Util.encryptData_CBC(config.data[propName]);
                  }
                  config.data[propName] = sm4Para;
                }
              }
            }
    
            //数据完整性:
            config.data["paraEndCheck"]=sm4Util.secretKey;
          }
        }
      }
      return config
    }, error => {
      console.log(error)
      Promise.reject(error)
    })
    
    // 响应拦截器
    service.interceptors.response.use(res => {
        // 未设置状态码则默认成功状态
        const code = res.data.code || 200;
        // 获取错误信息
        const msg = errorCode[code] || res.data.msg || errorCode['default']
        if (code === 401) {
          MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
              confirmButtonText: '重新登录',
              cancelButtonText: '取消',
              type: 'warning'
            }
          ).then(() => {
            store.dispatch('LogOut').then(() => {
              location.href = '/index';
            })
          }).catch(() => {
          });
        } else if (code === 500) {
          Message({
            message: msg,
            type: 'error'
          })
          return Promise.reject(new Error(msg))
        } else if (code !== 200) {
          Notification.error({
            title: msg
          })
          return Promise.reject('error')
        } else {
          //解密数据中除了code的所有项目
          // var newData={};
          if (res.data.isSecret == true) {
            for (var key in res.data) {
              if (key == "code") {
              } else {
                var value = res.data[key];
                value = sm4Util.decryptData_CBC(value);
    
                value = value.replace(/\u0000|\u0001|\u0002|\u0003|\u0004|\u0005|\u0006|\u0007|\u0008|\u0009|\u000a|\u000b|\u000c|\u000d|\u000e|\u000f|\u0010|\u0011|\u0012|\u0013|\u0014|\u0015|\u0016|\u0017|\u0018|\u0019|\u001a|\u001b|\u001c|\u001d|\u001e|\u001f|\u007F/g, "");
    
                //console.log("-----"+value);
                if (isJSON(value)) {
                  value = JSON.parse(value);
                } else if (isNumberStr(value)) {
                  if (value.indexOf(".") > -1) {
                    value = parseFloat(value);
                  } else {
                    value = parseInt(value);
                  }
                } else {
    
                }
                res.data[key] = value;
              }
            }
          }
          //console.log(res.data);
          return res.data
        }
      },
      error => {
        console.log('err' + error)
        let {message} = error;
        if (message == "Network Error") {
          message = "后端接口连接异常";
        } else if (message.includes("timeout")) {
          message = "系统接口请求超时";
        } else if (message.includes("Request failed with status code")) {
          message = "系统接口" + message.substr(message.length - 3) + "异常";
        }
        Message({
          message: message,
          type: 'error',
          duration: 5 * 1000
        })
        return Promise.reject(error)
      }
    )
    
    // 通用下载方法
    export function download(url, params, filename) {
      return service.post(url, params, {
        transformRequest: [(params) => {
          return tansParams(params)
        }],
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded'
        },
        responseType: 'blob'
      }).then((data) => {
        const content = data
        const blob = new Blob([content])
        if ('download' in document.createElement('a')) {
          const elink = document.createElement('a')
          elink.download = filename
          elink.style.display = 'none'
          elink.href = URL.createObjectURL(blob)
          document.body.appendChild(elink)
          elink.click()
          URL.revokeObjectURL(elink.href)
          document.body.removeChild(elink)
        } else {
          navigator.msSaveBlob(blob, filename)
        }
      }).catch((r) => {
        console.error(r)
      })
    }
    
    export default service
    
    export function isJSON(str) {
      if (typeof str == 'string') {
        str = str.trim();
        if (str.charAt(0) != "{" && str.charAt(0) != "[") {
          return false;
        }
        try {
          var obj = JSON.parse(str);
          return true;
        } catch (e) {
          console.log(e);
          return false;
        }
      }
    }
    

    更多相关内容
  • VC6.0,对sm4文档例子的C语言实现,加解密功能正常
  • SM4解密报错

    2020-09-16 11:35:00
    Exception in thread “main” javax.crypto.BadPaddingException: Given final block not properly padded ... 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。...

    Exception in thread “main” javax.crypto.BadPaddingException: Given final block not properly padded

    传入解密码方法的加密串不对,就会报这个错误;

    欢迎使用Markdown编辑器

    你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

    新的改变

    我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:

    1. 全新的界面设计 ,将会带来全新的写作体验;
    2. 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
    3. 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
    4. 全新的 KaTeX数学公式 语法;
    5. 增加了支持甘特图的mermaid语法1 功能;
    6. 增加了 多屏幕编辑 Markdown文章功能;
    7. 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
    8. 增加了 检查列表 功能。

    功能快捷键

    撤销:Ctrl/Command + Z
    重做:Ctrl/Command + Y
    加粗:Ctrl/Command + B
    斜体:Ctrl/Command + I
    标题:Ctrl/Command + Shift + H
    无序列表:Ctrl/Command + Shift + U
    有序列表:Ctrl/Command + Shift + O
    检查列表:Ctrl/Command + Shift + C
    插入代码:Ctrl/Command + Shift + K
    插入链接:Ctrl/Command + Shift + L
    插入图片:Ctrl/Command + Shift + G
    查找:Ctrl/Command + F
    替换:Ctrl/Command + G

    合理的创建标题,有助于目录的生成

    直接输入1次#,并按下space后,将生成1级标题。
    输入2次#,并按下space后,将生成2级标题。
    以此类推,我们支持6级标题。有助于使用TOC语法后生成一个完美的目录。

    如何改变文本的样式

    强调文本 强调文本

    加粗文本 加粗文本

    标记文本

    删除文本

    引用文本

    H2O is是液体。

    210 运算结果是 1024.

    插入链接与图片

    链接: link.

    图片: Alt

    带尺寸的图片: Alt

    居中的图片: Alt

    居中并且带尺寸的图片: Alt

    当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。

    如何插入一段漂亮的代码片

    博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

    // An highlighted block
    var foo = 'bar';
    

    生成一个适合你的列表

    • 项目
      • 项目
        • 项目
    1. 项目1
    2. 项目2
    3. 项目3
    • 计划任务
    • 完成任务

    创建一个表格

    一个简单的表格是这么创建的:

    项目Value
    电脑$1600
    手机$12
    导管$1

    设定内容居中、居左、居右

    使用:---------:居中
    使用:----------居左
    使用----------:居右

    第一列第二列第三列
    第一列文本居中第二列文本居右第三列文本居左

    SmartyPants

    SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:

    TYPEASCIIHTML
    Single backticks'Isn't this fun?'‘Isn’t this fun?’
    Quotes"Isn't this fun?"“Isn’t this fun?”
    Dashes-- is en-dash, --- is em-dash– is en-dash, — is em-dash

    创建一个自定义列表

    Markdown
    Text-to- HTML conversion tool
    Authors
    John
    Luke

    如何创建一个注脚

    一个具有注脚的文本。2

    注释也是必不可少的

    Markdown将文本转换为 HTML

    KaTeX数学公式

    您可以使用渲染LaTeX数学表达式 KaTeX:

    Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n1)!nN 是通过欧拉积分

    Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t   . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=0tz1etdt.

    你可以找到更多关于的信息 LaTeX 数学表达式here.

    新的甘特图功能,丰富你的文章

    Mon 06 Mon 13 Mon 20 已完成 进行中 计划一 计划二 现有任务 Adding GANTT diagram functionality to mermaid
    • 关于 甘特图 语法,参考 这儿,

    UML 图表

    可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图:

    张三 李四 王五 你好!李四, 最近怎么样? 你最近怎么样,王五? 我很好,谢谢! 我很好,谢谢! 李四想了很长时间, 文字太长了 不适合放在一行. 打量着王五... 很好... 王五, 你怎么样? 张三 李四 王五

    这将产生一个流程图。:

    链接
    长方形
    圆角长方形
    菱形
    • 关于 Mermaid 语法,参考 这儿,

    FLowchart流程图

    我们依旧会支持flowchart的流程图:

    Created with Raphaël 2.2.0 开始 我的操作 确认? 结束 yes no
    • 关于 Flowchart流程图 语法,参考 这儿.

    导出与导入

    导出

    如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。

    导入

    如果你想加载一篇你写过的.md文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
    继续你的创作。


    1. mermaid语法说明 ↩︎

    2. 注脚的解释 ↩︎

    展开全文
  • SMS4国密JAVA加密解密完整代码,无异常java类文件,导入即用。Convert.java 内部字符串进制转换类,SMS4.java 国密加密解密处理方法类。TestMain.java 测试类,调用 encrypt 加密 decode 解密
  • 国密SM4加密解密工具

    2018-10-14 20:08:48
    国密加密和解密工具,支持WIN7,WINXP,WIN10,WIN8系统
  • 做安全测评用到加解密,需要写小程序验证,之前在csdn上找到过一个资源,但是经过加密之后,不是正确的结果,经过多次查阅修改,最终验证通过,分享出来给大家使用(之前花了挺多积分,收一分,就当劳动报酬了)。
  • SM2签名入参填写“SM2Sign”、SM4解密入参填写“SM4DecryptECB”、SM4加密入参填写“SM4EncryptECB”. 2)参数二sM2Prikey:SM2私钥 3)参数三sM4Key:SM4密钥 4)参数四sInput:当smType=SM2Sign,则sInput入参...
  • SM4解密算法

    2018-01-15 15:33:52
    国家密码局于2012年发布的SM4国密算法,非常适合学习。
  • 1.Portable.BouncyCastle 引入 右键解决方案的引用,选择管理NuGet程序包 ...2.1.SM4Context public class SM4Context { public int mode; public long[] sk; public bool isPadding..

    1.Portable.BouncyCastle 引入

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

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

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

    2.SM4

    2.1.SM4Context

    public class SM4Context
        {
            public int mode;
    
            public long[] sk;
    
            public bool isPadding;
    
            public SM4Context()
            {
                this.mode = 1;
                this.isPadding = true;
                this.sk = new long[32];
            }
        }

    2.2.SM4

    public class SM4
        {
            public const int SM4_ENCRYPT = 1;
            public const int SM4_DECRYPT = 0;
    
            private long GET_ULONG_BE(byte[] b, int i)
            {
                long n = (long)(b[i] & 0xff) << 24 | (long)((b[i + 1] & 0xff) << 16) | (long)((b[i + 2] & 0xff) << 8) | (long)(b[i + 3] & 0xff) & 0xffffffffL;
                return n;
            }
    
            private void PUT_ULONG_BE(long n, byte[] b, int i)
            {
                b[i] = (byte)(int)(0xFF & n >> 24);
                b[i + 1] = (byte)(int)(0xFF & n >> 16);
                b[i + 2] = (byte)(int)(0xFF & n >> 8);
                b[i + 3] = (byte)(int)(0xFF & n);
            }
    
            private long SHL(long x, int n)
            {
                return (x & 0xFFFFFFFF) << n;
            }
    
            private long ROTL(long x, int n)
            {
                return SHL(x, n) | x >> (32 - n);
            }
    
            private void SWAP(long[] sk, int i)
            {
                long t = sk[i];
                sk[i] = sk[(31 - i)];
                sk[(31 - i)] = t;
            }
    
            public byte[] SboxTable = new byte[] { (byte) 0xd6, (byte) 0x90, (byte) 0xe9, (byte) 0xfe,
                (byte) 0xcc, (byte) 0xe1, 0x3d, (byte) 0xb7, 0x16, (byte) 0xb6,
                0x14, (byte) 0xc2, 0x28, (byte) 0xfb, 0x2c, 0x05, 0x2b, 0x67,
                (byte) 0x9a, 0x76, 0x2a, (byte) 0xbe, 0x04, (byte) 0xc3,
                (byte) 0xaa, 0x44, 0x13, 0x26, 0x49, (byte) 0x86, 0x06,
                (byte) 0x99, (byte) 0x9c, 0x42, 0x50, (byte) 0xf4, (byte) 0x91,
                (byte) 0xef, (byte) 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43,
                (byte) 0xed, (byte) 0xcf, (byte) 0xac, 0x62, (byte) 0xe4,
                (byte) 0xb3, 0x1c, (byte) 0xa9, (byte) 0xc9, 0x08, (byte) 0xe8,
                (byte) 0x95, (byte) 0x80, (byte) 0xdf, (byte) 0x94, (byte) 0xfa,
                0x75, (byte) 0x8f, 0x3f, (byte) 0xa6, 0x47, 0x07, (byte) 0xa7,
                (byte) 0xfc, (byte) 0xf3, 0x73, 0x17, (byte) 0xba, (byte) 0x83,
                0x59, 0x3c, 0x19, (byte) 0xe6, (byte) 0x85, 0x4f, (byte) 0xa8,
                0x68, 0x6b, (byte) 0x81, (byte) 0xb2, 0x71, 0x64, (byte) 0xda,
                (byte) 0x8b, (byte) 0xf8, (byte) 0xeb, 0x0f, 0x4b, 0x70, 0x56,
                (byte) 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, (byte) 0xd1,
                (byte) 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, (byte) 0x87,
                (byte) 0xd4, 0x00, 0x46, 0x57, (byte) 0x9f, (byte) 0xd3, 0x27,
                0x52, 0x4c, 0x36, 0x02, (byte) 0xe7, (byte) 0xa0, (byte) 0xc4,
                (byte) 0xc8, (byte) 0x9e, (byte) 0xea, (byte) 0xbf, (byte) 0x8a,
                (byte) 0xd2, 0x40, (byte) 0xc7, 0x38, (byte) 0xb5, (byte) 0xa3,
                (byte) 0xf7, (byte) 0xf2, (byte) 0xce, (byte) 0xf9, 0x61, 0x15,
                (byte) 0xa1, (byte) 0xe0, (byte) 0xae, 0x5d, (byte) 0xa4,
                (byte) 0x9b, 0x34, 0x1a, 0x55, (byte) 0xad, (byte) 0x93, 0x32,
                0x30, (byte) 0xf5, (byte) 0x8c, (byte) 0xb1, (byte) 0xe3, 0x1d,
                (byte) 0xf6, (byte) 0xe2, 0x2e, (byte) 0x82, 0x66, (byte) 0xca,
                0x60, (byte) 0xc0, 0x29, 0x23, (byte) 0xab, 0x0d, 0x53, 0x4e, 0x6f,
                (byte) 0xd5, (byte) 0xdb, 0x37, 0x45, (byte) 0xde, (byte) 0xfd,
                (byte) 0x8e, 0x2f, 0x03, (byte) 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b,
                0x51, (byte) 0x8d, 0x1b, (byte) 0xaf, (byte) 0x92, (byte) 0xbb,
                (byte) 0xdd, (byte) 0xbc, 0x7f, 0x11, (byte) 0xd9, 0x5c, 0x41,
                0x1f, 0x10, 0x5a, (byte) 0xd8, 0x0a, (byte) 0xc1, 0x31,
                (byte) 0x88, (byte) 0xa5, (byte) 0xcd, 0x7b, (byte) 0xbd, 0x2d,
                0x74, (byte) 0xd0, 0x12, (byte) 0xb8, (byte) 0xe5, (byte) 0xb4,
                (byte) 0xb0, (byte) 0x89, 0x69, (byte) 0x97, 0x4a, 0x0c,
                (byte) 0x96, 0x77, 0x7e, 0x65, (byte) 0xb9, (byte) 0xf1, 0x09,
                (byte) 0xc5, 0x6e, (byte) 0xc6, (byte) 0x84, 0x18, (byte) 0xf0,
                0x7d, (byte) 0xec, 0x3a, (byte) 0xdc, 0x4d, 0x20, 0x79,
                (byte) 0xee, 0x5f, 0x3e, (byte) 0xd7, (byte) 0xcb, 0x39, 0x48 };
    
            public uint[] FK = { 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc };
    
            public uint[] CK = { 0x00070e15,0x1c232a31,0x383f464d,0x545b6269,
                                            0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9,
                                            0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249,
                                            0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9,
                                            0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229,
                                            0x30373e45,0x4c535a61,0x686f767d,0x848b9299,
                                            0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209,
                                            0x10171e25,0x2c333a41,0x484f565d,0x646b7279 };
    
            private byte sm4Sbox(byte inch)
            {
                int i = inch & 0xFF;
                byte retVal = SboxTable[i];
                return retVal;
            }
    
            private long sm4Lt(long ka)
            {
                long bb = 0L;
                long c = 0L;
                byte[] a = new byte[4];
                byte[] b = new byte[4];
                PUT_ULONG_BE(ka, a, 0);
                b[0] = sm4Sbox(a[0]);
                b[1] = sm4Sbox(a[1]);
                b[2] = sm4Sbox(a[2]);
                b[3] = sm4Sbox(a[3]);
                bb = GET_ULONG_BE(b, 0);
                c = bb ^ ROTL(bb, 2) ^ ROTL(bb, 10) ^ ROTL(bb, 18) ^ ROTL(bb, 24);
                return c;
            }
    
            private long sm4F(long x0, long x1, long x2, long x3, long rk)
            {
                return x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk);
            }
    
            private long sm4CalciRK(long ka)
            {
                long bb = 0L;
                long rk = 0L;
                byte[] a = new byte[4];
                byte[] b = new byte[4];
                PUT_ULONG_BE(ka, a, 0);
                b[0] = sm4Sbox(a[0]);
                b[1] = sm4Sbox(a[1]);
                b[2] = sm4Sbox(a[2]);
                b[3] = sm4Sbox(a[3]);
                bb = GET_ULONG_BE(b, 0);
                rk = bb ^ ROTL(bb, 13) ^ ROTL(bb, 23);
                return rk;
            }
    
            private void sm4_setkey(long[] SK, byte[] key)
            {
                long[] MK = new long[4];
                long[] k = new long[36];
                int i = 0;
                MK[0] = GET_ULONG_BE(key, 0);
                MK[1] = GET_ULONG_BE(key, 4);
                MK[2] = GET_ULONG_BE(key, 8);
                MK[3] = GET_ULONG_BE(key, 12);
                k[0] = MK[0] ^ (long)FK[0];
                k[1] = MK[1] ^ (long)FK[1];
                k[2] = MK[2] ^ (long)FK[2];
                k[3] = MK[3] ^ (long)FK[3];
                for (; i < 32; i++)
                {
                    k[(i + 4)] = (k[i] ^ sm4CalciRK(k[(i + 1)] ^ k[(i + 2)] ^ k[(i + 3)] ^ (long)CK[i]));
                    SK[i] = k[(i + 4)];
                }
            }
    
            private void sm4_one_round(long[] sk, byte[] input, byte[] output)
            {
                int i = 0;
                long[] ulbuf = new long[36];
                ulbuf[0] = GET_ULONG_BE(input, 0);
                ulbuf[1] = GET_ULONG_BE(input, 4);
                ulbuf[2] = GET_ULONG_BE(input, 8);
                ulbuf[3] = GET_ULONG_BE(input, 12);
                while (i < 32)
                {
                    ulbuf[(i + 4)] = sm4F(ulbuf[i], ulbuf[(i + 1)], ulbuf[(i + 2)], ulbuf[(i + 3)], sk[i]);
                    i++;
                }
                PUT_ULONG_BE(ulbuf[35], output, 0);
                PUT_ULONG_BE(ulbuf[34], output, 4);
                PUT_ULONG_BE(ulbuf[33], output, 8);
                PUT_ULONG_BE(ulbuf[32], output, 12);
            }
    
            private byte[] padding(byte[] input, int mode)
            {
                if (input == null)
                {
                    return null;
                }
    
                byte[] ret = (byte[])null;
                if (mode == SM4_ENCRYPT)
                {
                    int p = 16 - input.Length % 16;
                    ret = new byte[input.Length + p];
                    Array.Copy(input, 0, ret, 0, input.Length);
                    for (int i = 0; i < p; i++)
                    {
                        ret[input.Length + i] = (byte)p;
                    }
                }
                else
                {
                    int p = input[input.Length - 1];
                    ret = new byte[input.Length - p];
                    Array.Copy(input, 0, ret, 0, input.Length - p);
                }
                return ret;
            }
    
            public void sm4_setkey_enc(SM4Context ctx, byte[] key)
            {
                ctx.mode = SM4_ENCRYPT;
                sm4_setkey(ctx.sk, key);
            }
    
            public void sm4_setkey_dec(SM4Context ctx, byte[] key)
            {
                int i = 0;
                ctx.mode = SM4_DECRYPT;
                sm4_setkey(ctx.sk, key);
                for (i = 0; i < 16; i++)
                {
                    SWAP(ctx.sk, i);
                }
            }
    
            public byte[] sm4_crypt_ecb(SM4Context ctx, byte[] input)
            {
                if ((ctx.isPadding) && (ctx.mode == SM4_ENCRYPT))
                {
                    input = padding(input, SM4_ENCRYPT);
                }
    
                int length = input.Length;
                byte[] bins = new byte[length];
                Array.Copy(input, 0, bins, 0, length);
                byte[] bous = new byte[length];
                for (int i = 0; length > 0; length -= 16, i++)
                {
                    byte[] inBytes = new byte[16];
                    byte[] outBytes = new byte[16];
                    Array.Copy(bins, i * 16, inBytes, 0, length > 16 ? 16 : length);
                    sm4_one_round(ctx.sk, inBytes, outBytes);
                    Array.Copy(outBytes, 0, bous, i * 16, length > 16 ? 16 : length);
                }
    
                if (ctx.isPadding && ctx.mode == SM4_DECRYPT)
                {
                    bous = padding(bous, SM4_DECRYPT);
                }
                return bous;
            }
    
            public byte[] sm4_crypt_cbc(SM4Context ctx, byte[] iv, byte[] input)
            {
                if (ctx.isPadding && ctx.mode == SM4_ENCRYPT)
                {
                    input = padding(input, SM4_ENCRYPT);
                }
    
                int i = 0;
                int length = input.Length;
                byte[] bins = new byte[length];
                Array.Copy(input, 0, bins, 0, length);
                byte[] bous = null;
                List<byte> bousList = new List<byte>();
                if (ctx.mode == SM4_ENCRYPT)
                {
                    for (int j = 0; length > 0; length -= 16, j++)
                    {
                        byte[] inBytes = new byte[16];
                        byte[] outBytes = new byte[16];
                        byte[] out1 = new byte[16];
    
                        Array.Copy(bins, i * 16, inBytes, 0, length > 16 ? 16 : length);
                        for (i = 0; i < 16; i++)
                        {
                            outBytes[i] = ((byte)(inBytes[i] ^ iv[i]));
                        }
                        sm4_one_round(ctx.sk, outBytes, out1);
                        Array.Copy(out1, 0, iv, 0, 16);
                        for (int k = 0; k < 16; k++)
                        {
                            bousList.Add(out1[k]);
                        }
                    }
                }
                else
                {
                    byte[] temp = new byte[16];
                    for (int j = 0; length > 0; length -= 16, j++)
                    {
                        byte[] inBytes = new byte[16];
                        byte[] outBytes = new byte[16];
                        byte[] out1 = new byte[16];
    
                        Array.Copy(bins, i * 16, inBytes, 0, length > 16 ? 16 : length);
                        Array.Copy(inBytes, 0, temp, 0, 16);
                        sm4_one_round(ctx.sk, inBytes, outBytes);
                        for (i = 0; i < 16; i++)
                        {
                            out1[i] = ((byte)(outBytes[i] ^ iv[i]));
                        }
                        Array.Copy(temp, 0, iv, 0, 16);
                        for (int k = 0; k < 16; k++)
                        {
                            bousList.Add(out1[k]);
                        }
                    }
    
                }
    
                if (ctx.isPadding && ctx.mode == SM4_DECRYPT)
                {
                    bous = padding(bousList.ToArray(), SM4_DECRYPT);
                    return bous;
                }
                else
                {
                    return bousList.ToArray();
                }
            }
        }

    2.3.Sm4Crypto

    public class Sm4Crypto
        {
            public string secretKey = "";
            public string iv = "";
            public bool hexString = false;
    
            #region ECB模式加密
            /// <summary>
            /// ECB模式加密
            /// </summary>
            /// <param name="plainText"></param>
            /// <returns></returns>
            public byte[] Encrypt_ECB(string plainText)
            {
                SM4Context ctx = new SM4Context();
                ctx.isPadding = true;
                ctx.mode = SM4.SM4_ENCRYPT;
    
                byte[] keyBytes;
                if (hexString)
                {
                    keyBytes = Hex.Decode(secretKey);
                }
                else
                {
                    keyBytes = Encoding.Default.GetBytes(secretKey);
                }
    
                SM4 sm4 = new SM4();
                sm4.sm4_setkey_enc(ctx, keyBytes);
                byte[] encrypted = sm4.sm4_crypt_ecb(ctx, Encoding.Default.GetBytes(plainText));
    
                return Hex.Encode(encrypted);
            }
            /// <summary>
            /// ECB模式加密
            /// </summary>
            /// <param name="plainBytes"></param>
            /// <returns></returns>
            public byte[] Encrypt_ECB(byte[] plainBytes)
            {
                SM4Context ctx = new SM4Context();
                ctx.isPadding = true;
                ctx.mode = SM4.SM4_ENCRYPT;
    
                byte[] keyBytes;
                if (hexString)
                {
                    keyBytes = Hex.Decode(secretKey);
                }
                else
                {
                    keyBytes = Encoding.Default.GetBytes(secretKey);
                }
    
                SM4 sm4 = new SM4();
                sm4.sm4_setkey_enc(ctx, keyBytes);
                byte[] encrypted = sm4.sm4_crypt_ecb(ctx, plainBytes);
    
                return Hex.Encode(encrypted);
            }
            /// <summary>
            /// ECB模式加密
            /// </summary>
            /// <param name="plainText"></param>
            /// <returns></returns>
            public string Encrypt_ECB_Str(string plainText)
            {
                SM4Context ctx = new SM4Context();
                ctx.isPadding = true;
                ctx.mode = SM4.SM4_ENCRYPT;
    
                byte[] keyBytes;
                if (hexString)
                {
                    keyBytes = Hex.Decode(secretKey);
                }
                else
                {
                    keyBytes = Encoding.Default.GetBytes(secretKey);
                }
    
                SM4 sm4 = new SM4();
                sm4.sm4_setkey_enc(ctx, keyBytes);
                byte[] encrypted = sm4.sm4_crypt_ecb(ctx, Encoding.Default.GetBytes(plainText));
    
                return Encoding.Default.GetString(Hex.Encode(encrypted));
            }
            /// <summary>
            /// ECB模式加密
            /// </summary>
            /// <param name="plainBytes"></param>
            /// <returns></returns>
            public string Encrypt_ECB_Str(byte[] plainBytes)
            {
                SM4Context ctx = new SM4Context();
                ctx.isPadding = true;
                ctx.mode = SM4.SM4_ENCRYPT;
    
                byte[] keyBytes;
                if (hexString)
                {
                    keyBytes = Hex.Decode(secretKey);
                }
                else
                {
                    keyBytes = Encoding.Default.GetBytes(secretKey);
                }
    
                SM4 sm4 = new SM4();
                sm4.sm4_setkey_enc(ctx, keyBytes);
                byte[] encrypted = sm4.sm4_crypt_ecb(ctx, plainBytes);
    
                return Encoding.Default.GetString(Hex.Encode(encrypted));
            }
            #endregion
    
            #region ECB模式解密
            /// <summary>
            /// ECB模式解密
            /// </summary>
            /// <param name="cipherText"></param>
            /// <returns></returns>
            public byte[] Decrypt_ECB(string cipherText)
            {
                SM4Context ctx = new SM4Context();
                ctx.isPadding = true;
                ctx.mode = SM4.SM4_DECRYPT;
    
                byte[] keyBytes;
                if (hexString)
                {
                    keyBytes = Hex.Decode(secretKey);
                }
                else
                {
                    keyBytes = Encoding.Default.GetBytes(secretKey);
                }
    
                SM4 sm4 = new SM4();
                sm4.sm4_setkey_dec(ctx, keyBytes);
                byte[] decrypted = sm4.sm4_crypt_ecb(ctx, Hex.Decode(cipherText));
                return decrypted;
            }
    
            /// <summary>
            /// ECB模式解密
            /// </summary>
            /// <param name="plainBytes"></param>
            /// <returns></returns>
            public byte[] Decrypt_ECB(byte[] cipherBytes)
            {
                SM4Context ctx = new SM4Context();
                ctx.isPadding = true;
                ctx.mode = SM4.SM4_DECRYPT;
    
                byte[] keyBytes;
                if (hexString)
                {
                    keyBytes = Hex.Decode(secretKey);
                }
                else
                {
                    keyBytes = Encoding.Default.GetBytes(secretKey);
                }
    
                SM4 sm4 = new SM4();
                sm4.sm4_setkey_dec(ctx, keyBytes);
                byte[] decrypted = sm4.sm4_crypt_ecb(ctx, Hex.Decode(cipherBytes));
                return decrypted;
            }
    
            /// <summary>
            /// ECB模式解密
            /// </summary>
            /// <param name="cipherText"></param>
            /// <returns></returns>
            public string Decrypt_ECB_Str(string cipherText)
            {
                SM4Context ctx = new SM4Context();
                ctx.isPadding = true;
                ctx.mode = SM4.SM4_DECRYPT;
    
                byte[] keyBytes;
                if (hexString)
                {
                    keyBytes = Hex.Decode(secretKey);
                }
                else
                {
                    keyBytes = Encoding.Default.GetBytes(secretKey);
                }
    
                SM4 sm4 = new SM4();
                sm4.sm4_setkey_dec(ctx, keyBytes);
                byte[] decrypted = sm4.sm4_crypt_ecb(ctx, Hex.Decode(cipherText));
                return Encoding.Default.GetString(decrypted);
            }
    
            /// <summary>
            /// ECB模式解密
            /// </summary>
            /// <param name="plainBytes"></param>
            /// <returns></returns>
            public string Decrypt_ECB_Str(byte[] cipherBytes)
            {
                SM4Context ctx = new SM4Context();
                ctx.isPadding = true;
                ctx.mode = SM4.SM4_DECRYPT;
    
                byte[] keyBytes;
                if (hexString)
                {
                    keyBytes = Hex.Decode(secretKey);
                }
                else
                {
                    keyBytes = Encoding.Default.GetBytes(secretKey);
                }
    
                SM4 sm4 = new SM4();
                sm4.sm4_setkey_dec(ctx, keyBytes);
                byte[] decrypted = sm4.sm4_crypt_ecb(ctx, Hex.Decode(cipherBytes));
                return Encoding.Default.GetString(decrypted);
            }
            #endregion
    
            #region CBC模式加密
            /// <summary>
            /// CBC模式加密
            /// </summary>
            /// <param name="plainText"></param>
            /// <returns></returns>
            public byte[] Encrypt_CBC(string plainText)
            {
                SM4Context ctx = new SM4Context();
                ctx.isPadding = true;
                ctx.mode = SM4.SM4_ENCRYPT;
    
                byte[] keyBytes;
                byte[] ivBytes;
                if (hexString)
                {
                    keyBytes = Hex.Decode(secretKey);
                    ivBytes = Hex.Decode(iv);
                }
                else
                {
                    keyBytes = Encoding.Default.GetBytes(secretKey);
                    ivBytes = Encoding.Default.GetBytes(iv);
                }
    
                SM4 sm4 = new SM4();
                sm4.sm4_setkey_enc(ctx, keyBytes);
                byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Encoding.Default.GetBytes(plainText));
    
                return Hex.Encode(encrypted);
            }
    
            /// <summary>
            /// CBC模式加密
            /// </summary>
            /// <param name="plainBytes"></param>
            /// <returns></returns>
            public byte[] Encrypt_CBC(byte[] plainBytes)
            {
                SM4Context ctx = new SM4Context();
                ctx.isPadding = true;
                ctx.mode = SM4.SM4_ENCRYPT;
    
                byte[] keyBytes;
                byte[] ivBytes;
                if (hexString)
                {
                    keyBytes = Hex.Decode(secretKey);
                    ivBytes = Hex.Decode(iv);
                }
                else
                {
                    keyBytes = Encoding.Default.GetBytes(secretKey);
                    ivBytes = Encoding.Default.GetBytes(iv);
                }
    
                SM4 sm4 = new SM4();
                sm4.sm4_setkey_enc(ctx, keyBytes);
                byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, plainBytes);
    
                return Hex.Encode(encrypted);
            }
    
            /// <summary>
            /// CBC模式加密
            /// </summary>
            /// <param name="plainText"></param>
            /// <returns></returns>
            public string Encrypt_CBC_Str(string plainText)
            {
                SM4Context ctx = new SM4Context();
                ctx.isPadding = true;
                ctx.mode = SM4.SM4_ENCRYPT;
    
                byte[] keyBytes;
                byte[] ivBytes;
                if (hexString)
                {
                    keyBytes = Hex.Decode(secretKey);
                    ivBytes = Hex.Decode(iv);
                }
                else
                {
                    keyBytes = Encoding.Default.GetBytes(secretKey);
                    ivBytes = Encoding.Default.GetBytes(iv);
                }
    
                SM4 sm4 = new SM4();
                sm4.sm4_setkey_enc(ctx, keyBytes);
                byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Encoding.Default.GetBytes(plainText));
    
                return Encoding.Default.GetString(Hex.Encode(encrypted));
            }
    
            /// <summary>
            /// CBC模式加密
            /// </summary>
            /// <param name="plainBytes"></param>
            /// <returns></returns>
            public string Encrypt_CBC_Str(byte[] plainBytes)
            {
                SM4Context ctx = new SM4Context();
                ctx.isPadding = true;
                ctx.mode = SM4.SM4_ENCRYPT;
    
                byte[] keyBytes;
                byte[] ivBytes;
                if (hexString)
                {
                    keyBytes = Hex.Decode(secretKey);
                    ivBytes = Hex.Decode(iv);
                }
                else
                {
                    keyBytes = Encoding.Default.GetBytes(secretKey);
                    ivBytes = Encoding.Default.GetBytes(iv);
                }
    
                SM4 sm4 = new SM4();
                sm4.sm4_setkey_enc(ctx, keyBytes);
                byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, plainBytes);
    
                return Encoding.Default.GetString(Hex.Encode(encrypted));
            }
            #endregion
    
            #region CBC模式解密
            /// <summary>
            /// CBC模式解密
            /// </summary>
            /// <param name="cipherText"></param>
            /// <returns></returns>
            public byte[] Decrypt_CBC(string cipherText)
            {
                SM4Context ctx = new SM4Context();
                ctx.isPadding = true;
                ctx.mode = SM4.SM4_DECRYPT;
    
                byte[] keyBytes;
                byte[] ivBytes;
                if (hexString)
                {
                    keyBytes = Hex.Decode(secretKey);
                    ivBytes = Hex.Decode(iv);
                }
                else
                {
                    keyBytes = Encoding.Default.GetBytes(secretKey);
                    ivBytes = Encoding.Default.GetBytes(iv);
                }
    
                SM4 sm4 = new SM4();
                sm4.sm4_setkey_dec(ctx, keyBytes);
                byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Hex.Decode(cipherText));
                return decrypted;
            }
    
            /// <summary>
            /// CBC模式解密
            /// </summary>
            /// <param name="cipherText"></param>
            /// <returns></returns>
            public byte[] Decrypt_CBC(byte[] cipherBytes)
            {
                SM4Context ctx = new SM4Context();
                ctx.isPadding = true;
                ctx.mode = SM4.SM4_DECRYPT;
    
                byte[] keyBytes;
                byte[] ivBytes;
                if (hexString)
                {
                    keyBytes = Hex.Decode(secretKey);
                    ivBytes = Hex.Decode(iv);
                }
                else
                {
                    keyBytes = Encoding.Default.GetBytes(secretKey);
                    ivBytes = Encoding.Default.GetBytes(iv);
                }
    
                SM4 sm4 = new SM4();
                sm4.sm4_setkey_dec(ctx, keyBytes);
                byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Hex.Decode(cipherBytes));
                return decrypted;
            }
            /// <summary>
            /// CBC模式解密
            /// </summary>
            /// <param name="cipherText"></param>
            /// <returns></returns>
            public string Decrypt_CBC_Str(string cipherText)
            {
                SM4Context ctx = new SM4Context();
                ctx.isPadding = true;
                ctx.mode = SM4.SM4_DECRYPT;
    
                byte[] keyBytes;
                byte[] ivBytes;
                if (hexString)
                {
                    keyBytes = Hex.Decode(secretKey);
                    ivBytes = Hex.Decode(iv);
                }
                else
                {
                    keyBytes = Encoding.Default.GetBytes(secretKey);
                    ivBytes = Encoding.Default.GetBytes(iv);
                }
    
                SM4 sm4 = new SM4();
                sm4.sm4_setkey_dec(ctx, keyBytes);
                byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Hex.Decode(cipherText));
                return Encoding.Default.GetString(decrypted);
            }
    
            /// <summary>
            /// CBC模式解密
            /// </summary>
            /// <param name="cipherText"></param>
            /// <returns></returns>
            public string Decrypt_CBC_Str(byte[] cipherBytes)
            {
                SM4Context ctx = new SM4Context();
                ctx.isPadding = true;
                ctx.mode = SM4.SM4_DECRYPT;
    
                byte[] keyBytes;
                byte[] ivBytes;
                if (hexString)
                {
                    keyBytes = Hex.Decode(secretKey);
                    ivBytes = Hex.Decode(iv);
                }
                else
                {
                    keyBytes = Encoding.Default.GetBytes(secretKey);
                    ivBytes = Encoding.Default.GetBytes(iv);
                }
    
                SM4 sm4 = new SM4();
                sm4.sm4_setkey_dec(ctx, keyBytes);
                byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Hex.Decode(cipherBytes));
                return Encoding.Default.GetString(decrypted);
            }
            #endregion
        }

    展开全文
  • SM4解密

    2021-01-26 16:11:46
    -- 一个开源的加解密算法包 --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcmail-jdk15on</artifactId> <version>1.66</version> </...

    依赖包

    <!-- 一个开源的加解密算法包 -->
    <dependency>
    	<groupId>org.bouncycastle</groupId>
    	<artifactId>bcmail-jdk15on</artifactId>
    	<version>1.66</version>
    </dependency>
    <!-- 实用工具相关,这里主要用了里面的hexUtil,也可以自己封装 -->
    <dependency>
    	<groupId>cn.hutool</groupId>
    	<artifactId>hutool-all</artifactId>
    	<version>5.4.1</version>
    </dependency>
    

    密钥产生

    //需要注意的是,使用KeyGenerator生成密钥种子的时候,windows和linux上会产生不一致。
    //例如:
    KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, PROVIDER_NAME);
    SecureRandom random = new SecureRandom();
    if(null != seed && !"".equals(seed)){
    	random.setSeed(seed.getBytes());
    }
    kg.init(keySize, random);
    
    //解决办法
    SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
    

    正式代码

    import cn.hutool.core.util.HexUtil;
    import com.spinfo.common.constants.UserConstants;
    import com.spinfo.controller.UserController;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    import org.bouncycastle.util.encoders.Base64;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.util.DigestUtils;
    
    import javax.crypto.*;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    import java.security.*;
    import java.util.Arrays;
    
    public class SM4Util {
    
       private static Logger logger = LoggerFactory.getLogger(SM4Util.class);
    
       private static final String PROVIDER_NAME = "BC";
       public static final String ALGORITHM_NAME = "SM4";
       public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";
       public static final String ALGORITHM_NAME_CBC_PADDING = "SM4/CBC/PKCS5Padding";
       public static final String DEFAULT_KEY = "random_seed";
       public static final int DEFAULT_KEY_SIZE = 128;
       private static final int ENCRYPT_MODE = 1;
       private static final int DECRYPT_MODE = 2;
    
       static {
          Security.addProvider(new BouncyCastleProvider());
       }
    
       public static byte[] generateKey() throws NoSuchAlgorithmException, NoSuchProviderException {
          return generateKey(DEFAULT_KEY, DEFAULT_KEY_SIZE);
       }
    
       public static byte[] generateKey(String seed) throws NoSuchAlgorithmException, NoSuchProviderException {
          return generateKey(seed, DEFAULT_KEY_SIZE);
       }
    
       public static byte[] generateKey(String seed, int keySize) throws NoSuchAlgorithmException, NoSuchProviderException {
          KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, PROVIDER_NAME);
          SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
          if(null != seed && !"".equals(seed)){
             random.setSeed(seed.getBytes());
          }
          kg.init(keySize, random);
          return kg.generateKey().getEncoded();
       }
    
       /**
        * ecb 加密
        * @param key
        * @param data
        */
       public static byte[] encryptEcbPadding(byte[] key, byte[] data) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
          Cipher cipher = generateEcbCipher(ENCRYPT_MODE, key);
          return cipher.doFinal(data);
       }
    
       /**
        * ecb 解密
        * @param key
        * @param cipherText
        */
       public static byte[] decryptEcbPadding(byte[] key, byte[] cipherText) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException {
          Cipher cipher = generateEcbCipher(DECRYPT_MODE, key);
          return cipher.doFinal(cipherText);
       }
    
       /**
        * cbc 加密
        * @param key
        * @param data
        */
       public static byte[] encryptCbcPadding(byte[] key, byte[] iv, byte[] data) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
          Cipher cipher = generateCbcCipher(ENCRYPT_MODE, key, iv);
          return cipher.doFinal(data);
       }
    
       public static String encryptCbcPaddingString(byte[] key, byte[] iv, byte[] data) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
          Cipher cipher = generateCbcCipher(ENCRYPT_MODE, key, iv);
          byte[] result = cipher.doFinal(data);
          return Base64.toBase64String(result);
       }
    
       /**
        * cbc 解密
        * @param key
        * @param iv
        * @param cipherText
        */
       public static byte[] decryptCbcPadding(byte[] key, byte[] iv, String cipherText) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidAlgorithmParameterException {
          byte[] cipherBytes = Base64.decode(cipherText);
          Cipher cipher = generateCbcCipher(DECRYPT_MODE, key, iv);
          return cipher.doFinal(cipherBytes);
       }
    
       public static byte[] decryptCbcPadding(byte[] key, byte[] iv, byte[] cipherText) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidAlgorithmParameterException {
          Cipher cipher = generateCbcCipher(DECRYPT_MODE, key, iv);
          return cipher.doFinal(cipherText);
       }
    
       /**
        * ecb cipher
        * @param mode
        * @param key
        * @return
        */
       private static Cipher generateEcbCipher(int mode, byte[] key) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException {
          Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_ECB_PADDING, PROVIDER_NAME);
          Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);
          cipher.init(mode, sm4Key);
          return cipher;
       }
    
       /**
        * cbc cipher
        * @param mode
        * @param key
        * @return
        */
       private static Cipher generateCbcCipher(int mode, byte[] key, byte[] iv) throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException {
          Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_CBC_PADDING, PROVIDER_NAME);
          Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);
          IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
          cipher.init(mode, sm4Key, ivParameterSpec);
          return cipher;
       }
    
       /**
        * ecb 加密 times 次
        * @param data
        * @param salt
        * @param times
        * @return=
        */
       public static String encryptEcbDataTimes(String data, String salt, int times) throws GeneralSecurityException {
          try {
             byte[] key = HexUtil.decodeHex(salt);
             byte[] bytes = data.getBytes();
    
             for(int i = 0; i < times; ++i) {
                bytes = encryptEcbPadding(key, bytes);
             }
    
             data = Base64.toBase64String(bytes);
             return data;
          } catch (BadPaddingException | IllegalBlockSizeException | NoSuchPaddingException | NoSuchProviderException | NoSuchAlgorithmException | InvalidKeyException var5) {
             throw new GeneralSecurityException("SM4加密失败");
          }
       }
    
       /**
        * ecb 解密 times 次
        * @param data
        * @param salt
        * @param times
        * @return
        * @throws GeneralSecurityException
        */
       public static String decryptEcbDataTimes(String data, String salt, int times) throws GeneralSecurityException {
          try {
             byte[] bytes = Base64.decode(data);
             byte[] key = HexUtil.decodeHex(salt);
    
             for(int i = 0; i < times; ++i) {
                bytes = decryptEcbPadding(key, bytes);
             }
    
             data = new String(bytes);
             return data;
          } catch (BadPaddingException | IllegalBlockSizeException | NoSuchPaddingException | NoSuchProviderException | NoSuchAlgorithmException | InvalidKeyException var5) {
             throw new GeneralSecurityException("SM4解密失败");
          }
       }
    
       /**
        * cbc 加密 times 次
        * @param data
        * @param salt
        * @param times
        * @return=
        */
       public static String encryptCbcDataTimes(String data, String salt, int times)  {
          try {
             byte[] iv = generateKey();
             byte[] key = generateKey(salt);
             byte[] bytes = data.getBytes();
    
             Cipher cipher = generateCbcCipher(ENCRYPT_MODE, key, iv);
             for(int i = 0; i < times; ++i) {
                bytes = cipher.doFinal(bytes);
             }
    
             data = Base64.toBase64String(bytes);
             return data;
          } catch (Exception e) {
             e.printStackTrace();
             return null;
          }
       }
    
       /**
        * cbc 解密 times 次
        * @param data
        * @param salt
        * @param times
        * @return
        * @throws GeneralSecurityException
        */
       public static String decryptCbcDataTimes(String data, String salt, int times) throws GeneralSecurityException {
          try {
             byte[] iv = generateKey();
             byte[] bytes = Base64.decode(data);
             byte[] key = generateKey(salt);
    
             Cipher cipher = generateCbcCipher(ENCRYPT_MODE, key, iv);
             for(int i = 0; i < times; ++i) {
                bytes = cipher.doFinal(bytes);
             }
    
             data = new String(bytes);
             return data;
          } catch (BadPaddingException | IllegalBlockSizeException | NoSuchPaddingException | NoSuchProviderException | NoSuchAlgorithmException | InvalidKeyException var5) {
             throw new GeneralSecurityException("SM4解密失败");
          }
       }
    }
    
    展开全文
  • C#编写的exe工具,可实现SM2签名验签,SM4解密,100%适用于黑龙江省国家医保接口中进行应用。 操作方式:使用编译程序调用exe工具,exe工具将结果写入目录SM2SM4.txt中,再读取txt内容即可。 提供给第三方无法实现...
  • SM4加密解密

    万次阅读 2020-02-21 12:11:12
    最近工作需要用到SM4加密解密算法,所以研究了一下。 内容主要参考自:https://blog.csdn.net/weixin_34411563/article/details/86000381 首先介绍一下SM4加密算法 SM4是我们自己国家的一个分组密码算法,是国家...
  • SM2签名入参填写“SM2Sign”、SM4解密入参填写“SM4DecryptECB”、SM4加密入参填写“SM4EncryptECB”. 2)参数二sM2Prikey:SM2私钥 3)参数三sM4Key:SM4密钥 4)参数四sInput:当smType=SM2Sign,则sInput入参...
  • Sm4【国密4加密解密】实战

    千次阅读 2022-04-11 10:36:17
    由于工作需要使用sm4加密一些个人隐私信息,就研究了一下sm4;感觉它和上章节讲的Rsa(非对称加密)很相似 国密算法SM1-SM4简介 SM1 :为对称加密。其加密强度与AES相当。该算法不公开,调用该算法时,需要通过加密...
  • 国产sm2,sm3,sm4解密

    万次阅读 2019-08-02 18:04:56
    有个为国家做的项目,其中需求是必须要用国产的加密,...SM2加解密需要用到的依赖 cnpm install sm2 --save cnpm install --save crypto-js 方法的封装 import sm2 from "sm2"; import CryptoJS from "crypto-js...
  • sm4算法加密解密

    万次阅读 多人点赞 2020-05-08 09:58:52
    一、基本知识 ...它将明文分成多个等长的模块(block),使用确定的算法和对称密钥对每组分别加密解密。 对称加密、加密算法主要可以分为两种,一个是非对称加密算法,另一个就是对称加密算法。...二、sm...
  • 密文主秘钥数据:89A4CA515B89220AAFA32D695D95A890 保护秘钥:B1F15C84DD6817B9 作为秘钥需转为16进制字符串:42314631354338344444363831374239 保护秘钥 + 密文数据 = 明文主秘钥 (解密) 明文主...
  • c/c++实现SM4加密解密算法 代码实现 sm4.h sm4.cpp main.cpp 代码实现 sm4.h /* * @Author: Jinzhuo-li * @Date: 2021-10-14 16:27:19 * @LastEditTime: 2021-10-25 15:28:41 * @LastEditors: Please set ...
  • Java实现国密SM2-SM3-Sm4解密, * RSA->SM2 * AES->SM4 * MD5->SM3 * SM3 加密 用于替换MD5
  • SM4 前端javascript代码实现加密解密4. SM4 后端java代码实现5. 测试SM4是否可用 1. SM算法简介 SM算法:国密即国家密码局认定的国产密码算法。主要有SM1,SM2,SM3,SM4。密钥长度和分组长度均为128位。 SM1 为...
  • sm4.js 二、Java后端 SM4.java SM4_Context.java Util.java SM4Utils.java 三、测试 一、前端 sm4.js /** * base64js * base64js.toByteArray(d.input) * base64js.fromByteArray(c); * 国密SM4加密...
  • 记录一下对一些稍大文件进行SM4解密的实现,这里只列出了核心代码,其他不涉及的代码或者有任何疑问可以查看我之前写的密码技术专题博客 var key = []byte("1234567812345678") var iv = []byte("1111111122222222...
  • 文章目录SM4实现ByteUtilSM4Util SM4实现 ByteUtil ByteUtil.js,用于通用的字节处理. // 左移 export let left_move = (text, number) => { if (text == null) { return null; } let result = ""; for (let...
  • 国密算法功能 1. SM2 加密解密、公钥私钥生成、签名与验签;... SM4 加密解密; 3. SM3加密 4. 代码实现、调用案例源码 代码经过本人测试通过,调用BouncyCastle.Crypto.dll的全部实现代码,源码分享。
  • C# SM4解密实现

    千次阅读 热门讨论 2019-06-07 08:13:06
    public class Sm4 { public const int SM4_ENCRYPT = 1; public const int SM4_DECRYPT = 0; private long GET_ULONG_BE(byte[] b, int i) { ...
  • 国密SM4加密解密

    千次阅读 2020-10-14 16:02:17
    i ++) { k [ i + 4 ] = k [ i ] ^ ( sm4CalciRK ( k [ i + 1 ] ^ k [ i + 2 ] ^ k [ i + 3 ] ^ CK [ i ])); SK [ i ] = k [ i + 4 ]; } } function sm4_one_round ( sk , input , output ) { let i = 0 ; const ...
  • SM4 加密、解密库。 SM3 杂凑算法编码。 适用 Delphi 版本:Delpih 7, 2010 (仅在这两个版本下测试过,使用过程尽量考虑兼容。因此其他版本的兼容必问题不大) 关于国密算法,网上基本只有 C/Java 的实现。...
  • 关于基于C# BouncyCastle,SM2、SM3、SM4 证书加解密应用例子。可应用于Java版本互通。
  • SM4前后端加密使用nopadding格式范例;

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,138
精华内容 3,255
关键字:

sm4解密