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

打印 上一主题 下一主题

主题 919|帖子 919|积分 2757

需求

   前端/后端使用 国密SM4 举行加密/解密,
【注意】前后端配合加解密时,必要我们自定义密钥 ,一样寻常由后端提供
  【方法1】 - 使用 sm4util 依赖


  • 下载 sm4util 依赖
    1. npm install sm4util
    复制代码
  • sm4util 依赖使用阐明

  • 使用 - ECB 模式加解密
    1. /**** 【1】导入依赖 ****/
    2. import { SM4Util } from 'sm4util'
    3. /**** 【2】使用(在改依赖中有使用说明) ****/
    4. // 1.使用默认密钥进行加密/解密
    5. var sm4 = new SM4Util()
    6. const miStr1 = sm4.encryptDefault_ECB('123') // sm4.encryptDefault_ECB(需要加密的字符串)
    7. console.log('miStr1----', miStr1)
    8. const jieStr1 = sm4.decryptDefault_ECB(miStr1) // sm4.decryptDefault_ECB(将字符串进行加密后生成的字符串)
    9. console.log('jieStr1----', jieStr1) // 123
    10. // 2.使用自定义密钥进行加密/解密(【注意】使用自定义密钥进行加密时,后端解密需要用相同的密钥进行解密 - 此处密钥可能不对)
    11. // var sm4 = new SM4Util()
    12. const miStr2 = sm4.encryptCustom_ECB('123', '93F3044B07393417A737E2CC389D01AF') // 加密  sm4.encryptCustom_ECB(需要加密的字符串, 密钥)
    13. console.log('miStr2----', miStr2)
    14. const jieStr2 = sm4.decryptCustom_ECB(miStr2, '93F3044B07393417A737E2CC389D01AF') // 解密  sm4.decryptCustom_ECB(将字符串进行加密后生成的字符串, 密钥)
    15. 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

  1. /**
  2. * base64js
  3. * base64js.toByteArray(d.input)
  4. * base64js.fromByteArray(c);
  5. * 国密SM4加密算法
  6. */
  7. ;(function (r) {
  8.   if (typeof exports === 'object' && typeof module !== 'undefined') {
  9.     module.exports = r()
  10.   } else {
  11.     if (typeof define === 'function' && define.amd) {
  12.       define([], r)
  13.     } else {
  14.       var e
  15.       if (typeof window !== 'undefined') {
  16.         e = window
  17.       } else {
  18.         if (typeof global !== 'undefined') {
  19.           e = global
  20.         } else {
  21.           if (typeof self !== 'undefined') {
  22.             e = self
  23.           } else {
  24.             e = this
  25.           }
  26.         }
  27.       }
  28.       e.base64js = r()
  29.     }
  30.   }
  31. })(function () {
  32.   var r, e, t
  33.   return (function r(e, t, n) {
  34.     function o(i, a) {
  35.       if (!t[i]) {
  36.         if (!e[i]) {
  37.           var u = typeof require == 'function' && require
  38.           if (!a && u) {
  39.             return u(i, !0)
  40.           }
  41.           if (f) {
  42.             return f(i, !0)
  43.           }
  44.           var d = new Error("Cannot find module '" + i + "'")
  45.           throw ((d.code = 'MODULE_NOT_FOUND'), d)
  46.         }
  47.         var c = (t[i] = { exports: {} })
  48.         e[i][0].call(
  49.           c.exports,
  50.           function (r) {
  51.             var t = e[i][1][r]
  52.             return o(t ? t : r)
  53.           },
  54.           c,
  55.           c.exports,
  56.           r,
  57.           e,
  58.           t,
  59.           n
  60.         )
  61.       }
  62.       return t[i].exports
  63.     }
  64.     var f = typeof require == 'function' && require
  65.     for (var i = 0; i < n.length; i++) {
  66.       o(n[i])
  67.     }
  68.     return o
  69.   })(
  70.     {
  71.       '/': [
  72.         function (r, e, t) {
  73.           t.byteLength = c
  74.           t.toByteArray = v
  75.           t.fromByteArray = s
  76.           var n = []
  77.           var o = []
  78.           var f = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
  79.           var i = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  80.           for (var a = 0, u = i.length; a < u; ++a) {
  81.             n[a] = i[a]
  82.             o[i.charCodeAt(a)] = a
  83.           }
  84.           o['-'.charCodeAt(0)] = 62
  85.           o['_'.charCodeAt(0)] = 63
  86.           function d(r) {
  87.             var e = r.length
  88.             if (e % 4 > 0) {
  89.               throw new Error('Invalid string. Length must be a multiple of 4')
  90.             }
  91.             return r[e - 2] === '=' ? 2 : r[e - 1] === '=' ? 1 : 0
  92.           }
  93.           function c(r) {
  94.             return (r.length * 3) / 4 - d(r)
  95.           }
  96.           function v(r) {
  97.             var e, t, n, i, a
  98.             var u = r.length
  99.             i = d(r)
  100.             a = new f((u * 3) / 4 - i)
  101.             t = i > 0 ? u - 4 : u
  102.             var c = 0
  103.             for (e = 0; e < t; e += 4) {
  104.               n =
  105.                 (o[r.charCodeAt(e)] << 18) |
  106.                 (o[r.charCodeAt(e + 1)] << 12) |
  107.                 (o[r.charCodeAt(e + 2)] << 6) |
  108.                 o[r.charCodeAt(e + 3)]
  109.               a[c++] = (n >> 16) & 255
  110.               a[c++] = (n >> 8) & 255
  111.               a[c++] = n & 255
  112.             }
  113.             if (i === 2) {
  114.               n = (o[r.charCodeAt(e)] << 2) | (o[r.charCodeAt(e + 1)] >> 4)
  115.               a[c++] = n & 255
  116.             } else {
  117.               if (i === 1) {
  118.                 n = (o[r.charCodeAt(e)] << 10) | (o[r.charCodeAt(e + 1)] << 4) | (o[r.charCodeAt(e + 2)] >> 2)
  119.                 a[c++] = (n >> 8) & 255
  120.                 a[c++] = n & 255
  121.               }
  122.             }
  123.             return a
  124.           }
  125.           function l(r) {
  126.             return n[(r >> 18) & 63] + n[(r >> 12) & 63] + n[(r >> 6) & 63] + n[r & 63]
  127.           }
  128.           function h(r, e, t) {
  129.             var n
  130.             var o = []
  131.             for (var f = e; f < t; f += 3) {
  132.               n = (r[f] << 16) + (r[f + 1] << 8) + r[f + 2]
  133.               o.push(l(n))
  134.             }
  135.             return o.join('')
  136.           }
  137.           function s(r) {
  138.             var e
  139.             var t = r.length
  140.             var o = t % 3
  141.             var f = ''
  142.             var i = []
  143.             var a = 16383
  144.             for (var u = 0, d = t - o; u < d; u += a) {
  145.               i.push(h(r, u, u + a > d ? d : u + a))
  146.             }
  147.             if (o === 1) {
  148.               e = r[t - 1]
  149.               f += n[e >> 2]
  150.               f += n[(e << 4) & 63]
  151.               f += '=='
  152.             } else {
  153.               if (o === 2) {
  154.                 e = (r[t - 2] << 8) + r[t - 1]
  155.                 f += n[e >> 10]
  156.                 f += n[(e >> 4) & 63]
  157.                 f += n[(e << 2) & 63]
  158.                 f += '='
  159.               }
  160.             }
  161.             i.push(f)
  162.             return i.join('')
  163.           }
  164.         },
  165.         {}
  166.       ]
  167.     },
  168.     {},
  169.     []
  170.   )('/')
  171. })
  172. /**
  173. * 国密SM4加密算法
  174. * @author wzk
  175. * @email 1216113487@qq.com
  176. * @company 中科软
  177. */
  178. function SM4_Context() {
  179.   this.mode = 1
  180.   this.isPadding = true
  181.   this.sk = new Array(32)
  182. }
  183. function SM4() {
  184.   this.SM4_ENCRYPT = 1
  185.   this.SM4_DECRYPT = 0
  186.   var SboxTable = [
  187.     0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, 0x2b, 0x67, 0x9a,
  188.     0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef,
  189.     0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62, 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80,
  190.     0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6, 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19,
  191.     0xe6, 0x85, 0x4f, 0xa8, 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d,
  192.     0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, 0xd4, 0x00,
  193.     0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, 0xea, 0xbf, 0x8a, 0xd2, 0x40,
  194.     0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1, 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55,
  195.     0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3, 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23,
  196.     0xab, 0x0d, 0x53, 0x4e, 0x6f, 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c,
  197.     0x5b, 0x51, 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8, 0x0a,
  198.     0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, 0x89, 0x69, 0x97, 0x4a,
  199.     0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d,
  200.     0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48
  201.   ]
  202.   var FK = [0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc]
  203.   var CK = [
  204.     0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, 0xe0e7eef5,
  205.     0xfc030a11, 0x181f262d, 0x343b4249, 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, 0xc0c7ced5, 0xdce3eaf1,
  206.     0xf8ff060d, 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed,
  207.     0xf4fb0209, 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
  208.   ]
  209.   this.GET_ULONG_BE = function (b, i) {
  210.     return ((b[i] & 0xff) << 24) | ((b[i + 1] & 0xff) << 16) | ((b[i + 2] & 0xff) << 8) | (b[i + 3] & 0xff & 0xffffffff)
  211.   }
  212.   this.PUT_ULONG_BE = function (n, b, i) {
  213.     var t1 = 0xff & (n >> 24)
  214.     var t2 = 0xff & (n >> 16)
  215.     var t3 = 0xff & (n >> 8)
  216.     var t4 = 0xff & n
  217.     b[i] = t1 > 128 ? t1 - 256 : t1
  218.     b[i + 1] = t2 > 128 ? t2 - 256 : t2
  219.     b[i + 2] = t3 > 128 ? t3 - 256 : t3
  220.     b[i + 3] = t4 > 128 ? t4 - 256 : t4
  221.   }
  222.   this.SHL = function (x, n) {
  223.     return (x & 0xffffffff) << n
  224.   }
  225.   this.ROTL = function (x, n) {
  226.     var s = this.SHL(x, n)
  227.     var ss = x >> (32 - n)
  228.     return this.SHL(x, n) | (x >> (32 - n))
  229.   }
  230.   this.sm4Lt = function (ka) {
  231.     var bb = 0
  232.     var c = 0
  233.     var a = new Array(4)
  234.     var b = new Array(4)
  235.     this.PUT_ULONG_BE(ka, a, 0)
  236.     b[0] = this.sm4Sbox(a[0])
  237.     b[1] = this.sm4Sbox(a[1])
  238.     b[2] = this.sm4Sbox(a[2])
  239.     b[3] = this.sm4Sbox(a[3])
  240.     bb = this.GET_ULONG_BE(b, 0)
  241.     c = bb ^ this.ROTL(bb, 2) ^ this.ROTL(bb, 10) ^ this.ROTL(bb, 18) ^ this.ROTL(bb, 24)
  242.     return c
  243.   }
  244.   this.sm4F = function (x0, x1, x2, x3, rk) {
  245.     return x0 ^ this.sm4Lt(x1 ^ x2 ^ x3 ^ rk)
  246.   }
  247.   this.sm4CalciRK = function (ka) {
  248.     var bb = 0
  249.     var rk = 0
  250.     var a = new Array(4)
  251.     var b = new Array(4)
  252.     this.PUT_ULONG_BE(ka, a, 0)
  253.     b[0] = this.sm4Sbox(a[0])
  254.     b[1] = this.sm4Sbox(a[1])
  255.     b[2] = this.sm4Sbox(a[2])
  256.     b[3] = this.sm4Sbox(a[3])
  257.     bb = this.GET_ULONG_BE(b, 0)
  258.     rk = bb ^ this.ROTL(bb, 13) ^ this.ROTL(bb, 23)
  259.     return rk
  260.   }
  261.   this.sm4Sbox = function (inch) {
  262.     var i = inch & 0xff
  263.     var retVal = SboxTable[i]
  264.     return retVal > 128 ? retVal - 256 : retVal
  265.   }
  266.   this.sm4_setkey_enc = function (ctx, key) {
  267.     if (ctx == null) {
  268.       alert('ctx is null!')
  269.       return false
  270.     }
  271.     console.log('key----', key)
  272.     if (key == null || key.length != 16) {
  273.       alert('key error!')
  274.       return false
  275.     }
  276.     ctx.mode = this.SM4_ENCRYPT
  277.     this.sm4_setkey(ctx.sk, key)
  278.   }
  279.   this.sm4_setkey = function (SK, key) {
  280.     var MK = new Array(4)
  281.     var k = new Array(36)
  282.     var i = 0
  283.     MK[0] = this.GET_ULONG_BE(key, 0)
  284.     MK[1] = this.GET_ULONG_BE(key, 4)
  285.     MK[2] = this.GET_ULONG_BE(key, 8)
  286.     MK[3] = this.GET_ULONG_BE(key, 12)
  287.     k[0] = MK[0] ^ FK[0]
  288.     k[1] = MK[1] ^ FK[1]
  289.     k[2] = MK[2] ^ FK[2]
  290.     k[3] = MK[3] ^ FK[3]
  291.     for (var i = 0; i < 32; i++) {
  292.       k[i + 4] = k[i] ^ this.sm4CalciRK(k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ CK[i])
  293.       SK[i] = k[i + 4]
  294.     }
  295.   }
  296.   this.padding = function (input, mode) {
  297.     if (input == null) {
  298.       return null
  299.     }
  300.     var ret = null
  301.     if (mode == this.SM4_ENCRYPT) {
  302.       var p = parseInt(16 - (input.length % 16))
  303.       ret = input.slice(0)
  304.       for (var i = 0; i < p; i++) {
  305.         ret[input.length + i] = p
  306.       }
  307.     } else {
  308.       var p = input[input.length - 1]
  309.       ret = input.slice(0, input.length - p)
  310.     }
  311.     return ret
  312.   }
  313.   this.sm4_one_round = function (sk, input, output) {
  314.     var i = 0
  315.     var ulbuf = new Array(36)
  316.     ulbuf[0] = this.GET_ULONG_BE(input, 0)
  317.     ulbuf[1] = this.GET_ULONG_BE(input, 4)
  318.     ulbuf[2] = this.GET_ULONG_BE(input, 8)
  319.     ulbuf[3] = this.GET_ULONG_BE(input, 12)
  320.     while (i < 32) {
  321.       ulbuf[i + 4] = this.sm4F(ulbuf[i], ulbuf[i + 1], ulbuf[i + 2], ulbuf[i + 3], sk[i])
  322.       i++
  323.     }
  324.     this.PUT_ULONG_BE(ulbuf[35], output, 0)
  325.     this.PUT_ULONG_BE(ulbuf[34], output, 4)
  326.     this.PUT_ULONG_BE(ulbuf[33], output, 8)
  327.     this.PUT_ULONG_BE(ulbuf[32], output, 12)
  328.   }
  329.   this.sm4_crypt_ecb = function (ctx, input) {
  330.     if (input == null) {
  331.       alert('input is null!')
  332.     }
  333.     if (ctx.isPadding && ctx.mode == this.SM4_ENCRYPT) {
  334.       input = this.padding(input, this.SM4_ENCRYPT)
  335.     }
  336.     var i = 0
  337.     var length = input.length
  338.     var bous = new Array()
  339.     for (; length > 0; length -= 16) {
  340.       var out = new Array(16)
  341.       var ins = input.slice(i * 16, 16 * (i + 1))
  342.       this.sm4_one_round(ctx.sk, ins, out)
  343.       bous = bous.concat(out)
  344.       i++
  345.     }
  346.     var output = bous
  347.     if (ctx.isPadding && ctx.mode == this.SM4_DECRYPT) {
  348.       output = this.padding(output, this.SM4_DECRYPT)
  349.     }
  350.     for (var i = 0; i < output.length; i++) {
  351.       if (output[i] < 0) {
  352.         output[i] = output[i] + 256
  353.       }
  354.     }
  355.     return output
  356.   }
  357.   this.sm4_crypt_cbc = function (ctx, iv, input) {
  358.     if (iv == null || iv.length != 16) {
  359.       alert('iv error!')
  360.     }
  361.     if (input == null) {
  362.       alert('input is null!')
  363.     }
  364.     if (ctx.isPadding && ctx.mode == this.SM4_ENCRYPT) {
  365.       input = this.padding(input, this.SM4_ENCRYPT)
  366.     }
  367.     var i = 0
  368.     var length = input.length
  369.     var bous = new Array()
  370.     if (ctx.mode == this.SM4_ENCRYPT) {
  371.       var k = 0
  372.       for (; length > 0; length -= 16) {
  373.         var out = new Array(16)
  374.         var out1 = new Array(16)
  375.         var ins = input.slice(k * 16, 16 * (k + 1))
  376.         for (i = 0; i < 16; i++) {
  377.           out[i] = ins[i] ^ iv[i]
  378.         }
  379.         this.sm4_one_round(ctx.sk, out, out1)
  380.         iv = out1.slice(0, 16)
  381.         bous = bous.concat(out1)
  382.         k++
  383.       }
  384.     } else {
  385.       var temp = []
  386.       var k = 0
  387.       for (; length > 0; length -= 16) {
  388.         var out = new Array(16)
  389.         var out1 = new Array(16)
  390.         var ins = input.slice(k * 16, 16 * (k + 1))
  391.         temp = ins.slice(0, 16)
  392.         sm4_one_round(ctx.sk, ins, out)
  393.         for (i = 0; i < 16; i++) {
  394.           out1[i] = out[i] ^ iv[i]
  395.         }
  396.         iv = temp.slice(0, 16)
  397.         bous = bous.concat(out1)
  398.         k++
  399.       }
  400.     }
  401.     var output = bous
  402.     if (ctx.isPadding && ctx.mode == this.SM4_DECRYPT) {
  403.       output = this.padding(output, this.SM4_DECRYPT)
  404.     }
  405.     for (var i = 0; i < output.length; i++) {
  406.       if (output[i] < 0) {
  407.         output[i] = output[i] + 256
  408.       }
  409.     }
  410.     return output
  411.   }
  412. }
  413. // function SM4Util(key = '1111111111111111') {
  414. function SM4Util() {
  415.   console.log('SM4Util key----', key)
  416.   // 和后端key一致(key为密钥)
  417.   // this.secretKey = key
  418.   this.secretKey = '1111111111111111'
  419.   // 当时用CBC模式的时候
  420.   this.iv = '1111111111111111'
  421.   this.hexString = false
  422.   // ECB模式加密
  423.   this.encryptData_ECB = function (plainText) {
  424.     try {
  425.       var sm4 = new SM4()
  426.       var ctx = new SM4_Context()
  427.       ctx.isPadding = true
  428.       ctx.mode = sm4.SM4_ENCRYPT
  429.       var keyBytes = stringToByte(this.secretKey)
  430.       sm4.sm4_setkey_enc(ctx, keyBytes)
  431.       var encrypted = sm4.sm4_crypt_ecb(ctx, stringToByte(plainText))
  432.       var cipherText = base64js.fromByteArray(encrypted)
  433.       if (cipherText != null && cipherText.trim().length > 0) {
  434.         cipherText.replace(/(\s*|\t|\r|\n)/g, '')
  435.       }
  436.       return cipherText
  437.     } catch (e) {
  438.       console.error(e)
  439.       return null
  440.     }
  441.   }
  442.   // CBC模式加密
  443.   this.encryptData_CBC = function (plainText) {
  444.     try {
  445.       var sm4 = new SM4()
  446.       var ctx = new SM4_Context()
  447.       ctx.isPadding = true
  448.       ctx.mode = sm4.SM4_ENCRYPT
  449.       var keyBytes = stringToByte(this.secretKey)
  450.       var ivBytes = stringToByte(this.iv)
  451.       sm4.sm4_setkey_enc(ctx, keyBytes)
  452.       var encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, stringToByte(plainText))
  453.       var cipherText = base64js.fromByteArray(encrypted)
  454.       if (cipherText != null && cipherText.trim().length > 0) {
  455.         cipherText.replace(/(\s*|\t|\r|\n)/g, '')
  456.       }
  457.       return cipherText
  458.     } catch (e) {
  459.       console.error(e)
  460.       return null
  461.     }
  462.   }
  463.   stringToByte = function (str) {
  464.     var bytes = new Array()
  465.     var len, c
  466.     len = str.length
  467.     for (var i = 0; i < len; i++) {
  468.       c = str.charCodeAt(i)
  469.       if (c >= 0x010000 && c <= 0x10ffff) {
  470.         bytes.push(((c >> 18) & 0x07) | 0xf0)
  471.         bytes.push(((c >> 12) & 0x3f) | 0x80)
  472.         bytes.push(((c >> 6) & 0x3f) | 0x80)
  473.         bytes.push((c & 0x3f) | 0x80)
  474.       } else if (c >= 0x000800 && c <= 0x00ffff) {
  475.         bytes.push(((c >> 12) & 0x0f) | 0xe0)
  476.         bytes.push(((c >> 6) & 0x3f) | 0x80)
  477.         bytes.push((c & 0x3f) | 0x80)
  478.       } else if (c >= 0x000080 && c <= 0x0007ff) {
  479.         bytes.push(((c >> 6) & 0x1f) | 0xc0)
  480.         bytes.push((c & 0x3f) | 0x80)
  481.       } else {
  482.         bytes.push(c & 0xff)
  483.       }
  484.     }
  485.     console.log('bytes----', bytes)
  486.     return bytes
  487.   }
  488.   byteToString = function (arr) {
  489.     if (typeof arr === 'string') {
  490.       return arr
  491.     }
  492.     var str = '',
  493.       _arr = arr
  494.     for (var i = 0; i < _arr.length; i++) {
  495.       var one = _arr[i].toString(2),
  496.         v = one.match(/^1+?(?=0)/)
  497.       if (v && one.length == 8) {
  498.         var bytesLength = v[0].length
  499.         var store = _arr[i].toString(2).slice(7 - bytesLength)
  500.         for (var st = 1; st < bytesLength; st++) {
  501.           store += _arr[st + i].toString(2).slice(2)
  502.         }
  503.         str += String.fromCharCode(parseInt(store, 2))
  504.         i += bytesLength - 1
  505.       } else {
  506.         str += String.fromCharCode(_arr[i])
  507.       }
  508.     }
  509.     return str
  510.   }
  511. }
复制代码
2. body 标签上引入该文件

  1. <script src="/sm4.js"></script>
  2. <body></body>
复制代码
3. 使用 - ECB 模式加密

  1. // 加密 - 使用默认秘钥 1111111111111111
  2. var sm4 = new SM4Util();
  3. sm4.encryptData_ECB('123');  
  4. // 加密 - 使用自定义秘钥 93F3044B07393417A737E2CC389D01AF (需将 sm4.js 文件中SM4Util 函数处注释的代码打开)
  5. var sm4 = new SM4Util('93F3044B07393417A737E2CC389D01AF');
  6. sm4.encryptData_ECB('123');  // 后端解密的好像对不上,
复制代码
该加密办法参考博客 https://blog.csdn.net/wzk_blog/article/details/122668114
【方法3】

1. 当地写 js 文件

@/utils/SM4Util/index.js
  1. let base64js = require('./base64js')
  2. let Hex = require('./hex')
  3. let SM4 = require('./sm4')
  4. function SM4Util() {}
  5. /**
  6. * sm4 ecb 加密
  7. * @param utf8Str
  8. * @param utf8Key
  9. */
  10. SM4Util.sm4ECBEncrypt = function (utf8Str, utf8Key) {
  11.   if (!utf8Key) {
  12.     utf8Key = 'zzfh!@#$QazxWsxc'
  13.   }
  14.   let sm4 = new SM4()
  15.   let keyBytes = Hex.utf8StrToBytes(utf8Key)
  16.   let contentBytes = Hex.utf8StrToBytes(utf8Str)
  17.   let cipher = sm4.encrypt_ecb(keyBytes, contentBytes)
  18.   return base64js.fromByteArray(cipher)
  19. }
  20. /**
  21. * sm4 ecb 解密
  22. * @param utf8Str
  23. * @param utf8Key
  24. */
  25. SM4Util.sm4ECBDecrypt = function (base64Str, utf8Key) {
  26.   if (!utf8Key) {
  27.     utf8Key = 'zzfh!@#$QazxWsxc'
  28.   }
  29.   let sm4 = new SM4()
  30.   let keyBytes = Hex.utf8StrToBytes(utf8Key)
  31.   let contentBytes = base64js.toByteArray(base64Str)
  32.   let plain = sm4.decrypt_ecb(keyBytes, contentBytes)
  33.   return Hex.bytesToUtf8Str(plain)
  34. }
  35. /**
  36. * sm4 cbc 加密
  37. * @param utf8Str
  38. * @param utf8Key
  39. * @param utf8Iv
  40. */
  41. SM4Util.sm4CBCEncrypt = function (utf8Str, utf8Key, utf8Iv) {
  42.   if (!utf8Key) {
  43.     utf8Key = 'cmbtest1cmbtest1'
  44.   }
  45.   if (!utf8Iv) {
  46.     utf8Iv = 'cmbtest1cmbtest1'
  47.   }
  48.   let sm4 = new SM4()
  49.   let keyBytes = Hex.utf8StrToBytes(utf8Key)
  50.   let ivBytes = Hex.utf8StrToBytes(utf8Iv)
  51.   let contentBytes = Hex.utf8StrToBytes(utf8Str)
  52.   let cipher = sm4.encrypt_cbc(keyBytes, ivBytes, contentBytes)
  53.   return base64js.fromByteArray(cipher)
  54. }
  55. /**
  56. * sm4 cbc 解密
  57. * @param utf8Str
  58. * @param utf8Key
  59. * @param utf8Iv
  60. */
  61. SM4Util.sm4CBCDecrypt = function (base64Str, utf8Key, utf8Iv) {
  62.   if (!utf8Key) {
  63.     utf8Key = 'cmbtest1cmbtest1'
  64.   }
  65.   if (!utf8Iv) {
  66.     utf8Iv = 'cmbtest1cmbtest1'
  67.   }
  68.   let sm4 = new SM4()
  69.   let keyBytes = Hex.utf8StrToBytes(utf8Key)
  70.   let ivBytes = Hex.utf8StrToBytes(utf8Iv)
  71.   let contentBytes = base64js.toByteArray(base64Str)
  72.   let plain = sm4.decrypt_cbc(keyBytes, ivBytes, contentBytes)
  73.   return Hex.bytesToUtf8Str(plain)
  74. }
  75. module.exports = SM4Util
复制代码
@/utils/SM4Util/base64js.js
  1. /**
  2. * base64js
  3. * base64js.toByteArray(utf8Str)
  4. * base64js.fromByteArray(bytes);
  5. */
  6. ;(function (r) {
  7.   if (typeof exports === 'object' && typeof module !== 'undefined') {
  8.     module.exports = r()
  9.   } else {
  10.     if (typeof define === 'function' && define.amd) {
  11.       define([], r)
  12.     } else {
  13.       var e
  14.       if (typeof window !== 'undefined') {
  15.         e = window
  16.       } else {
  17.         if (typeof global !== 'undefined') {
  18.           e = global
  19.         } else {
  20.           if (typeof self !== 'undefined') {
  21.             e = self
  22.           } else {
  23.             e = this
  24.           }
  25.         }
  26.       }
  27.       e.base64js = r()
  28.     }
  29.   }
  30. })(function () {
  31.   var r, e, t
  32.   return (function r(e, t, n) {
  33.     function o(i, a) {
  34.       if (!t[i]) {
  35.         if (!e[i]) {
  36.           var u = typeof require == 'function' && require
  37.           if (!a && u) {
  38.             return u(i, !0)
  39.           }
  40.           if (f) {
  41.             return f(i, !0)
  42.           }
  43.           var d = new Error("Cannot find module '" + i + "'")
  44.           throw ((d.code = 'MODULE_NOT_FOUND'), d)
  45.         }
  46.         var c = (t[i] = {
  47.           exports: {}
  48.         })
  49.         e[i][0].call(
  50.           c.exports,
  51.           function (r) {
  52.             var t = e[i][1][r]
  53.             return o(t ? t : r)
  54.           },
  55.           c,
  56.           c.exports,
  57.           r,
  58.           e,
  59.           t,
  60.           n
  61.         )
  62.       }
  63.       return t[i].exports
  64.     }
  65.     var f = typeof require == 'function' && require
  66.     for (var i = 0; i < n.length; i++) {
  67.       o(n[i])
  68.     }
  69.     return o
  70.   })(
  71.     {
  72.       '/': [
  73.         function (r, e, t) {
  74.           t.byteLength = c
  75.           t.toByteArray = v
  76.           t.fromByteArray = s
  77.           var n = []
  78.           var o = []
  79.           var f = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
  80.           var i = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  81.           for (var a = 0, u = i.length; a < u; ++a) {
  82.             n[a] = i[a]
  83.             o[i.charCodeAt(a)] = a
  84.           }
  85.           o['-'.charCodeAt(0)] = 62
  86.           o['_'.charCodeAt(0)] = 63
  87.           function d(r) {
  88.             var e = r.length
  89.             if (e % 4 > 0) {
  90.               throw new Error('Invalid string. Length must be a multiple of 4')
  91.             }
  92.             return r[e - 2] === '=' ? 2 : r[e - 1] === '=' ? 1 : 0
  93.           }
  94.           function c(r) {
  95.             return (r.length * 3) / 4 - d(r)
  96.           }
  97.           function v(r) {
  98.             var e, t, n, i, a
  99.             var u = r.length
  100.             i = d(r)
  101.             a = new f((u * 3) / 4 - i)
  102.             t = i > 0 ? u - 4 : u
  103.             var c = 0
  104.             for (e = 0; e < t; e += 4) {
  105.               n =
  106.                 (o[r.charCodeAt(e)] << 18) |
  107.                 (o[r.charCodeAt(e + 1)] << 12) |
  108.                 (o[r.charCodeAt(e + 2)] << 6) |
  109.                 o[r.charCodeAt(e + 3)]
  110.               a[c++] = (n >> 16) & 255
  111.               a[c++] = (n >> 8) & 255
  112.               a[c++] = n & 255
  113.             }
  114.             if (i === 2) {
  115.               n = (o[r.charCodeAt(e)] << 2) | (o[r.charCodeAt(e + 1)] >> 4)
  116.               a[c++] = n & 255
  117.             } else {
  118.               if (i === 1) {
  119.                 n = (o[r.charCodeAt(e)] << 10) | (o[r.charCodeAt(e + 1)] << 4) | (o[r.charCodeAt(e + 2)] >> 2)
  120.                 a[c++] = (n >> 8) & 255
  121.                 a[c++] = n & 255
  122.               }
  123.             }
  124.             return a
  125.           }
  126.           function l(r) {
  127.             return n[(r >> 18) & 63] + n[(r >> 12) & 63] + n[(r >> 6) & 63] + n[r & 63]
  128.           }
  129.           function h(r, e, t) {
  130.             var n
  131.             var o = []
  132.             for (var f = e; f < t; f += 3) {
  133.               n = (r[f] << 16) + (r[f + 1] << 8) + r[f + 2]
  134.               o.push(l(n))
  135.             }
  136.             return o.join('')
  137.           }
  138.           function s(r) {
  139.             var e
  140.             var t = r.length
  141.             var o = t % 3
  142.             var f = ''
  143.             var i = []
  144.             var a = 16383
  145.             for (var u = 0, d = t - o; u < d; u += a) {
  146.               i.push(h(r, u, u + a > d ? d : u + a))
  147.             }
  148.             if (o === 1) {
  149.               e = r[t - 1]
  150.               f += n[e >> 2]
  151.               f += n[(e << 4) & 63]
  152.               f += '=='
  153.             } else {
  154.               if (o === 2) {
  155.                 e = (r[t - 2] << 8) + r[t - 1]
  156.                 f += n[e >> 10]
  157.                 f += n[(e >> 4) & 63]
  158.                 f += n[(e << 2) & 63]
  159.                 f += '='
  160.               }
  161.             }
  162.             i.push(f)
  163.             return i.join('')
  164.           }
  165.         },
  166.         {}
  167.       ]
  168.     },
  169.     {},
  170.     []
  171.   )('/')
  172. })
复制代码
@/utils/SM4Util/hex.js
  1. function Hex() {}
  2. /**
  3. * 数组转为16进制字符串
  4. * @param b  数组
  5. * @param pos  指定位置
  6. * @param len  长度
  7. * @returns {string}
  8. */
  9. Hex.encode = function (b, pos, len) {
  10.   var hexCh = new Array(len * 2)
  11.   var hexCode = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F')
  12.   for (var i = pos, j = 0; i < len + pos; i++, j++) {
  13.     hexCh[j] = hexCode[(b[i] & 0xff) >> 4]
  14.     hexCh[++j] = hexCode[b[i] & 0x0f]
  15.   }
  16.   return hexCh.join('')
  17. }
  18. /**
  19. * 16进制字符串转为字节数组
  20. * @param hex
  21. * @returns {any[]|null}
  22. */
  23. Hex.decode = function (hex) {
  24.   if (hex == null || hex == '') {
  25.     return null
  26.   }
  27.   if (hex.length % 2 != 0) {
  28.     return null
  29.   }
  30.   var ascLen = hex.length / 2
  31.   var hexCh = this.toCharCodeArray(hex)
  32.   var asc = new Array(ascLen)
  33.   for (var i = 0; i < ascLen; i++) {
  34.     if (hexCh[2 * i] >= 0x30 && hexCh[2 * i] <= 0x39) {
  35.       asc[i] = (hexCh[2 * i] - 0x30) << 4
  36.     } else if (hexCh[2 * i] >= 0x41 && hexCh[2 * i] <= 0x46) {
  37.       //A-F : 0x41-0x46
  38.       asc[i] = (hexCh[2 * i] - 0x41 + 10) << 4
  39.     } else if (hexCh[2 * i] >= 0x61 && hexCh[2 * i] <= 0x66) {
  40.       //a-f  : 0x61-0x66
  41.       asc[i] = (hexCh[2 * i] - 0x61 + 10) << 4
  42.     } else {
  43.       return null
  44.     }
  45.     if (hexCh[2 * i + 1] >= 0x30 && hexCh[2 * i + 1] <= 0x39) {
  46.       asc[i] = asc[i] | (hexCh[2 * i + 1] - 0x30)
  47.     } else if (hexCh[2 * i + 1] >= 0x41 && hexCh[2 * i + 1] <= 0x46) {
  48.       asc[i] = asc[i] | (hexCh[2 * i + 1] - 0x41 + 10)
  49.     } else if (hexCh[2 * i + 1] >= 0x61 && hexCh[2 * i + 1] <= 0x66) {
  50.       asc[i] = asc[i] | (hexCh[2 * i + 1] - 0x61 + 10)
  51.     } else {
  52.       return null
  53.     }
  54.   }
  55.   return asc
  56. }
  57. /**
  58. * utf8字符串转为字节数组
  59. * @param utf8Str
  60. * @returns {[]}
  61. */
  62. Hex.utf8StrToBytes = function (utf8Str) {
  63.   var ens = encodeURIComponent(utf8Str)
  64.   var es = unescape(ens)
  65.   var esLen = es.length
  66.   // Convert
  67.   var words = []
  68.   for (var i = 0; i < esLen; i++) {
  69.     words[i] = es.charCodeAt(i)
  70.   }
  71.   return words
  72. }
  73. /**
  74. * 字节数组转为utf8字符串
  75. * @param bytesArray
  76. * @returns {string}
  77. */
  78. Hex.bytesToUtf8Str = function (bytesArray) {
  79.   var utf8Byte = bytesArray
  80.   var latin1Chars = []
  81.   for (var i = 0; i < utf8Byte.length; i++) {
  82.     latin1Chars.push(String.fromCharCode(utf8Byte[i]))
  83.   }
  84.   return decodeURIComponent(escape(latin1Chars.join('')))
  85. }
  86. /**
  87. * 16进制字符串转为utf8字符串
  88. * @param utf8Str
  89. * @returns {string}
  90. */
  91. Hex.hexToUtf8Str = function (utf8Str) {
  92.   var utf8Byte = Hex.decode(utf8Str)
  93.   var latin1Chars = []
  94.   for (var i = 0; i < utf8Byte.length; i++) {
  95.     latin1Chars.push(String.fromCharCode(utf8Byte[i]))
  96.   }
  97.   return decodeURIComponent(escape(latin1Chars.join('')))
  98. }
  99. /**
  100. * utf8字符串转为16进制字符串
  101. * @param utf8Str
  102. * @returns {string}
  103. */
  104. Hex.utf8StrToHex = function (utf8Str) {
  105.   var ens = encodeURIComponent(utf8Str)
  106.   var es = unescape(ens)
  107.   var esLen = es.length
  108.   // Convert
  109.   var words = []
  110.   for (var i = 0; i < esLen; i++) {
  111.     words[i] = es.charCodeAt(i).toString(16)
  112.   }
  113.   return words.join('')
  114. }
  115. /**
  116. * 字符串中每个字符转为数组中每个元素,数字,字母同Hex.utf8StrToBytes()方法
  117. * @param chs
  118. * @returns {any[]}
  119. */
  120. Hex.toCharCodeArray = function (chs) {
  121.   var chArr = new Array(chs.length)
  122.   for (var i = 0; i < chs.length; i++) {
  123.     chArr[i] = chs.charCodeAt(i)
  124.   }
  125.   return chArr
  126. }
  127. module.exports = Hex
复制代码
@/utils/SM4Util/sm4.js
  1. /*
  2. * sm4-1.0.js
  3. *
  4. * Copyright (c) 2019 RuXing Liang
  5. */
  6. /**
  7. * @name sm4-1.0.js
  8. * @author RuXing Liang
  9. * @version 1.0.0 (2019-04-19)
  10. */
  11. function SM4() {
  12.   this.sbox = new Array(
  13.     0xd6,
  14.     0x90,
  15.     0xe9,
  16.     0xfe,
  17.     0xcc,
  18.     0xe1,
  19.     0x3d,
  20.     0xb7,
  21.     0x16,
  22.     0xb6,
  23.     0x14,
  24.     0xc2,
  25.     0x28,
  26.     0xfb,
  27.     0x2c,
  28.     0x05,
  29.     0x2b,
  30.     0x67,
  31.     0x9a,
  32.     0x76,
  33.     0x2a,
  34.     0xbe,
  35.     0x04,
  36.     0xc3,
  37.     0xaa,
  38.     0x44,
  39.     0x13,
  40.     0x26,
  41.     0x49,
  42.     0x86,
  43.     0x06,
  44.     0x99,
  45.     0x9c,
  46.     0x42,
  47.     0x50,
  48.     0xf4,
  49.     0x91,
  50.     0xef,
  51.     0x98,
  52.     0x7a,
  53.     0x33,
  54.     0x54,
  55.     0x0b,
  56.     0x43,
  57.     0xed,
  58.     0xcf,
  59.     0xac,
  60.     0x62,
  61.     0xe4,
  62.     0xb3,
  63.     0x1c,
  64.     0xa9,
  65.     0xc9,
  66.     0x08,
  67.     0xe8,
  68.     0x95,
  69.     0x80,
  70.     0xdf,
  71.     0x94,
  72.     0xfa,
  73.     0x75,
  74.     0x8f,
  75.     0x3f,
  76.     0xa6,
  77.     0x47,
  78.     0x07,
  79.     0xa7,
  80.     0xfc,
  81.     0xf3,
  82.     0x73,
  83.     0x17,
  84.     0xba,
  85.     0x83,
  86.     0x59,
  87.     0x3c,
  88.     0x19,
  89.     0xe6,
  90.     0x85,
  91.     0x4f,
  92.     0xa8,
  93.     0x68,
  94.     0x6b,
  95.     0x81,
  96.     0xb2,
  97.     0x71,
  98.     0x64,
  99.     0xda,
  100.     0x8b,
  101.     0xf8,
  102.     0xeb,
  103.     0x0f,
  104.     0x4b,
  105.     0x70,
  106.     0x56,
  107.     0x9d,
  108.     0x35,
  109.     0x1e,
  110.     0x24,
  111.     0x0e,
  112.     0x5e,
  113.     0x63,
  114.     0x58,
  115.     0xd1,
  116.     0xa2,
  117.     0x25,
  118.     0x22,
  119.     0x7c,
  120.     0x3b,
  121.     0x01,
  122.     0x21,
  123.     0x78,
  124.     0x87,
  125.     0xd4,
  126.     0x00,
  127.     0x46,
  128.     0x57,
  129.     0x9f,
  130.     0xd3,
  131.     0x27,
  132.     0x52,
  133.     0x4c,
  134.     0x36,
  135.     0x02,
  136.     0xe7,
  137.     0xa0,
  138.     0xc4,
  139.     0xc8,
  140.     0x9e,
  141.     0xea,
  142.     0xbf,
  143.     0x8a,
  144.     0xd2,
  145.     0x40,
  146.     0xc7,
  147.     0x38,
  148.     0xb5,
  149.     0xa3,
  150.     0xf7,
  151.     0xf2,
  152.     0xce,
  153.     0xf9,
  154.     0x61,
  155.     0x15,
  156.     0xa1,
  157.     0xe0,
  158.     0xae,
  159.     0x5d,
  160.     0xa4,
  161.     0x9b,
  162.     0x34,
  163.     0x1a,
  164.     0x55,
  165.     0xad,
  166.     0x93,
  167.     0x32,
  168.     0x30,
  169.     0xf5,
  170.     0x8c,
  171.     0xb1,
  172.     0xe3,
  173.     0x1d,
  174.     0xf6,
  175.     0xe2,
  176.     0x2e,
  177.     0x82,
  178.     0x66,
  179.     0xca,
  180.     0x60,
  181.     0xc0,
  182.     0x29,
  183.     0x23,
  184.     0xab,
  185.     0x0d,
  186.     0x53,
  187.     0x4e,
  188.     0x6f,
  189.     0xd5,
  190.     0xdb,
  191.     0x37,
  192.     0x45,
  193.     0xde,
  194.     0xfd,
  195.     0x8e,
  196.     0x2f,
  197.     0x03,
  198.     0xff,
  199.     0x6a,
  200.     0x72,
  201.     0x6d,
  202.     0x6c,
  203.     0x5b,
  204.     0x51,
  205.     0x8d,
  206.     0x1b,
  207.     0xaf,
  208.     0x92,
  209.     0xbb,
  210.     0xdd,
  211.     0xbc,
  212.     0x7f,
  213.     0x11,
  214.     0xd9,
  215.     0x5c,
  216.     0x41,
  217.     0x1f,
  218.     0x10,
  219.     0x5a,
  220.     0xd8,
  221.     0x0a,
  222.     0xc1,
  223.     0x31,
  224.     0x88,
  225.     0xa5,
  226.     0xcd,
  227.     0x7b,
  228.     0xbd,
  229.     0x2d,
  230.     0x74,
  231.     0xd0,
  232.     0x12,
  233.     0xb8,
  234.     0xe5,
  235.     0xb4,
  236.     0xb0,
  237.     0x89,
  238.     0x69,
  239.     0x97,
  240.     0x4a,
  241.     0x0c,
  242.     0x96,
  243.     0x77,
  244.     0x7e,
  245.     0x65,
  246.     0xb9,
  247.     0xf1,
  248.     0x09,
  249.     0xc5,
  250.     0x6e,
  251.     0xc6,
  252.     0x84,
  253.     0x18,
  254.     0xf0,
  255.     0x7d,
  256.     0xec,
  257.     0x3a,
  258.     0xdc,
  259.     0x4d,
  260.     0x20,
  261.     0x79,
  262.     0xee,
  263.     0x5f,
  264.     0x3e,
  265.     0xd7,
  266.     0xcb,
  267.     0x39,
  268.     0x48
  269.   )
  270.   this.fk = new Array(0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc)
  271.   this.ck = new Array(
  272.     0x00070e15,
  273.     0x1c232a31,
  274.     0x383f464d,
  275.     0x545b6269,
  276.     0x70777e85,
  277.     0x8c939aa1,
  278.     0xa8afb6bd,
  279.     0xc4cbd2d9,
  280.     0xe0e7eef5,
  281.     0xfc030a11,
  282.     0x181f262d,
  283.     0x343b4249,
  284.     0x50575e65,
  285.     0x6c737a81,
  286.     0x888f969d,
  287.     0xa4abb2b9,
  288.     0xc0c7ced5,
  289.     0xdce3eaf1,
  290.     0xf8ff060d,
  291.     0x141b2229,
  292.     0x30373e45,
  293.     0x4c535a61,
  294.     0x686f767d,
  295.     0x848b9299,
  296.     0xa0a7aeb5,
  297.     0xbcc3cad1,
  298.     0xd8dfe6ed,
  299.     0xf4fb0209,
  300.     0x10171e25,
  301.     0x2c333a41,
  302.     0x484f565d,
  303.     0x646b7279
  304.   )
  305. }
  306. SM4.prototype = {
  307.   expandKey: function (key) {
  308.     var k = new Array(36)
  309.     var mk = byteArrayToIntArray(key)
  310.     k[0] = mk[0] ^ this.fk[0]
  311.     k[1] = mk[1] ^ this.fk[1]
  312.     k[2] = mk[2] ^ this.fk[2]
  313.     k[3] = mk[3] ^ this.fk[3]
  314.     var rk = new Array(32)
  315.     for (var i = 0; i < 32; i++) {
  316.       k[i + 4] = k[i] ^ this.T1(k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ this.ck[i])
  317.       rk[i] = k[i + 4]
  318.     }
  319.     return rk
  320.   },
  321.   T1: function (ta) {
  322.     var rk = 0
  323.     var b = new Array(4)
  324.     var a = intToByte(ta)
  325.     b[0] = this.sbox[a[0] & 0xff]
  326.     b[1] = this.sbox[a[1] & 0xff]
  327.     b[2] = this.sbox[a[2] & 0xff]
  328.     b[3] = this.sbox[a[3] & 0xff]
  329.     var bint = byteToInt(b, 0)
  330.     var rk = bint ^ ((bint << 13) | (bint >>> (32 - 13))) ^ ((bint << 23) | (bint >>> (32 - 23)))
  331.     return rk
  332.   },
  333.   one_encrypt: function (rk, data) {
  334.     var x = new Array(36)
  335.     x[0] = byteToInt(data, 0)
  336.     x[1] = byteToInt(data, 4)
  337.     x[2] = byteToInt(data, 8)
  338.     x[3] = byteToInt(data, 12)
  339.     for (var i = 0; i < 32; i++) {
  340.       x[i + 4] = x[i] ^ this.T0(x[i + 1] ^ x[i + 2] ^ x[i + 3] ^ rk[i])
  341.     }
  342.     var tmpx = new Array(4)
  343.     for (var i = 35; i >= 32; i--) {
  344.       tmpx[35 - i] = x[i]
  345.     }
  346.     var xbyte = intArrayToByteArray(tmpx)
  347.     return xbyte
  348.   },
  349.   T0: function (ta) {
  350.     var a = intToByte(ta)
  351.     var b = new Array(4)
  352.     b[0] = this.sbox[a[0] & 0xff]
  353.     b[1] = this.sbox[a[1] & 0xff]
  354.     b[2] = this.sbox[a[2] & 0xff]
  355.     b[3] = this.sbox[a[3] & 0xff]
  356.     var bint = byteToInt(b, 0)
  357.     var c =
  358.       bint ^
  359.       ((bint << 2) | (bint >>> (32 - 2))) ^
  360.       ((bint << 10) | (bint >>> (32 - 10))) ^
  361.       ((bint << 18) | (bint >>> (32 - 18))) ^
  362.       ((bint << 24) | (bint >>> (32 - 24)))
  363.     return c
  364.   },
  365.   pkcs7padding: function (input, mode) {
  366.     if (input == null) {
  367.       return null
  368.     }
  369.     var ret = null
  370.     if (mode == 1) {
  371.       //填充
  372.       var p = 16 - (input.length % 16)
  373.       ret = new Array(input.length + p)
  374.       arrayCopy(input, 0, ret, 0, input.length)
  375.       for (var i = 0; i < p; i++) {
  376.         ret[input.length + i] = p
  377.       }
  378.     } //去除填充
  379.     else {
  380.       var p = input[input.length - 1]
  381.       ret = new Array(input.length - p)
  382.       arrayCopy(input, 0, ret, 0, input.length - p)
  383.     }
  384.     return ret
  385.   },
  386.   /**
  387.    *
  388.    * @param key 字节数组
  389.    * @param data 字节数组
  390.    * @returns {any[]|null}
  391.    */
  392.   encrypt_ecb: function (key, data) {
  393.     if (key == undefined || key == null || key.length % 16 != 0) {
  394.       console.log('sm4 key is error!')
  395.       return null
  396.     }
  397.     if (data == undefined || data == null || data.length <= 0) {
  398.       console.log('data is error!')
  399.       return null
  400.     }
  401.     var rk = this.expandKey(key)
  402.     /*if(debug){
  403.           var rkb = intArrayToByteArray(rk);
  404.           console.log(Hex.encode(rkb,0,rkb.length));
  405.       }*/
  406.     var blockLen = 16
  407.     var loop = parseInt(data.length / blockLen) //注意不能整除会有小数,要取整
  408.     var cipher = new Array((loop + 1) * blockLen)
  409.     var tmp = new Array(blockLen)
  410.     var oneCipher = null
  411.     for (var i = 0; i < loop; i++) {
  412.       arrayCopy(data, i * blockLen, tmp, 0, blockLen)
  413.       oneCipher = this.one_encrypt(rk, tmp)
  414.       arrayCopy(oneCipher, 0, cipher, i * blockLen, blockLen)
  415.     }
  416.     var lessData = new Array(data.length % blockLen)
  417.     if (lessData.length > 0) {
  418.       arrayCopy(data, loop * blockLen, lessData, 0, data.length % blockLen)
  419.     }
  420.     var padding = this.pkcs7padding(lessData, 1)
  421.     oneCipher = this.one_encrypt(rk, padding)
  422.     arrayCopy(oneCipher, 0, cipher, loop * blockLen, blockLen)
  423.     return cipher
  424.   },
  425.   /**
  426.    *
  427.    * @param key  字节数组
  428.    * @param data  字节数组
  429.    * @returns {any[]|null}
  430.    */
  431.   decrypt_ecb: function (key, data) {
  432.     if (key == undefined || key == null || key.length % 16 != 0) {
  433.       console.log('sm4 key is error!')
  434.       return null
  435.     }
  436.     if (data == undefined || data == null || data.length % 16 != 0) {
  437.       console.log('data is error!')
  438.       return null
  439.     }
  440.     var rk = this.expandKey(key)
  441.     var nrk = new Array(32)
  442.     for (var i = 0; i < rk.length; i++) {
  443.       nrk[i] = rk[32 - i - 1]
  444.     }
  445.     var blockLen = 16
  446.     var loop = data.length / blockLen - 1
  447.     var tmp = new Array(blockLen)
  448.     var onePlain = null
  449.     var plain = null
  450.     //先解密最后一部分,确定数据长度
  451.     arrayCopy(data, loop * blockLen, tmp, 0, blockLen)
  452.     onePlain = this.one_encrypt(nrk, tmp)
  453.     var lastPart = this.pkcs7padding(onePlain, 0)
  454.     plain = new Array(loop * blockLen + lastPart.length)
  455.     arrayCopy(lastPart, 0, plain, loop * blockLen, lastPart.length)
  456.     //解密剩下部分数据
  457.     for (var i = 0; i < loop; i++) {
  458.       arrayCopy(data, i * blockLen, tmp, 0, blockLen)
  459.       onePlain = this.one_encrypt(nrk, tmp)
  460.       arrayCopy(onePlain, 0, plain, i * blockLen, blockLen)
  461.     }
  462.     return plain
  463.   },
  464.   encrypt_cbc: function (key, iv, data) {
  465.     if (key == undefined || key == null || key.length % 16 != 0) {
  466.       console.log('sm4 key is error!')
  467.       return null
  468.     }
  469.     if (data == undefined || data == null || data.length <= 0) {
  470.       console.log('data is error!')
  471.       return null
  472.     }
  473.     if (iv == undefined || iv == null || iv.length % 16 != 0) {
  474.       console.log('iv is error!')
  475.       return null
  476.     }
  477.     var rk = this.expandKey(key)
  478.     var blockLen = 16
  479.     var loop = parseInt(data.length / blockLen) //注意不能整除会有小数,要取整
  480.     var cipher = new Array((loop + 1) * blockLen)
  481.     var tmp = new Array(blockLen)
  482.     var oneCipher = null
  483.     for (var i = 0; i < loop; i++) {
  484.       arrayCopy(data, i * blockLen, tmp, 0, blockLen)
  485.       for (var j = 0; j < blockLen; j++) {
  486.         tmp[j] = tmp[j] ^ iv[j]
  487.       }
  488.       iv = this.one_encrypt(rk, tmp)
  489.       arrayCopy(iv, 0, cipher, i * blockLen, blockLen)
  490.     }
  491.     var lessData = new Array(data.length % blockLen)
  492.     if (lessData.length > 0) {
  493.       arrayCopy(data, loop * blockLen, lessData, 0, data.length % blockLen)
  494.     }
  495.     var padding = this.pkcs7padding(lessData, 1)
  496.     for (var i = 0; i < blockLen; i++) {
  497.       padding[i] = padding[i] ^ iv[i]
  498.     }
  499.     iv = this.one_encrypt(rk, padding)
  500.     arrayCopy(iv, 0, cipher, loop * blockLen, blockLen)
  501.     return cipher
  502.   },
  503.   decrypt_cbc: function (key, iv, data) {
  504.     if (key == undefined || key == null || key.length % 16 != 0) {
  505.       console.log('sm4 key is error!')
  506.       return null
  507.     }
  508.     if (data == undefined || data == null || data.length % 16 != 0) {
  509.       console.log('data is error!')
  510.       return null
  511.     }
  512.     if (iv == undefined || iv == null || iv.length % 16 != 0) {
  513.       console.log('iv is error!')
  514.       return null
  515.     }
  516.     var rk = this.expandKey(key)
  517.     var nrk = new Array(32)
  518.     for (var i = 0; i < rk.length; i++) {
  519.       nrk[i] = rk[32 - i - 1]
  520.     }
  521.     var blockLen = 16
  522.     var loop = data.length / blockLen
  523.     var tmp = new Array(blockLen)
  524.     var onePlain = null
  525.     var plain = null
  526.     //解密
  527.     plain = new Array(data.length)
  528.     for (var i = 0; i < loop; i++) {
  529.       arrayCopy(data, i * blockLen, tmp, 0, blockLen)
  530.       onePlain = this.one_encrypt(nrk, tmp)
  531.       for (var j = 0; j < blockLen; j++) {
  532.         onePlain[j] = onePlain[j] ^ iv[j]
  533.       }
  534.       arrayCopy(tmp, 0, iv, 0, blockLen)
  535.       arrayCopy(onePlain, 0, plain, i * blockLen, blockLen)
  536.     }
  537.     //去填充,确定数据长度
  538.     //arrayCopy(data,data.length-blockLen,tmp,0,blockLen);
  539.     var lastPart = this.pkcs7padding(onePlain, 0)
  540.     var realPlain = new Array(plain.length - blockLen + lastPart.length)
  541.     arrayCopy(plain, 0, realPlain, 0, plain.length - blockLen)
  542.     arrayCopy(lastPart, 0, realPlain, plain.length - blockLen, lastPart.length)
  543.     return realPlain
  544.   }
  545. }
  546. ///工具类/
  547. /*
  548. * 数组复制
  549. */
  550. function arrayCopy(src, pos1, dest, pos2, len) {
  551.   var realLen = len
  552.   if (pos1 + len > src.length && pos2 + len <= dest.length) {
  553.     realLen = src.length - pos1
  554.   } else if (pos2 + len > dest.length && pos1 + len <= src.length) {
  555.     realLen = dest.length - pos2
  556.   } else if (pos1 + len <= src.length && pos2 + len <= dest.length) {
  557.     realLen = len
  558.   } else if (dest.length < src.length) {
  559.     realLen = dest.length - pos2
  560.   } else {
  561.     realLen = src.length - pos2
  562.   }
  563.   for (var i = 0; i < realLen; i++) {
  564.     dest[i + pos2] = src[i + pos1]
  565.   }
  566. }
  567. /*
  568. * 长整型转成字节,一个长整型为8字节
  569. * 返回:字节数组
  570. */
  571. function longToByte(num) {
  572.   //TODO 这里目前只转换了低四字节,因为js没有长整型,得要封装
  573.   return new Array(
  574.     0,
  575.     0,
  576.     0,
  577.     0,
  578.     (num >> 24) & 0x000000ff,
  579.     (num >> 16) & 0x000000ff,
  580.     (num >> 8) & 0x000000ff,
  581.     num & 0x000000ff
  582.   )
  583. }
  584. /*
  585. * int数转成byte数组
  586. * 事实上只不过转成byte大小的数,实际占用空间还是4字节
  587. * 返回:字节数组
  588. */
  589. function intToByte(num) {
  590.   return new Array((num >> 24) & 0x000000ff, (num >> 16) & 0x000000ff, (num >> 8) & 0x000000ff, num & 0x000000ff)
  591. }
  592. /*
  593. * int数组转成byte数组,一个int数值转成四个byte
  594. * 返回:byte数组
  595. */
  596. function intArrayToByteArray(nums) {
  597.   var b = new Array(nums.length * 4)
  598.   for (var i = 0; i < nums.length; i++) {
  599.     arrayCopy(intToByte(nums[i]), 0, b, i * 4, 4)
  600.   }
  601.   return b
  602. }
  603. /*
  604. * byte数组转成int数值
  605. * 返回:int数值
  606. */
  607. function byteToInt(b, pos) {
  608.   if (pos + 3 < b.length) {
  609.     return (b[pos] << 24) | (b[pos + 1] << 16) | (b[pos + 2] << 8) | b[pos + 3]
  610.   } else if (pos + 2 < b.length) {
  611.     return (b[pos + 1] << 16) | (b[pos + 2] << 8) | b[pos + 3]
  612.   } else if (pos + 1 < b.length) {
  613.     return (b[pos] << 8) | b[pos + 1]
  614.   } else {
  615.     return b[pos]
  616.   }
  617. }
  618. /*
  619. * byte数组转成int数组,每四个字节转成一个int数值
  620. *
  621. */
  622. function byteArrayToIntArray(b) {
  623.   // var arrLen = b.length%4==0 ? b.length/4:b.length/4+1;
  624.   var arrLen = Math.ceil(b.length / 4) //向上取整
  625.   var out = new Array(arrLen)
  626.   for (var i = 0; i < b.length; i++) {
  627.     b[i] = b[i] & 0xff //避免负数造成影响
  628.   }
  629.   for (var i = 0; i < out.length; i++) {
  630.     out[i] = byteToInt(b, i * 4)
  631.   }
  632.   return out
  633. }
  634. module.exports = SM4
复制代码
2. 使用 - ECB 模式加解密

  1. import SM4Util from '@/utils/SM4Util'
  2. const miStr = SM4Util.sm4ECBEncrypt('13012345678', '93F3044B07393417') // 加密 SM4Util.sm4ECBEncrypt(需要加密的字符串, 密钥)
  3. console.log('miStr----', miStr) // 8O/HeW8uoXU/CkcDaXRpxQ==
  4. const jieStr = SM4Util.sm4ECBDecrypt(miStr, '93F3044B07393417') // 解密 SM4Util.sm4ECBDecrypt(加密后的字符串, 密钥)
  5. console.log('jieStr----', jieStr) // 13012345678
  6. // 加密后传给后端进行解密
复制代码
大概出现的报错

若出现该报错,即为解密失败,大概是加密堕落导致 Uncaught RangeError: Invalid array length


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

西河刘卡车医

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表