0


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

目录

需求

前端/后端使用

国密SM4

进行加密/解密,
【注意】前后端配合加解密时,需要我们

自定义密钥

,一般由后端提供

【方法1】 - 使用 sm4util 依赖

  1. 下载 sm4util 依赖npminstall sm4util
  2. sm4util 依赖使用说明sm4util 依赖使用说明
  3. 使用 - ECB 模式加解密/**** 【1】导入依赖 ****/import{ SM4Util }from'sm4util'/**** 【2】使用(在改依赖中有使用说明) ****/// 1.使用默认密钥进行加密/解密var sm4 =newSM4Util()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(functionr(e, t, n){functiono(i, a){if(!t[i]){if(!e[i]){var u =typeof require =='function'&& require
          if(!a && u){returnu(i,!0)}if(f){returnf(i,!0)}var d =newError("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]returno(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)]=63functiond(r){var e = r.length
            if(e %4>0){thrownewError('Invalid string. Length must be a multiple of 4')}return r[e -2]==='='?2: r[e -1]==='='?1:0}functionc(r){return(r.length *3)/4-d(r)}functionv(r){var e, t, n, i, a
            var u = r.length
            i =d(r)
            a =newf((u *3)/4- i)
            t = i >0? u -4: u
            var c =0for(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
          }functionl(r){return n[(r >>18)&63]+ n[(r >>12)&63]+ n[(r >>6)&63]+ n[r &63]}functionh(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('')}functions(r){var e
            var t = r.length
            var o = t %3var f =''var i =[]var a =16383for(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 [email protected]
 * @company 中科软
 */functionSM4_Context(){this.mode =1this.isPadding =truethis.sk =newArray(32)}functionSM4(){this.SM4_ENCRYPT=1this.SM4_DECRYPT=0var 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]varFK=[0xa3b1bac6,0x56aa3350,0x677d9197,0xb27022dc]varCK=[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)returnthis.SHL(x, n)|(x >>(32- n))}this.sm4Lt=function(ka){var bb =0var c =0var a =newArray(4)var b =newArray(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 =0var rk =0var a =newArray(4)var b =newArray(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 &0xffvar retVal = SboxTable[i]return retVal >128? retVal -256: retVal
  }this.sm4_setkey_enc=function(ctx, key){if(ctx ==null){alert('ctx is null!')returnfalse}
    console.log('key----', key)if(key ==null|| key.length !=16){alert('key error!')returnfalse}
    ctx.mode =this.SM4_ENCRYPTthis.sm4_setkey(ctx.sk, key)}this.sm4_setkey=function(SK, key){varMK=newArray(4)var k =newArray(36)var i =0MK[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){returnnull}var ret =nullif(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 =0var ulbuf =newArray(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 =0var length = input.length
    var bous =newArray()for(; length >0; length -=16){var out =newArray(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 =0var length = input.length
    var bous =newArray()if(ctx.mode ==this.SM4_ENCRYPT){var k =0for(; length >0; length -=16){var out =newArray(16)var out1 =newArray(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 =0for(; length >0; length -=16){var out =newArray(16)var out1 =newArray(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') {functionSM4Util(){
  console.log('SM4Util key----', key)// 和后端key一致(key为密钥)// this.secretKey = keythis.secretKey ='1111111111111111'// 当时用CBC模式的时候this.iv ='1111111111111111'this.hexString =false// ECB模式加密this.encryptData_ECB=function(plainText){try{var sm4 =newSM4()var ctx =newSM4_Context()
      ctx.isPadding =true
      ctx.mode = sm4.SM4_ENCRYPTvar 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)returnnull}}// CBC模式加密this.encryptData_CBC=function(plainText){try{var sm4 =newSM4()var ctx =newSM4_Context()
      ctx.isPadding =true
      ctx.mode = sm4.SM4_ENCRYPTvar 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)returnnull}}stringToByte=function(str){var bytes =newArray()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)}elseif(c >=0x000800&& c <=0x00ffff){
        bytes.push(((c >>12)&0x0f)|0xe0)
        bytes.push(((c >>6)&0x3f)|0x80)
        bytes.push((c &0x3f)|0x80)}elseif(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 标签上引入该文件

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

3. 使用 - ECB 模式加密

// 加密 - 使用默认秘钥 1111111111111111var sm4 =newSM4Util();
sm4.encryptData_ECB('123');// 加密 - 使用自定义秘钥 93F3044B07393417A737E2CC389D01AF (需将 sm4.js 文件中SM4Util 函数处注释的代码打开)var sm4 =newSM4Util('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')letSM4=require('./sm4')functionSM4Util(){}/**
 * sm4 ecb 加密
 * @param utf8Str
 * @param utf8Key
 */
SM4Util.sm4ECBEncrypt=function(utf8Str, utf8Key){if(!utf8Key){
    utf8Key ='zzfh!@#$QazxWsxc'}let sm4 =newSM4()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 =newSM4()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 =newSM4()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 =newSM4()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(functionr(e, t, n){functiono(i, a){if(!t[i]){if(!e[i]){var u =typeof require =='function'&& require
          if(!a && u){returnu(i,!0)}if(f){returnf(i,!0)}var d =newError("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]returno(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)]=63functiond(r){var e = r.length
            if(e %4>0){thrownewError('Invalid string. Length must be a multiple of 4')}return r[e -2]==='='?2: r[e -1]==='='?1:0}functionc(r){return(r.length *3)/4-d(r)}functionv(r){var e, t, n, i, a
            var u = r.length
            i =d(r)
            a =newf((u *3)/4- i)
            t = i >0? u -4: u
            var c =0for(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
          }functionl(r){return n[(r >>18)&63]+ n[(r >>12)&63]+ n[(r >>6)&63]+ n[r &63]}functionh(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('')}functions(r){var e
            var t = r.length
            var o = t %3var f =''var i =[]var a =16383for(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
functionHex(){}/**
 * 数组转为16进制字符串
 * @param b  数组
 * @param pos  指定位置
 * @param len  长度
 * @returns {string}
 */
Hex.encode=function(b, pos, len){var hexCh =newArray(len *2)var hexCode =newArray('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 ==''){returnnull}if(hex.length %2!=0){returnnull}var ascLen = hex.length /2var hexCh =this.toCharCodeArray(hex)var asc =newArray(ascLen)for(var i =0; i < ascLen; i++){if(hexCh[2* i]>=0x30&& hexCh[2* i]<=0x39){
      asc[i]=(hexCh[2* i]-0x30)<<4}elseif(hexCh[2* i]>=0x41&& hexCh[2* i]<=0x46){//A-F : 0x41-0x46
      asc[i]=(hexCh[2* i]-0x41+10)<<4}elseif(hexCh[2* i]>=0x61&& hexCh[2* i]<=0x66){//a-f  : 0x61-0x66
      asc[i]=(hexCh[2* i]-0x61+10)<<4}else{returnnull}if(hexCh[2* i +1]>=0x30&& hexCh[2* i +1]<=0x39){
      asc[i]= asc[i]|(hexCh[2* i +1]-0x30)}elseif(hexCh[2* i +1]>=0x41&& hexCh[2* i +1]<=0x46){
      asc[i]= asc[i]|(hexCh[2* i +1]-0x41+10)}elseif(hexCh[2* i +1]>=0x61&& hexCh[2* i +1]<=0x66){
      asc[i]= asc[i]|(hexCh[2* i +1]-0x61+10)}else{returnnull}}return asc
}/**
 * utf8字符串转为字节数组
 * @param utf8Str
 * @returns {[]}
 */
Hex.utf8StrToBytes=function(utf8Str){var ens =encodeURIComponent(utf8Str)var es =unescape(ens)var esLen = es.length
  // Convertvar 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]))}returndecodeURIComponent(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]))}returndecodeURIComponent(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

  // Convertvar 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 =newArray(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)
 */functionSM4(){this.sbox =newArray(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 =newArray(0xa3b1bac6,0x56aa3350,0x677d9197,0xb27022dc)this.ck =newArray(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 =newArray(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 =newArray(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 =0var b =newArray(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 =newArray(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 =newArray(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 =newArray(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){returnnull}var ret =nullif(mode ==1){//填充var p =16-(input.length %16)
      ret =newArray(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 =newArray(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!')returnnull}if(data ==undefined|| data ==null|| data.length <=0){
      console.log('data is error!')returnnull}var rk =this.expandKey(key)/*if(debug){
          var rkb = intArrayToByteArray(rk);
          console.log(Hex.encode(rkb,0,rkb.length));
      }*/var blockLen =16var loop =parseInt(data.length / blockLen)//注意不能整除会有小数,要取整var cipher =newArray((loop +1)* blockLen)var tmp =newArray(blockLen)var oneCipher =nullfor(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 =newArray(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!')returnnull}if(data ==undefined|| data ==null|| data.length %16!=0){
      console.log('data is error!')returnnull}var rk =this.expandKey(key)var nrk =newArray(32)for(var i =0; i < rk.length; i++){
      nrk[i]= rk[32- i -1]}var blockLen =16var loop = data.length / blockLen -1var tmp =newArray(blockLen)var onePlain =nullvar plain =null//先解密最后一部分,确定数据长度arrayCopy(data, loop * blockLen, tmp,0, blockLen)
    onePlain =this.one_encrypt(nrk, tmp)var lastPart =this.pkcs7padding(onePlain,0)

    plain =newArray(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!')returnnull}if(data ==undefined|| data ==null|| data.length <=0){
      console.log('data is error!')returnnull}if(iv ==undefined|| iv ==null|| iv.length %16!=0){
      console.log('iv is error!')returnnull}var rk =this.expandKey(key)var blockLen =16var loop =parseInt(data.length / blockLen)//注意不能整除会有小数,要取整var cipher =newArray((loop +1)* blockLen)var tmp =newArray(blockLen)var oneCipher =nullfor(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 =newArray(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!')returnnull}if(data ==undefined|| data ==null|| data.length %16!=0){
      console.log('data is error!')returnnull}if(iv ==undefined|| iv ==null|| iv.length %16!=0){
      console.log('iv is error!')returnnull}var rk =this.expandKey(key)var nrk =newArray(32)for(var i =0; i < rk.length; i++){
      nrk[i]= rk[32- i -1]}var blockLen =16var loop = data.length / blockLen
    var tmp =newArray(blockLen)var onePlain =nullvar plain =null//解密
    plain =newArray(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 =newArray(plain.length - blockLen + lastPart.length)arrayCopy(plain,0, realPlain,0, plain.length - blockLen)arrayCopy(lastPart,0, realPlain, plain.length - blockLen, lastPart.length)return realPlain
  }}///工具类//*
 * 数组复制
 */functionarrayCopy(src, pos1, dest, pos2, len){var realLen = len
  if(pos1 + len > src.length && pos2 + len <= dest.length){
    realLen = src.length - pos1
  }elseif(pos2 + len > dest.length && pos1 + len <= src.length){
    realLen = dest.length - pos2
  }elseif(pos1 + len <= src.length && pos2 + len <= dest.length){
    realLen = len
  }elseif(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字节
 * 返回:字节数组
 */functionlongToByte(num){//TODO 这里目前只转换了低四字节,因为js没有长整型,得要封装returnnewArray(0,0,0,0,(num >>24)&0x000000ff,(num >>16)&0x000000ff,(num >>8)&0x000000ff,
    num &0x000000ff)}/*
 * int数转成byte数组
 * 事实上只不过转成byte大小的数,实际占用空间还是4字节
 * 返回:字节数组
 */functionintToByte(num){returnnewArray((num >>24)&0x000000ff,(num >>16)&0x000000ff,(num >>8)&0x000000ff, num &0x000000ff)}/*
 * int数组转成byte数组,一个int数值转成四个byte
 * 返回:byte数组
 */functionintArrayToByteArray(nums){var b =newArray(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数值
 */functionbyteToInt(b, pos){if(pos +3< b.length){return(b[pos]<<24)|(b[pos +1]<<16)|(b[pos +2]<<8)| b[pos +3]}elseif(pos +2< b.length){return(b[pos +1]<<16)|(b[pos +2]<<8)| b[pos +3]}elseif(pos +1< b.length){return(b[pos]<<8)| b[pos +1]}else{return b[pos]}}/*
 * byte数组转成int数组,每四个字节转成一个int数值
 *
 */functionbyteArrayToIntArray(b){// var arrLen = b.length%4==0 ? b.length/4:b.length/4+1;var arrLen = Math.ceil(b.length /4)//向上取整var out =newArray(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// 加密后传给后端进行解密

本文转载自: https://blog.csdn.net/m0_53562074/article/details/130248050
版权归原作者 Fighting_p 所有, 如有侵权,请联系我们删除。

“前端使用国密SM4进行加密、解密”的评论:

还没有评论