前端使用国密SM4进行加密、解密

这篇具有很好参考价值的文章主要介绍了前端使用国密SM4进行加密、解密。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

需求

前端/后端使用 国密SM4 进行加密/解密,
【注意】前后端配合加解密时,需要我们自定义密钥 ,一般由后端提供

【方法1】 - 使用 sm4util 依赖

  1. 下载 sm4util 依赖

    npm install sm4util
    
  2. sm4util 依赖使用说明
    前端使用国密SM4进行加密、解密

  3. 使用 - ECB 模式加解密

    /**** 【1】导入依赖 ****/ 
    import { SM4Util } from 'sm4util'
    
    /**** 【2】使用(在改依赖中有使用说明) ****/
    // 1.使用默认密钥进行加密/解密
    var sm4 = new SM4Util()
    const miStr1 = sm4.encryptDefault_ECB('123') // sm4.encryptDefault_ECB(需要加密的字符串)
    console.log('miStr1----', miStr1)
    const jieStr1 = sm4.decryptDefault_ECB(miStr1) // sm4.decryptDefault_ECB(将字符串进行加密后生成的字符串)
    console.log('jieStr1----', jieStr1) // 123
    
    // 2.使用自定义密钥进行加密/解密(【注意】使用自定义密钥进行加密时,后端解密需要用相同的密钥进行解密 - 此处密钥可能不对)
    // var sm4 = new SM4Util()
    const miStr2 = sm4.encryptCustom_ECB('123', '93F3044B07393417A737E2CC389D01AF') // 加密  sm4.encryptCustom_ECB(需要加密的字符串, 密钥)
    console.log('miStr2----', miStr2)
    const jieStr2 = sm4.decryptCustom_ECB(miStr2, '93F3044B07393417A737E2CC389D01AF') // 解密  sm4.decryptCustom_ECB(将字符串进行加密后生成的字符串, 密钥)
    console.log('jieStr2----', jieStr2) // 123
    

后端代码参考:https://blog.csdn.net/qq_48922459/article/details/122130283

【方法2】sm4.js引入

这种办法好像只能使用默认密钥 key,不能自定义 key 我使用的自定义 key 会报错 "key error" (也有可能是我的 密钥不对)
我使用自定义密钥 - 得改sm4.js 代码,详见 SM4Util 函数 定义处被注释的代码

1. /public/sm4.js

/**
 * base64js
 * base64js.toByteArray(d.input)
 * base64js.fromByteArray(c);
 * 国密SM4加密算法
 */
;(function (r) {
  if (typeof exports === 'object' && typeof module !== 'undefined') {
    module.exports = r()
  } else {
    if (typeof define === 'function' && define.amd) {
      define([], r)
    } else {
      var e
      if (typeof window !== 'undefined') {
        e = window
      } else {
        if (typeof global !== 'undefined') {
          e = global
        } else {
          if (typeof self !== 'undefined') {
            e = self
          } else {
            e = this
          }
        }
      }
      e.base64js = r()
    }
  }
})(function () {
  var r, e, t
  return (function r(e, t, n) {
    function o(i, a) {
      if (!t[i]) {
        if (!e[i]) {
          var u = typeof require == 'function' && require
          if (!a && u) {
            return u(i, !0)
          }
          if (f) {
            return f(i, !0)
          }
          var d = new Error("Cannot find module '" + i + "'")
          throw ((d.code = 'MODULE_NOT_FOUND'), d)
        }
        var c = (t[i] = { exports: {} })
        e[i][0].call(
          c.exports,
          function (r) {
            var t = e[i][1][r]
            return o(t ? t : r)
          },
          c,
          c.exports,
          r,
          e,
          t,
          n
        )
      }
      return t[i].exports
    }
    var f = typeof require == 'function' && require
    for (var i = 0; i < n.length; i++) {
      o(n[i])
    }
    return o
  })(
    {
      '/': [
        function (r, e, t) {
          t.byteLength = c
          t.toByteArray = v
          t.fromByteArray = s
          var n = []
          var o = []
          var f = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
          var i = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
          for (var a = 0, u = i.length; a < u; ++a) {
            n[a] = i[a]
            o[i.charCodeAt(a)] = a
          }
          o['-'.charCodeAt(0)] = 62
          o['_'.charCodeAt(0)] = 63
          function d(r) {
            var e = r.length
            if (e % 4 > 0) {
              throw new Error('Invalid string. Length must be a multiple of 4')
            }
            return r[e - 2] === '=' ? 2 : r[e - 1] === '=' ? 1 : 0
          }
          function c(r) {
            return (r.length * 3) / 4 - d(r)
          }
          function v(r) {
            var e, t, n, i, a
            var u = r.length
            i = d(r)
            a = new f((u * 3) / 4 - i)
            t = i > 0 ? u - 4 : u
            var c = 0
            for (e = 0; e < t; e += 4) {
              n =
                (o[r.charCodeAt(e)] << 18) |
                (o[r.charCodeAt(e + 1)] << 12) |
                (o[r.charCodeAt(e + 2)] << 6) |
                o[r.charCodeAt(e + 3)]
              a[c++] = (n >> 16) & 255
              a[c++] = (n >> 8) & 255
              a[c++] = n & 255
            }
            if (i === 2) {
              n = (o[r.charCodeAt(e)] << 2) | (o[r.charCodeAt(e + 1)] >> 4)
              a[c++] = n & 255
            } else {
              if (i === 1) {
                n = (o[r.charCodeAt(e)] << 10) | (o[r.charCodeAt(e + 1)] << 4) | (o[r.charCodeAt(e + 2)] >> 2)
                a[c++] = (n >> 8) & 255
                a[c++] = n & 255
              }
            }
            return a
          }
          function l(r) {
            return n[(r >> 18) & 63] + n[(r >> 12) & 63] + n[(r >> 6) & 63] + n[r & 63]
          }
          function h(r, e, t) {
            var n
            var o = []
            for (var f = e; f < t; f += 3) {
              n = (r[f] << 16) + (r[f + 1] << 8) + r[f + 2]
              o.push(l(n))
            }
            return o.join('')
          }
          function s(r) {
            var e
            var t = r.length
            var o = t % 3
            var f = ''
            var i = []
            var a = 16383
            for (var u = 0, d = t - o; u < d; u += a) {
              i.push(h(r, u, u + a > d ? d : u + a))
            }
            if (o === 1) {
              e = r[t - 1]
              f += n[e >> 2]
              f += n[(e << 4) & 63]
              f += '=='
            } else {
              if (o === 2) {
                e = (r[t - 2] << 8) + r[t - 1]
                f += n[e >> 10]
                f += n[(e >> 4) & 63]
                f += n[(e << 2) & 63]
                f += '='
              }
            }
            i.push(f)
            return i.join('')
          }
        },
        {}
      ]
    },
    {},
    []
  )('/')
})

/**
 * 国密SM4加密算法
 * @author wzk
 * @email 1216113487@qq.com
 * @company 中科软
 */
function SM4_Context() {
  this.mode = 1
  this.isPadding = true
  this.sk = new Array(32)
}

function SM4() {
  this.SM4_ENCRYPT = 1
  this.SM4_DECRYPT = 0

  var SboxTable = [
    0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, 0x2b, 0x67, 0x9a,
    0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef,
    0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62, 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80,
    0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6, 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19,
    0xe6, 0x85, 0x4f, 0xa8, 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d,
    0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, 0xd4, 0x00,
    0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, 0xea, 0xbf, 0x8a, 0xd2, 0x40,
    0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1, 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55,
    0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3, 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23,
    0xab, 0x0d, 0x53, 0x4e, 0x6f, 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c,
    0x5b, 0x51, 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8, 0x0a,
    0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, 0x89, 0x69, 0x97, 0x4a,
    0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d,
    0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48
  ]

  var FK = [0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc]

  var 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
  ]

  this.GET_ULONG_BE = function (b, i) {
    return ((b[i] & 0xff) << 24) | ((b[i + 1] & 0xff) << 16) | ((b[i + 2] & 0xff) << 8) | (b[i + 3] & 0xff & 0xffffffff)
  }

  this.PUT_ULONG_BE = function (n, b, i) {
    var t1 = 0xff & (n >> 24)
    var t2 = 0xff & (n >> 16)
    var t3 = 0xff & (n >> 8)
    var t4 = 0xff & n
    b[i] = t1 > 128 ? t1 - 256 : t1
    b[i + 1] = t2 > 128 ? t2 - 256 : t2
    b[i + 2] = t3 > 128 ? t3 - 256 : t3
    b[i + 3] = t4 > 128 ? t4 - 256 : t4
  }

  this.SHL = function (x, n) {
    return (x & 0xffffffff) << n
  }

  this.ROTL = function (x, n) {
    var s = this.SHL(x, n)
    var ss = x >> (32 - n)
    return this.SHL(x, n) | (x >> (32 - n))
  }

  this.sm4Lt = function (ka) {
    var bb = 0
    var c = 0
    var a = new Array(4)
    var b = new Array(4)
    this.PUT_ULONG_BE(ka, a, 0)
    b[0] = this.sm4Sbox(a[0])
    b[1] = this.sm4Sbox(a[1])
    b[2] = this.sm4Sbox(a[2])
    b[3] = this.sm4Sbox(a[3])
    bb = this.GET_ULONG_BE(b, 0)
    c = bb ^ this.ROTL(bb, 2) ^ this.ROTL(bb, 10) ^ this.ROTL(bb, 18) ^ this.ROTL(bb, 24)
    return c
  }

  this.sm4F = function (x0, x1, x2, x3, rk) {
    return x0 ^ this.sm4Lt(x1 ^ x2 ^ x3 ^ rk)
  }

  this.sm4CalciRK = function (ka) {
    var bb = 0
    var rk = 0
    var a = new Array(4)
    var b = new Array(4)
    this.PUT_ULONG_BE(ka, a, 0)
    b[0] = this.sm4Sbox(a[0])
    b[1] = this.sm4Sbox(a[1])
    b[2] = this.sm4Sbox(a[2])
    b[3] = this.sm4Sbox(a[3])
    bb = this.GET_ULONG_BE(b, 0)
    rk = bb ^ this.ROTL(bb, 13) ^ this.ROTL(bb, 23)
    return rk
  }

  this.sm4Sbox = function (inch) {
    var i = inch & 0xff
    var retVal = SboxTable[i]
    return retVal > 128 ? retVal - 256 : retVal
  }

  this.sm4_setkey_enc = function (ctx, key) {
    if (ctx == null) {
      alert('ctx is null!')
      return false
    }
    console.log('key----', key)
    if (key == null || key.length != 16) {
      alert('key error!')
      return false
    }
    ctx.mode = this.SM4_ENCRYPT
    this.sm4_setkey(ctx.sk, key)
  }

  this.sm4_setkey = function (SK, key) {
    var MK = new Array(4)
    var k = new Array(36)
    var i = 0
    MK[0] = this.GET_ULONG_BE(key, 0)
    MK[1] = this.GET_ULONG_BE(key, 4)
    MK[2] = this.GET_ULONG_BE(key, 8)
    MK[3] = this.GET_ULONG_BE(key, 12)
    k[0] = MK[0] ^ FK[0]
    k[1] = MK[1] ^ FK[1]
    k[2] = MK[2] ^ FK[2]
    k[3] = MK[3] ^ FK[3]
    for (var i = 0; i < 32; i++) {
      k[i + 4] = k[i] ^ this.sm4CalciRK(k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ CK[i])
      SK[i] = k[i + 4]
    }
  }
  this.padding = function (input, mode) {
    if (input == null) {
      return null
    }
    var ret = null
    if (mode == this.SM4_ENCRYPT) {
      var p = parseInt(16 - (input.length % 16))
      ret = input.slice(0)
      for (var i = 0; i < p; i++) {
        ret[input.length + i] = p
      }
    } else {
      var p = input[input.length - 1]
      ret = input.slice(0, input.length - p)
    }
    return ret
  }
  this.sm4_one_round = function (sk, input, output) {
    var i = 0
    var ulbuf = new Array(36)
    ulbuf[0] = this.GET_ULONG_BE(input, 0)
    ulbuf[1] = this.GET_ULONG_BE(input, 4)
    ulbuf[2] = this.GET_ULONG_BE(input, 8)
    ulbuf[3] = this.GET_ULONG_BE(input, 12)
    while (i < 32) {
      ulbuf[i + 4] = this.sm4F(ulbuf[i], ulbuf[i + 1], ulbuf[i + 2], ulbuf[i + 3], sk[i])
      i++
    }
    this.PUT_ULONG_BE(ulbuf[35], output, 0)
    this.PUT_ULONG_BE(ulbuf[34], output, 4)
    this.PUT_ULONG_BE(ulbuf[33], output, 8)
    this.PUT_ULONG_BE(ulbuf[32], output, 12)
  }

  this.sm4_crypt_ecb = function (ctx, input) {
    if (input == null) {
      alert('input is null!')
    }
    if (ctx.isPadding && ctx.mode == this.SM4_ENCRYPT) {
      input = this.padding(input, this.SM4_ENCRYPT)
    }

    var i = 0
    var length = input.length
    var bous = new Array()
    for (; length > 0; length -= 16) {
      var out = new Array(16)
      var ins = input.slice(i * 16, 16 * (i + 1))
      this.sm4_one_round(ctx.sk, ins, out)
      bous = bous.concat(out)
      i++
    }

    var output = bous
    if (ctx.isPadding && ctx.mode == this.SM4_DECRYPT) {
      output = this.padding(output, this.SM4_DECRYPT)
    }
    for (var i = 0; i < output.length; i++) {
      if (output[i] < 0) {
        output[i] = output[i] + 256
      }
    }
    return output
  }

  this.sm4_crypt_cbc = function (ctx, iv, input) {
    if (iv == null || iv.length != 16) {
      alert('iv error!')
    }

    if (input == null) {
      alert('input is null!')
    }

    if (ctx.isPadding && ctx.mode == this.SM4_ENCRYPT) {
      input = this.padding(input, this.SM4_ENCRYPT)
    }

    var i = 0
    var length = input.length
    var bous = new Array()
    if (ctx.mode == this.SM4_ENCRYPT) {
      var k = 0
      for (; length > 0; length -= 16) {
        var out = new Array(16)
        var out1 = new Array(16)
        var ins = input.slice(k * 16, 16 * (k + 1))

        for (i = 0; i < 16; i++) {
          out[i] = ins[i] ^ iv[i]
        }
        this.sm4_one_round(ctx.sk, out, out1)
        iv = out1.slice(0, 16)
        bous = bous.concat(out1)
        k++
      }
    } else {
      var temp = []
      var k = 0
      for (; length > 0; length -= 16) {
        var out = new Array(16)
        var out1 = new Array(16)
        var ins = input.slice(k * 16, 16 * (k + 1))
        temp = ins.slice(0, 16)
        sm4_one_round(ctx.sk, ins, out)
        for (i = 0; i < 16; i++) {
          out1[i] = out[i] ^ iv[i]
        }
        iv = temp.slice(0, 16)
        bous = bous.concat(out1)
        k++
      }
    }

    var output = bous
    if (ctx.isPadding && ctx.mode == this.SM4_DECRYPT) {
      output = this.padding(output, this.SM4_DECRYPT)
    }

    for (var i = 0; i < output.length; i++) {
      if (output[i] < 0) {
        output[i] = output[i] + 256
      }
    }
    return output
  }
}

// function SM4Util(key = '1111111111111111') {
function SM4Util() {
  console.log('SM4Util key----', key)
  // 和后端key一致(key为密钥)
  // this.secretKey = key
  this.secretKey = '1111111111111111'
  // 当时用CBC模式的时候
  this.iv = '1111111111111111'
  this.hexString = false

  // ECB模式加密
  this.encryptData_ECB = function (plainText) {
    try {
      var sm4 = new SM4()
      var ctx = new SM4_Context()
      ctx.isPadding = true
      ctx.mode = sm4.SM4_ENCRYPT
      var keyBytes = stringToByte(this.secretKey)
      sm4.sm4_setkey_enc(ctx, keyBytes)
      var encrypted = sm4.sm4_crypt_ecb(ctx, stringToByte(plainText))
      var cipherText = base64js.fromByteArray(encrypted)
      if (cipherText != null && cipherText.trim().length > 0) {
        cipherText.replace(/(\s*|\t|\r|\n)/g, '')
      }
      return cipherText
    } catch (e) {
      console.error(e)
      return null
    }
  }
  // CBC模式加密
  this.encryptData_CBC = function (plainText) {
    try {
      var sm4 = new SM4()
      var ctx = new SM4_Context()
      ctx.isPadding = true
      ctx.mode = sm4.SM4_ENCRYPT

      var keyBytes = stringToByte(this.secretKey)
      var ivBytes = stringToByte(this.iv)

      sm4.sm4_setkey_enc(ctx, keyBytes)
      var encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, stringToByte(plainText))
      var cipherText = base64js.fromByteArray(encrypted)
      if (cipherText != null && cipherText.trim().length > 0) {
        cipherText.replace(/(\s*|\t|\r|\n)/g, '')
      }
      return cipherText
    } catch (e) {
      console.error(e)
      return null
    }
  }

  stringToByte = function (str) {
    var bytes = new Array()
    var len, c
    len = str.length
    for (var i = 0; i < len; i++) {
      c = str.charCodeAt(i)
      if (c >= 0x010000 && c <= 0x10ffff) {
        bytes.push(((c >> 18) & 0x07) | 0xf0)
        bytes.push(((c >> 12) & 0x3f) | 0x80)
        bytes.push(((c >> 6) & 0x3f) | 0x80)
        bytes.push((c & 0x3f) | 0x80)
      } else if (c >= 0x000800 && c <= 0x00ffff) {
        bytes.push(((c >> 12) & 0x0f) | 0xe0)
        bytes.push(((c >> 6) & 0x3f) | 0x80)
        bytes.push((c & 0x3f) | 0x80)
      } else if (c >= 0x000080 && c <= 0x0007ff) {
        bytes.push(((c >> 6) & 0x1f) | 0xc0)
        bytes.push((c & 0x3f) | 0x80)
      } else {
        bytes.push(c & 0xff)
      }
    }
    console.log('bytes----', bytes)
    return bytes
  }

  byteToString = function (arr) {
    if (typeof arr === 'string') {
      return arr
    }
    var str = '',
      _arr = arr
    for (var i = 0; i < _arr.length; i++) {
      var one = _arr[i].toString(2),
        v = one.match(/^1+?(?=0)/)
      if (v && one.length == 8) {
        var bytesLength = v[0].length
        var store = _arr[i].toString(2).slice(7 - bytesLength)
        for (var st = 1; st < bytesLength; st++) {
          store += _arr[st + i].toString(2).slice(2)
        }
        str += String.fromCharCode(parseInt(store, 2))
        i += bytesLength - 1
      } else {
        str += String.fromCharCode(_arr[i])
      }
    }
    return str
  }
}

2. body 标签上引入该文件

<script src="/sm4.js"></script>
<body></body>

3. 使用 - ECB 模式加密

// 加密 - 使用默认秘钥 1111111111111111
var sm4 = new SM4Util();
sm4.encryptData_ECB('123');  
// 加密 - 使用自定义秘钥 93F3044B07393417A737E2CC389D01AF (需将 sm4.js 文件中SM4Util 函数处注释的代码打开)
var sm4 = new SM4Util('93F3044B07393417A737E2CC389D01AF');
sm4.encryptData_ECB('123');  // 后端解密的好像对不上,

该加密办法参考博客 https://blog.csdn.net/wzk_blog/article/details/122668114

【方法3】

1. 本地写 js 文件

@/utils/SM4Util/index.js

let base64js = require('./base64js')
let Hex = require('./hex')
let SM4 = require('./sm4')

function SM4Util() {}

/**
 * sm4 ecb 加密
 * @param utf8Str
 * @param utf8Key
 */
SM4Util.sm4ECBEncrypt = function (utf8Str, utf8Key) {
  if (!utf8Key) {
    utf8Key = 'zzfh!@#$QazxWsxc'
  }
  let sm4 = new SM4()
  let keyBytes = Hex.utf8StrToBytes(utf8Key)
  let contentBytes = Hex.utf8StrToBytes(utf8Str)
  let cipher = sm4.encrypt_ecb(keyBytes, contentBytes)
  return base64js.fromByteArray(cipher)
}

/**
 * sm4 ecb 解密
 * @param utf8Str
 * @param utf8Key
 */
SM4Util.sm4ECBDecrypt = function (base64Str, utf8Key) {
  if (!utf8Key) {
    utf8Key = 'zzfh!@#$QazxWsxc'
  }
  let sm4 = new SM4()
  let keyBytes = Hex.utf8StrToBytes(utf8Key)
  let contentBytes = base64js.toByteArray(base64Str)
  let plain = sm4.decrypt_ecb(keyBytes, contentBytes)
  return Hex.bytesToUtf8Str(plain)
}

/**
 * sm4 cbc 加密
 * @param utf8Str
 * @param utf8Key
 * @param utf8Iv
 */
SM4Util.sm4CBCEncrypt = function (utf8Str, utf8Key, utf8Iv) {
  if (!utf8Key) {
    utf8Key = 'cmbtest1cmbtest1'
  }
  if (!utf8Iv) {
    utf8Iv = 'cmbtest1cmbtest1'
  }
  let sm4 = new SM4()
  let keyBytes = Hex.utf8StrToBytes(utf8Key)
  let ivBytes = Hex.utf8StrToBytes(utf8Iv)
  let contentBytes = Hex.utf8StrToBytes(utf8Str)
  let cipher = sm4.encrypt_cbc(keyBytes, ivBytes, contentBytes)
  return base64js.fromByteArray(cipher)
}

/**
 * sm4 cbc 解密
 * @param utf8Str
 * @param utf8Key
 * @param utf8Iv
 */
SM4Util.sm4CBCDecrypt = function (base64Str, utf8Key, utf8Iv) {
  if (!utf8Key) {
    utf8Key = 'cmbtest1cmbtest1'
  }
  if (!utf8Iv) {
    utf8Iv = 'cmbtest1cmbtest1'
  }
  let sm4 = new SM4()
  let keyBytes = Hex.utf8StrToBytes(utf8Key)
  let ivBytes = Hex.utf8StrToBytes(utf8Iv)
  let contentBytes = base64js.toByteArray(base64Str)
  let plain = sm4.decrypt_cbc(keyBytes, ivBytes, contentBytes)
  return Hex.bytesToUtf8Str(plain)
}

module.exports = SM4Util

@/utils/SM4Util/base64js.js

/**
 * base64js
 * base64js.toByteArray(utf8Str)
 * base64js.fromByteArray(bytes);
 */
;(function (r) {
  if (typeof exports === 'object' && typeof module !== 'undefined') {
    module.exports = r()
  } else {
    if (typeof define === 'function' && define.amd) {
      define([], r)
    } else {
      var e
      if (typeof window !== 'undefined') {
        e = window
      } else {
        if (typeof global !== 'undefined') {
          e = global
        } else {
          if (typeof self !== 'undefined') {
            e = self
          } else {
            e = this
          }
        }
      }
      e.base64js = r()
    }
  }
})(function () {
  var r, e, t
  return (function r(e, t, n) {
    function o(i, a) {
      if (!t[i]) {
        if (!e[i]) {
          var u = typeof require == 'function' && require
          if (!a && u) {
            return u(i, !0)
          }
          if (f) {
            return f(i, !0)
          }
          var d = new Error("Cannot find module '" + i + "'")
          throw ((d.code = 'MODULE_NOT_FOUND'), d)
        }
        var c = (t[i] = {
          exports: {}
        })
        e[i][0].call(
          c.exports,
          function (r) {
            var t = e[i][1][r]
            return o(t ? t : r)
          },
          c,
          c.exports,
          r,
          e,
          t,
          n
        )
      }
      return t[i].exports
    }
    var f = typeof require == 'function' && require
    for (var i = 0; i < n.length; i++) {
      o(n[i])
    }
    return o
  })(
    {
      '/': [
        function (r, e, t) {
          t.byteLength = c
          t.toByteArray = v
          t.fromByteArray = s
          var n = []
          var o = []
          var f = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
          var i = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
          for (var a = 0, u = i.length; a < u; ++a) {
            n[a] = i[a]
            o[i.charCodeAt(a)] = a
          }
          o['-'.charCodeAt(0)] = 62
          o['_'.charCodeAt(0)] = 63

          function d(r) {
            var e = r.length
            if (e % 4 > 0) {
              throw new Error('Invalid string. Length must be a multiple of 4')
            }
            return r[e - 2] === '=' ? 2 : r[e - 1] === '=' ? 1 : 0
          }

          function c(r) {
            return (r.length * 3) / 4 - d(r)
          }

          function v(r) {
            var e, t, n, i, a
            var u = r.length
            i = d(r)
            a = new f((u * 3) / 4 - i)
            t = i > 0 ? u - 4 : u
            var c = 0
            for (e = 0; e < t; e += 4) {
              n =
                (o[r.charCodeAt(e)] << 18) |
                (o[r.charCodeAt(e + 1)] << 12) |
                (o[r.charCodeAt(e + 2)] << 6) |
                o[r.charCodeAt(e + 3)]
              a[c++] = (n >> 16) & 255
              a[c++] = (n >> 8) & 255
              a[c++] = n & 255
            }
            if (i === 2) {
              n = (o[r.charCodeAt(e)] << 2) | (o[r.charCodeAt(e + 1)] >> 4)
              a[c++] = n & 255
            } else {
              if (i === 1) {
                n = (o[r.charCodeAt(e)] << 10) | (o[r.charCodeAt(e + 1)] << 4) | (o[r.charCodeAt(e + 2)] >> 2)
                a[c++] = (n >> 8) & 255
                a[c++] = n & 255
              }
            }
            return a
          }

          function l(r) {
            return n[(r >> 18) & 63] + n[(r >> 12) & 63] + n[(r >> 6) & 63] + n[r & 63]
          }

          function h(r, e, t) {
            var n
            var o = []
            for (var f = e; f < t; f += 3) {
              n = (r[f] << 16) + (r[f + 1] << 8) + r[f + 2]
              o.push(l(n))
            }
            return o.join('')
          }

          function s(r) {
            var e
            var t = r.length
            var o = t % 3
            var f = ''
            var i = []
            var a = 16383
            for (var u = 0, d = t - o; u < d; u += a) {
              i.push(h(r, u, u + a > d ? d : u + a))
            }
            if (o === 1) {
              e = r[t - 1]
              f += n[e >> 2]
              f += n[(e << 4) & 63]
              f += '=='
            } else {
              if (o === 2) {
                e = (r[t - 2] << 8) + r[t - 1]
                f += n[e >> 10]
                f += n[(e >> 4) & 63]
                f += n[(e << 2) & 63]
                f += '='
              }
            }
            i.push(f)
            return i.join('')
          }
        },
        {}
      ]
    },
    {},
    []
  )('/')
})

@/utils/SM4Util/hex.js

function Hex() {}

/**
 * 数组转为16进制字符串
 * @param b  数组
 * @param pos  指定位置
 * @param len  长度
 * @returns {string}
 */
Hex.encode = function (b, pos, len) {
  var hexCh = new Array(len * 2)
  var hexCode = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F')

  for (var i = pos, j = 0; i < len + pos; i++, j++) {
    hexCh[j] = hexCode[(b[i] & 0xff) >> 4]
    hexCh[++j] = hexCode[b[i] & 0x0f]
  }

  return hexCh.join('')
}
/**
 * 16进制字符串转为字节数组
 * @param hex
 * @returns {any[]|null}
 */
Hex.decode = function (hex) {
  if (hex == null || hex == '') {
    return null
  }
  if (hex.length % 2 != 0) {
    return null
  }

  var ascLen = hex.length / 2
  var hexCh = this.toCharCodeArray(hex)
  var asc = new Array(ascLen)

  for (var i = 0; i < ascLen; i++) {
    if (hexCh[2 * i] >= 0x30 && hexCh[2 * i] <= 0x39) {
      asc[i] = (hexCh[2 * i] - 0x30) << 4
    } else if (hexCh[2 * i] >= 0x41 && hexCh[2 * i] <= 0x46) {
      //A-F : 0x41-0x46
      asc[i] = (hexCh[2 * i] - 0x41 + 10) << 4
    } else if (hexCh[2 * i] >= 0x61 && hexCh[2 * i] <= 0x66) {
      //a-f  : 0x61-0x66
      asc[i] = (hexCh[2 * i] - 0x61 + 10) << 4
    } else {
      return null
    }

    if (hexCh[2 * i + 1] >= 0x30 && hexCh[2 * i + 1] <= 0x39) {
      asc[i] = asc[i] | (hexCh[2 * i + 1] - 0x30)
    } else if (hexCh[2 * i + 1] >= 0x41 && hexCh[2 * i + 1] <= 0x46) {
      asc[i] = asc[i] | (hexCh[2 * i + 1] - 0x41 + 10)
    } else if (hexCh[2 * i + 1] >= 0x61 && hexCh[2 * i + 1] <= 0x66) {
      asc[i] = asc[i] | (hexCh[2 * i + 1] - 0x61 + 10)
    } else {
      return null
    }
  }
  return asc
}

/**
 * utf8字符串转为字节数组
 * @param utf8Str
 * @returns {[]}
 */
Hex.utf8StrToBytes = function (utf8Str) {
  var ens = encodeURIComponent(utf8Str)
  var es = unescape(ens)
  var esLen = es.length
  // Convert
  var words = []
  for (var i = 0; i < esLen; i++) {
    words[i] = es.charCodeAt(i)
  }
  return words
}
/**
 * 字节数组转为utf8字符串
 * @param bytesArray
 * @returns {string}
 */
Hex.bytesToUtf8Str = function (bytesArray) {
  var utf8Byte = bytesArray
  var latin1Chars = []
  for (var i = 0; i < utf8Byte.length; i++) {
    latin1Chars.push(String.fromCharCode(utf8Byte[i]))
  }
  return decodeURIComponent(escape(latin1Chars.join('')))
}

/**
 * 16进制字符串转为utf8字符串
 * @param utf8Str
 * @returns {string}
 */
Hex.hexToUtf8Str = function (utf8Str) {
  var utf8Byte = Hex.decode(utf8Str)
  var latin1Chars = []
  for (var i = 0; i < utf8Byte.length; i++) {
    latin1Chars.push(String.fromCharCode(utf8Byte[i]))
  }
  return decodeURIComponent(escape(latin1Chars.join('')))
}

/**
 * utf8字符串转为16进制字符串
 * @param utf8Str
 * @returns {string}
 */
Hex.utf8StrToHex = function (utf8Str) {
  var ens = encodeURIComponent(utf8Str)
  var es = unescape(ens)
  var esLen = es.length

  // Convert
  var words = []
  for (var i = 0; i < esLen; i++) {
    words[i] = es.charCodeAt(i).toString(16)
  }
  return words.join('')
}

/**
 * 字符串中每个字符转为数组中每个元素,数字,字母同Hex.utf8StrToBytes()方法
 * @param chs
 * @returns {any[]}
 */
Hex.toCharCodeArray = function (chs) {
  var chArr = new Array(chs.length)
  for (var i = 0; i < chs.length; i++) {
    chArr[i] = chs.charCodeAt(i)
  }
  return chArr
}

module.exports = Hex

@/utils/SM4Util/sm4.js

/*
 * sm4-1.0.js
 *
 * Copyright (c) 2019 RuXing Liang
 */
/**
 * @name sm4-1.0.js
 * @author RuXing Liang
 * @version 1.0.0 (2019-04-19)
 */
function SM4() {
  this.sbox = new Array(
    0xd6,
    0x90,
    0xe9,
    0xfe,
    0xcc,
    0xe1,
    0x3d,
    0xb7,
    0x16,
    0xb6,
    0x14,
    0xc2,
    0x28,
    0xfb,
    0x2c,
    0x05,
    0x2b,
    0x67,
    0x9a,
    0x76,
    0x2a,
    0xbe,
    0x04,
    0xc3,
    0xaa,
    0x44,
    0x13,
    0x26,
    0x49,
    0x86,
    0x06,
    0x99,
    0x9c,
    0x42,
    0x50,
    0xf4,
    0x91,
    0xef,
    0x98,
    0x7a,
    0x33,
    0x54,
    0x0b,
    0x43,
    0xed,
    0xcf,
    0xac,
    0x62,
    0xe4,
    0xb3,
    0x1c,
    0xa9,
    0xc9,
    0x08,
    0xe8,
    0x95,
    0x80,
    0xdf,
    0x94,
    0xfa,
    0x75,
    0x8f,
    0x3f,
    0xa6,
    0x47,
    0x07,
    0xa7,
    0xfc,
    0xf3,
    0x73,
    0x17,
    0xba,
    0x83,
    0x59,
    0x3c,
    0x19,
    0xe6,
    0x85,
    0x4f,
    0xa8,
    0x68,
    0x6b,
    0x81,
    0xb2,
    0x71,
    0x64,
    0xda,
    0x8b,
    0xf8,
    0xeb,
    0x0f,
    0x4b,
    0x70,
    0x56,
    0x9d,
    0x35,
    0x1e,
    0x24,
    0x0e,
    0x5e,
    0x63,
    0x58,
    0xd1,
    0xa2,
    0x25,
    0x22,
    0x7c,
    0x3b,
    0x01,
    0x21,
    0x78,
    0x87,
    0xd4,
    0x00,
    0x46,
    0x57,
    0x9f,
    0xd3,
    0x27,
    0x52,
    0x4c,
    0x36,
    0x02,
    0xe7,
    0xa0,
    0xc4,
    0xc8,
    0x9e,
    0xea,
    0xbf,
    0x8a,
    0xd2,
    0x40,
    0xc7,
    0x38,
    0xb5,
    0xa3,
    0xf7,
    0xf2,
    0xce,
    0xf9,
    0x61,
    0x15,
    0xa1,
    0xe0,
    0xae,
    0x5d,
    0xa4,
    0x9b,
    0x34,
    0x1a,
    0x55,
    0xad,
    0x93,
    0x32,
    0x30,
    0xf5,
    0x8c,
    0xb1,
    0xe3,
    0x1d,
    0xf6,
    0xe2,
    0x2e,
    0x82,
    0x66,
    0xca,
    0x60,
    0xc0,
    0x29,
    0x23,
    0xab,
    0x0d,
    0x53,
    0x4e,
    0x6f,
    0xd5,
    0xdb,
    0x37,
    0x45,
    0xde,
    0xfd,
    0x8e,
    0x2f,
    0x03,
    0xff,
    0x6a,
    0x72,
    0x6d,
    0x6c,
    0x5b,
    0x51,
    0x8d,
    0x1b,
    0xaf,
    0x92,
    0xbb,
    0xdd,
    0xbc,
    0x7f,
    0x11,
    0xd9,
    0x5c,
    0x41,
    0x1f,
    0x10,
    0x5a,
    0xd8,
    0x0a,
    0xc1,
    0x31,
    0x88,
    0xa5,
    0xcd,
    0x7b,
    0xbd,
    0x2d,
    0x74,
    0xd0,
    0x12,
    0xb8,
    0xe5,
    0xb4,
    0xb0,
    0x89,
    0x69,
    0x97,
    0x4a,
    0x0c,
    0x96,
    0x77,
    0x7e,
    0x65,
    0xb9,
    0xf1,
    0x09,
    0xc5,
    0x6e,
    0xc6,
    0x84,
    0x18,
    0xf0,
    0x7d,
    0xec,
    0x3a,
    0xdc,
    0x4d,
    0x20,
    0x79,
    0xee,
    0x5f,
    0x3e,
    0xd7,
    0xcb,
    0x39,
    0x48
  )

  this.fk = new Array(0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc)
  this.ck = new Array(
    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
  )
}

SM4.prototype = {
  expandKey: function (key) {
    var k = new Array(36)
    var mk = byteArrayToIntArray(key)
    k[0] = mk[0] ^ this.fk[0]
    k[1] = mk[1] ^ this.fk[1]
    k[2] = mk[2] ^ this.fk[2]
    k[3] = mk[3] ^ this.fk[3]
    var rk = new Array(32)
    for (var i = 0; i < 32; i++) {
      k[i + 4] = k[i] ^ this.T1(k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ this.ck[i])
      rk[i] = k[i + 4]
    }
    return rk
  },
  T1: function (ta) {
    var rk = 0
    var b = new Array(4)
    var a = intToByte(ta)
    b[0] = this.sbox[a[0] & 0xff]
    b[1] = this.sbox[a[1] & 0xff]
    b[2] = this.sbox[a[2] & 0xff]
    b[3] = this.sbox[a[3] & 0xff]
    var bint = byteToInt(b, 0)
    var rk = bint ^ ((bint << 13) | (bint >>> (32 - 13))) ^ ((bint << 23) | (bint >>> (32 - 23)))
    return rk
  },
  one_encrypt: function (rk, data) {
    var x = new Array(36)
    x[0] = byteToInt(data, 0)
    x[1] = byteToInt(data, 4)
    x[2] = byteToInt(data, 8)
    x[3] = byteToInt(data, 12)
    for (var i = 0; i < 32; i++) {
      x[i + 4] = x[i] ^ this.T0(x[i + 1] ^ x[i + 2] ^ x[i + 3] ^ rk[i])
    }
    var tmpx = new Array(4)
    for (var i = 35; i >= 32; i--) {
      tmpx[35 - i] = x[i]
    }
    var xbyte = intArrayToByteArray(tmpx)

    return xbyte
  },
  T0: function (ta) {
    var a = intToByte(ta)
    var b = new Array(4)
    b[0] = this.sbox[a[0] & 0xff]
    b[1] = this.sbox[a[1] & 0xff]
    b[2] = this.sbox[a[2] & 0xff]
    b[3] = this.sbox[a[3] & 0xff]
    var bint = byteToInt(b, 0)
    var c =
      bint ^
      ((bint << 2) | (bint >>> (32 - 2))) ^
      ((bint << 10) | (bint >>> (32 - 10))) ^
      ((bint << 18) | (bint >>> (32 - 18))) ^
      ((bint << 24) | (bint >>> (32 - 24)))
    return c
  },
  pkcs7padding: function (input, mode) {
    if (input == null) {
      return null
    }

    var ret = null
    if (mode == 1) {
      //填充
      var p = 16 - (input.length % 16)
      ret = new Array(input.length + p)
      arrayCopy(input, 0, ret, 0, input.length)
      for (var i = 0; i < p; i++) {
        ret[input.length + i] = p
      }
    } //去除填充
    else {
      var p = input[input.length - 1]
      ret = new Array(input.length - p)
      arrayCopy(input, 0, ret, 0, input.length - p)
    }
    return ret
  },
  /**
   *
   * @param key 字节数组
   * @param data 字节数组
   * @returns {any[]|null}
   */
  encrypt_ecb: function (key, data) {
    if (key == undefined || key == null || key.length % 16 != 0) {
      console.log('sm4 key is error!')
      return null
    }
    if (data == undefined || data == null || data.length <= 0) {
      console.log('data is error!')
      return null
    }
    var rk = this.expandKey(key)
    /*if(debug){
          var rkb = intArrayToByteArray(rk);
          console.log(Hex.encode(rkb,0,rkb.length));
      }*/

    var blockLen = 16
    var loop = parseInt(data.length / blockLen) //注意不能整除会有小数,要取整
    var cipher = new Array((loop + 1) * blockLen)
    var tmp = new Array(blockLen)
    var oneCipher = null

    for (var i = 0; i < loop; i++) {
      arrayCopy(data, i * blockLen, tmp, 0, blockLen)
      oneCipher = this.one_encrypt(rk, tmp)
      arrayCopy(oneCipher, 0, cipher, i * blockLen, blockLen)
    }

    var lessData = new Array(data.length % blockLen)
    if (lessData.length > 0) {
      arrayCopy(data, loop * blockLen, lessData, 0, data.length % blockLen)
    }
    var padding = this.pkcs7padding(lessData, 1)
    oneCipher = this.one_encrypt(rk, padding)
    arrayCopy(oneCipher, 0, cipher, loop * blockLen, blockLen)

    return cipher
  },
  /**
   *
   * @param key  字节数组
   * @param data  字节数组
   * @returns {any[]|null}
   */
  decrypt_ecb: function (key, data) {
    if (key == undefined || key == null || key.length % 16 != 0) {
      console.log('sm4 key is error!')
      return null
    }
    if (data == undefined || data == null || data.length % 16 != 0) {
      console.log('data is error!')
      return null
    }
    var rk = this.expandKey(key)
    var nrk = new Array(32)
    for (var i = 0; i < rk.length; i++) {
      nrk[i] = rk[32 - i - 1]
    }
    var blockLen = 16
    var loop = data.length / blockLen - 1
    var tmp = new Array(blockLen)
    var onePlain = null
    var plain = null
    //先解密最后一部分,确定数据长度
    arrayCopy(data, loop * blockLen, tmp, 0, blockLen)
    onePlain = this.one_encrypt(nrk, tmp)
    var lastPart = this.pkcs7padding(onePlain, 0)

    plain = new Array(loop * blockLen + lastPart.length)
    arrayCopy(lastPart, 0, plain, loop * blockLen, lastPart.length)

    //解密剩下部分数据
    for (var i = 0; i < loop; i++) {
      arrayCopy(data, i * blockLen, tmp, 0, blockLen)
      onePlain = this.one_encrypt(nrk, tmp)
      arrayCopy(onePlain, 0, plain, i * blockLen, blockLen)
    }

    return plain
  },
  encrypt_cbc: function (key, iv, data) {
    if (key == undefined || key == null || key.length % 16 != 0) {
      console.log('sm4 key is error!')
      return null
    }
    if (data == undefined || data == null || data.length <= 0) {
      console.log('data is error!')
      return null
    }
    if (iv == undefined || iv == null || iv.length % 16 != 0) {
      console.log('iv is error!')
      return null
    }
    var rk = this.expandKey(key)

    var blockLen = 16
    var loop = parseInt(data.length / blockLen) //注意不能整除会有小数,要取整
    var cipher = new Array((loop + 1) * blockLen)
    var tmp = new Array(blockLen)
    var oneCipher = null

    for (var i = 0; i < loop; i++) {
      arrayCopy(data, i * blockLen, tmp, 0, blockLen)
      for (var j = 0; j < blockLen; j++) {
        tmp[j] = tmp[j] ^ iv[j]
      }
      iv = this.one_encrypt(rk, tmp)
      arrayCopy(iv, 0, cipher, i * blockLen, blockLen)
    }

    var lessData = new Array(data.length % blockLen)
    if (lessData.length > 0) {
      arrayCopy(data, loop * blockLen, lessData, 0, data.length % blockLen)
    }
    var padding = this.pkcs7padding(lessData, 1)
    for (var i = 0; i < blockLen; i++) {
      padding[i] = padding[i] ^ iv[i]
    }
    iv = this.one_encrypt(rk, padding)
    arrayCopy(iv, 0, cipher, loop * blockLen, blockLen)

    return cipher
  },
  decrypt_cbc: function (key, iv, data) {
    if (key == undefined || key == null || key.length % 16 != 0) {
      console.log('sm4 key is error!')
      return null
    }
    if (data == undefined || data == null || data.length % 16 != 0) {
      console.log('data is error!')
      return null
    }
    if (iv == undefined || iv == null || iv.length % 16 != 0) {
      console.log('iv is error!')
      return null
    }
    var rk = this.expandKey(key)
    var nrk = new Array(32)
    for (var i = 0; i < rk.length; i++) {
      nrk[i] = rk[32 - i - 1]
    }
    var blockLen = 16
    var loop = data.length / blockLen
    var tmp = new Array(blockLen)
    var onePlain = null
    var plain = null

    //解密
    plain = new Array(data.length)
    for (var i = 0; i < loop; i++) {
      arrayCopy(data, i * blockLen, tmp, 0, blockLen)
      onePlain = this.one_encrypt(nrk, tmp)
      for (var j = 0; j < blockLen; j++) {
        onePlain[j] = onePlain[j] ^ iv[j]
      }
      arrayCopy(tmp, 0, iv, 0, blockLen)
      arrayCopy(onePlain, 0, plain, i * blockLen, blockLen)
    }

    //去填充,确定数据长度
    //arrayCopy(data,data.length-blockLen,tmp,0,blockLen);
    var lastPart = this.pkcs7padding(onePlain, 0)

    var realPlain = new Array(plain.length - blockLen + lastPart.length)
    arrayCopy(plain, 0, realPlain, 0, plain.length - blockLen)
    arrayCopy(lastPart, 0, realPlain, plain.length - blockLen, lastPart.length)
    return realPlain
  }
}

///工具类/
/*
 * 数组复制
 */
function arrayCopy(src, pos1, dest, pos2, len) {
  var realLen = len
  if (pos1 + len > src.length && pos2 + len <= dest.length) {
    realLen = src.length - pos1
  } else if (pos2 + len > dest.length && pos1 + len <= src.length) {
    realLen = dest.length - pos2
  } else if (pos1 + len <= src.length && pos2 + len <= dest.length) {
    realLen = len
  } else if (dest.length < src.length) {
    realLen = dest.length - pos2
  } else {
    realLen = src.length - pos2
  }

  for (var i = 0; i < realLen; i++) {
    dest[i + pos2] = src[i + pos1]
  }
}

/*
 * 长整型转成字节,一个长整型为8字节
 * 返回:字节数组
 */
function longToByte(num) {
  //TODO 这里目前只转换了低四字节,因为js没有长整型,得要封装
  return new Array(
    0,
    0,
    0,
    0,
    (num >> 24) & 0x000000ff,
    (num >> 16) & 0x000000ff,
    (num >> 8) & 0x000000ff,
    num & 0x000000ff
  )
}

/*
 * int数转成byte数组
 * 事实上只不过转成byte大小的数,实际占用空间还是4字节
 * 返回:字节数组
 */
function intToByte(num) {
  return new Array((num >> 24) & 0x000000ff, (num >> 16) & 0x000000ff, (num >> 8) & 0x000000ff, num & 0x000000ff)
}

/*
 * int数组转成byte数组,一个int数值转成四个byte
 * 返回:byte数组
 */
function intArrayToByteArray(nums) {
  var b = new Array(nums.length * 4)

  for (var i = 0; i < nums.length; i++) {
    arrayCopy(intToByte(nums[i]), 0, b, i * 4, 4)
  }

  return b
}

/*
 * byte数组转成int数值
 * 返回:int数值
 */
function byteToInt(b, pos) {
  if (pos + 3 < b.length) {
    return (b[pos] << 24) | (b[pos + 1] << 16) | (b[pos + 2] << 8) | b[pos + 3]
  } else if (pos + 2 < b.length) {
    return (b[pos + 1] << 16) | (b[pos + 2] << 8) | b[pos + 3]
  } else if (pos + 1 < b.length) {
    return (b[pos] << 8) | b[pos + 1]
  } else {
    return b[pos]
  }
}

/*
 * byte数组转成int数组,每四个字节转成一个int数值
 *
 */
function byteArrayToIntArray(b) {
  // var arrLen = b.length%4==0 ? b.length/4:b.length/4+1;
  var arrLen = Math.ceil(b.length / 4) //向上取整
  var out = new Array(arrLen)
  for (var i = 0; i < b.length; i++) {
    b[i] = b[i] & 0xff //避免负数造成影响
  }
  for (var i = 0; i < out.length; i++) {
    out[i] = byteToInt(b, i * 4)
  }
  return out
}

module.exports = SM4

2. 使用 - ECB 模式加解密

import SM4Util from '@/utils/SM4Util'
const miStr = SM4Util.sm4ECBEncrypt('13012345678', '93F3044B07393417') // 加密 SM4Util.sm4ECBEncrypt(需要加密的字符串, 密钥)
console.log('miStr----', miStr) // 8O/HeW8uoXU/CkcDaXRpxQ==
const jieStr = SM4Util.sm4ECBDecrypt(miStr, '93F3044B07393417') // 解密 SM4Util.sm4ECBDecrypt(加密后的字符串, 密钥)
console.log('jieStr----', jieStr) // 13012345678

// 加密后传给后端进行解密

可能出现的报错

若出现该报错,即为解密失败,可能是加密出错导致 Uncaught RangeError: Invalid array length
前端使用国密SM4进行加密、解密文章来源地址https://www.toymoban.com/news/detail-422440.html

到了这里,关于前端使用国密SM4进行加密、解密的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • java实现国密SM4的加密和解密方式(即时通讯的消息对话加密采用SM2还是SM4)

    1.对于即时通讯的消息对话加密采用SM2还是SM4更合适? 对于即时通讯的消息对话加密,建议采用SM4对称加密算法,而不是SM2非对称加密算法。 SM2主要用于数字签名和密钥交换,其加密速度比SM4慢,而且SM2不太适合对长消息进行加密,因为它只能对比较短的数据块进行加密,这

    2024年02月07日
    浏览(50)
  • 医保移动支付加密解密请求工具封装【国密SM2SM4】

    医保移动支付加密解密请求工具封装 定点医药机构向地方移动支付中心发起费用明细上传、支付下单、医保退费等交易时需要发送密文,由于各大医疗机构厂商的开发语各不相同,可能要有java的、c#的、python的、pb的、nodjs的、php的、还可能有Delphi的等。。。。很多开发语言

    2024年01月21日
    浏览(50)
  • java运用SM4国密算法对文件的加密与解密的实现

    首先我们在idae开发工具导入导入pom.xml的两个必要依赖  jar包下载地址:百度网盘 请输入提取码   npn8  图上systemPath 为jar包的文件路径,我们需要使用以下的路径存储jar包。(也可以自己设置) java包的文件路径如图所示 然后创建所需要加密的文件 ,需要加密的文件内容,

    2024年03月27日
    浏览(29)
  • C# 实现 国密SM4/ECB/PKCS7Padding对称加密解密

    C# 实现 国密SM4/ECB/PKCS7Padding对称加密解密,为了演示方便本问使用的是Visual Studio 2022 来构建代码的 1、新建项目,之后选择 项目 鼠标右键选择  管理NuGet程序包管理,输入  BouncyCastle 回车 添加BouncyCastle程序包 2、代码如下:CBC模式 代码如下:ECB模式 3、运行 4、SM4密码算法

    2024年02月11日
    浏览(32)
  • 前端SM4加密解密

    前后端加密一致,如果不一致就是key有问题 调用方法: sm4.js文件

    2024年04月25日
    浏览(34)
  • 前端sm2国密加密解密

    1.下载国密包 2.获取后端的公钥 注sm-crypto使用BC库加解密前端密钥与后端密钥是两队,非常规的base64密钥 前端公钥需要在前面加04占位否则无法解密 3.前端使用公钥进行加密 生成的加密串加04方便后端解密 4.前端使用私钥解密

    2024年02月11日
    浏览(37)
  • 国密SM2前端加密解密示例

    目录 一、 安装sm2依赖 二、编写代码 1、data中绑定数据 2、公钥加密 3、私钥解密 4、按钮绑定一下,数据可见一下 三、完整代码 要改变的数据phone和过程数据copyphone,公钥publicKey和私钥privateKey 具体生成测试公钥私钥可参照SM2加解密 C1为65字节第1字节为压缩标识,这里固定为

    2024年02月03日
    浏览(39)
  • vue普通加密以及国密SM2、SM3、sm4的使用

    sm-crypto:https://www.npmjs.com/package/sm-crypto 1. SM2是非对称加密算法 它是基于椭圆曲线密码的公钥密码算法标准,其秘钥长度256bit,包含数字签名、密钥交换和公钥加密,用于替换RSA/DH/ECDSA/ECDH等国际算法。可以满足电子认证服务系统等应用需求,由国家密码管理局于2010年12月17号

    2023年04月09日
    浏览(22)
  • 使用 Java Bouncy Castle实现国密算法SM4、SM3以及SM2的加密

    国密算法的实现借助了Java库函数 Bouncy Castle,加密库安装使用教程请参考链接 SM4,又称为商密算法,是一种分组密码算法,于2012年由中国密码技术研究中心(中国密码学会成员)发布,目前已成为我国国家密码算法,并在多个领域得到了广泛的应用。SM4算法采用了32轮迭代结

    2024年02月16日
    浏览(25)
  • 国密算法-SM4加解密工具类

    运行结果:

    2024年02月11日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包