Selaa lähdekoodia

云端授权验证、支付接口、查询订单等接口

Your Name 1 vuosi sitten
vanhempi
commit
8d6e9beea0
58 muutettua tiedostoa jossa 12753 lisäystä ja 2 poistoa
  1. 1 0
      app.js
  2. 32 0
      js/SM4.js
  3. 50 0
      js/SM4Exten.js
  4. 176 0
      js/api.js
  5. 1374 0
      miniprogram_npm/jsbn/index.js
  6. 0 0
      miniprogram_npm/jsbn/index.js.map
  7. 1837 0
      miniprogram_npm/miniprogram-sm-crypto/index.js
  8. 1610 0
      miniprogram_npm/sm-crypto/index.js
  9. 0 0
      miniprogram_npm/sm-crypto/index.js.map
  10. 28 0
      node_modules/.package-lock.json
  11. 2 0
      node_modules/jsbn/.npmignore
  12. 16 0
      node_modules/jsbn/CHANGELOG.md
  13. 40 0
      node_modules/jsbn/LICENSE
  14. 173 0
      node_modules/jsbn/README.md
  15. 11 0
      node_modules/jsbn/example.html
  16. 5 0
      node_modules/jsbn/example.js
  17. 1361 0
      node_modules/jsbn/index.js
  18. 21 0
      node_modules/jsbn/package.json
  19. 3 0
      node_modules/jsbn/test/es6-import.js
  20. 11 0
      node_modules/miniprogram-sm-crypto/.babelrc
  21. 97 0
      node_modules/miniprogram-sm-crypto/.eslintrc.js
  22. 21 0
      node_modules/miniprogram-sm-crypto/LICENSE
  23. 168 0
      node_modules/miniprogram-sm-crypto/README.md
  24. 92 0
      node_modules/miniprogram-sm-crypto/UPDATE.md
  25. 28 0
      node_modules/miniprogram-sm-crypto/gulpfile.js
  26. 1837 0
      node_modules/miniprogram-sm-crypto/miniprogram_dist/index.js
  27. 65 0
      node_modules/miniprogram-sm-crypto/package.json
  28. 5 0
      node_modules/miniprogram-sm-crypto/src/index.js
  29. 161 0
      node_modules/miniprogram-sm-crypto/src/sm2/asn1.js
  30. 332 0
      node_modules/miniprogram-sm-crypto/src/sm2/ec.js
  31. 261 0
      node_modules/miniprogram-sm-crypto/src/sm2/index.js
  32. 170 0
      node_modules/miniprogram-sm-crypto/src/sm2/sm3.js
  33. 194 0
      node_modules/miniprogram-sm-crypto/src/sm2/utils.js
  34. 94 0
      node_modules/miniprogram-sm-crypto/src/sm3/index.js
  35. 359 0
      node_modules/miniprogram-sm-crypto/src/sm4/index.js
  36. 3 0
      node_modules/sm-crypto/.babelrc
  37. 97 0
      node_modules/sm-crypto/.eslintrc.js
  38. 82 0
      node_modules/sm-crypto/CHANGELOG.md
  39. 7 0
      node_modules/sm-crypto/LICENCE_MIT
  40. 171 0
      node_modules/sm-crypto/README.md
  41. 0 0
      node_modules/sm-crypto/dist/sm2.js
  42. 0 0
      node_modules/sm-crypto/dist/sm3.js
  43. 0 0
      node_modules/sm-crypto/dist/sm4.js
  44. 42 0
      node_modules/sm-crypto/package.json
  45. 5 0
      node_modules/sm-crypto/src/index.js
  46. 161 0
      node_modules/sm-crypto/src/sm2/asn1.js
  47. 332 0
      node_modules/sm-crypto/src/sm2/ec.js
  48. 261 0
      node_modules/sm-crypto/src/sm2/index.js
  49. 170 0
      node_modules/sm-crypto/src/sm2/sm3.js
  50. 194 0
      node_modules/sm-crypto/src/sm2/utils.js
  51. 94 0
      node_modules/sm-crypto/src/sm3/index.js
  52. 359 0
      node_modules/sm-crypto/src/sm4/index.js
  53. 26 0
      node_modules/sm-crypto/webpack.config.js
  54. 34 0
      package-lock.json
  55. 6 0
      package.json
  56. 71 0
      pages/login/login.js
  57. 1 1
      pages/login/login.wxml
  58. 2 1
      project.private.config.json

+ 1 - 0
app.js

@@ -12,6 +12,7 @@ App({
         // 发送 res.code 到后台换取 openId, sessionKey, unionId
       }
     })
+    
   },
   globalData: {
     userInfo: null

+ 32 - 0
js/SM4.js

@@ -0,0 +1,32 @@
+const sm4 = require('sm-crypto');
+//const sm4 = require('miniprogram-sm-crypto').sm4;
+function stringToHex(str) {
+  console.log('stringToHex');
+  const buffer = new ArrayBuffer(str.length);
+  const view = new Uint8Array(buffer);
+  for (let i = 0; i < str.length; i++) {
+    view[i] = str.charCodeAt(i);
+  }
+  return Array.from(view, byte => byte.toString(16).padStart(2, '0')).join('');
+}
+
+function sm4EcbEncrypt(plaintext, key) {
+  // 确保密钥是32字符的十六进制字符串
+  if (key.length !== 32 || !/^[0-9a-fA-F]+$/.test(key)) {
+    throw new Error('密钥必须是32字符的十六进制字符串');
+  }
+
+
+  console.log('plaintext :' + plaintext);
+  // 使用 sm-crypto 进行 SM4 ECB 加密
+  const ciphertextHex = sm4.sm4.encrypt(plaintext,key);
+  console.log('ciphertextHex :' + ciphertextHex);
+    // 将明文转换为十六进制字符串
+    const plaintextHex = stringToHex(ciphertextHex);
+    console.log('plaintextHex :' + plaintextHex);
+  return plaintextHex;
+}
+
+module.exports = {
+  sm4EcbEncrypt,
+};

+ 50 - 0
js/SM4Exten.js

@@ -0,0 +1,50 @@
+// 假设我们有一个名为 sm4 的模块,它提供了加密功能
+const sm4 = require('sm-crypto'); // 这里需要替换为实际的路径或库名
+
+function SM4Encrypt_ECB(plainText, secretKey, hexString = false) {
+  const sm4Context = {
+    isPadding: true,
+    mode: 'encrypt', // 使用加密模式
+  };
+
+  let key;
+  if (!hexString) {
+    key = wx.arrayBufferToBase64(new TextEncoder().encode(secretKey));
+  } else {
+    key = decodeHexString(secretKey); // 需要自己实现decodeHexString函数
+  }
+
+  // 设置加密密钥
+  sm4.setKey(sm4Context, key);
+
+  // 加密数据
+  const encryptedData = sm4.encryptECB(sm4Context, new TextEncoder().encode(plainText));
+
+  // 返回编码后的结果
+  return encodeBytesToHex(encryptedData);
+}
+
+function decodeHexString(hexString) {
+  // 实现与C# Decode方法相同的逻辑
+  if (hexString.length % 2 !== 0) {
+    throw new Error("Hexadecimal string must have an even length");
+  }
+  let bytes = [];
+  for (let i = 0; i < hexString.length; i += 2) {
+    bytes.push(parseInt(hexString.substr(i, 2), 16));
+  }
+  return bytes;
+}
+
+function encodeBytesToHex(bytes) {
+  // 实现与C# Encode方法相同的逻辑
+  let hexString = '';
+  for (let byte of bytes) {
+    hexString += ('0' + byte.toString(16)).slice(-2);
+  }
+  return hexString;
+}
+
+module.exports = {
+  SM4Encrypt_ECB,
+};

+ 176 - 0
js/api.js

@@ -0,0 +1,176 @@
+const sm4 = require('../js/SM4');
+const SM4Exten = require('../js/SM4Exten');
+const miniprogramsm4 = require("../miniprogram_npm/miniprogram-sm-crypto/index").sm4;
+const secretId = "D2BCF8DE-AA24-4BF6-9C34-C8DD325E412B";//小程序应用ID
+const Secret = "6C680A47B87740138DFB299FC69A64E1";//小程序应用密钥
+const api_root = 'http://192.168.0.202:5006/'
+const CurrentBuId = '12345678-9abc-def0-1234-56789abcdef0';
+
+function request(path, method = 'GET', data = null) {
+
+  return new Promise((resolve, reject) => { 
+    var sign_method = "HMAC_SM4";
+    var url = api_root +  path;
+    var nonce = generateRandomString();
+    const timestamp = Date.now();
+    let jsonString = (data != null && method != 'GET') ? JSON.stringify(data) : '';
+    console.log('request :' + jsonString);
+    var stringToSign = "sign_method=" +sign_method + 
+                       "&secret_id=" +secretId+
+                       "&nonce=" +  nonce +
+                       "&timestamp=" + timestamp + 
+                       jsonString;
+                       debugger
+    console.log('加密串 :' + stringToSign);
+    let key =  stringToHex(Secret);//key转16进制
+    key = getFirst32Chars(key);//截取前16位
+    let signature = miniprogramsm4.encrypt(stringToSign, key)//sm4加密
+    //signature = signature.toUpperCase();
+    signature = stringToBase64(signature);//加密字符串转base64
+    console.log('signature :' + signature);
+    wx.request({
+      header: {
+        "sign_method": sign_method,
+        "secret_id": secretId,
+        "nonce": nonce,
+        "timestamp": timestamp,
+        "signature": signature,
+        "CurrentBuId" : CurrentBuId
+      },
+      url: url, 
+      method: method,
+      data: data,
+      success: res => {
+        console.log("success");
+        resolve(res);
+      },
+      fail: res => {
+        console.log("request fail");
+        resolve(res);
+      },
+    })
+
+  });
+
+}
+//字符串转base64
+function stringToBase64(str) {
+  // 定义Base64字符集
+  const base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+  
+  // 将字符串转换为UTF-8字节数组
+  let utf8Bytes = [];
+  for (let i = 0; i < str.length; i++) {
+    let charCode = str.charCodeAt(i);
+    
+    if (charCode < 128) { // 1字节字符
+      utf8Bytes.push(charCode);
+    } else if (charCode < 2048) { // 2字节字符
+      utf8Bytes.push((charCode >> 6) | 192);
+      utf8Bytes.push((charCode & 63) | 128);
+    } else if (charCode < 65536) { // 3字节字符
+      utf8Bytes.push((charCode >> 12) | 224);
+      utf8Bytes.push(((charCode >> 6) & 63) | 128);
+      utf8Bytes.push((charCode & 63) | 128);
+    } else { // 4字节字符
+      utf8Bytes.push((charCode >> 18) | 240);
+      utf8Bytes.push(((charCode >> 12) & 63) | 128);
+      utf8Bytes.push(((charCode >> 6) & 63) | 128);
+      utf8Bytes.push((charCode & 63) | 128);
+    }
+  }
+
+  let base64Str = '';
+  let paddingCount = 0;
+
+  // 处理每3个字节(24位),转换为4个Base64字符
+  for (let i = 0; i < utf8Bytes.length; i += 3) {
+    let byte1 = utf8Bytes[i];
+    let byte2 = i + 1 < utf8Bytes.length ? utf8Bytes[i + 1] : 0;
+    let byte3 = i + 2 < utf8Bytes.length ? utf8Bytes[i + 2] : 0;
+
+    let chunk = (byte1 << 16) | (byte2 << 8) | byte3;
+
+    let char1 = base64Chars[(chunk >> 18) & 63];
+    let char2 = base64Chars[(chunk >> 12) & 63];
+    let char3 = i + 1 < utf8Bytes.length ? base64Chars[(chunk >> 6) & 63] : '=';
+    let char4 = i + 2 < utf8Bytes.length ? base64Chars[chunk & 63] : '=';
+
+    base64Str += char1 + char2 + char3 + char4;
+
+    // 计算需要填充的'='号数量
+    if (i + 2 >= utf8Bytes.length) {
+      paddingCount = (utf8Bytes.length - i) % 3;
+    }
+  }
+
+  return base64Str;
+}
+//截取字符串
+function getFirst32Chars(str) {
+  if (typeof str !== 'string') {
+    throw new Error('Input must be a string');
+  }
+  
+  // 如果字符串长度小于等于32,则返回整个字符串;否则返回前32个字符
+  return str.length <= 32 ? str : str.slice(0, 32);
+}
+
+//字符串转16进制
+function stringToHex(str) {
+  let hex = '';
+  for (let i = 0; i < str.length; i++) {
+    // 获取字符的字符编码
+    const charCode = str.charCodeAt(i);
+    // 将字符编码转换为16进制,并确保始终为两位数(不足两位前面补0)
+    const hexValue = charCode.toString(16).padStart(2, '0');
+    hex += hexValue;
+  }
+  return hex;
+}
+
+function generateRandomString(minLength = 6, maxLength = 10) {
+  // 定义字符集
+  const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+
+  // 生成随机长度
+  const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;
+
+  let result = '';
+  for (let i = 0; i < length; i++) {
+    // 随机选择一个字符
+    const randomIndex = Math.floor(Math.random() * charset.length);
+    result += charset[randomIndex];
+  }
+
+  return result;
+}
+
+//获取站点信息
+function request_getSite(data) {
+  return request('api/Nozzle/GetNozzleInfo?Nozzleid='+ data, "GET",data);
+}
+//支付
+function request_wechatPay(data) {
+  return request('api/Transactions/UnifiedOrder?trxid='+ data, "GET",data);
+}
+
+//获取站点信息与用户信息
+function request_GetSiteInfo(data) {
+  return request('api/Site/GetSiteInfo', "GET",data);
+}
+
+//小程序用户查询未支付订单
+function request_GetMiniProgramTransactionsUnpaidQuery(data) {
+  return request('api/Transactions/GetMiniProgramTransactionsUnpaidQuery', "GET",data);
+}
+
+//小程序用户根据抢号查询未支付订单
+function request_GetMiniProgramTransactionsUnpaidNozzle(data) {
+  return request('api/Transactions/GetMiniProgramTransactionsUnpaidNozzle', "GET",data);
+}
+
+export default {
+  request_getSite,
+  request_wechatPay
+}

+ 1374 - 0
miniprogram_npm/jsbn/index.js

@@ -0,0 +1,1374 @@
+module.exports = (function() {
+var __MODS__ = {};
+var __DEFINE__ = function(modId, func, req) { var m = { exports: {}, _tempexports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; };
+var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = __MODS__[modId].m; m._exports = m._tempexports; var desp = Object.getOwnPropertyDescriptor(m, "exports"); if (desp && desp.configurable) Object.defineProperty(m, "exports", { set: function (val) { if(typeof val === "object" && val !== m._exports) { m._exports.__proto__ = val.__proto__; Object.keys(val).forEach(function (k) { m._exports[k] = val[k]; }); } m._tempexports = val }, get: function () { return m._tempexports; } }); __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); } return __MODS__[modId].m.exports; };
+var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } };
+var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; };
+__DEFINE__(1738722861363, function(require, module, exports) {
+(function(){
+
+    // Copyright (c) 2005  Tom Wu
+    // All Rights Reserved.
+    // See "LICENSE" for details.
+
+    // Basic JavaScript BN library - subset useful for RSA encryption.
+
+    // Bits per digit
+    var dbits;
+
+    // JavaScript engine analysis
+    var canary = 0xdeadbeefcafe;
+    var j_lm = ((canary&0xffffff)==0xefcafe);
+
+    // (public) Constructor
+    function BigInteger(a,b,c) {
+      if(a != null)
+        if("number" == typeof a) this.fromNumber(a,b,c);
+        else if(b == null && "string" != typeof a) this.fromString(a,256);
+        else this.fromString(a,b);
+    }
+
+    // return new, unset BigInteger
+    function nbi() { return new BigInteger(null); }
+
+    // am: Compute w_j += (x*this_i), propagate carries,
+    // c is initial carry, returns final carry.
+    // c < 3*dvalue, x < 2*dvalue, this_i < dvalue
+    // We need to select the fastest one that works in this environment.
+
+    // am1: use a single mult and divide to get the high bits,
+    // max digit bits should be 26 because
+    // max internal value = 2*dvalue^2-2*dvalue (< 2^53)
+    function am1(i,x,w,j,c,n) {
+      while(--n >= 0) {
+        var v = x*this[i++]+w[j]+c;
+        c = Math.floor(v/0x4000000);
+        w[j++] = v&0x3ffffff;
+      }
+      return c;
+    }
+    // am2 avoids a big mult-and-extract completely.
+    // Max digit bits should be <= 30 because we do bitwise ops
+    // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
+    function am2(i,x,w,j,c,n) {
+      var xl = x&0x7fff, xh = x>>15;
+      while(--n >= 0) {
+        var l = this[i]&0x7fff;
+        var h = this[i++]>>15;
+        var m = xh*l+h*xl;
+        l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
+        c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
+        w[j++] = l&0x3fffffff;
+      }
+      return c;
+    }
+    // Alternately, set max digit bits to 28 since some
+    // browsers slow down when dealing with 32-bit numbers.
+    function am3(i,x,w,j,c,n) {
+      var xl = x&0x3fff, xh = x>>14;
+      while(--n >= 0) {
+        var l = this[i]&0x3fff;
+        var h = this[i++]>>14;
+        var m = xh*l+h*xl;
+        l = xl*l+((m&0x3fff)<<14)+w[j]+c;
+        c = (l>>28)+(m>>14)+xh*h;
+        w[j++] = l&0xfffffff;
+      }
+      return c;
+    }
+    var inBrowser = typeof navigator !== "undefined";
+    if(inBrowser && j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
+      BigInteger.prototype.am = am2;
+      dbits = 30;
+    }
+    else if(inBrowser && j_lm && (navigator.appName != "Netscape")) {
+      BigInteger.prototype.am = am1;
+      dbits = 26;
+    }
+    else { // Mozilla/Netscape seems to prefer am3
+      BigInteger.prototype.am = am3;
+      dbits = 28;
+    }
+
+    BigInteger.prototype.DB = dbits;
+    BigInteger.prototype.DM = ((1<<dbits)-1);
+    BigInteger.prototype.DV = (1<<dbits);
+
+    var BI_FP = 52;
+    BigInteger.prototype.FV = Math.pow(2,BI_FP);
+    BigInteger.prototype.F1 = BI_FP-dbits;
+    BigInteger.prototype.F2 = 2*dbits-BI_FP;
+
+    // Digit conversions
+    var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
+    var BI_RC = new Array();
+    var rr,vv;
+    rr = "0".charCodeAt(0);
+    for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
+    rr = "a".charCodeAt(0);
+    for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
+    rr = "A".charCodeAt(0);
+    for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
+
+    function int2char(n) { return BI_RM.charAt(n); }
+    function intAt(s,i) {
+      var c = BI_RC[s.charCodeAt(i)];
+      return (c==null)?-1:c;
+    }
+
+    // (protected) copy this to r
+    function bnpCopyTo(r) {
+      for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
+      r.t = this.t;
+      r.s = this.s;
+    }
+
+    // (protected) set from integer value x, -DV <= x < DV
+    function bnpFromInt(x) {
+      this.t = 1;
+      this.s = (x<0)?-1:0;
+      if(x > 0) this[0] = x;
+      else if(x < -1) this[0] = x+this.DV;
+      else this.t = 0;
+    }
+
+    // return bigint initialized to value
+    function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
+
+    // (protected) set from string and radix
+    function bnpFromString(s,b) {
+      var k;
+      if(b == 16) k = 4;
+      else if(b == 8) k = 3;
+      else if(b == 256) k = 8; // byte array
+      else if(b == 2) k = 1;
+      else if(b == 32) k = 5;
+      else if(b == 4) k = 2;
+      else { this.fromRadix(s,b); return; }
+      this.t = 0;
+      this.s = 0;
+      var i = s.length, mi = false, sh = 0;
+      while(--i >= 0) {
+        var x = (k==8)?s[i]&0xff:intAt(s,i);
+        if(x < 0) {
+          if(s.charAt(i) == "-") mi = true;
+          continue;
+        }
+        mi = false;
+        if(sh == 0)
+          this[this.t++] = x;
+        else if(sh+k > this.DB) {
+          this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
+          this[this.t++] = (x>>(this.DB-sh));
+        }
+        else
+          this[this.t-1] |= x<<sh;
+        sh += k;
+        if(sh >= this.DB) sh -= this.DB;
+      }
+      if(k == 8 && (s[0]&0x80) != 0) {
+        this.s = -1;
+        if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
+      }
+      this.clamp();
+      if(mi) BigInteger.ZERO.subTo(this,this);
+    }
+
+    // (protected) clamp off excess high words
+    function bnpClamp() {
+      var c = this.s&this.DM;
+      while(this.t > 0 && this[this.t-1] == c) --this.t;
+    }
+
+    // (public) return string representation in given radix
+    function bnToString(b) {
+      if(this.s < 0) return "-"+this.negate().toString(b);
+      var k;
+      if(b == 16) k = 4;
+      else if(b == 8) k = 3;
+      else if(b == 2) k = 1;
+      else if(b == 32) k = 5;
+      else if(b == 4) k = 2;
+      else return this.toRadix(b);
+      var km = (1<<k)-1, d, m = false, r = "", i = this.t;
+      var p = this.DB-(i*this.DB)%k;
+      if(i-- > 0) {
+        if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
+        while(i >= 0) {
+          if(p < k) {
+            d = (this[i]&((1<<p)-1))<<(k-p);
+            d |= this[--i]>>(p+=this.DB-k);
+          }
+          else {
+            d = (this[i]>>(p-=k))&km;
+            if(p <= 0) { p += this.DB; --i; }
+          }
+          if(d > 0) m = true;
+          if(m) r += int2char(d);
+        }
+      }
+      return m?r:"0";
+    }
+
+    // (public) -this
+    function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
+
+    // (public) |this|
+    function bnAbs() { return (this.s<0)?this.negate():this; }
+
+    // (public) return + if this > a, - if this < a, 0 if equal
+    function bnCompareTo(a) {
+      var r = this.s-a.s;
+      if(r != 0) return r;
+      var i = this.t;
+      r = i-a.t;
+      if(r != 0) return (this.s<0)?-r:r;
+      while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
+      return 0;
+    }
+
+    // returns bit length of the integer x
+    function nbits(x) {
+      var r = 1, t;
+      if((t=x>>>16) != 0) { x = t; r += 16; }
+      if((t=x>>8) != 0) { x = t; r += 8; }
+      if((t=x>>4) != 0) { x = t; r += 4; }
+      if((t=x>>2) != 0) { x = t; r += 2; }
+      if((t=x>>1) != 0) { x = t; r += 1; }
+      return r;
+    }
+
+    // (public) return the number of bits in "this"
+    function bnBitLength() {
+      if(this.t <= 0) return 0;
+      return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
+    }
+
+    // (protected) r = this << n*DB
+    function bnpDLShiftTo(n,r) {
+      var i;
+      for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
+      for(i = n-1; i >= 0; --i) r[i] = 0;
+      r.t = this.t+n;
+      r.s = this.s;
+    }
+
+    // (protected) r = this >> n*DB
+    function bnpDRShiftTo(n,r) {
+      for(var i = n; i < this.t; ++i) r[i-n] = this[i];
+      r.t = Math.max(this.t-n,0);
+      r.s = this.s;
+    }
+
+    // (protected) r = this << n
+    function bnpLShiftTo(n,r) {
+      var bs = n%this.DB;
+      var cbs = this.DB-bs;
+      var bm = (1<<cbs)-1;
+      var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
+      for(i = this.t-1; i >= 0; --i) {
+        r[i+ds+1] = (this[i]>>cbs)|c;
+        c = (this[i]&bm)<<bs;
+      }
+      for(i = ds-1; i >= 0; --i) r[i] = 0;
+      r[ds] = c;
+      r.t = this.t+ds+1;
+      r.s = this.s;
+      r.clamp();
+    }
+
+    // (protected) r = this >> n
+    function bnpRShiftTo(n,r) {
+      r.s = this.s;
+      var ds = Math.floor(n/this.DB);
+      if(ds >= this.t) { r.t = 0; return; }
+      var bs = n%this.DB;
+      var cbs = this.DB-bs;
+      var bm = (1<<bs)-1;
+      r[0] = this[ds]>>bs;
+      for(var i = ds+1; i < this.t; ++i) {
+        r[i-ds-1] |= (this[i]&bm)<<cbs;
+        r[i-ds] = this[i]>>bs;
+      }
+      if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
+      r.t = this.t-ds;
+      r.clamp();
+    }
+
+    // (protected) r = this - a
+    function bnpSubTo(a,r) {
+      var i = 0, c = 0, m = Math.min(a.t,this.t);
+      while(i < m) {
+        c += this[i]-a[i];
+        r[i++] = c&this.DM;
+        c >>= this.DB;
+      }
+      if(a.t < this.t) {
+        c -= a.s;
+        while(i < this.t) {
+          c += this[i];
+          r[i++] = c&this.DM;
+          c >>= this.DB;
+        }
+        c += this.s;
+      }
+      else {
+        c += this.s;
+        while(i < a.t) {
+          c -= a[i];
+          r[i++] = c&this.DM;
+          c >>= this.DB;
+        }
+        c -= a.s;
+      }
+      r.s = (c<0)?-1:0;
+      if(c < -1) r[i++] = this.DV+c;
+      else if(c > 0) r[i++] = c;
+      r.t = i;
+      r.clamp();
+    }
+
+    // (protected) r = this * a, r != this,a (HAC 14.12)
+    // "this" should be the larger one if appropriate.
+    function bnpMultiplyTo(a,r) {
+      var x = this.abs(), y = a.abs();
+      var i = x.t;
+      r.t = i+y.t;
+      while(--i >= 0) r[i] = 0;
+      for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
+      r.s = 0;
+      r.clamp();
+      if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
+    }
+
+    // (protected) r = this^2, r != this (HAC 14.16)
+    function bnpSquareTo(r) {
+      var x = this.abs();
+      var i = r.t = 2*x.t;
+      while(--i >= 0) r[i] = 0;
+      for(i = 0; i < x.t-1; ++i) {
+        var c = x.am(i,x[i],r,2*i,0,1);
+        if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
+          r[i+x.t] -= x.DV;
+          r[i+x.t+1] = 1;
+        }
+      }
+      if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
+      r.s = 0;
+      r.clamp();
+    }
+
+    // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
+    // r != q, this != m.  q or r may be null.
+    function bnpDivRemTo(m,q,r) {
+      var pm = m.abs();
+      if(pm.t <= 0) return;
+      var pt = this.abs();
+      if(pt.t < pm.t) {
+        if(q != null) q.fromInt(0);
+        if(r != null) this.copyTo(r);
+        return;
+      }
+      if(r == null) r = nbi();
+      var y = nbi(), ts = this.s, ms = m.s;
+      var nsh = this.DB-nbits(pm[pm.t-1]);   // normalize modulus
+      if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
+      else { pm.copyTo(y); pt.copyTo(r); }
+      var ys = y.t;
+      var y0 = y[ys-1];
+      if(y0 == 0) return;
+      var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
+      var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
+      var i = r.t, j = i-ys, t = (q==null)?nbi():q;
+      y.dlShiftTo(j,t);
+      if(r.compareTo(t) >= 0) {
+        r[r.t++] = 1;
+        r.subTo(t,r);
+      }
+      BigInteger.ONE.dlShiftTo(ys,t);
+      t.subTo(y,y);  // "negative" y so we can replace sub with am later
+      while(y.t < ys) y[y.t++] = 0;
+      while(--j >= 0) {
+        // Estimate quotient digit
+        var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
+        if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) {   // Try it out
+          y.dlShiftTo(j,t);
+          r.subTo(t,r);
+          while(r[i] < --qd) r.subTo(t,r);
+        }
+      }
+      if(q != null) {
+        r.drShiftTo(ys,q);
+        if(ts != ms) BigInteger.ZERO.subTo(q,q);
+      }
+      r.t = ys;
+      r.clamp();
+      if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder
+      if(ts < 0) BigInteger.ZERO.subTo(r,r);
+    }
+
+    // (public) this mod a
+    function bnMod(a) {
+      var r = nbi();
+      this.abs().divRemTo(a,null,r);
+      if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
+      return r;
+    }
+
+    // Modular reduction using "classic" algorithm
+    function Classic(m) { this.m = m; }
+    function cConvert(x) {
+      if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
+      else return x;
+    }
+    function cRevert(x) { return x; }
+    function cReduce(x) { x.divRemTo(this.m,null,x); }
+    function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
+    function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
+
+    Classic.prototype.convert = cConvert;
+    Classic.prototype.revert = cRevert;
+    Classic.prototype.reduce = cReduce;
+    Classic.prototype.mulTo = cMulTo;
+    Classic.prototype.sqrTo = cSqrTo;
+
+    // (protected) return "-1/this % 2^DB"; useful for Mont. reduction
+    // justification:
+    //         xy == 1 (mod m)
+    //         xy =  1+km
+    //   xy(2-xy) = (1+km)(1-km)
+    // x[y(2-xy)] = 1-k^2m^2
+    // x[y(2-xy)] == 1 (mod m^2)
+    // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
+    // should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
+    // JS multiply "overflows" differently from C/C++, so care is needed here.
+    function bnpInvDigit() {
+      if(this.t < 1) return 0;
+      var x = this[0];
+      if((x&1) == 0) return 0;
+      var y = x&3;       // y == 1/x mod 2^2
+      y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4
+      y = (y*(2-(x&0xff)*y))&0xff;   // y == 1/x mod 2^8
+      y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff;    // y == 1/x mod 2^16
+      // last step - calculate inverse mod DV directly;
+      // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
+      y = (y*(2-x*y%this.DV))%this.DV;       // y == 1/x mod 2^dbits
+      // we really want the negative inverse, and -DV < y < DV
+      return (y>0)?this.DV-y:-y;
+    }
+
+    // Montgomery reduction
+    function Montgomery(m) {
+      this.m = m;
+      this.mp = m.invDigit();
+      this.mpl = this.mp&0x7fff;
+      this.mph = this.mp>>15;
+      this.um = (1<<(m.DB-15))-1;
+      this.mt2 = 2*m.t;
+    }
+
+    // xR mod m
+    function montConvert(x) {
+      var r = nbi();
+      x.abs().dlShiftTo(this.m.t,r);
+      r.divRemTo(this.m,null,r);
+      if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
+      return r;
+    }
+
+    // x/R mod m
+    function montRevert(x) {
+      var r = nbi();
+      x.copyTo(r);
+      this.reduce(r);
+      return r;
+    }
+
+    // x = x/R mod m (HAC 14.32)
+    function montReduce(x) {
+      while(x.t <= this.mt2) // pad x so am has enough room later
+        x[x.t++] = 0;
+      for(var i = 0; i < this.m.t; ++i) {
+        // faster way of calculating u0 = x[i]*mp mod DV
+        var j = x[i]&0x7fff;
+        var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
+        // use am to combine the multiply-shift-add into one call
+        j = i+this.m.t;
+        x[j] += this.m.am(0,u0,x,i,0,this.m.t);
+        // propagate carry
+        while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
+      }
+      x.clamp();
+      x.drShiftTo(this.m.t,x);
+      if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
+    }
+
+    // r = "x^2/R mod m"; x != r
+    function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
+
+    // r = "xy/R mod m"; x,y != r
+    function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
+
+    Montgomery.prototype.convert = montConvert;
+    Montgomery.prototype.revert = montRevert;
+    Montgomery.prototype.reduce = montReduce;
+    Montgomery.prototype.mulTo = montMulTo;
+    Montgomery.prototype.sqrTo = montSqrTo;
+
+    // (protected) true iff this is even
+    function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
+
+    // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
+    function bnpExp(e,z) {
+      if(e > 0xffffffff || e < 1) return BigInteger.ONE;
+      var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
+      g.copyTo(r);
+      while(--i >= 0) {
+        z.sqrTo(r,r2);
+        if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
+        else { var t = r; r = r2; r2 = t; }
+      }
+      return z.revert(r);
+    }
+
+    // (public) this^e % m, 0 <= e < 2^32
+    function bnModPowInt(e,m) {
+      var z;
+      if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
+      return this.exp(e,z);
+    }
+
+    // protected
+    BigInteger.prototype.copyTo = bnpCopyTo;
+    BigInteger.prototype.fromInt = bnpFromInt;
+    BigInteger.prototype.fromString = bnpFromString;
+    BigInteger.prototype.clamp = bnpClamp;
+    BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
+    BigInteger.prototype.drShiftTo = bnpDRShiftTo;
+    BigInteger.prototype.lShiftTo = bnpLShiftTo;
+    BigInteger.prototype.rShiftTo = bnpRShiftTo;
+    BigInteger.prototype.subTo = bnpSubTo;
+    BigInteger.prototype.multiplyTo = bnpMultiplyTo;
+    BigInteger.prototype.squareTo = bnpSquareTo;
+    BigInteger.prototype.divRemTo = bnpDivRemTo;
+    BigInteger.prototype.invDigit = bnpInvDigit;
+    BigInteger.prototype.isEven = bnpIsEven;
+    BigInteger.prototype.exp = bnpExp;
+
+    // public
+    BigInteger.prototype.toString = bnToString;
+    BigInteger.prototype.negate = bnNegate;
+    BigInteger.prototype.abs = bnAbs;
+    BigInteger.prototype.compareTo = bnCompareTo;
+    BigInteger.prototype.bitLength = bnBitLength;
+    BigInteger.prototype.mod = bnMod;
+    BigInteger.prototype.modPowInt = bnModPowInt;
+
+    // "constants"
+    BigInteger.ZERO = nbv(0);
+    BigInteger.ONE = nbv(1);
+
+    // Copyright (c) 2005-2009  Tom Wu
+    // All Rights Reserved.
+    // See "LICENSE" for details.
+
+    // Extended JavaScript BN functions, required for RSA private ops.
+
+    // Version 1.1: new BigInteger("0", 10) returns "proper" zero
+    // Version 1.2: square() API, isProbablePrime fix
+
+    // (public)
+    function bnClone() { var r = nbi(); this.copyTo(r); return r; }
+
+    // (public) return value as integer
+    function bnIntValue() {
+      if(this.s < 0) {
+        if(this.t == 1) return this[0]-this.DV;
+        else if(this.t == 0) return -1;
+      }
+      else if(this.t == 1) return this[0];
+      else if(this.t == 0) return 0;
+      // assumes 16 < DB < 32
+      return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];
+    }
+
+    // (public) return value as byte
+    function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }
+
+    // (public) return value as short (assumes DB>=16)
+    function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }
+
+    // (protected) return x s.t. r^x < DV
+    function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }
+
+    // (public) 0 if this == 0, 1 if this > 0
+    function bnSigNum() {
+      if(this.s < 0) return -1;
+      else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
+      else return 1;
+    }
+
+    // (protected) convert to radix string
+    function bnpToRadix(b) {
+      if(b == null) b = 10;
+      if(this.signum() == 0 || b < 2 || b > 36) return "0";
+      var cs = this.chunkSize(b);
+      var a = Math.pow(b,cs);
+      var d = nbv(a), y = nbi(), z = nbi(), r = "";
+      this.divRemTo(d,y,z);
+      while(y.signum() > 0) {
+        r = (a+z.intValue()).toString(b).substr(1) + r;
+        y.divRemTo(d,y,z);
+      }
+      return z.intValue().toString(b) + r;
+    }
+
+    // (protected) convert from radix string
+    function bnpFromRadix(s,b) {
+      this.fromInt(0);
+      if(b == null) b = 10;
+      var cs = this.chunkSize(b);
+      var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
+      for(var i = 0; i < s.length; ++i) {
+        var x = intAt(s,i);
+        if(x < 0) {
+          if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
+          continue;
+        }
+        w = b*w+x;
+        if(++j >= cs) {
+          this.dMultiply(d);
+          this.dAddOffset(w,0);
+          j = 0;
+          w = 0;
+        }
+      }
+      if(j > 0) {
+        this.dMultiply(Math.pow(b,j));
+        this.dAddOffset(w,0);
+      }
+      if(mi) BigInteger.ZERO.subTo(this,this);
+    }
+
+    // (protected) alternate constructor
+    function bnpFromNumber(a,b,c) {
+      if("number" == typeof b) {
+        // new BigInteger(int,int,RNG)
+        if(a < 2) this.fromInt(1);
+        else {
+          this.fromNumber(a,c);
+          if(!this.testBit(a-1))    // force MSB set
+            this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);
+          if(this.isEven()) this.dAddOffset(1,0); // force odd
+          while(!this.isProbablePrime(b)) {
+            this.dAddOffset(2,0);
+            if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);
+          }
+        }
+      }
+      else {
+        // new BigInteger(int,RNG)
+        var x = new Array(), t = a&7;
+        x.length = (a>>3)+1;
+        b.nextBytes(x);
+        if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
+        this.fromString(x,256);
+      }
+    }
+
+    // (public) convert to bigendian byte array
+    function bnToByteArray() {
+      var i = this.t, r = new Array();
+      r[0] = this.s;
+      var p = this.DB-(i*this.DB)%8, d, k = 0;
+      if(i-- > 0) {
+        if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)
+          r[k++] = d|(this.s<<(this.DB-p));
+        while(i >= 0) {
+          if(p < 8) {
+            d = (this[i]&((1<<p)-1))<<(8-p);
+            d |= this[--i]>>(p+=this.DB-8);
+          }
+          else {
+            d = (this[i]>>(p-=8))&0xff;
+            if(p <= 0) { p += this.DB; --i; }
+          }
+          if((d&0x80) != 0) d |= -256;
+          if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
+          if(k > 0 || d != this.s) r[k++] = d;
+        }
+      }
+      return r;
+    }
+
+    function bnEquals(a) { return(this.compareTo(a)==0); }
+    function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
+    function bnMax(a) { return(this.compareTo(a)>0)?this:a; }
+
+    // (protected) r = this op a (bitwise)
+    function bnpBitwiseTo(a,op,r) {
+      var i, f, m = Math.min(a.t,this.t);
+      for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);
+      if(a.t < this.t) {
+        f = a.s&this.DM;
+        for(i = m; i < this.t; ++i) r[i] = op(this[i],f);
+        r.t = this.t;
+      }
+      else {
+        f = this.s&this.DM;
+        for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);
+        r.t = a.t;
+      }
+      r.s = op(this.s,a.s);
+      r.clamp();
+    }
+
+    // (public) this & a
+    function op_and(x,y) { return x&y; }
+    function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }
+
+    // (public) this | a
+    function op_or(x,y) { return x|y; }
+    function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }
+
+    // (public) this ^ a
+    function op_xor(x,y) { return x^y; }
+    function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }
+
+    // (public) this & ~a
+    function op_andnot(x,y) { return x&~y; }
+    function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }
+
+    // (public) ~this
+    function bnNot() {
+      var r = nbi();
+      for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];
+      r.t = this.t;
+      r.s = ~this.s;
+      return r;
+    }
+
+    // (public) this << n
+    function bnShiftLeft(n) {
+      var r = nbi();
+      if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);
+      return r;
+    }
+
+    // (public) this >> n
+    function bnShiftRight(n) {
+      var r = nbi();
+      if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);
+      return r;
+    }
+
+    // return index of lowest 1-bit in x, x < 2^31
+    function lbit(x) {
+      if(x == 0) return -1;
+      var r = 0;
+      if((x&0xffff) == 0) { x >>= 16; r += 16; }
+      if((x&0xff) == 0) { x >>= 8; r += 8; }
+      if((x&0xf) == 0) { x >>= 4; r += 4; }
+      if((x&3) == 0) { x >>= 2; r += 2; }
+      if((x&1) == 0) ++r;
+      return r;
+    }
+
+    // (public) returns index of lowest 1-bit (or -1 if none)
+    function bnGetLowestSetBit() {
+      for(var i = 0; i < this.t; ++i)
+        if(this[i] != 0) return i*this.DB+lbit(this[i]);
+      if(this.s < 0) return this.t*this.DB;
+      return -1;
+    }
+
+    // return number of 1 bits in x
+    function cbit(x) {
+      var r = 0;
+      while(x != 0) { x &= x-1; ++r; }
+      return r;
+    }
+
+    // (public) return number of set bits
+    function bnBitCount() {
+      var r = 0, x = this.s&this.DM;
+      for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);
+      return r;
+    }
+
+    // (public) true iff nth bit is set
+    function bnTestBit(n) {
+      var j = Math.floor(n/this.DB);
+      if(j >= this.t) return(this.s!=0);
+      return((this[j]&(1<<(n%this.DB)))!=0);
+    }
+
+    // (protected) this op (1<<n)
+    function bnpChangeBit(n,op) {
+      var r = BigInteger.ONE.shiftLeft(n);
+      this.bitwiseTo(r,op,r);
+      return r;
+    }
+
+    // (public) this | (1<<n)
+    function bnSetBit(n) { return this.changeBit(n,op_or); }
+
+    // (public) this & ~(1<<n)
+    function bnClearBit(n) { return this.changeBit(n,op_andnot); }
+
+    // (public) this ^ (1<<n)
+    function bnFlipBit(n) { return this.changeBit(n,op_xor); }
+
+    // (protected) r = this + a
+    function bnpAddTo(a,r) {
+      var i = 0, c = 0, m = Math.min(a.t,this.t);
+      while(i < m) {
+        c += this[i]+a[i];
+        r[i++] = c&this.DM;
+        c >>= this.DB;
+      }
+      if(a.t < this.t) {
+        c += a.s;
+        while(i < this.t) {
+          c += this[i];
+          r[i++] = c&this.DM;
+          c >>= this.DB;
+        }
+        c += this.s;
+      }
+      else {
+        c += this.s;
+        while(i < a.t) {
+          c += a[i];
+          r[i++] = c&this.DM;
+          c >>= this.DB;
+        }
+        c += a.s;
+      }
+      r.s = (c<0)?-1:0;
+      if(c > 0) r[i++] = c;
+      else if(c < -1) r[i++] = this.DV+c;
+      r.t = i;
+      r.clamp();
+    }
+
+    // (public) this + a
+    function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }
+
+    // (public) this - a
+    function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }
+
+    // (public) this * a
+    function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }
+
+    // (public) this^2
+    function bnSquare() { var r = nbi(); this.squareTo(r); return r; }
+
+    // (public) this / a
+    function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }
+
+    // (public) this % a
+    function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }
+
+    // (public) [this/a,this%a]
+    function bnDivideAndRemainder(a) {
+      var q = nbi(), r = nbi();
+      this.divRemTo(a,q,r);
+      return new Array(q,r);
+    }
+
+    // (protected) this *= n, this >= 0, 1 < n < DV
+    function bnpDMultiply(n) {
+      this[this.t] = this.am(0,n-1,this,0,0,this.t);
+      ++this.t;
+      this.clamp();
+    }
+
+    // (protected) this += n << w words, this >= 0
+    function bnpDAddOffset(n,w) {
+      if(n == 0) return;
+      while(this.t <= w) this[this.t++] = 0;
+      this[w] += n;
+      while(this[w] >= this.DV) {
+        this[w] -= this.DV;
+        if(++w >= this.t) this[this.t++] = 0;
+        ++this[w];
+      }
+    }
+
+    // A "null" reducer
+    function NullExp() {}
+    function nNop(x) { return x; }
+    function nMulTo(x,y,r) { x.multiplyTo(y,r); }
+    function nSqrTo(x,r) { x.squareTo(r); }
+
+    NullExp.prototype.convert = nNop;
+    NullExp.prototype.revert = nNop;
+    NullExp.prototype.mulTo = nMulTo;
+    NullExp.prototype.sqrTo = nSqrTo;
+
+    // (public) this^e
+    function bnPow(e) { return this.exp(e,new NullExp()); }
+
+    // (protected) r = lower n words of "this * a", a.t <= n
+    // "this" should be the larger one if appropriate.
+    function bnpMultiplyLowerTo(a,n,r) {
+      var i = Math.min(this.t+a.t,n);
+      r.s = 0; // assumes a,this >= 0
+      r.t = i;
+      while(i > 0) r[--i] = 0;
+      var j;
+      for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);
+      for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);
+      r.clamp();
+    }
+
+    // (protected) r = "this * a" without lower n words, n > 0
+    // "this" should be the larger one if appropriate.
+    function bnpMultiplyUpperTo(a,n,r) {
+      --n;
+      var i = r.t = this.t+a.t-n;
+      r.s = 0; // assumes a,this >= 0
+      while(--i >= 0) r[i] = 0;
+      for(i = Math.max(n-this.t,0); i < a.t; ++i)
+        r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);
+      r.clamp();
+      r.drShiftTo(1,r);
+    }
+
+    // Barrett modular reduction
+    function Barrett(m) {
+      // setup Barrett
+      this.r2 = nbi();
+      this.q3 = nbi();
+      BigInteger.ONE.dlShiftTo(2*m.t,this.r2);
+      this.mu = this.r2.divide(m);
+      this.m = m;
+    }
+
+    function barrettConvert(x) {
+      if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);
+      else if(x.compareTo(this.m) < 0) return x;
+      else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
+    }
+
+    function barrettRevert(x) { return x; }
+
+    // x = x mod m (HAC 14.42)
+    function barrettReduce(x) {
+      x.drShiftTo(this.m.t-1,this.r2);
+      if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }
+      this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);
+      this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);
+      while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);
+      x.subTo(this.r2,x);
+      while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
+    }
+
+    // r = x^2 mod m; x != r
+    function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
+
+    // r = x*y mod m; x,y != r
+    function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
+
+    Barrett.prototype.convert = barrettConvert;
+    Barrett.prototype.revert = barrettRevert;
+    Barrett.prototype.reduce = barrettReduce;
+    Barrett.prototype.mulTo = barrettMulTo;
+    Barrett.prototype.sqrTo = barrettSqrTo;
+
+    // (public) this^e % m (HAC 14.85)
+    function bnModPow(e,m) {
+      var i = e.bitLength(), k, r = nbv(1), z;
+      if(i <= 0) return r;
+      else if(i < 18) k = 1;
+      else if(i < 48) k = 3;
+      else if(i < 144) k = 4;
+      else if(i < 768) k = 5;
+      else k = 6;
+      if(i < 8)
+        z = new Classic(m);
+      else if(m.isEven())
+        z = new Barrett(m);
+      else
+        z = new Montgomery(m);
+
+      // precomputation
+      var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;
+      g[1] = z.convert(this);
+      if(k > 1) {
+        var g2 = nbi();
+        z.sqrTo(g[1],g2);
+        while(n <= km) {
+          g[n] = nbi();
+          z.mulTo(g2,g[n-2],g[n]);
+          n += 2;
+        }
+      }
+
+      var j = e.t-1, w, is1 = true, r2 = nbi(), t;
+      i = nbits(e[j])-1;
+      while(j >= 0) {
+        if(i >= k1) w = (e[j]>>(i-k1))&km;
+        else {
+          w = (e[j]&((1<<(i+1))-1))<<(k1-i);
+          if(j > 0) w |= e[j-1]>>(this.DB+i-k1);
+        }
+
+        n = k;
+        while((w&1) == 0) { w >>= 1; --n; }
+        if((i -= n) < 0) { i += this.DB; --j; }
+        if(is1) {    // ret == 1, don't bother squaring or multiplying it
+          g[w].copyTo(r);
+          is1 = false;
+        }
+        else {
+          while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }
+          if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }
+          z.mulTo(r2,g[w],r);
+        }
+
+        while(j >= 0 && (e[j]&(1<<i)) == 0) {
+          z.sqrTo(r,r2); t = r; r = r2; r2 = t;
+          if(--i < 0) { i = this.DB-1; --j; }
+        }
+      }
+      return z.revert(r);
+    }
+
+    // (public) gcd(this,a) (HAC 14.54)
+    function bnGCD(a) {
+      var x = (this.s<0)?this.negate():this.clone();
+      var y = (a.s<0)?a.negate():a.clone();
+      if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }
+      var i = x.getLowestSetBit(), g = y.getLowestSetBit();
+      if(g < 0) return x;
+      if(i < g) g = i;
+      if(g > 0) {
+        x.rShiftTo(g,x);
+        y.rShiftTo(g,y);
+      }
+      while(x.signum() > 0) {
+        if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);
+        if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);
+        if(x.compareTo(y) >= 0) {
+          x.subTo(y,x);
+          x.rShiftTo(1,x);
+        }
+        else {
+          y.subTo(x,y);
+          y.rShiftTo(1,y);
+        }
+      }
+      if(g > 0) y.lShiftTo(g,y);
+      return y;
+    }
+
+    // (protected) this % n, n < 2^26
+    function bnpModInt(n) {
+      if(n <= 0) return 0;
+      var d = this.DV%n, r = (this.s<0)?n-1:0;
+      if(this.t > 0)
+        if(d == 0) r = this[0]%n;
+        else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;
+      return r;
+    }
+
+    // (public) 1/this % m (HAC 14.61)
+    function bnModInverse(m) {
+      var ac = m.isEven();
+      if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
+      var u = m.clone(), v = this.clone();
+      var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
+      while(u.signum() != 0) {
+        while(u.isEven()) {
+          u.rShiftTo(1,u);
+          if(ac) {
+            if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
+            a.rShiftTo(1,a);
+          }
+          else if(!b.isEven()) b.subTo(m,b);
+          b.rShiftTo(1,b);
+        }
+        while(v.isEven()) {
+          v.rShiftTo(1,v);
+          if(ac) {
+            if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
+            c.rShiftTo(1,c);
+          }
+          else if(!d.isEven()) d.subTo(m,d);
+          d.rShiftTo(1,d);
+        }
+        if(u.compareTo(v) >= 0) {
+          u.subTo(v,u);
+          if(ac) a.subTo(c,a);
+          b.subTo(d,b);
+        }
+        else {
+          v.subTo(u,v);
+          if(ac) c.subTo(a,c);
+          d.subTo(b,d);
+        }
+      }
+      if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
+      if(d.compareTo(m) >= 0) return d.subtract(m);
+      if(d.signum() < 0) d.addTo(m,d); else return d;
+      if(d.signum() < 0) return d.add(m); else return d;
+    }
+
+    var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997];
+    var lplim = (1<<26)/lowprimes[lowprimes.length-1];
+
+    // (public) test primality with certainty >= 1-.5^t
+    function bnIsProbablePrime(t) {
+      var i, x = this.abs();
+      if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {
+        for(i = 0; i < lowprimes.length; ++i)
+          if(x[0] == lowprimes[i]) return true;
+        return false;
+      }
+      if(x.isEven()) return false;
+      i = 1;
+      while(i < lowprimes.length) {
+        var m = lowprimes[i], j = i+1;
+        while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];
+        m = x.modInt(m);
+        while(i < j) if(m%lowprimes[i++] == 0) return false;
+      }
+      return x.millerRabin(t);
+    }
+
+    // (protected) true if probably prime (HAC 4.24, Miller-Rabin)
+    function bnpMillerRabin(t) {
+      var n1 = this.subtract(BigInteger.ONE);
+      var k = n1.getLowestSetBit();
+      if(k <= 0) return false;
+      var r = n1.shiftRight(k);
+      t = (t+1)>>1;
+      if(t > lowprimes.length) t = lowprimes.length;
+      var a = nbi();
+      for(var i = 0; i < t; ++i) {
+        //Pick bases at random, instead of starting at 2
+        a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);
+        var y = a.modPow(r,this);
+        if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
+          var j = 1;
+          while(j++ < k && y.compareTo(n1) != 0) {
+            y = y.modPowInt(2,this);
+            if(y.compareTo(BigInteger.ONE) == 0) return false;
+          }
+          if(y.compareTo(n1) != 0) return false;
+        }
+      }
+      return true;
+    }
+
+    // protected
+    BigInteger.prototype.chunkSize = bnpChunkSize;
+    BigInteger.prototype.toRadix = bnpToRadix;
+    BigInteger.prototype.fromRadix = bnpFromRadix;
+    BigInteger.prototype.fromNumber = bnpFromNumber;
+    BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
+    BigInteger.prototype.changeBit = bnpChangeBit;
+    BigInteger.prototype.addTo = bnpAddTo;
+    BigInteger.prototype.dMultiply = bnpDMultiply;
+    BigInteger.prototype.dAddOffset = bnpDAddOffset;
+    BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
+    BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
+    BigInteger.prototype.modInt = bnpModInt;
+    BigInteger.prototype.millerRabin = bnpMillerRabin;
+
+    // public
+    BigInteger.prototype.clone = bnClone;
+    BigInteger.prototype.intValue = bnIntValue;
+    BigInteger.prototype.byteValue = bnByteValue;
+    BigInteger.prototype.shortValue = bnShortValue;
+    BigInteger.prototype.signum = bnSigNum;
+    BigInteger.prototype.toByteArray = bnToByteArray;
+    BigInteger.prototype.equals = bnEquals;
+    BigInteger.prototype.min = bnMin;
+    BigInteger.prototype.max = bnMax;
+    BigInteger.prototype.and = bnAnd;
+    BigInteger.prototype.or = bnOr;
+    BigInteger.prototype.xor = bnXor;
+    BigInteger.prototype.andNot = bnAndNot;
+    BigInteger.prototype.not = bnNot;
+    BigInteger.prototype.shiftLeft = bnShiftLeft;
+    BigInteger.prototype.shiftRight = bnShiftRight;
+    BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
+    BigInteger.prototype.bitCount = bnBitCount;
+    BigInteger.prototype.testBit = bnTestBit;
+    BigInteger.prototype.setBit = bnSetBit;
+    BigInteger.prototype.clearBit = bnClearBit;
+    BigInteger.prototype.flipBit = bnFlipBit;
+    BigInteger.prototype.add = bnAdd;
+    BigInteger.prototype.subtract = bnSubtract;
+    BigInteger.prototype.multiply = bnMultiply;
+    BigInteger.prototype.divide = bnDivide;
+    BigInteger.prototype.remainder = bnRemainder;
+    BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
+    BigInteger.prototype.modPow = bnModPow;
+    BigInteger.prototype.modInverse = bnModInverse;
+    BigInteger.prototype.pow = bnPow;
+    BigInteger.prototype.gcd = bnGCD;
+    BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
+
+    // JSBN-specific extension
+    BigInteger.prototype.square = bnSquare;
+
+    // Expose the Barrett function
+    BigInteger.prototype.Barrett = Barrett
+
+    // BigInteger interfaces not implemented in jsbn:
+
+    // BigInteger(int signum, byte[] magnitude)
+    // double doubleValue()
+    // float floatValue()
+    // int hashCode()
+    // long longValue()
+    // static BigInteger valueOf(long val)
+
+    // Random number generator - requires a PRNG backend, e.g. prng4.js
+
+    // For best results, put code like
+    // <body onClick='rng_seed_time();' onKeyPress='rng_seed_time();'>
+    // in your main HTML document.
+
+    var rng_state;
+    var rng_pool;
+    var rng_pptr;
+
+    // Mix in a 32-bit integer into the pool
+    function rng_seed_int(x) {
+      rng_pool[rng_pptr++] ^= x & 255;
+      rng_pool[rng_pptr++] ^= (x >> 8) & 255;
+      rng_pool[rng_pptr++] ^= (x >> 16) & 255;
+      rng_pool[rng_pptr++] ^= (x >> 24) & 255;
+      if(rng_pptr >= rng_psize) rng_pptr -= rng_psize;
+    }
+
+    // Mix in the current time (w/milliseconds) into the pool
+    function rng_seed_time() {
+      rng_seed_int(new Date().getTime());
+    }
+
+    // Initialize the pool with junk if needed.
+    if(rng_pool == null) {
+      rng_pool = new Array();
+      rng_pptr = 0;
+      var t;
+      if(typeof window !== "undefined" && window.crypto) {
+        if (window.crypto.getRandomValues) {
+          // Use webcrypto if available
+          var ua = new Uint8Array(32);
+          window.crypto.getRandomValues(ua);
+          for(t = 0; t < 32; ++t)
+            rng_pool[rng_pptr++] = ua[t];
+        }
+        else if(navigator.appName == "Netscape" && navigator.appVersion < "5") {
+          // Extract entropy (256 bits) from NS4 RNG if available
+          var z = window.crypto.random(32);
+          for(t = 0; t < z.length; ++t)
+            rng_pool[rng_pptr++] = z.charCodeAt(t) & 255;
+        }
+      }
+      while(rng_pptr < rng_psize) {  // extract some randomness from Math.random()
+        t = Math.floor(65536 * Math.random());
+        rng_pool[rng_pptr++] = t >>> 8;
+        rng_pool[rng_pptr++] = t & 255;
+      }
+      rng_pptr = 0;
+      rng_seed_time();
+      //rng_seed_int(window.screenX);
+      //rng_seed_int(window.screenY);
+    }
+
+    function rng_get_byte() {
+      if(rng_state == null) {
+        rng_seed_time();
+        rng_state = prng_newstate();
+        rng_state.init(rng_pool);
+        for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr)
+          rng_pool[rng_pptr] = 0;
+        rng_pptr = 0;
+        //rng_pool = null;
+      }
+      // TODO: allow reseeding after first request
+      return rng_state.next();
+    }
+
+    function rng_get_bytes(ba) {
+      var i;
+      for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte();
+    }
+
+    function SecureRandom() {}
+
+    SecureRandom.prototype.nextBytes = rng_get_bytes;
+
+    // prng4.js - uses Arcfour as a PRNG
+
+    function Arcfour() {
+      this.i = 0;
+      this.j = 0;
+      this.S = new Array();
+    }
+
+    // Initialize arcfour context from key, an array of ints, each from [0..255]
+    function ARC4init(key) {
+      var i, j, t;
+      for(i = 0; i < 256; ++i)
+        this.S[i] = i;
+      j = 0;
+      for(i = 0; i < 256; ++i) {
+        j = (j + this.S[i] + key[i % key.length]) & 255;
+        t = this.S[i];
+        this.S[i] = this.S[j];
+        this.S[j] = t;
+      }
+      this.i = 0;
+      this.j = 0;
+    }
+
+    function ARC4next() {
+      var t;
+      this.i = (this.i + 1) & 255;
+      this.j = (this.j + this.S[this.i]) & 255;
+      t = this.S[this.i];
+      this.S[this.i] = this.S[this.j];
+      this.S[this.j] = t;
+      return this.S[(t + this.S[this.i]) & 255];
+    }
+
+    Arcfour.prototype.init = ARC4init;
+    Arcfour.prototype.next = ARC4next;
+
+    // Plug in your RNG constructor here
+    function prng_newstate() {
+      return new Arcfour();
+    }
+
+    // Pool size must be a multiple of 4 and greater than 32.
+    // An array of bytes the size of the pool will be passed to init()
+    var rng_psize = 256;
+
+    if (typeof exports !== 'undefined') {
+        exports = module.exports = {
+            default: BigInteger,
+            BigInteger: BigInteger,
+            SecureRandom: SecureRandom,
+        };
+    } else {
+        this.jsbn = {
+          BigInteger: BigInteger,
+          SecureRandom: SecureRandom
+        };
+    }
+
+}).call(this);
+
+}, function(modId) {var map = {}; return __REQUIRE__(map[modId], modId); })
+return __REQUIRE__(1738722861363);
+})()
+//miniprogram-npm-outsideDeps=[]
+//# sourceMappingURL=index.js.map

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
miniprogram_npm/jsbn/index.js.map


+ 1837 - 0
miniprogram_npm/miniprogram-sm-crypto/index.js

@@ -0,0 +1,1837 @@
+module.exports =
+/******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// define __esModule on exports
+/******/ 	__webpack_require__.r = function(exports) {
+/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 		}
+/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 	};
+/******/
+/******/ 	// create a fake namespace object
+/******/ 	// mode & 1: value is a module id, require it
+/******/ 	// mode & 2: merge all properties of value into the ns
+/******/ 	// mode & 4: return value when already ns object
+/******/ 	// mode & 8|1: behave like require
+/******/ 	__webpack_require__.t = function(value, mode) {
+/******/ 		if(mode & 1) value = __webpack_require__(value);
+/******/ 		if(mode & 8) return value;
+/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ 		var ns = Object.create(null);
+/******/ 		__webpack_require__.r(ns);
+/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ 		return ns;
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+/******/
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = 2);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports) {
+
+module.exports = require("jsbn");
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+// 消息扩展
+var W = new Uint32Array(68);
+var M = new Uint32Array(64); // W'
+
+/**
+ * 循环左移
+ */
+function rotl(x, n) {
+  var s = n & 31;
+  return x << s | x >>> 32 - s;
+}
+
+/**
+ * 二进制异或运算
+ */
+function xor(x, y) {
+  var result = [];
+  for (var i = x.length - 1; i >= 0; i--) {
+    result[i] = (x[i] ^ y[i]) & 0xff;
+  }return result;
+}
+
+/**
+ * 压缩函数中的置换函数 P0(X) = X xor (X <<< 9) xor (X <<< 17)
+ */
+function P0(X) {
+  return X ^ rotl(X, 9) ^ rotl(X, 17);
+}
+
+/**
+ * 消息扩展中的置换函数 P1(X) = X xor (X <<< 15) xor (X <<< 23)
+ */
+function P1(X) {
+  return X ^ rotl(X, 15) ^ rotl(X, 23);
+}
+
+/**
+ * sm3 本体
+ */
+function sm3(array) {
+  var len = array.length * 8;
+
+  // k 是满足 len + 1 + k = 448mod512 的最小的非负整数
+  var k = len % 512;
+  // 如果 448 <= (512 % len) < 512,需要多补充 (len % 448) 比特'0'以满足总比特长度为512的倍数
+  k = k >= 448 ? 512 - k % 448 - 1 : 448 - k - 1;
+
+  // 填充
+  var kArr = new Array((k - 7) / 8);
+  var lenArr = new Array(8);
+  for (var i = 0, _len = kArr.length; i < _len; i++) {
+    kArr[i] = 0;
+  }for (var _i = 0, _len2 = lenArr.length; _i < _len2; _i++) {
+    lenArr[_i] = 0;
+  }len = len.toString(2);
+  for (var _i2 = 7; _i2 >= 0; _i2--) {
+    if (len.length > 8) {
+      var start = len.length - 8;
+      lenArr[_i2] = parseInt(len.substr(start), 2);
+      len = len.substr(0, start);
+    } else if (len.length > 0) {
+      lenArr[_i2] = parseInt(len, 2);
+      len = '';
+    }
+  }
+  var m = new Uint8Array([].concat(array, [0x80], kArr, lenArr));
+  var dataView = new DataView(m.buffer, 0);
+
+  // 迭代压缩
+  var n = m.length / 64;
+  var V = new Uint32Array([0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e]);
+  for (var _i3 = 0; _i3 < n; _i3++) {
+    W.fill(0);
+    M.fill(0);
+
+    // 将消息分组B划分为 16 个字 W0, W1,……,W15
+    var _start = 16 * _i3;
+    for (var j = 0; j < 16; j++) {
+      W[j] = dataView.getUint32((_start + j) * 4, false);
+    }
+
+    // W16 ~ W67:W[j] <- P1(W[j−16] xor W[j−9] xor (W[j−3] <<< 15)) xor (W[j−13] <<< 7) xor W[j−6]
+    for (var _j = 16; _j < 68; _j++) {
+      W[_j] = P1(W[_j - 16] ^ W[_j - 9] ^ rotl(W[_j - 3], 15)) ^ rotl(W[_j - 13], 7) ^ W[_j - 6];
+    }
+
+    // W′0 ~ W′63:W′[j] = W[j] xor W[j+4]
+    for (var _j2 = 0; _j2 < 64; _j2++) {
+      M[_j2] = W[_j2] ^ W[_j2 + 4];
+    }
+
+    // 压缩
+    var T1 = 0x79cc4519;
+    var T2 = 0x7a879d8a;
+    // 字寄存器
+    var A = V[0];
+    var B = V[1];
+    var C = V[2];
+    var D = V[3];
+    var E = V[4];
+    var F = V[5];
+    var G = V[6];
+    var H = V[7];
+    // 中间变量
+    var SS1 = void 0;
+    var SS2 = void 0;
+    var TT1 = void 0;
+    var TT2 = void 0;
+    var T = void 0;
+    for (var _j3 = 0; _j3 < 64; _j3++) {
+      T = _j3 >= 0 && _j3 <= 15 ? T1 : T2;
+      SS1 = rotl(rotl(A, 12) + E + rotl(T, _j3), 7);
+      SS2 = SS1 ^ rotl(A, 12);
+
+      TT1 = (_j3 >= 0 && _j3 <= 15 ? A ^ B ^ C : A & B | A & C | B & C) + D + SS2 + M[_j3];
+      TT2 = (_j3 >= 0 && _j3 <= 15 ? E ^ F ^ G : E & F | ~E & G) + H + SS1 + W[_j3];
+
+      D = C;
+      C = rotl(B, 9);
+      B = A;
+      A = TT1;
+      H = G;
+      G = rotl(F, 19);
+      F = E;
+      E = P0(TT2);
+    }
+
+    V[0] ^= A;
+    V[1] ^= B;
+    V[2] ^= C;
+    V[3] ^= D;
+    V[4] ^= E;
+    V[5] ^= F;
+    V[6] ^= G;
+    V[7] ^= H;
+  }
+
+  // 转回 uint8
+  var result = [];
+  for (var _i4 = 0, _len3 = V.length; _i4 < _len3; _i4++) {
+    var word = V[_i4];
+    result.push((word & 0xff000000) >>> 24, (word & 0xff0000) >>> 16, (word & 0xff00) >>> 8, word & 0xff);
+  }
+
+  return result;
+}
+
+/**
+ * hmac 实现
+ */
+var blockLen = 64;
+var iPad = new Uint8Array(blockLen);
+var oPad = new Uint8Array(blockLen);
+for (var i = 0; i < blockLen; i++) {
+  iPad[i] = 0x36;
+  oPad[i] = 0x5c;
+}
+function hmac(input, key) {
+  // 密钥填充
+  if (key.length > blockLen) key = sm3(key);
+  while (key.length < blockLen) {
+    key.push(0);
+  }var iPadKey = xor(key, iPad);
+  var oPadKey = xor(key, oPad);
+
+  var hash = sm3([].concat(iPadKey, input));
+  return sm3([].concat(oPadKey, hash));
+}
+
+module.exports = {
+  sm3: sm3,
+  hmac: hmac
+};
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+module.exports = {
+  sm2: __webpack_require__(3),
+  sm3: __webpack_require__(7),
+  sm4: __webpack_require__(8)
+};
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+/* eslint-disable no-use-before-define */
+var _require = __webpack_require__(0),
+    BigInteger = _require.BigInteger;
+
+var _require2 = __webpack_require__(4),
+    encodeDer = _require2.encodeDer,
+    decodeDer = _require2.decodeDer;
+
+var _ = __webpack_require__(5);
+var sm3 = __webpack_require__(1).sm3;
+
+var _$generateEcparam = _.generateEcparam(),
+    G = _$generateEcparam.G,
+    curve = _$generateEcparam.curve,
+    n = _$generateEcparam.n;
+
+var C1C2C3 = 0;
+
+/**
+ * 加密
+ */
+function doEncrypt(msg, publicKey) {
+  var cipherMode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
+
+  msg = typeof msg === 'string' ? _.hexToArray(_.utf8ToHex(msg)) : Array.prototype.slice.call(msg);
+  publicKey = _.getGlobalCurve().decodePointHex(publicKey); // 先将公钥转成点
+
+  var keypair = _.generateKeyPairHex();
+  var k = new BigInteger(keypair.privateKey, 16); // 随机数 k
+
+  // c1 = k * G
+  var c1 = keypair.publicKey;
+  if (c1.length > 128) c1 = c1.substr(c1.length - 128);
+
+  // (x2, y2) = k * publicKey
+  var p = publicKey.multiply(k);
+  var x2 = _.hexToArray(_.leftPad(p.getX().toBigInteger().toRadix(16), 64));
+  var y2 = _.hexToArray(_.leftPad(p.getY().toBigInteger().toRadix(16), 64));
+
+  // c3 = hash(x2 || msg || y2)
+  var c3 = _.arrayToHex(sm3([].concat(x2, msg, y2)));
+
+  var ct = 1;
+  var offset = 0;
+  var t = []; // 256 位
+  var z = [].concat(x2, y2);
+  var nextT = function nextT() {
+    // (1) Hai = hash(z || ct)
+    // (2) ct++
+    t = sm3([].concat(z, [ct >> 24 & 0x00ff, ct >> 16 & 0x00ff, ct >> 8 & 0x00ff, ct & 0x00ff]));
+    ct++;
+    offset = 0;
+  };
+  nextT(); // 先生成 Ha1
+
+  for (var i = 0, len = msg.length; i < len; i++) {
+    // t = Ha1 || Ha2 || Ha3 || Ha4
+    if (offset === t.length) nextT();
+
+    // c2 = msg ^ t
+    msg[i] ^= t[offset++] & 0xff;
+  }
+  var c2 = _.arrayToHex(msg);
+
+  return cipherMode === C1C2C3 ? c1 + c2 + c3 : c1 + c3 + c2;
+}
+
+/**
+ * 解密
+ */
+function doDecrypt(encryptData, privateKey) {
+  var cipherMode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
+
+  var _ref = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {},
+      _ref$output = _ref.output,
+      output = _ref$output === undefined ? 'string' : _ref$output;
+
+  privateKey = new BigInteger(privateKey, 16);
+
+  var c3 = encryptData.substr(128, 64);
+  var c2 = encryptData.substr(128 + 64);
+
+  if (cipherMode === C1C2C3) {
+    c3 = encryptData.substr(encryptData.length - 64);
+    c2 = encryptData.substr(128, encryptData.length - 128 - 64);
+  }
+
+  var msg = _.hexToArray(c2);
+  var c1 = _.getGlobalCurve().decodePointHex('04' + encryptData.substr(0, 128));
+
+  var p = c1.multiply(privateKey);
+  var x2 = _.hexToArray(_.leftPad(p.getX().toBigInteger().toRadix(16), 64));
+  var y2 = _.hexToArray(_.leftPad(p.getY().toBigInteger().toRadix(16), 64));
+
+  var ct = 1;
+  var offset = 0;
+  var t = []; // 256 位
+  var z = [].concat(x2, y2);
+  var nextT = function nextT() {
+    // (1) Hai = hash(z || ct)
+    // (2) ct++
+    t = sm3([].concat(z, [ct >> 24 & 0x00ff, ct >> 16 & 0x00ff, ct >> 8 & 0x00ff, ct & 0x00ff]));
+    ct++;
+    offset = 0;
+  };
+  nextT(); // 先生成 Ha1
+
+  for (var i = 0, len = msg.length; i < len; i++) {
+    // t = Ha1 || Ha2 || Ha3 || Ha4
+    if (offset === t.length) nextT();
+
+    // c2 = msg ^ t
+    msg[i] ^= t[offset++] & 0xff;
+  }
+
+  // c3 = hash(x2 || msg || y2)
+  var checkC3 = _.arrayToHex(sm3([].concat(x2, msg, y2)));
+
+  if (checkC3 === c3.toLowerCase()) {
+    return output === 'array' ? msg : _.arrayToUtf8(msg);
+  } else {
+    return output === 'array' ? [] : '';
+  }
+}
+
+/**
+ * 签名
+ */
+function doSignature(msg, privateKey) {
+  var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
+      pointPool = _ref2.pointPool,
+      der = _ref2.der,
+      hash = _ref2.hash,
+      publicKey = _ref2.publicKey,
+      userId = _ref2.userId;
+
+  var hashHex = typeof msg === 'string' ? _.utf8ToHex(msg) : _.arrayToHex(msg);
+
+  if (hash) {
+    // sm3杂凑
+    publicKey = publicKey || getPublicKeyFromPrivateKey(privateKey);
+    hashHex = getHash(hashHex, publicKey, userId);
+  }
+
+  var dA = new BigInteger(privateKey, 16);
+  var e = new BigInteger(hashHex, 16);
+
+  // k
+  var k = null;
+  var r = null;
+  var s = null;
+
+  do {
+    do {
+      var point = void 0;
+      if (pointPool && pointPool.length) {
+        point = pointPool.pop();
+      } else {
+        point = getPoint();
+      }
+      k = point.k;
+
+      // r = (e + x1) mod n
+      r = e.add(point.x1).mod(n);
+    } while (r.equals(BigInteger.ZERO) || r.add(k).equals(n));
+
+    // s = ((1 + dA)^-1 * (k - r * dA)) mod n
+    s = dA.add(BigInteger.ONE).modInverse(n).multiply(k.subtract(r.multiply(dA))).mod(n);
+  } while (s.equals(BigInteger.ZERO));
+
+  if (der) return encodeDer(r, s); // asn.1 der 编码
+
+  return _.leftPad(r.toString(16), 64) + _.leftPad(s.toString(16), 64);
+}
+
+/**
+ * 验签
+ */
+function doVerifySignature(msg, signHex, publicKey) {
+  var _ref3 = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {},
+      der = _ref3.der,
+      hash = _ref3.hash,
+      userId = _ref3.userId;
+
+  var hashHex = typeof msg === 'string' ? _.utf8ToHex(msg) : _.arrayToHex(msg);
+
+  if (hash) {
+    // sm3杂凑
+    hashHex = getHash(hashHex, publicKey, userId);
+  }
+
+  var r = void 0;var s = void 0;
+  if (der) {
+    var decodeDerObj = decodeDer(signHex); // asn.1 der 解码
+    r = decodeDerObj.r;
+    s = decodeDerObj.s;
+  } else {
+    r = new BigInteger(signHex.substring(0, 64), 16);
+    s = new BigInteger(signHex.substring(64), 16);
+  }
+
+  var PA = curve.decodePointHex(publicKey);
+  var e = new BigInteger(hashHex, 16);
+
+  // t = (r + s) mod n
+  var t = r.add(s).mod(n);
+
+  if (t.equals(BigInteger.ZERO)) return false;
+
+  // x1y1 = s * G + t * PA
+  var x1y1 = G.multiply(s).add(PA.multiply(t));
+
+  // R = (e + x1) mod n
+  var R = e.add(x1y1.getX().toBigInteger()).mod(n);
+
+  return r.equals(R);
+}
+
+/**
+ * sm3杂凑算法
+ */
+function getHash(hashHex, publicKey) {
+  var userId = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '1234567812345678';
+
+  // z = hash(entl || userId || a || b || gx || gy || px || py)
+  userId = _.utf8ToHex(userId);
+  var a = _.leftPad(G.curve.a.toBigInteger().toRadix(16), 64);
+  var b = _.leftPad(G.curve.b.toBigInteger().toRadix(16), 64);
+  var gx = _.leftPad(G.getX().toBigInteger().toRadix(16), 64);
+  var gy = _.leftPad(G.getY().toBigInteger().toRadix(16), 64);
+  var px = void 0;
+  var py = void 0;
+  if (publicKey.length === 128) {
+    px = publicKey.substr(0, 64);
+    py = publicKey.substr(64, 64);
+  } else {
+    var point = G.curve.decodePointHex(publicKey);
+    px = _.leftPad(point.getX().toBigInteger().toRadix(16), 64);
+    py = _.leftPad(point.getY().toBigInteger().toRadix(16), 64);
+  }
+  var data = _.hexToArray(userId + a + b + gx + gy + px + py);
+
+  var entl = userId.length * 4;
+  data.unshift(entl & 0x00ff);
+  data.unshift(entl >> 8 & 0x00ff);
+
+  var z = sm3(data);
+
+  // e = hash(z || msg)
+  return _.arrayToHex(sm3(z.concat(_.hexToArray(hashHex))));
+}
+
+/**
+ * 计算公钥
+ */
+function getPublicKeyFromPrivateKey(privateKey) {
+  var PA = G.multiply(new BigInteger(privateKey, 16));
+  var x = _.leftPad(PA.getX().toBigInteger().toString(16), 64);
+  var y = _.leftPad(PA.getY().toBigInteger().toString(16), 64);
+  return '04' + x + y;
+}
+
+/**
+ * 获取椭圆曲线点
+ */
+function getPoint() {
+  var keypair = _.generateKeyPairHex();
+  var PA = curve.decodePointHex(keypair.publicKey);
+
+  keypair.k = new BigInteger(keypair.privateKey, 16);
+  keypair.x1 = PA.getX().toBigInteger();
+
+  return keypair;
+}
+
+module.exports = {
+  generateKeyPairHex: _.generateKeyPairHex,
+  compressPublicKeyHex: _.compressPublicKeyHex,
+  comparePublicKeyHex: _.comparePublicKeyHex,
+  doEncrypt: doEncrypt,
+  doDecrypt: doDecrypt,
+  doSignature: doSignature,
+  doVerifySignature: doVerifySignature,
+  getPublicKeyFromPrivateKey: getPublicKeyFromPrivateKey,
+  getPoint: getPoint,
+  verifyPublicKey: _.verifyPublicKey
+};
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/* eslint-disable class-methods-use-this */
+var _require = __webpack_require__(0),
+    BigInteger = _require.BigInteger;
+
+function bigintToValue(bigint) {
+  var h = bigint.toString(16);
+  if (h[0] !== '-') {
+    // 正数
+    if (h.length % 2 === 1) h = '0' + h; // 补齐到整字节
+    else if (!h.match(/^[0-7]/)) h = '00' + h; // 非0开头,则补一个全0字节
+  } else {
+    // 负数
+    h = h.substr(1);
+
+    var len = h.length;
+    if (len % 2 === 1) len += 1; // 补齐到整字节
+    else if (!h.match(/^[0-7]/)) len += 2; // 非0开头,则补一个全0字节
+
+    var mask = '';
+    for (var i = 0; i < len; i++) {
+      mask += 'f';
+    }mask = new BigInteger(mask, 16);
+
+    // 对绝对值取反,加1
+    h = mask.xor(bigint).add(BigInteger.ONE);
+    h = h.toString(16).replace(/^-/, '');
+  }
+  return h;
+}
+
+var ASN1Object = function () {
+  function ASN1Object() {
+    _classCallCheck(this, ASN1Object);
+
+    this.tlv = null;
+    this.t = '00';
+    this.l = '00';
+    this.v = '';
+  }
+
+  /**
+   * 获取 der 编码比特流16进制串
+   */
+
+
+  ASN1Object.prototype.getEncodedHex = function getEncodedHex() {
+    if (!this.tlv) {
+      this.v = this.getValue();
+      this.l = this.getLength();
+      this.tlv = this.t + this.l + this.v;
+    }
+    return this.tlv;
+  };
+
+  ASN1Object.prototype.getLength = function getLength() {
+    var n = this.v.length / 2; // 字节数
+    var nHex = n.toString(16);
+    if (nHex.length % 2 === 1) nHex = '0' + nHex; // 补齐到整字节
+
+    if (n < 128) {
+      // 短格式,以 0 开头
+      return nHex;
+    } else {
+      // 长格式,以 1 开头
+      var head = 128 + nHex.length / 2; // 1(1位) + 真正的长度占用字节数(7位) + 真正的长度
+      return head.toString(16) + nHex;
+    }
+  };
+
+  ASN1Object.prototype.getValue = function getValue() {
+    return '';
+  };
+
+  return ASN1Object;
+}();
+
+var DERInteger = function (_ASN1Object) {
+  _inherits(DERInteger, _ASN1Object);
+
+  function DERInteger(bigint) {
+    _classCallCheck(this, DERInteger);
+
+    var _this = _possibleConstructorReturn(this, _ASN1Object.call(this));
+
+    _this.t = '02'; // 整型标签说明
+    if (bigint) _this.v = bigintToValue(bigint);
+    return _this;
+  }
+
+  DERInteger.prototype.getValue = function getValue() {
+    return this.v;
+  };
+
+  return DERInteger;
+}(ASN1Object);
+
+var DERSequence = function (_ASN1Object2) {
+  _inherits(DERSequence, _ASN1Object2);
+
+  function DERSequence(asn1Array) {
+    _classCallCheck(this, DERSequence);
+
+    var _this2 = _possibleConstructorReturn(this, _ASN1Object2.call(this));
+
+    _this2.t = '30'; // 序列标签说明
+    _this2.asn1Array = asn1Array;
+    return _this2;
+  }
+
+  DERSequence.prototype.getValue = function getValue() {
+    this.v = this.asn1Array.map(function (asn1Object) {
+      return asn1Object.getEncodedHex();
+    }).join('');
+    return this.v;
+  };
+
+  return DERSequence;
+}(ASN1Object);
+
+/**
+ * 获取 l 占用字节数
+ */
+
+
+function getLenOfL(str, start) {
+  if (+str[start + 2] < 8) return 1; // l 以0开头,则表示短格式,只占一个字节
+  return +str.substr(start + 2, 2) & 0x7f + 1; // 长格式,取第一个字节后7位作为长度真正占用字节数,再加上本身
+}
+
+/**
+ * 获取 l
+ */
+function getL(str, start) {
+  // 获取 l
+  var len = getLenOfL(str, start);
+  var l = str.substr(start + 2, len * 2);
+
+  if (!l) return -1;
+  var bigint = +l[0] < 8 ? new BigInteger(l, 16) : new BigInteger(l.substr(2), 16);
+
+  return bigint.intValue();
+}
+
+/**
+ * 获取 v 的位置
+ */
+function getStartOfV(str, start) {
+  var len = getLenOfL(str, start);
+  return start + (len + 1) * 2;
+}
+
+module.exports = {
+  /**
+   * ASN.1 der 编码,针对 sm2 签名
+   */
+  encodeDer: function encodeDer(r, s) {
+    var derR = new DERInteger(r);
+    var derS = new DERInteger(s);
+    var derSeq = new DERSequence([derR, derS]);
+
+    return derSeq.getEncodedHex();
+  },
+
+
+  /**
+   * 解析 ASN.1 der,针对 sm2 验签
+   */
+  decodeDer: function decodeDer(input) {
+    // 结构:
+    // input = | tSeq | lSeq | vSeq |
+    // vSeq = | tR | lR | vR | tS | lS | vS |
+    var start = getStartOfV(input, 0);
+
+    var vIndexR = getStartOfV(input, start);
+    var lR = getL(input, start);
+    var vR = input.substr(vIndexR, lR * 2);
+
+    var nextStart = vIndexR + vR.length;
+    var vIndexS = getStartOfV(input, nextStart);
+    var lS = getL(input, nextStart);
+    var vS = input.substr(vIndexS, lS * 2);
+
+    var r = new BigInteger(vR, 16);
+    var s = new BigInteger(vS, 16);
+
+    return { r: r, s: s };
+  }
+};
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+/* eslint-disable no-bitwise, no-mixed-operators, no-use-before-define, max-len */
+var _require = __webpack_require__(0),
+    BigInteger = _require.BigInteger,
+    SecureRandom = _require.SecureRandom;
+
+var _require2 = __webpack_require__(6),
+    ECCurveFp = _require2.ECCurveFp;
+
+var rng = new SecureRandom();
+
+var _generateEcparam = generateEcparam(),
+    curve = _generateEcparam.curve,
+    G = _generateEcparam.G,
+    n = _generateEcparam.n;
+
+/**
+ * 获取公共椭圆曲线
+ */
+
+
+function getGlobalCurve() {
+  return curve;
+}
+
+/**
+ * 生成ecparam
+ */
+function generateEcparam() {
+  // 椭圆曲线
+  var p = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16);
+  var a = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16);
+  var b = new BigInteger('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93', 16);
+  var curve = new ECCurveFp(p, a, b);
+
+  // 基点
+  var gxHex = '32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7';
+  var gyHex = 'BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0';
+  var G = curve.decodePointHex('04' + gxHex + gyHex);
+
+  var n = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123', 16);
+
+  return { curve: curve, G: G, n: n };
+}
+
+/**
+ * 生成密钥对:publicKey = privateKey * G
+ */
+function generateKeyPairHex(a, b, c) {
+  var random = a ? new BigInteger(a, b, c) : new BigInteger(n.bitLength(), rng);
+  var d = random.mod(n.subtract(BigInteger.ONE)).add(BigInteger.ONE); // 随机数
+  var privateKey = leftPad(d.toString(16), 64);
+
+  var P = G.multiply(d); // P = dG,p 为公钥,d 为私钥
+  var Px = leftPad(P.getX().toBigInteger().toString(16), 64);
+  var Py = leftPad(P.getY().toBigInteger().toString(16), 64);
+  var publicKey = '04' + Px + Py;
+
+  return { privateKey: privateKey, publicKey: publicKey };
+}
+
+/**
+ * 生成压缩公钥
+ */
+function compressPublicKeyHex(s) {
+  if (s.length !== 130) throw new Error('Invalid public key to compress');
+
+  var len = (s.length - 2) / 2;
+  var xHex = s.substr(2, len);
+  var y = new BigInteger(s.substr(len + 2, len), 16);
+
+  var prefix = '03';
+  if (y.mod(new BigInteger('2')).equals(BigInteger.ZERO)) prefix = '02';
+
+  return prefix + xHex;
+}
+
+/**
+ * utf8串转16进制串
+ */
+function utf8ToHex(input) {
+  input = unescape(encodeURIComponent(input));
+
+  var length = input.length;
+
+  // 转换到字数组
+  var words = [];
+  for (var i = 0; i < length; i++) {
+    words[i >>> 2] |= (input.charCodeAt(i) & 0xff) << 24 - i % 4 * 8;
+  }
+
+  // 转换到16进制
+  var hexChars = [];
+  for (var _i = 0; _i < length; _i++) {
+    var bite = words[_i >>> 2] >>> 24 - _i % 4 * 8 & 0xff;
+    hexChars.push((bite >>> 4).toString(16));
+    hexChars.push((bite & 0x0f).toString(16));
+  }
+
+  return hexChars.join('');
+}
+
+/**
+ * 补全16进制字符串
+ */
+function leftPad(input, num) {
+  if (input.length >= num) return input;
+
+  return new Array(num - input.length + 1).join('0') + input;
+}
+
+/**
+ * 转成16进制串
+ */
+function arrayToHex(arr) {
+  return arr.map(function (item) {
+    item = item.toString(16);
+    return item.length === 1 ? '0' + item : item;
+  }).join('');
+}
+
+/**
+ * 转成utf8串
+ */
+function arrayToUtf8(arr) {
+  var words = [];
+  var j = 0;
+  for (var i = 0; i < arr.length * 2; i += 2) {
+    words[i >>> 3] |= parseInt(arr[j], 10) << 24 - i % 8 * 4;
+    j++;
+  }
+
+  try {
+    var latin1Chars = [];
+
+    for (var _i2 = 0; _i2 < arr.length; _i2++) {
+      var bite = words[_i2 >>> 2] >>> 24 - _i2 % 4 * 8 & 0xff;
+      latin1Chars.push(String.fromCharCode(bite));
+    }
+
+    return decodeURIComponent(escape(latin1Chars.join('')));
+  } catch (e) {
+    throw new Error('Malformed UTF-8 data');
+  }
+}
+
+/**
+ * 转成字节数组
+ */
+function hexToArray(hexStr) {
+  var words = [];
+  var hexStrLength = hexStr.length;
+
+  if (hexStrLength % 2 !== 0) {
+    hexStr = leftPad(hexStr, hexStrLength + 1);
+  }
+
+  hexStrLength = hexStr.length;
+
+  for (var i = 0; i < hexStrLength; i += 2) {
+    words.push(parseInt(hexStr.substr(i, 2), 16));
+  }
+  return words;
+}
+
+/**
+ * 验证公钥是否为椭圆曲线上的点
+ */
+function verifyPublicKey(publicKey) {
+  var point = curve.decodePointHex(publicKey);
+  if (!point) return false;
+
+  var x = point.getX();
+  var y = point.getY();
+
+  // 验证 y^2 是否等于 x^3 + ax + b
+  return y.square().equals(x.multiply(x.square()).add(x.multiply(curve.a)).add(curve.b));
+}
+
+/**
+ * 验证公钥是否等价,等价返回true
+ */
+function comparePublicKeyHex(publicKey1, publicKey2) {
+  var point1 = curve.decodePointHex(publicKey1);
+  if (!point1) return false;
+
+  var point2 = curve.decodePointHex(publicKey2);
+  if (!point2) return false;
+
+  return point1.equals(point2);
+}
+
+module.exports = {
+  getGlobalCurve: getGlobalCurve,
+  generateEcparam: generateEcparam,
+  generateKeyPairHex: generateKeyPairHex,
+  compressPublicKeyHex: compressPublicKeyHex,
+  utf8ToHex: utf8ToHex,
+  leftPad: leftPad,
+  arrayToHex: arrayToHex,
+  arrayToUtf8: arrayToUtf8,
+  hexToArray: hexToArray,
+  verifyPublicKey: verifyPublicKey,
+  comparePublicKeyHex: comparePublicKeyHex
+};
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/* eslint-disable no-case-declarations, max-len */
+var _require = __webpack_require__(0),
+    BigInteger = _require.BigInteger;
+
+/**
+ * thanks for Tom Wu : http://www-cs-students.stanford.edu/~tjw/jsbn/
+ *
+ * Basic Javascript Elliptic Curve implementation
+ * Ported loosely from BouncyCastle's Java EC code
+ * Only Fp curves implemented for now
+ */
+
+var TWO = new BigInteger('2');
+var THREE = new BigInteger('3');
+
+/**
+ * 椭圆曲线域元素
+ */
+
+var ECFieldElementFp = function () {
+  function ECFieldElementFp(q, x) {
+    _classCallCheck(this, ECFieldElementFp);
+
+    this.x = x;
+    this.q = q;
+    // TODO if (x.compareTo(q) >= 0) error
+  }
+
+  /**
+   * 判断相等
+   */
+
+
+  ECFieldElementFp.prototype.equals = function equals(other) {
+    if (other === this) return true;
+    return this.q.equals(other.q) && this.x.equals(other.x);
+  };
+
+  /**
+   * 返回具体数值
+   */
+
+
+  ECFieldElementFp.prototype.toBigInteger = function toBigInteger() {
+    return this.x;
+  };
+
+  /**
+   * 取反
+   */
+
+
+  ECFieldElementFp.prototype.negate = function negate() {
+    return new ECFieldElementFp(this.q, this.x.negate().mod(this.q));
+  };
+
+  /**
+   * 相加
+   */
+
+
+  ECFieldElementFp.prototype.add = function add(b) {
+    return new ECFieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q));
+  };
+
+  /**
+   * 相减
+   */
+
+
+  ECFieldElementFp.prototype.subtract = function subtract(b) {
+    return new ECFieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q));
+  };
+
+  /**
+   * 相乘
+   */
+
+
+  ECFieldElementFp.prototype.multiply = function multiply(b) {
+    return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q));
+  };
+
+  /**
+   * 相除
+   */
+
+
+  ECFieldElementFp.prototype.divide = function divide(b) {
+    return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger().modInverse(this.q)).mod(this.q));
+  };
+
+  /**
+   * 平方
+   */
+
+
+  ECFieldElementFp.prototype.square = function square() {
+    return new ECFieldElementFp(this.q, this.x.square().mod(this.q));
+  };
+
+  return ECFieldElementFp;
+}();
+
+var ECPointFp = function () {
+  function ECPointFp(curve, x, y, z) {
+    _classCallCheck(this, ECPointFp);
+
+    this.curve = curve;
+    this.x = x;
+    this.y = y;
+    // 标准射影坐标系:zinv == null 或 z * zinv == 1
+    this.z = z == null ? BigInteger.ONE : z;
+    this.zinv = null;
+    // TODO: compression flag
+  }
+
+  ECPointFp.prototype.getX = function getX() {
+    if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q);
+
+    return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q));
+  };
+
+  ECPointFp.prototype.getY = function getY() {
+    if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q);
+
+    return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q));
+  };
+
+  /**
+   * 判断相等
+   */
+
+
+  ECPointFp.prototype.equals = function equals(other) {
+    if (other === this) return true;
+    if (this.isInfinity()) return other.isInfinity();
+    if (other.isInfinity()) return this.isInfinity();
+
+    // u = y2 * z1 - y1 * z2
+    var u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q);
+    if (!u.equals(BigInteger.ZERO)) return false;
+
+    // v = x2 * z1 - x1 * z2
+    var v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q);
+    return v.equals(BigInteger.ZERO);
+  };
+
+  /**
+   * 是否是无穷远点
+   */
+
+
+  ECPointFp.prototype.isInfinity = function isInfinity() {
+    if (this.x === null && this.y === null) return true;
+    return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO);
+  };
+
+  /**
+   * 取反,x 轴对称点
+   */
+
+
+  ECPointFp.prototype.negate = function negate() {
+    return new ECPointFp(this.curve, this.x, this.y.negate(), this.z);
+  };
+
+  /**
+   * 相加
+   *
+   * 标准射影坐标系:
+   *
+   * λ1 = x1 * z2
+   * λ2 = x2 * z1
+   * λ3 = λ1 − λ2
+   * λ4 = y1 * z2
+   * λ5 = y2 * z1
+   * λ6 = λ4 − λ5
+   * λ7 = λ1 + λ2
+   * λ8 = z1 * z2
+   * λ9 = λ3^2
+   * λ10 = λ3 * λ9
+   * λ11 = λ8 * λ6^2 − λ7 * λ9
+   * x3 = λ3 * λ11
+   * y3 = λ6 * (λ9 * λ1 − λ11) − λ4 * λ10
+   * z3 = λ10 * λ8
+   */
+
+
+  ECPointFp.prototype.add = function add(b) {
+    if (this.isInfinity()) return b;
+    if (b.isInfinity()) return this;
+
+    var x1 = this.x.toBigInteger();
+    var y1 = this.y.toBigInteger();
+    var z1 = this.z;
+    var x2 = b.x.toBigInteger();
+    var y2 = b.y.toBigInteger();
+    var z2 = b.z;
+    var q = this.curve.q;
+
+    var w1 = x1.multiply(z2).mod(q);
+    var w2 = x2.multiply(z1).mod(q);
+    var w3 = w1.subtract(w2);
+    var w4 = y1.multiply(z2).mod(q);
+    var w5 = y2.multiply(z1).mod(q);
+    var w6 = w4.subtract(w5);
+
+    if (BigInteger.ZERO.equals(w3)) {
+      if (BigInteger.ZERO.equals(w6)) {
+        return this.twice(); // this == b,计算自加
+      }
+      return this.curve.infinity; // this == -b,则返回无穷远点
+    }
+
+    var w7 = w1.add(w2);
+    var w8 = z1.multiply(z2).mod(q);
+    var w9 = w3.square().mod(q);
+    var w10 = w3.multiply(w9).mod(q);
+    var w11 = w8.multiply(w6.square()).subtract(w7.multiply(w9)).mod(q);
+
+    var x3 = w3.multiply(w11).mod(q);
+    var y3 = w6.multiply(w9.multiply(w1).subtract(w11)).subtract(w4.multiply(w10)).mod(q);
+    var z3 = w10.multiply(w8).mod(q);
+
+    return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3);
+  };
+
+  /**
+   * 自加
+   *
+   * 标准射影坐标系:
+   *
+   * λ1 = 3 * x1^2 + a * z1^2
+   * λ2 = 2 * y1 * z1
+   * λ3 = y1^2
+   * λ4 = λ3 * x1 * z1
+   * λ5 = λ2^2
+   * λ6 = λ1^2 − 8 * λ4
+   * x3 = λ2 * λ6
+   * y3 = λ1 * (4 * λ4 − λ6) − 2 * λ5 * λ3
+   * z3 = λ2 * λ5
+   */
+
+
+  ECPointFp.prototype.twice = function twice() {
+    if (this.isInfinity()) return this;
+    if (!this.y.toBigInteger().signum()) return this.curve.infinity;
+
+    var x1 = this.x.toBigInteger();
+    var y1 = this.y.toBigInteger();
+    var z1 = this.z;
+    var q = this.curve.q;
+    var a = this.curve.a.toBigInteger();
+
+    var w1 = x1.square().multiply(THREE).add(a.multiply(z1.square())).mod(q);
+    var w2 = y1.shiftLeft(1).multiply(z1).mod(q);
+    var w3 = y1.square().mod(q);
+    var w4 = w3.multiply(x1).multiply(z1).mod(q);
+    var w5 = w2.square().mod(q);
+    var w6 = w1.square().subtract(w4.shiftLeft(3)).mod(q);
+
+    var x3 = w2.multiply(w6).mod(q);
+    var y3 = w1.multiply(w4.shiftLeft(2).subtract(w6)).subtract(w5.shiftLeft(1).multiply(w3)).mod(q);
+    var z3 = w2.multiply(w5).mod(q);
+
+    return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3);
+  };
+
+  /**
+   * 倍点计算
+   */
+
+
+  ECPointFp.prototype.multiply = function multiply(k) {
+    if (this.isInfinity()) return this;
+    if (!k.signum()) return this.curve.infinity;
+
+    // 使用加减法
+    var k3 = k.multiply(THREE);
+    var neg = this.negate();
+    var Q = this;
+
+    for (var i = k3.bitLength() - 2; i > 0; i--) {
+      Q = Q.twice();
+
+      var k3Bit = k3.testBit(i);
+      var kBit = k.testBit(i);
+
+      if (k3Bit !== kBit) {
+        Q = Q.add(k3Bit ? this : neg);
+      }
+    }
+
+    return Q;
+  };
+
+  return ECPointFp;
+}();
+
+/**
+ * 椭圆曲线 y^2 = x^3 + ax + b
+ */
+
+
+var ECCurveFp = function () {
+  function ECCurveFp(q, a, b) {
+    _classCallCheck(this, ECCurveFp);
+
+    this.q = q;
+    this.a = this.fromBigInteger(a);
+    this.b = this.fromBigInteger(b);
+    this.infinity = new ECPointFp(this, null, null); // 无穷远点
+  }
+
+  /**
+   * 判断两个椭圆曲线是否相等
+   */
+
+
+  ECCurveFp.prototype.equals = function equals(other) {
+    if (other === this) return true;
+    return this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b);
+  };
+
+  /**
+   * 生成椭圆曲线域元素
+   */
+
+
+  ECCurveFp.prototype.fromBigInteger = function fromBigInteger(x) {
+    return new ECFieldElementFp(this.q, x);
+  };
+
+  /**
+   * 解析 16 进制串为椭圆曲线点
+   */
+
+
+  ECCurveFp.prototype.decodePointHex = function decodePointHex(s) {
+    switch (parseInt(s.substr(0, 2), 16)) {
+      // 第一个字节
+      case 0:
+        return this.infinity;
+      case 2:
+      case 3:
+        // 压缩
+        var x = this.fromBigInteger(new BigInteger(s.substr(2), 16));
+        // 对 p ≡ 3 (mod4),即存在正整数 u,使得 p = 4u + 3
+        // 计算 y = (√ (x^3 + ax + b) % p)^(u + 1) modp
+        var y = this.fromBigInteger(x.multiply(x.square()).add(x.multiply(this.a)).add(this.b).toBigInteger().modPow(this.q.divide(new BigInteger('4')).add(BigInteger.ONE), this.q));
+        // 算出结果 2 进制最后 1 位不等于第 1 个字节减 2 则取反
+        if (!y.toBigInteger().mod(TWO).equals(new BigInteger(s.substr(0, 2), 16).subtract(TWO))) {
+          y = y.negate();
+        }
+        return new ECPointFp(this, x, y);
+      case 4:
+      case 6:
+      case 7:
+        var len = (s.length - 2) / 2;
+        var xHex = s.substr(2, len);
+        var yHex = s.substr(len + 2, len);
+
+        return new ECPointFp(this, this.fromBigInteger(new BigInteger(xHex, 16)), this.fromBigInteger(new BigInteger(yHex, 16)));
+      default:
+        // 不支持
+        return null;
+    }
+  };
+
+  return ECCurveFp;
+}();
+
+module.exports = {
+  ECPointFp: ECPointFp,
+  ECCurveFp: ECCurveFp
+};
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var _require = __webpack_require__(1),
+    sm3 = _require.sm3,
+    hmac = _require.hmac;
+
+/**
+ * 补全16进制字符串
+ */
+
+
+function leftPad(input, num) {
+  if (input.length >= num) return input;
+
+  return new Array(num - input.length + 1).join('0') + input;
+}
+
+/**
+ * 字节数组转 16 进制串
+ */
+function ArrayToHex(arr) {
+  return arr.map(function (item) {
+    item = item.toString(16);
+    return item.length === 1 ? '0' + item : item;
+  }).join('');
+}
+
+/**
+ * 转成字节数组
+ */
+function hexToArray(hexStr) {
+  var words = [];
+  var hexStrLength = hexStr.length;
+
+  if (hexStrLength % 2 !== 0) {
+    hexStr = leftPad(hexStr, hexStrLength + 1);
+  }
+
+  hexStrLength = hexStr.length;
+
+  for (var i = 0; i < hexStrLength; i += 2) {
+    words.push(parseInt(hexStr.substr(i, 2), 16));
+  }
+  return words;
+}
+
+/**
+ * utf8 串转字节数组
+ */
+function utf8ToArray(str) {
+  var arr = [];
+
+  for (var i = 0, len = str.length; i < len; i++) {
+    var point = str.codePointAt(i);
+
+    if (point <= 0x007f) {
+      // 单字节,标量值:00000000 00000000 0zzzzzzz
+      arr.push(point);
+    } else if (point <= 0x07ff) {
+      // 双字节,标量值:00000000 00000yyy yyzzzzzz
+      arr.push(0xc0 | point >>> 6); // 110yyyyy(0xc0-0xdf)
+      arr.push(0x80 | point & 0x3f); // 10zzzzzz(0x80-0xbf)
+    } else if (point <= 0xD7FF || point >= 0xE000 && point <= 0xFFFF) {
+      // 三字节:标量值:00000000 xxxxyyyy yyzzzzzz
+      arr.push(0xe0 | point >>> 12); // 1110xxxx(0xe0-0xef)
+      arr.push(0x80 | point >>> 6 & 0x3f); // 10yyyyyy(0x80-0xbf)
+      arr.push(0x80 | point & 0x3f); // 10zzzzzz(0x80-0xbf)
+    } else if (point >= 0x010000 && point <= 0x10FFFF) {
+      // 四字节:标量值:000wwwxx xxxxyyyy yyzzzzzz
+      i++;
+      arr.push(0xf0 | point >>> 18 & 0x1c); // 11110www(0xf0-0xf7)
+      arr.push(0x80 | point >>> 12 & 0x3f); // 10xxxxxx(0x80-0xbf)
+      arr.push(0x80 | point >>> 6 & 0x3f); // 10yyyyyy(0x80-0xbf)
+      arr.push(0x80 | point & 0x3f); // 10zzzzzz(0x80-0xbf)
+    } else {
+      // 五、六字节,暂时不支持
+      arr.push(point);
+      throw new Error('input is not supported');
+    }
+  }
+
+  return arr;
+}
+
+module.exports = function (input, options) {
+  input = typeof input === 'string' ? utf8ToArray(input) : Array.prototype.slice.call(input);
+
+  if (options) {
+    var mode = options.mode || 'hmac';
+    if (mode !== 'hmac') throw new Error('invalid mode');
+
+    var key = options.key;
+    if (!key) throw new Error('invalid key');
+
+    key = typeof key === 'string' ? hexToArray(key) : Array.prototype.slice.call(key);
+    return ArrayToHex(hmac(input, key));
+  }
+
+  return ArrayToHex(sm3(input));
+};
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+/* eslint-disable no-bitwise, no-mixed-operators, complexity */
+var DECRYPT = 0;
+var ROUND = 32;
+var BLOCK = 16;
+
+var Sbox = [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 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];
+
+/**
+ * 16 进制串转字节数组
+ */
+function hexToArray(str) {
+  var arr = [];
+  for (var i = 0, len = str.length; i < len; i += 2) {
+    arr.push(parseInt(str.substr(i, 2), 16));
+  }
+  return arr;
+}
+
+/**
+ * 字节数组转 16 进制串
+ */
+function ArrayToHex(arr) {
+  return arr.map(function (item) {
+    item = item.toString(16);
+    return item.length === 1 ? '0' + item : item;
+  }).join('');
+}
+
+/**
+ * utf8 串转字节数组
+ */
+function utf8ToArray(str) {
+  var arr = [];
+
+  for (var i = 0, len = str.length; i < len; i++) {
+    var point = str.codePointAt(i);
+
+    if (point <= 0x007f) {
+      // 单字节,标量值:00000000 00000000 0zzzzzzz
+      arr.push(point);
+    } else if (point <= 0x07ff) {
+      // 双字节,标量值:00000000 00000yyy yyzzzzzz
+      arr.push(0xc0 | point >>> 6); // 110yyyyy(0xc0-0xdf)
+      arr.push(0x80 | point & 0x3f); // 10zzzzzz(0x80-0xbf)
+    } else if (point <= 0xD7FF || point >= 0xE000 && point <= 0xFFFF) {
+      // 三字节:标量值:00000000 xxxxyyyy yyzzzzzz
+      arr.push(0xe0 | point >>> 12); // 1110xxxx(0xe0-0xef)
+      arr.push(0x80 | point >>> 6 & 0x3f); // 10yyyyyy(0x80-0xbf)
+      arr.push(0x80 | point & 0x3f); // 10zzzzzz(0x80-0xbf)
+    } else if (point >= 0x010000 && point <= 0x10FFFF) {
+      // 四字节:标量值:000wwwxx xxxxyyyy yyzzzzzz
+      i++;
+      arr.push(0xf0 | point >>> 18 & 0x1c); // 11110www(0xf0-0xf7)
+      arr.push(0x80 | point >>> 12 & 0x3f); // 10xxxxxx(0x80-0xbf)
+      arr.push(0x80 | point >>> 6 & 0x3f); // 10yyyyyy(0x80-0xbf)
+      arr.push(0x80 | point & 0x3f); // 10zzzzzz(0x80-0xbf)
+    } else {
+      // 五、六字节,暂时不支持
+      arr.push(point);
+      throw new Error('input is not supported');
+    }
+  }
+
+  return arr;
+}
+
+/**
+ * 字节数组转 utf8 串
+ */
+function arrayToUtf8(arr) {
+  var str = [];
+  for (var i = 0, len = arr.length; i < len; i++) {
+    if (arr[i] >= 0xf0 && arr[i] <= 0xf7) {
+      // 四字节
+      str.push(String.fromCodePoint(((arr[i] & 0x07) << 18) + ((arr[i + 1] & 0x3f) << 12) + ((arr[i + 2] & 0x3f) << 6) + (arr[i + 3] & 0x3f)));
+      i += 3;
+    } else if (arr[i] >= 0xe0 && arr[i] <= 0xef) {
+      // 三字节
+      str.push(String.fromCodePoint(((arr[i] & 0x0f) << 12) + ((arr[i + 1] & 0x3f) << 6) + (arr[i + 2] & 0x3f)));
+      i += 2;
+    } else if (arr[i] >= 0xc0 && arr[i] <= 0xdf) {
+      // 双字节
+      str.push(String.fromCodePoint(((arr[i] & 0x1f) << 6) + (arr[i + 1] & 0x3f)));
+      i++;
+    } else {
+      // 单字节
+      str.push(String.fromCodePoint(arr[i]));
+    }
+  }
+
+  return str.join('');
+}
+
+/**
+ * 32 比特循环左移
+ */
+function rotl(x, n) {
+  var s = n & 31;
+  return x << s | x >>> 32 - s;
+}
+
+/**
+ * 非线性变换
+ */
+function byteSub(a) {
+  return (Sbox[a >>> 24 & 0xFF] & 0xFF) << 24 | (Sbox[a >>> 16 & 0xFF] & 0xFF) << 16 | (Sbox[a >>> 8 & 0xFF] & 0xFF) << 8 | Sbox[a & 0xFF] & 0xFF;
+}
+
+/**
+ * 线性变换,加密/解密用
+ */
+function l1(b) {
+  return b ^ rotl(b, 2) ^ rotl(b, 10) ^ rotl(b, 18) ^ rotl(b, 24);
+}
+
+/**
+ * 线性变换,生成轮密钥用
+ */
+function l2(b) {
+  return b ^ rotl(b, 13) ^ rotl(b, 23);
+}
+
+/**
+ * 以一组 128 比特进行加密/解密操作
+ */
+function sms4Crypt(input, output, roundKey) {
+  var x = new Array(4);
+
+  // 字节数组转成字数组(此处 1 字 = 32 比特)
+  var tmp = new Array(4);
+  for (var i = 0; i < 4; i++) {
+    tmp[0] = input[4 * i] & 0xff;
+    tmp[1] = input[4 * i + 1] & 0xff;
+    tmp[2] = input[4 * i + 2] & 0xff;
+    tmp[3] = input[4 * i + 3] & 0xff;
+    x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
+  }
+
+  // x[i + 4] = x[i] ^ l1(byteSub(x[i + 1] ^ x[i + 2] ^ x[i + 3] ^ roundKey[i]))
+  for (var r = 0, mid; r < 32; r += 4) {
+    mid = x[1] ^ x[2] ^ x[3] ^ roundKey[r + 0];
+    x[0] ^= l1(byteSub(mid)); // x[4]
+
+    mid = x[2] ^ x[3] ^ x[0] ^ roundKey[r + 1];
+    x[1] ^= l1(byteSub(mid)); // x[5]
+
+    mid = x[3] ^ x[0] ^ x[1] ^ roundKey[r + 2];
+    x[2] ^= l1(byteSub(mid)); // x[6]
+
+    mid = x[0] ^ x[1] ^ x[2] ^ roundKey[r + 3];
+    x[3] ^= l1(byteSub(mid)); // x[7]
+  }
+
+  // 反序变换
+  for (var j = 0; j < 16; j += 4) {
+    output[j] = x[3 - j / 4] >>> 24 & 0xff;
+    output[j + 1] = x[3 - j / 4] >>> 16 & 0xff;
+    output[j + 2] = x[3 - j / 4] >>> 8 & 0xff;
+    output[j + 3] = x[3 - j / 4] & 0xff;
+  }
+}
+
+/**
+ * 密钥扩展算法
+ */
+function sms4KeyExt(key, roundKey, cryptFlag) {
+  var x = new Array(4);
+
+  // 字节数组转成字数组(此处 1 字 = 32 比特)
+  var tmp = new Array(4);
+  for (var i = 0; i < 4; i++) {
+    tmp[0] = key[0 + 4 * i] & 0xff;
+    tmp[1] = key[1 + 4 * i] & 0xff;
+    tmp[2] = key[2 + 4 * i] & 0xff;
+    tmp[3] = key[3 + 4 * i] & 0xff;
+    x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
+  }
+
+  // 与系统参数做异或
+  x[0] ^= 0xa3b1bac6;
+  x[1] ^= 0x56aa3350;
+  x[2] ^= 0x677d9197;
+  x[3] ^= 0xb27022dc;
+
+  // roundKey[i] = x[i + 4] = x[i] ^ l2(byteSub(x[i + 1] ^ x[i + 2] ^ x[i + 3] ^ CK[i]))
+  for (var r = 0, mid; r < 32; r += 4) {
+    mid = x[1] ^ x[2] ^ x[3] ^ CK[r + 0];
+    roundKey[r + 0] = x[0] ^= l2(byteSub(mid)); // x[4]
+
+    mid = x[2] ^ x[3] ^ x[0] ^ CK[r + 1];
+    roundKey[r + 1] = x[1] ^= l2(byteSub(mid)); // x[5]
+
+    mid = x[3] ^ x[0] ^ x[1] ^ CK[r + 2];
+    roundKey[r + 2] = x[2] ^= l2(byteSub(mid)); // x[6]
+
+    mid = x[0] ^ x[1] ^ x[2] ^ CK[r + 3];
+    roundKey[r + 3] = x[3] ^= l2(byteSub(mid)); // x[7]
+  }
+
+  // 解密时使用反序的轮密钥
+  if (cryptFlag === DECRYPT) {
+    for (var _r = 0, _mid; _r < 16; _r++) {
+      _mid = roundKey[_r];
+      roundKey[_r] = roundKey[31 - _r];
+      roundKey[31 - _r] = _mid;
+    }
+  }
+}
+
+function sm4(inArray, key, cryptFlag) {
+  var _ref = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {},
+      _ref$padding = _ref.padding,
+      padding = _ref$padding === undefined ? 'pkcs#7' : _ref$padding,
+      mode = _ref.mode,
+      _ref$iv = _ref.iv,
+      iv = _ref$iv === undefined ? [] : _ref$iv,
+      _ref$output = _ref.output,
+      output = _ref$output === undefined ? 'string' : _ref$output;
+
+  if (mode === 'cbc') {
+    // CBC 模式,默认走 ECB 模式
+    if (typeof iv === 'string') iv = hexToArray(iv);
+    if (iv.length !== 128 / 8) {
+      // iv 不是 128 比特
+      throw new Error('iv is invalid');
+    }
+  }
+
+  // 检查 key
+  if (typeof key === 'string') key = hexToArray(key);
+  if (key.length !== 128 / 8) {
+    // key 不是 128 比特
+    throw new Error('key is invalid');
+  }
+
+  // 检查输入
+  if (typeof inArray === 'string') {
+    if (cryptFlag !== DECRYPT) {
+      // 加密,输入为 utf8 串
+      inArray = utf8ToArray(inArray);
+    } else {
+      // 解密,输入为 16 进制串
+      inArray = hexToArray(inArray);
+    }
+  } else {
+    inArray = [].concat(inArray);
+  }
+
+  // 新增填充,sm4 是 16 个字节一个分组,所以统一走到 pkcs#7
+  if ((padding === 'pkcs#5' || padding === 'pkcs#7') && cryptFlag !== DECRYPT) {
+    var paddingCount = BLOCK - inArray.length % BLOCK;
+    for (var i = 0; i < paddingCount; i++) {
+      inArray.push(paddingCount);
+    }
+  }
+
+  // 生成轮密钥
+  var roundKey = new Array(ROUND);
+  sms4KeyExt(key, roundKey, cryptFlag);
+
+  var outArray = [];
+  var lastVector = iv;
+  var restLen = inArray.length;
+  var point = 0;
+  while (restLen >= BLOCK) {
+    var input = inArray.slice(point, point + 16);
+    var _output = new Array(16);
+
+    if (mode === 'cbc') {
+      for (var _i = 0; _i < BLOCK; _i++) {
+        if (cryptFlag !== DECRYPT) {
+          // 加密过程在组加密前进行异或
+          input[_i] ^= lastVector[_i];
+        }
+      }
+    }
+
+    sms4Crypt(input, _output, roundKey);
+
+    for (var _i2 = 0; _i2 < BLOCK; _i2++) {
+      if (mode === 'cbc') {
+        if (cryptFlag === DECRYPT) {
+          // 解密过程在组解密后进行异或
+          _output[_i2] ^= lastVector[_i2];
+        }
+      }
+
+      outArray[point + _i2] = _output[_i2];
+    }
+
+    if (mode === 'cbc') {
+      if (cryptFlag !== DECRYPT) {
+        // 使用上一次输出作为加密向量
+        lastVector = _output;
+      } else {
+        // 使用上一次输入作为解密向量
+        lastVector = input;
+      }
+    }
+
+    restLen -= BLOCK;
+    point += BLOCK;
+  }
+
+  // 去除填充,sm4 是 16 个字节一个分组,所以统一走到 pkcs#7
+  if ((padding === 'pkcs#5' || padding === 'pkcs#7') && cryptFlag === DECRYPT) {
+    var len = outArray.length;
+    var _paddingCount = outArray[len - 1];
+    for (var _i3 = 1; _i3 <= _paddingCount; _i3++) {
+      if (outArray[len - _i3] !== _paddingCount) throw new Error('padding is invalid');
+    }
+    outArray.splice(len - _paddingCount, _paddingCount);
+  }
+
+  // 调整输出
+  if (output !== 'array') {
+    if (cryptFlag !== DECRYPT) {
+      // 加密,输出转 16 进制串
+      return ArrayToHex(outArray);
+    } else {
+      // 解密,输出转 utf8 串
+      return arrayToUtf8(outArray);
+    }
+  } else {
+    return outArray;
+  }
+}
+
+module.exports = {
+  encrypt: function encrypt(inArray, key, options) {
+    return sm4(inArray, key, 1, options);
+  },
+  decrypt: function decrypt(inArray, key, options) {
+    return sm4(inArray, key, 0, options);
+  }
+};
+
+/***/ })
+/******/ ]);

+ 1610 - 0
miniprogram_npm/sm-crypto/index.js

@@ -0,0 +1,1610 @@
+module.exports = (function() {
+var __MODS__ = {};
+var __DEFINE__ = function(modId, func, req) { var m = { exports: {}, _tempexports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; };
+var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = __MODS__[modId].m; m._exports = m._tempexports; var desp = Object.getOwnPropertyDescriptor(m, "exports"); if (desp && desp.configurable) Object.defineProperty(m, "exports", { set: function (val) { if(typeof val === "object" && val !== m._exports) { m._exports.__proto__ = val.__proto__; Object.keys(val).forEach(function (k) { m._exports[k] = val[k]; }); } m._tempexports = val }, get: function () { return m._tempexports; } }); __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); } return __MODS__[modId].m.exports; };
+var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } };
+var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; };
+__DEFINE__(1738722861364, function(require, module, exports) {
+module.exports = {
+  sm2: require('./sm2/index'),
+  sm3: require('./sm3/index'),
+  sm4: require('./sm4/index'),
+}
+
+}, function(modId) {var map = {"./sm2/index":1738722861365,"./sm3/index":1738722861370,"./sm4/index":1738722861371}; return __REQUIRE__(map[modId], modId); })
+__DEFINE__(1738722861365, function(require, module, exports) {
+/* eslint-disable no-use-before-define */
+const {BigInteger} = require('jsbn')
+const {encodeDer, decodeDer} = require('./asn1')
+const _ = require('./utils')
+const sm3 = require('./sm3').sm3
+
+const {G, curve, n} = _.generateEcparam()
+const C1C2C3 = 0
+
+/**
+ * 加密
+ */
+function doEncrypt(msg, publicKey, cipherMode = 1) {
+  msg = typeof msg === 'string' ? _.hexToArray(_.utf8ToHex(msg)) : Array.prototype.slice.call(msg)
+  publicKey = _.getGlobalCurve().decodePointHex(publicKey) // 先将公钥转成点
+
+  const keypair = _.generateKeyPairHex()
+  const k = new BigInteger(keypair.privateKey, 16) // 随机数 k
+
+  // c1 = k * G
+  let c1 = keypair.publicKey
+  if (c1.length > 128) c1 = c1.substr(c1.length - 128)
+
+  // (x2, y2) = k * publicKey
+  const p = publicKey.multiply(k)
+  const x2 = _.hexToArray(_.leftPad(p.getX().toBigInteger().toRadix(16), 64))
+  const y2 = _.hexToArray(_.leftPad(p.getY().toBigInteger().toRadix(16), 64))
+
+  // c3 = hash(x2 || msg || y2)
+  const c3 = _.arrayToHex(sm3([].concat(x2, msg, y2)))
+
+  let ct = 1
+  let offset = 0
+  let t = [] // 256 位
+  const z = [].concat(x2, y2)
+  const nextT = () => {
+    // (1) Hai = hash(z || ct)
+    // (2) ct++
+    t = sm3([...z, ct >> 24 & 0x00ff, ct >> 16 & 0x00ff, ct >> 8 & 0x00ff, ct & 0x00ff])
+    ct++
+    offset = 0
+  }
+  nextT() // 先生成 Ha1
+
+  for (let i = 0, len = msg.length; i < len; i++) {
+    // t = Ha1 || Ha2 || Ha3 || Ha4
+    if (offset === t.length) nextT()
+
+    // c2 = msg ^ t
+    msg[i] ^= t[offset++] & 0xff
+  }
+  const c2 = _.arrayToHex(msg)
+
+  return cipherMode === C1C2C3 ? c1 + c2 + c3 : c1 + c3 + c2
+}
+
+/**
+ * 解密
+ */
+function doDecrypt(encryptData, privateKey, cipherMode = 1, {
+  output = 'string',
+} = {}) {
+  privateKey = new BigInteger(privateKey, 16)
+
+  let c3 = encryptData.substr(128, 64)
+  let c2 = encryptData.substr(128 + 64)
+
+  if (cipherMode === C1C2C3) {
+    c3 = encryptData.substr(encryptData.length - 64)
+    c2 = encryptData.substr(128, encryptData.length - 128 - 64)
+  }
+
+  const msg = _.hexToArray(c2)
+  const c1 = _.getGlobalCurve().decodePointHex('04' + encryptData.substr(0, 128))
+
+  const p = c1.multiply(privateKey)
+  const x2 = _.hexToArray(_.leftPad(p.getX().toBigInteger().toRadix(16), 64))
+  const y2 = _.hexToArray(_.leftPad(p.getY().toBigInteger().toRadix(16), 64))
+
+  let ct = 1
+  let offset = 0
+  let t = [] // 256 位
+  const z = [].concat(x2, y2)
+  const nextT = () => {
+    // (1) Hai = hash(z || ct)
+    // (2) ct++
+    t = sm3([...z, ct >> 24 & 0x00ff, ct >> 16 & 0x00ff, ct >> 8 & 0x00ff, ct & 0x00ff])
+    ct++
+    offset = 0
+  }
+  nextT() // 先生成 Ha1
+
+  for (let i = 0, len = msg.length; i < len; i++) {
+    // t = Ha1 || Ha2 || Ha3 || Ha4
+    if (offset === t.length) nextT()
+
+    // c2 = msg ^ t
+    msg[i] ^= t[offset++] & 0xff
+  }
+
+  // c3 = hash(x2 || msg || y2)
+  const checkC3 = _.arrayToHex(sm3([].concat(x2, msg, y2)))
+
+  if (checkC3 === c3.toLowerCase()) {
+    return output === 'array' ? msg : _.arrayToUtf8(msg)
+  } else {
+    return output === 'array' ? [] : ''
+  }
+}
+
+/**
+ * 签名
+ */
+function doSignature(msg, privateKey, {
+  pointPool, der, hash, publicKey, userId
+} = {}) {
+  let hashHex = typeof msg === 'string' ? _.utf8ToHex(msg) : _.arrayToHex(msg)
+
+  if (hash) {
+    // sm3杂凑
+    publicKey = publicKey || getPublicKeyFromPrivateKey(privateKey)
+    hashHex = getHash(hashHex, publicKey, userId)
+  }
+
+  const dA = new BigInteger(privateKey, 16)
+  const e = new BigInteger(hashHex, 16)
+
+  // k
+  let k = null
+  let r = null
+  let s = null
+
+  do {
+    do {
+      let point
+      if (pointPool && pointPool.length) {
+        point = pointPool.pop()
+      } else {
+        point = getPoint()
+      }
+      k = point.k
+
+      // r = (e + x1) mod n
+      r = e.add(point.x1).mod(n)
+    } while (r.equals(BigInteger.ZERO) || r.add(k).equals(n))
+
+    // s = ((1 + dA)^-1 * (k - r * dA)) mod n
+    s = dA.add(BigInteger.ONE).modInverse(n).multiply(k.subtract(r.multiply(dA))).mod(n)
+  } while (s.equals(BigInteger.ZERO))
+
+  if (der) return encodeDer(r, s) // asn.1 der 编码
+
+  return _.leftPad(r.toString(16), 64) + _.leftPad(s.toString(16), 64)
+}
+
+/**
+ * 验签
+ */
+function doVerifySignature(msg, signHex, publicKey, {der, hash, userId} = {}) {
+  let hashHex = typeof msg === 'string' ? _.utf8ToHex(msg) : _.arrayToHex(msg)
+
+  if (hash) {
+    // sm3杂凑
+    hashHex = getHash(hashHex, publicKey, userId)
+  }
+
+  let r; let
+    s
+  if (der) {
+    const decodeDerObj = decodeDer(signHex) // asn.1 der 解码
+    r = decodeDerObj.r
+    s = decodeDerObj.s
+  } else {
+    r = new BigInteger(signHex.substring(0, 64), 16)
+    s = new BigInteger(signHex.substring(64), 16)
+  }
+
+  const PA = curve.decodePointHex(publicKey)
+  const e = new BigInteger(hashHex, 16)
+
+  // t = (r + s) mod n
+  const t = r.add(s).mod(n)
+
+  if (t.equals(BigInteger.ZERO)) return false
+
+  // x1y1 = s * G + t * PA
+  const x1y1 = G.multiply(s).add(PA.multiply(t))
+
+  // R = (e + x1) mod n
+  const R = e.add(x1y1.getX().toBigInteger()).mod(n)
+
+  return r.equals(R)
+}
+
+/**
+ * sm3杂凑算法
+ */
+function getHash(hashHex, publicKey, userId = '1234567812345678') {
+  // z = hash(entl || userId || a || b || gx || gy || px || py)
+  userId = _.utf8ToHex(userId)
+  const a = _.leftPad(G.curve.a.toBigInteger().toRadix(16), 64)
+  const b = _.leftPad(G.curve.b.toBigInteger().toRadix(16), 64)
+  const gx = _.leftPad(G.getX().toBigInteger().toRadix(16), 64)
+  const gy = _.leftPad(G.getY().toBigInteger().toRadix(16), 64)
+  let px
+  let py
+  if (publicKey.length === 128) {
+    px = publicKey.substr(0, 64)
+    py = publicKey.substr(64, 64)
+  } else {
+    const point = G.curve.decodePointHex(publicKey)
+    px = _.leftPad(point.getX().toBigInteger().toRadix(16), 64)
+    py = _.leftPad(point.getY().toBigInteger().toRadix(16), 64)
+  }
+  const data = _.hexToArray(userId + a + b + gx + gy + px + py)
+
+  const entl = userId.length * 4
+  data.unshift(entl & 0x00ff)
+  data.unshift(entl >> 8 & 0x00ff)
+
+  const z = sm3(data)
+
+  // e = hash(z || msg)
+  return _.arrayToHex(sm3(z.concat(_.hexToArray(hashHex))))
+}
+
+/**
+ * 计算公钥
+ */
+function getPublicKeyFromPrivateKey(privateKey) {
+  const PA = G.multiply(new BigInteger(privateKey, 16))
+  const x = _.leftPad(PA.getX().toBigInteger().toString(16), 64)
+  const y = _.leftPad(PA.getY().toBigInteger().toString(16), 64)
+  return '04' + x + y
+}
+
+/**
+ * 获取椭圆曲线点
+ */
+function getPoint() {
+  const keypair = _.generateKeyPairHex()
+  const PA = curve.decodePointHex(keypair.publicKey)
+
+  keypair.k = new BigInteger(keypair.privateKey, 16)
+  keypair.x1 = PA.getX().toBigInteger()
+
+  return keypair
+}
+
+module.exports = {
+  generateKeyPairHex: _.generateKeyPairHex,
+  compressPublicKeyHex: _.compressPublicKeyHex,
+  comparePublicKeyHex: _.comparePublicKeyHex,
+  doEncrypt,
+  doDecrypt,
+  doSignature,
+  doVerifySignature,
+  getPublicKeyFromPrivateKey,
+  getPoint,
+  verifyPublicKey: _.verifyPublicKey,
+}
+
+}, function(modId) { var map = {"./asn1":1738722861366,"./utils":1738722861367,"./sm3":1738722861369}; return __REQUIRE__(map[modId], modId); })
+__DEFINE__(1738722861366, function(require, module, exports) {
+/* eslint-disable class-methods-use-this */
+const {BigInteger} = require('jsbn')
+
+function bigintToValue(bigint) {
+  let h = bigint.toString(16)
+  if (h[0] !== '-') {
+    // 正数
+    if (h.length % 2 === 1) h = '0' + h // 补齐到整字节
+    else if (!h.match(/^[0-7]/)) h = '00' + h // 非0开头,则补一个全0字节
+  } else {
+    // 负数
+    h = h.substr(1)
+
+    let len = h.length
+    if (len % 2 === 1) len += 1 // 补齐到整字节
+    else if (!h.match(/^[0-7]/)) len += 2 // 非0开头,则补一个全0字节
+
+    let mask = ''
+    for (let i = 0; i < len; i++) mask += 'f'
+    mask = new BigInteger(mask, 16)
+
+    // 对绝对值取反,加1
+    h = mask.xor(bigint).add(BigInteger.ONE)
+    h = h.toString(16).replace(/^-/, '')
+  }
+  return h
+}
+
+class ASN1Object {
+  constructor() {
+    this.tlv = null
+    this.t = '00'
+    this.l = '00'
+    this.v = ''
+  }
+
+  /**
+   * 获取 der 编码比特流16进制串
+   */
+  getEncodedHex() {
+    if (!this.tlv) {
+      this.v = this.getValue()
+      this.l = this.getLength()
+      this.tlv = this.t + this.l + this.v
+    }
+    return this.tlv
+  }
+
+  getLength() {
+    const n = this.v.length / 2 // 字节数
+    let nHex = n.toString(16)
+    if (nHex.length % 2 === 1) nHex = '0' + nHex // 补齐到整字节
+
+    if (n < 128) {
+      // 短格式,以 0 开头
+      return nHex
+    } else {
+      // 长格式,以 1 开头
+      const head = 128 + nHex.length / 2 // 1(1位) + 真正的长度占用字节数(7位) + 真正的长度
+      return head.toString(16) + nHex
+    }
+  }
+
+  getValue() {
+    return ''
+  }
+}
+
+class DERInteger extends ASN1Object {
+  constructor(bigint) {
+    super()
+
+    this.t = '02' // 整型标签说明
+    if (bigint) this.v = bigintToValue(bigint)
+  }
+
+  getValue() {
+    return this.v
+  }
+}
+
+class DERSequence extends ASN1Object {
+  constructor(asn1Array) {
+    super()
+
+    this.t = '30' // 序列标签说明
+    this.asn1Array = asn1Array
+  }
+
+  getValue() {
+    this.v = this.asn1Array.map(asn1Object => asn1Object.getEncodedHex()).join('')
+    return this.v
+  }
+}
+
+/**
+ * 获取 l 占用字节数
+ */
+function getLenOfL(str, start) {
+  if (+str[start + 2] < 8) return 1 // l 以0开头,则表示短格式,只占一个字节
+  return +str.substr(start + 2, 2) & 0x7f + 1 // 长格式,取第一个字节后7位作为长度真正占用字节数,再加上本身
+}
+
+/**
+ * 获取 l
+ */
+function getL(str, start) {
+  // 获取 l
+  const len = getLenOfL(str, start)
+  const l = str.substr(start + 2, len * 2)
+
+  if (!l) return -1
+  const bigint = +l[0] < 8 ? new BigInteger(l, 16) : new BigInteger(l.substr(2), 16)
+
+  return bigint.intValue()
+}
+
+/**
+ * 获取 v 的位置
+ */
+function getStartOfV(str, start) {
+  const len = getLenOfL(str, start)
+  return start + (len + 1) * 2
+}
+
+module.exports = {
+  /**
+   * ASN.1 der 编码,针对 sm2 签名
+   */
+  encodeDer(r, s) {
+    const derR = new DERInteger(r)
+    const derS = new DERInteger(s)
+    const derSeq = new DERSequence([derR, derS])
+
+    return derSeq.getEncodedHex()
+  },
+
+  /**
+   * 解析 ASN.1 der,针对 sm2 验签
+   */
+  decodeDer(input) {
+    // 结构:
+    // input = | tSeq | lSeq | vSeq |
+    // vSeq = | tR | lR | vR | tS | lS | vS |
+    const start = getStartOfV(input, 0)
+
+    const vIndexR = getStartOfV(input, start)
+    const lR = getL(input, start)
+    const vR = input.substr(vIndexR, lR * 2)
+
+    const nextStart = vIndexR + vR.length
+    const vIndexS = getStartOfV(input, nextStart)
+    const lS = getL(input, nextStart)
+    const vS = input.substr(vIndexS, lS * 2)
+
+    const r = new BigInteger(vR, 16)
+    const s = new BigInteger(vS, 16)
+
+    return {r, s}
+  }
+}
+
+}, function(modId) { var map = {}; return __REQUIRE__(map[modId], modId); })
+__DEFINE__(1738722861367, function(require, module, exports) {
+/* eslint-disable no-bitwise, no-mixed-operators, no-use-before-define, max-len */
+const {BigInteger, SecureRandom} = require('jsbn')
+const {ECCurveFp} = require('./ec')
+
+const rng = new SecureRandom()
+const {curve, G, n} = generateEcparam()
+
+/**
+ * 获取公共椭圆曲线
+ */
+function getGlobalCurve() {
+  return curve
+}
+
+/**
+ * 生成ecparam
+ */
+function generateEcparam() {
+  // 椭圆曲线
+  const p = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16)
+  const a = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16)
+  const b = new BigInteger('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93', 16)
+  const curve = new ECCurveFp(p, a, b)
+
+  // 基点
+  const gxHex = '32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7'
+  const gyHex = 'BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0'
+  const G = curve.decodePointHex('04' + gxHex + gyHex)
+
+  const n = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123', 16)
+
+  return {curve, G, n}
+}
+
+/**
+ * 生成密钥对:publicKey = privateKey * G
+ */
+function generateKeyPairHex(a, b, c) {
+  const random = a ? new BigInteger(a, b, c) : new BigInteger(n.bitLength(), rng)
+  const d = random.mod(n.subtract(BigInteger.ONE)).add(BigInteger.ONE) // 随机数
+  const privateKey = leftPad(d.toString(16), 64)
+
+  const P = G.multiply(d) // P = dG,p 为公钥,d 为私钥
+  const Px = leftPad(P.getX().toBigInteger().toString(16), 64)
+  const Py = leftPad(P.getY().toBigInteger().toString(16), 64)
+  const publicKey = '04' + Px + Py
+
+  return {privateKey, publicKey}
+}
+
+/**
+ * 生成压缩公钥
+ */
+function compressPublicKeyHex(s) {
+  if (s.length !== 130) throw new Error('Invalid public key to compress')
+
+  const len = (s.length - 2) / 2
+  const xHex = s.substr(2, len)
+  const y = new BigInteger(s.substr(len + 2, len), 16)
+
+  let prefix = '03'
+  if (y.mod(new BigInteger('2')).equals(BigInteger.ZERO)) prefix = '02'
+
+  return prefix + xHex
+}
+
+/**
+ * utf8串转16进制串
+ */
+function utf8ToHex(input) {
+  input = unescape(encodeURIComponent(input))
+
+  const length = input.length
+
+  // 转换到字数组
+  const words = []
+  for (let i = 0; i < length; i++) {
+    words[i >>> 2] |= (input.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8)
+  }
+
+  // 转换到16进制
+  const hexChars = []
+  for (let i = 0; i < length; i++) {
+    const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff
+    hexChars.push((bite >>> 4).toString(16))
+    hexChars.push((bite & 0x0f).toString(16))
+  }
+
+  return hexChars.join('')
+}
+
+/**
+ * 补全16进制字符串
+ */
+function leftPad(input, num) {
+  if (input.length >= num) return input
+
+  return (new Array(num - input.length + 1)).join('0') + input
+}
+
+/**
+ * 转成16进制串
+ */
+function arrayToHex(arr) {
+  return arr.map(item => {
+    item = item.toString(16)
+    return item.length === 1 ? '0' + item : item
+  }).join('')
+}
+
+/**
+ * 转成utf8串
+ */
+function arrayToUtf8(arr) {
+  const words = []
+  let j = 0
+  for (let i = 0; i < arr.length * 2; i += 2) {
+    words[i >>> 3] |= parseInt(arr[j], 10) << (24 - (i % 8) * 4)
+    j++
+  }
+
+  try {
+    const latin1Chars = []
+
+    for (let i = 0; i < arr.length; i++) {
+      const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff
+      latin1Chars.push(String.fromCharCode(bite))
+    }
+
+    return decodeURIComponent(escape(latin1Chars.join('')))
+  } catch (e) {
+    throw new Error('Malformed UTF-8 data')
+  }
+}
+
+/**
+ * 转成字节数组
+ */
+function hexToArray(hexStr) {
+  const words = []
+  let hexStrLength = hexStr.length
+
+  if (hexStrLength % 2 !== 0) {
+    hexStr = leftPad(hexStr, hexStrLength + 1)
+  }
+
+  hexStrLength = hexStr.length
+
+  for (let i = 0; i < hexStrLength; i += 2) {
+    words.push(parseInt(hexStr.substr(i, 2), 16))
+  }
+  return words
+}
+
+/**
+ * 验证公钥是否为椭圆曲线上的点
+ */
+function verifyPublicKey(publicKey) {
+  const point = curve.decodePointHex(publicKey)
+  if (!point) return false
+
+  const x = point.getX()
+  const y = point.getY()
+
+  // 验证 y^2 是否等于 x^3 + ax + b
+  return y.square().equals(x.multiply(x.square()).add(x.multiply(curve.a)).add(curve.b))
+}
+
+/**
+ * 验证公钥是否等价,等价返回true
+ */
+function comparePublicKeyHex(publicKey1, publicKey2) {
+  const point1 = curve.decodePointHex(publicKey1)
+  if (!point1) return false
+
+  const point2 = curve.decodePointHex(publicKey2)
+  if (!point2) return false
+
+  return point1.equals(point2)
+}
+
+module.exports = {
+  getGlobalCurve,
+  generateEcparam,
+  generateKeyPairHex,
+  compressPublicKeyHex,
+  utf8ToHex,
+  leftPad,
+  arrayToHex,
+  arrayToUtf8,
+  hexToArray,
+  verifyPublicKey,
+  comparePublicKeyHex,
+}
+
+}, function(modId) { var map = {"./ec":1738722861368}; return __REQUIRE__(map[modId], modId); })
+__DEFINE__(1738722861368, function(require, module, exports) {
+/* eslint-disable no-case-declarations, max-len */
+const {BigInteger} = require('jsbn')
+
+/**
+ * thanks for Tom Wu : http://www-cs-students.stanford.edu/~tjw/jsbn/
+ *
+ * Basic Javascript Elliptic Curve implementation
+ * Ported loosely from BouncyCastle's Java EC code
+ * Only Fp curves implemented for now
+ */
+
+const TWO = new BigInteger('2')
+const THREE = new BigInteger('3')
+
+/**
+ * 椭圆曲线域元素
+ */
+class ECFieldElementFp {
+  constructor(q, x) {
+    this.x = x
+    this.q = q
+    // TODO if (x.compareTo(q) >= 0) error
+  }
+
+  /**
+   * 判断相等
+   */
+  equals(other) {
+    if (other === this) return true
+    return (this.q.equals(other.q) && this.x.equals(other.x))
+  }
+
+  /**
+   * 返回具体数值
+   */
+  toBigInteger() {
+    return this.x
+  }
+
+  /**
+   * 取反
+   */
+  negate() {
+    return new ECFieldElementFp(this.q, this.x.negate().mod(this.q))
+  }
+
+  /**
+   * 相加
+   */
+  add(b) {
+    return new ECFieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q))
+  }
+
+  /**
+   * 相减
+   */
+  subtract(b) {
+    return new ECFieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q))
+  }
+
+  /**
+   * 相乘
+   */
+  multiply(b) {
+    return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q))
+  }
+
+  /**
+   * 相除
+   */
+  divide(b) {
+    return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger().modInverse(this.q)).mod(this.q))
+  }
+
+  /**
+   * 平方
+   */
+  square() {
+    return new ECFieldElementFp(this.q, this.x.square().mod(this.q))
+  }
+}
+
+class ECPointFp {
+  constructor(curve, x, y, z) {
+    this.curve = curve
+    this.x = x
+    this.y = y
+    // 标准射影坐标系:zinv == null 或 z * zinv == 1
+    this.z = z == null ? BigInteger.ONE : z
+    this.zinv = null
+    // TODO: compression flag
+  }
+
+  getX() {
+    if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q)
+
+    return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q))
+  }
+
+  getY() {
+    if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q)
+
+    return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q))
+  }
+
+  /**
+   * 判断相等
+   */
+  equals(other) {
+    if (other === this) return true
+    if (this.isInfinity()) return other.isInfinity()
+    if (other.isInfinity()) return this.isInfinity()
+
+    // u = y2 * z1 - y1 * z2
+    const u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q)
+    if (!u.equals(BigInteger.ZERO)) return false
+
+    // v = x2 * z1 - x1 * z2
+    const v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q)
+    return v.equals(BigInteger.ZERO)
+  }
+
+  /**
+   * 是否是无穷远点
+   */
+  isInfinity() {
+    if ((this.x === null) && (this.y === null)) return true
+    return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO)
+  }
+
+  /**
+   * 取反,x 轴对称点
+   */
+  negate() {
+    return new ECPointFp(this.curve, this.x, this.y.negate(), this.z)
+  }
+
+  /**
+   * 相加
+   *
+   * 标准射影坐标系:
+   *
+   * λ1 = x1 * z2
+   * λ2 = x2 * z1
+   * λ3 = λ1 − λ2
+   * λ4 = y1 * z2
+   * λ5 = y2 * z1
+   * λ6 = λ4 − λ5
+   * λ7 = λ1 + λ2
+   * λ8 = z1 * z2
+   * λ9 = λ3^2
+   * λ10 = λ3 * λ9
+   * λ11 = λ8 * λ6^2 − λ7 * λ9
+   * x3 = λ3 * λ11
+   * y3 = λ6 * (λ9 * λ1 − λ11) − λ4 * λ10
+   * z3 = λ10 * λ8
+   */
+  add(b) {
+    if (this.isInfinity()) return b
+    if (b.isInfinity()) return this
+
+    const x1 = this.x.toBigInteger()
+    const y1 = this.y.toBigInteger()
+    const z1 = this.z
+    const x2 = b.x.toBigInteger()
+    const y2 = b.y.toBigInteger()
+    const z2 = b.z
+    const q = this.curve.q
+
+    const w1 = x1.multiply(z2).mod(q)
+    const w2 = x2.multiply(z1).mod(q)
+    const w3 = w1.subtract(w2)
+    const w4 = y1.multiply(z2).mod(q)
+    const w5 = y2.multiply(z1).mod(q)
+    const w6 = w4.subtract(w5)
+
+    if (BigInteger.ZERO.equals(w3)) {
+      if (BigInteger.ZERO.equals(w6)) {
+        return this.twice() // this == b,计算自加
+      }
+      return this.curve.infinity // this == -b,则返回无穷远点
+    }
+
+    const w7 = w1.add(w2)
+    const w8 = z1.multiply(z2).mod(q)
+    const w9 = w3.square().mod(q)
+    const w10 = w3.multiply(w9).mod(q)
+    const w11 = w8.multiply(w6.square()).subtract(w7.multiply(w9)).mod(q)
+
+    const x3 = w3.multiply(w11).mod(q)
+    const y3 = w6.multiply(w9.multiply(w1).subtract(w11)).subtract(w4.multiply(w10)).mod(q)
+    const z3 = w10.multiply(w8).mod(q)
+
+    return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3)
+  }
+
+  /**
+   * 自加
+   *
+   * 标准射影坐标系:
+   *
+   * λ1 = 3 * x1^2 + a * z1^2
+   * λ2 = 2 * y1 * z1
+   * λ3 = y1^2
+   * λ4 = λ3 * x1 * z1
+   * λ5 = λ2^2
+   * λ6 = λ1^2 − 8 * λ4
+   * x3 = λ2 * λ6
+   * y3 = λ1 * (4 * λ4 − λ6) − 2 * λ5 * λ3
+   * z3 = λ2 * λ5
+   */
+  twice() {
+    if (this.isInfinity()) return this
+    if (!this.y.toBigInteger().signum()) return this.curve.infinity
+
+    const x1 = this.x.toBigInteger()
+    const y1 = this.y.toBigInteger()
+    const z1 = this.z
+    const q = this.curve.q
+    const a = this.curve.a.toBigInteger()
+
+    const w1 = x1.square().multiply(THREE).add(a.multiply(z1.square())).mod(q)
+    const w2 = y1.shiftLeft(1).multiply(z1).mod(q)
+    const w3 = y1.square().mod(q)
+    const w4 = w3.multiply(x1).multiply(z1).mod(q)
+    const w5 = w2.square().mod(q)
+    const w6 = w1.square().subtract(w4.shiftLeft(3)).mod(q)
+
+    const x3 = w2.multiply(w6).mod(q)
+    const y3 = w1.multiply(w4.shiftLeft(2).subtract(w6)).subtract(w5.shiftLeft(1).multiply(w3)).mod(q)
+    const z3 = w2.multiply(w5).mod(q)
+
+    return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3)
+  }
+
+  /**
+   * 倍点计算
+   */
+  multiply(k) {
+    if (this.isInfinity()) return this
+    if (!k.signum()) return this.curve.infinity
+
+    // 使用加减法
+    const k3 = k.multiply(THREE)
+    const neg = this.negate()
+    let Q = this
+
+    for (let i = k3.bitLength() - 2; i > 0; i--) {
+      Q = Q.twice()
+
+      const k3Bit = k3.testBit(i)
+      const kBit = k.testBit(i)
+
+      if (k3Bit !== kBit) {
+        Q = Q.add(k3Bit ? this : neg)
+      }
+    }
+
+    return Q
+  }
+}
+
+/**
+ * 椭圆曲线 y^2 = x^3 + ax + b
+ */
+class ECCurveFp {
+  constructor(q, a, b) {
+    this.q = q
+    this.a = this.fromBigInteger(a)
+    this.b = this.fromBigInteger(b)
+    this.infinity = new ECPointFp(this, null, null) // 无穷远点
+  }
+
+  /**
+   * 判断两个椭圆曲线是否相等
+   */
+  equals(other) {
+    if (other === this) return true
+    return (this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b))
+  }
+
+  /**
+   * 生成椭圆曲线域元素
+   */
+  fromBigInteger(x) {
+    return new ECFieldElementFp(this.q, x)
+  }
+
+  /**
+   * 解析 16 进制串为椭圆曲线点
+   */
+  decodePointHex(s) {
+    switch (parseInt(s.substr(0, 2), 16)) {
+      // 第一个字节
+      case 0:
+        return this.infinity
+      case 2:
+      case 3:
+        // 压缩
+        const x = this.fromBigInteger(new BigInteger(s.substr(2), 16))
+        // 对 p ≡ 3 (mod4),即存在正整数 u,使得 p = 4u + 3
+        // 计算 y = (√ (x^3 + ax + b) % p)^(u + 1) modp
+        let y = this.fromBigInteger(x.multiply(x.square()).add(
+          x.multiply(this.a)
+        ).add(this.b).toBigInteger()
+          .modPow(
+            this.q.divide(new BigInteger('4')).add(BigInteger.ONE), this.q
+          ))
+        // 算出结果 2 进制最后 1 位不等于第 1 个字节减 2 则取反
+        if (!y.toBigInteger().mod(TWO).equals(new BigInteger(s.substr(0, 2), 16).subtract(TWO))) {
+          y = y.negate()
+        }
+        return new ECPointFp(this, x, y)
+      case 4:
+      case 6:
+      case 7:
+        const len = (s.length - 2) / 2
+        const xHex = s.substr(2, len)
+        const yHex = s.substr(len + 2, len)
+
+        return new ECPointFp(this, this.fromBigInteger(new BigInteger(xHex, 16)), this.fromBigInteger(new BigInteger(yHex, 16)))
+      default:
+        // 不支持
+        return null
+    }
+  }
+}
+
+module.exports = {
+  ECPointFp,
+  ECCurveFp,
+}
+
+}, function(modId) { var map = {}; return __REQUIRE__(map[modId], modId); })
+__DEFINE__(1738722861369, function(require, module, exports) {
+// 消息扩展
+const W = new Uint32Array(68)
+const M = new Uint32Array(64) // W'
+
+/**
+ * 循环左移
+ */
+function rotl(x, n) {
+  const s = n & 31
+  return (x << s) | (x >>> (32 - s))
+}
+
+/**
+ * 二进制异或运算
+ */
+function xor(x, y) {
+  const result = []
+  for (let i = x.length - 1; i >= 0; i--) result[i] = (x[i] ^ y[i]) & 0xff
+  return result
+}
+
+/**
+ * 压缩函数中的置换函数 P0(X) = X xor (X <<< 9) xor (X <<< 17)
+ */
+function P0(X) {
+  return (X ^ rotl(X, 9)) ^ rotl(X, 17)
+}
+
+/**
+ * 消息扩展中的置换函数 P1(X) = X xor (X <<< 15) xor (X <<< 23)
+ */
+function P1(X) {
+  return (X ^ rotl(X, 15)) ^ rotl(X, 23)
+}
+
+/**
+ * sm3 本体
+ */
+function sm3(array) {
+  let len = array.length * 8
+
+  // k 是满足 len + 1 + k = 448mod512 的最小的非负整数
+  let k = len % 512
+  // 如果 448 <= (512 % len) < 512,需要多补充 (len % 448) 比特'0'以满足总比特长度为512的倍数
+  k = k >= 448 ? 512 - (k % 448) - 1 : 448 - k - 1
+
+  // 填充
+  const kArr = new Array((k - 7) / 8)
+  const lenArr = new Array(8)
+  for (let i = 0, len = kArr.length; i < len; i++) kArr[i] = 0
+  for (let i = 0, len = lenArr.length; i < len; i++) lenArr[i] = 0
+  len = len.toString(2)
+  for (let i = 7; i >= 0; i--) {
+    if (len.length > 8) {
+      const start = len.length - 8
+      lenArr[i] = parseInt(len.substr(start), 2)
+      len = len.substr(0, start)
+    } else if (len.length > 0) {
+      lenArr[i] = parseInt(len, 2)
+      len = ''
+    }
+  }
+  const m = new Uint8Array([...array, 0x80, ...kArr, ...lenArr])
+  const dataView = new DataView(m.buffer, 0)
+
+  // 迭代压缩
+  const n = m.length / 64
+  const V = new Uint32Array([0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e])
+  for (let i = 0; i < n; i++) {
+    W.fill(0)
+    M.fill(0)
+
+    // 将消息分组B划分为 16 个字 W0, W1,……,W15
+    const start = 16 * i
+    for (let j = 0; j < 16; j++) {
+      W[j] = dataView.getUint32((start + j) * 4, false)
+    }
+
+    // W16 ~ W67:W[j] <- P1(W[j−16] xor W[j−9] xor (W[j−3] <<< 15)) xor (W[j−13] <<< 7) xor W[j−6]
+    for (let j = 16; j < 68; j++) {
+      W[j] = (P1((W[j - 16] ^ W[j - 9]) ^ rotl(W[j - 3], 15)) ^ rotl(W[j - 13], 7)) ^ W[j - 6]
+    }
+
+    // W′0 ~ W′63:W′[j] = W[j] xor W[j+4]
+    for (let j = 0; j < 64; j++) {
+      M[j] = W[j] ^ W[j + 4]
+    }
+
+    // 压缩
+    const T1 = 0x79cc4519
+    const T2 = 0x7a879d8a
+    // 字寄存器
+    let A = V[0]
+    let B = V[1]
+    let C = V[2]
+    let D = V[3]
+    let E = V[4]
+    let F = V[5]
+    let G = V[6]
+    let H = V[7]
+    // 中间变量
+    let SS1
+    let SS2
+    let TT1
+    let TT2
+    let T
+    for (let j = 0; j < 64; j++) {
+      T = j >= 0 && j <= 15 ? T1 : T2
+      SS1 = rotl(rotl(A, 12) + E + rotl(T, j), 7)
+      SS2 = SS1 ^ rotl(A, 12)
+
+      TT1 = (j >= 0 && j <= 15 ? ((A ^ B) ^ C) : (((A & B) | (A & C)) | (B & C))) + D + SS2 + M[j]
+      TT2 = (j >= 0 && j <= 15 ? ((E ^ F) ^ G) : ((E & F) | ((~E) & G))) + H + SS1 + W[j]
+
+      D = C
+      C = rotl(B, 9)
+      B = A
+      A = TT1
+      H = G
+      G = rotl(F, 19)
+      F = E
+      E = P0(TT2)
+    }
+
+    V[0] ^= A
+    V[1] ^= B
+    V[2] ^= C
+    V[3] ^= D
+    V[4] ^= E
+    V[5] ^= F
+    V[6] ^= G
+    V[7] ^= H
+  }
+
+  // 转回 uint8
+  const result = []
+  for (let i = 0, len = V.length; i < len; i++) {
+    const word = V[i]
+    result.push((word & 0xff000000) >>> 24, (word & 0xff0000) >>> 16, (word & 0xff00) >>> 8, word & 0xff)
+  }
+
+  return result
+}
+
+/**
+ * hmac 实现
+ */
+const blockLen = 64
+const iPad = new Uint8Array(blockLen)
+const oPad = new Uint8Array(blockLen)
+for (let i = 0; i < blockLen; i++) {
+  iPad[i] = 0x36
+  oPad[i] = 0x5c
+}
+function hmac(input, key) {
+  // 密钥填充
+  if (key.length > blockLen) key = sm3(key)
+  while (key.length < blockLen) key.push(0)
+
+  const iPadKey = xor(key, iPad)
+  const oPadKey = xor(key, oPad)
+
+  const hash = sm3([...iPadKey, ...input])
+  return sm3([...oPadKey, ...hash])
+}
+
+module.exports = {
+  sm3,
+  hmac,
+}
+
+}, function(modId) { var map = {}; return __REQUIRE__(map[modId], modId); })
+__DEFINE__(1738722861370, function(require, module, exports) {
+const {sm3, hmac} = require('../sm2/sm3')
+
+/**
+ * 补全16进制字符串
+ */
+function leftPad(input, num) {
+  if (input.length >= num) return input
+
+  return (new Array(num - input.length + 1)).join('0') + input
+}
+
+/**
+ * 字节数组转 16 进制串
+ */
+function ArrayToHex(arr) {
+  return arr.map(item => {
+    item = item.toString(16)
+    return item.length === 1 ? '0' + item : item
+  }).join('')
+}
+
+/**
+ * 转成字节数组
+ */
+function hexToArray(hexStr) {
+  const words = []
+  let hexStrLength = hexStr.length
+
+  if (hexStrLength % 2 !== 0) {
+    hexStr = leftPad(hexStr, hexStrLength + 1)
+  }
+
+  hexStrLength = hexStr.length
+
+  for (let i = 0; i < hexStrLength; i += 2) {
+    words.push(parseInt(hexStr.substr(i, 2), 16))
+  }
+  return words
+}
+
+/**
+ * utf8 串转字节数组
+ */
+function utf8ToArray(str) {
+  const arr = []
+
+  for (let i = 0, len = str.length; i < len; i++) {
+    const point = str.codePointAt(i)
+
+    if (point <= 0x007f) {
+      // 单字节,标量值:00000000 00000000 0zzzzzzz
+      arr.push(point)
+    } else if (point <= 0x07ff) {
+      // 双字节,标量值:00000000 00000yyy yyzzzzzz
+      arr.push(0xc0 | (point >>> 6)) // 110yyyyy(0xc0-0xdf)
+      arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
+    } else if (point <= 0xD7FF || (point >= 0xE000 && point <= 0xFFFF)) {
+      // 三字节:标量值:00000000 xxxxyyyy yyzzzzzz
+      arr.push(0xe0 | (point >>> 12)) // 1110xxxx(0xe0-0xef)
+      arr.push(0x80 | ((point >>> 6) & 0x3f)) // 10yyyyyy(0x80-0xbf)
+      arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
+    } else if (point >= 0x010000 && point <= 0x10FFFF) {
+      // 四字节:标量值:000wwwxx xxxxyyyy yyzzzzzz
+      i++
+      arr.push((0xf0 | (point >>> 18) & 0x1c)) // 11110www(0xf0-0xf7)
+      arr.push((0x80 | ((point >>> 12) & 0x3f))) // 10xxxxxx(0x80-0xbf)
+      arr.push((0x80 | ((point >>> 6) & 0x3f))) // 10yyyyyy(0x80-0xbf)
+      arr.push((0x80 | (point & 0x3f))) // 10zzzzzz(0x80-0xbf)
+    } else {
+      // 五、六字节,暂时不支持
+      arr.push(point)
+      throw new Error('input is not supported')
+    }
+  }
+
+  return arr
+}
+
+module.exports = function (input, options) {
+  input = typeof input === 'string' ? utf8ToArray(input) : Array.prototype.slice.call(input)
+
+  if (options) {
+    const mode = options.mode || 'hmac'
+    if (mode !== 'hmac') throw new Error('invalid mode')
+
+    let key = options.key
+    if (!key) throw new Error('invalid key')
+
+    key = typeof key === 'string' ? hexToArray(key) : Array.prototype.slice.call(key)
+    return ArrayToHex(hmac(input, key))
+  }
+
+  return ArrayToHex(sm3(input))
+}
+
+}, function(modId) { var map = {"../sm2/sm3":1738722861369}; return __REQUIRE__(map[modId], modId); })
+__DEFINE__(1738722861371, function(require, module, exports) {
+/* eslint-disable no-bitwise, no-mixed-operators, complexity */
+const DECRYPT = 0
+const ROUND = 32
+const BLOCK = 16
+
+const Sbox = [
+  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
+]
+
+const 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
+]
+
+/**
+ * 16 进制串转字节数组
+ */
+function hexToArray(str) {
+  const arr = []
+  for (let i = 0, len = str.length; i < len; i += 2) {
+    arr.push(parseInt(str.substr(i, 2), 16))
+  }
+  return arr
+}
+
+/**
+ * 字节数组转 16 进制串
+ */
+function ArrayToHex(arr) {
+  return arr.map(item => {
+    item = item.toString(16)
+    return item.length === 1 ? '0' + item : item
+  }).join('')
+}
+
+/**
+ * utf8 串转字节数组
+ */
+function utf8ToArray(str) {
+  const arr = []
+
+  for (let i = 0, len = str.length; i < len; i++) {
+    const point = str.codePointAt(i)
+
+    if (point <= 0x007f) {
+      // 单字节,标量值:00000000 00000000 0zzzzzzz
+      arr.push(point)
+    } else if (point <= 0x07ff) {
+      // 双字节,标量值:00000000 00000yyy yyzzzzzz
+      arr.push(0xc0 | (point >>> 6)) // 110yyyyy(0xc0-0xdf)
+      arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
+    } else if (point <= 0xD7FF || (point >= 0xE000 && point <= 0xFFFF)) {
+      // 三字节:标量值:00000000 xxxxyyyy yyzzzzzz
+      arr.push(0xe0 | (point >>> 12)) // 1110xxxx(0xe0-0xef)
+      arr.push(0x80 | ((point >>> 6) & 0x3f)) // 10yyyyyy(0x80-0xbf)
+      arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
+    } else if (point >= 0x010000 && point <= 0x10FFFF) {
+      // 四字节:标量值:000wwwxx xxxxyyyy yyzzzzzz
+      i++
+      arr.push((0xf0 | (point >>> 18) & 0x1c)) // 11110www(0xf0-0xf7)
+      arr.push((0x80 | ((point >>> 12) & 0x3f))) // 10xxxxxx(0x80-0xbf)
+      arr.push((0x80 | ((point >>> 6) & 0x3f))) // 10yyyyyy(0x80-0xbf)
+      arr.push((0x80 | (point & 0x3f))) // 10zzzzzz(0x80-0xbf)
+    } else {
+      // 五、六字节,暂时不支持
+      arr.push(point)
+      throw new Error('input is not supported')
+    }
+  }
+
+  return arr
+}
+
+/**
+ * 字节数组转 utf8 串
+ */
+function arrayToUtf8(arr) {
+  const str = []
+  for (let i = 0, len = arr.length; i < len; i++) {
+    if (arr[i] >= 0xf0 && arr[i] <= 0xf7) {
+      // 四字节
+      str.push(String.fromCodePoint(((arr[i] & 0x07) << 18) + ((arr[i + 1] & 0x3f) << 12) + ((arr[i + 2] & 0x3f) << 6) + (arr[i + 3] & 0x3f)))
+      i += 3
+    } else if (arr[i] >= 0xe0 && arr[i] <= 0xef) {
+      // 三字节
+      str.push(String.fromCodePoint(((arr[i] & 0x0f) << 12) + ((arr[i + 1] & 0x3f) << 6) + (arr[i + 2] & 0x3f)))
+      i += 2
+    } else if (arr[i] >= 0xc0 && arr[i] <= 0xdf) {
+      // 双字节
+      str.push(String.fromCodePoint(((arr[i] & 0x1f) << 6) + (arr[i + 1] & 0x3f)))
+      i++
+    } else {
+      // 单字节
+      str.push(String.fromCodePoint(arr[i]))
+    }
+  }
+
+  return str.join('')
+}
+
+/**
+ * 32 比特循环左移
+ */
+function rotl(x, n) {
+  const s = n & 31
+  return (x << s) | (x >>> (32 - s))
+}
+
+/**
+ * 非线性变换
+ */
+function byteSub(a) {
+  return (Sbox[a >>> 24 & 0xFF] & 0xFF) << 24 |
+    (Sbox[a >>> 16 & 0xFF] & 0xFF) << 16 |
+    (Sbox[a >>> 8 & 0xFF] & 0xFF) << 8 |
+    (Sbox[a & 0xFF] & 0xFF)
+}
+
+/**
+ * 线性变换,加密/解密用
+ */
+function l1(b) {
+  return b ^ rotl(b, 2) ^ rotl(b, 10) ^ rotl(b, 18) ^ rotl(b, 24)
+}
+
+/**
+ * 线性变换,生成轮密钥用
+ */
+function l2(b) {
+  return b ^ rotl(b, 13) ^ rotl(b, 23)
+}
+
+/**
+ * 以一组 128 比特进行加密/解密操作
+ */
+function sms4Crypt(input, output, roundKey) {
+  const x = new Array(4)
+
+  // 字节数组转成字数组(此处 1 字 = 32 比特)
+  const tmp = new Array(4)
+  for (let i = 0; i < 4; i++) {
+    tmp[0] = input[4 * i] & 0xff
+    tmp[1] = input[4 * i + 1] & 0xff
+    tmp[2] = input[4 * i + 2] & 0xff
+    tmp[3] = input[4 * i + 3] & 0xff
+    x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3]
+  }
+
+  // x[i + 4] = x[i] ^ l1(byteSub(x[i + 1] ^ x[i + 2] ^ x[i + 3] ^ roundKey[i]))
+  for (let r = 0, mid; r < 32; r += 4) {
+    mid = x[1] ^ x[2] ^ x[3] ^ roundKey[r + 0]
+    x[0] ^= l1(byteSub(mid)) // x[4]
+
+    mid = x[2] ^ x[3] ^ x[0] ^ roundKey[r + 1]
+    x[1] ^= l1(byteSub(mid)) // x[5]
+
+    mid = x[3] ^ x[0] ^ x[1] ^ roundKey[r + 2]
+    x[2] ^= l1(byteSub(mid)) // x[6]
+
+    mid = x[0] ^ x[1] ^ x[2] ^ roundKey[r + 3]
+    x[3] ^= l1(byteSub(mid)) // x[7]
+  }
+
+  // 反序变换
+  for (let j = 0; j < 16; j += 4) {
+    output[j] = x[3 - j / 4] >>> 24 & 0xff
+    output[j + 1] = x[3 - j / 4] >>> 16 & 0xff
+    output[j + 2] = x[3 - j / 4] >>> 8 & 0xff
+    output[j + 3] = x[3 - j / 4] & 0xff
+  }
+}
+
+/**
+ * 密钥扩展算法
+ */
+function sms4KeyExt(key, roundKey, cryptFlag) {
+  const x = new Array(4)
+
+  // 字节数组转成字数组(此处 1 字 = 32 比特)
+  const tmp = new Array(4)
+  for (let i = 0; i < 4; i++) {
+    tmp[0] = key[0 + 4 * i] & 0xff
+    tmp[1] = key[1 + 4 * i] & 0xff
+    tmp[2] = key[2 + 4 * i] & 0xff
+    tmp[3] = key[3 + 4 * i] & 0xff
+    x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3]
+  }
+
+  // 与系统参数做异或
+  x[0] ^= 0xa3b1bac6
+  x[1] ^= 0x56aa3350
+  x[2] ^= 0x677d9197
+  x[3] ^= 0xb27022dc
+
+  // roundKey[i] = x[i + 4] = x[i] ^ l2(byteSub(x[i + 1] ^ x[i + 2] ^ x[i + 3] ^ CK[i]))
+  for (let r = 0, mid; r < 32; r += 4) {
+    mid = x[1] ^ x[2] ^ x[3] ^ CK[r + 0]
+    roundKey[r + 0] = x[0] ^= l2(byteSub(mid)) // x[4]
+
+    mid = x[2] ^ x[3] ^ x[0] ^ CK[r + 1]
+    roundKey[r + 1] = x[1] ^= l2(byteSub(mid)) // x[5]
+
+    mid = x[3] ^ x[0] ^ x[1] ^ CK[r + 2]
+    roundKey[r + 2] = x[2] ^= l2(byteSub(mid)) // x[6]
+
+    mid = x[0] ^ x[1] ^ x[2] ^ CK[r + 3]
+    roundKey[r + 3] = x[3] ^= l2(byteSub(mid)) // x[7]
+  }
+
+  // 解密时使用反序的轮密钥
+  if (cryptFlag === DECRYPT) {
+    for (let r = 0, mid; r < 16; r++) {
+      mid = roundKey[r]
+      roundKey[r] = roundKey[31 - r]
+      roundKey[31 - r] = mid
+    }
+  }
+}
+
+function sm4(inArray, key, cryptFlag, {
+  padding = 'pkcs#7', mode, iv = [], output = 'string'
+} = {}) {
+  if (mode === 'cbc') {
+    // CBC 模式,默认走 ECB 模式
+    if (typeof iv === 'string') iv = hexToArray(iv)
+    if (iv.length !== (128 / 8)) {
+      // iv 不是 128 比特
+      throw new Error('iv is invalid')
+    }
+  }
+
+  // 检查 key
+  if (typeof key === 'string') key = hexToArray(key)
+  if (key.length !== (128 / 8)) {
+    // key 不是 128 比特
+    throw new Error('key is invalid')
+  }
+
+  // 检查输入
+  if (typeof inArray === 'string') {
+    if (cryptFlag !== DECRYPT) {
+      // 加密,输入为 utf8 串
+      inArray = utf8ToArray(inArray)
+    } else {
+      // 解密,输入为 16 进制串
+      inArray = hexToArray(inArray)
+    }
+  } else {
+    inArray = [...inArray]
+  }
+
+  // 新增填充,sm4 是 16 个字节一个分组,所以统一走到 pkcs#7
+  if ((padding === 'pkcs#5' || padding === 'pkcs#7') && cryptFlag !== DECRYPT) {
+    const paddingCount = BLOCK - inArray.length % BLOCK
+    for (let i = 0; i < paddingCount; i++) inArray.push(paddingCount)
+  }
+
+  // 生成轮密钥
+  const roundKey = new Array(ROUND)
+  sms4KeyExt(key, roundKey, cryptFlag)
+
+  const outArray = []
+  let lastVector = iv
+  let restLen = inArray.length
+  let point = 0
+  while (restLen >= BLOCK) {
+    const input = inArray.slice(point, point + 16)
+    const output = new Array(16)
+
+    if (mode === 'cbc') {
+      for (let i = 0; i < BLOCK; i++) {
+        if (cryptFlag !== DECRYPT) {
+          // 加密过程在组加密前进行异或
+          input[i] ^= lastVector[i]
+        }
+      }
+    }
+
+    sms4Crypt(input, output, roundKey)
+
+
+    for (let i = 0; i < BLOCK; i++) {
+      if (mode === 'cbc') {
+        if (cryptFlag === DECRYPT) {
+          // 解密过程在组解密后进行异或
+          output[i] ^= lastVector[i]
+        }
+      }
+
+      outArray[point + i] = output[i]
+    }
+
+    if (mode === 'cbc') {
+      if (cryptFlag !== DECRYPT) {
+        // 使用上一次输出作为加密向量
+        lastVector = output
+      } else {
+        // 使用上一次输入作为解密向量
+        lastVector = input
+      }
+    }
+
+    restLen -= BLOCK
+    point += BLOCK
+  }
+
+  // 去除填充,sm4 是 16 个字节一个分组,所以统一走到 pkcs#7
+  if ((padding === 'pkcs#5' || padding === 'pkcs#7') && cryptFlag === DECRYPT) {
+    const len = outArray.length
+    const paddingCount = outArray[len - 1]
+    for (let i = 1; i <= paddingCount; i++) {
+      if (outArray[len - i] !== paddingCount) throw new Error('padding is invalid')
+    }
+    outArray.splice(len - paddingCount, paddingCount)
+  }
+
+  // 调整输出
+  if (output !== 'array') {
+    if (cryptFlag !== DECRYPT) {
+      // 加密,输出转 16 进制串
+      return ArrayToHex(outArray)
+    } else {
+      // 解密,输出转 utf8 串
+      return arrayToUtf8(outArray)
+    }
+  } else {
+    return outArray
+  }
+}
+
+module.exports = {
+  encrypt(inArray, key, options) {
+    return sm4(inArray, key, 1, options)
+  },
+  decrypt(inArray, key, options) {
+    return sm4(inArray, key, 0, options)
+  }
+}
+
+}, function(modId) { var map = {}; return __REQUIRE__(map[modId], modId); })
+return __REQUIRE__(1738722861364);
+})()
+//miniprogram-npm-outsideDeps=["jsbn"]
+//# sourceMappingURL=index.js.map

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
miniprogram_npm/sm-crypto/index.js.map


+ 28 - 0
node_modules/.package-lock.json

@@ -0,0 +1,28 @@
+{
+  "name": "Fuelwx",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "node_modules/jsbn": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
+      "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
+    },
+    "node_modules/miniprogram-sm-crypto": {
+      "version": "0.3.13",
+      "resolved": "https://registry.npmjs.org/miniprogram-sm-crypto/-/miniprogram-sm-crypto-0.3.13.tgz",
+      "integrity": "sha512-H7qwbCEmIXZzekCSgEWeHh1mb4cnz0E42YH3U5xqpOaJBB2Sj9ySq0hTGv0f+Jwo5SknABR6fw+EtjnMyJ/O/Q==",
+      "dependencies": {
+        "jsbn": "^1.1.0"
+      }
+    },
+    "node_modules/sm-crypto": {
+      "version": "0.3.13",
+      "resolved": "https://registry.npmjs.org/sm-crypto/-/sm-crypto-0.3.13.tgz",
+      "integrity": "sha512-ztNF+pZq6viCPMA1A6KKu3bgpkmYti5avykRHbcFIdSipFdkVmfUw2CnpM2kBJyppIalqvczLNM3wR8OQ0pT5w==",
+      "dependencies": {
+        "jsbn": "^1.1.0"
+      }
+    }
+  }
+}

+ 2 - 0
node_modules/jsbn/.npmignore

@@ -0,0 +1,2 @@
+node_modules
+.DS_Store

+ 16 - 0
node_modules/jsbn/CHANGELOG.md

@@ -0,0 +1,16 @@
+# v1.1.0
+
+- Allow for es6 "default import", e.g. `import BigInteger from 'jsbn'`.
+- Updated license file to read MIT
+
+
+# v1.0.0
+
+- breaking change: `require('jsbn')` no longer returns `BigInteger`. Use `require('jsbn').BigInteger` instead.
+
+
+
+# v0.1.1
+
+- fixed backwards-incompatible change in v0.1.0 where `require('jsbn') != BigInteger`. This patch version allows for `var BigInteger = require('jsbn')` or `var BigInteger = require('jsbn').BigInteger`.
+

+ 40 - 0
node_modules/jsbn/LICENSE

@@ -0,0 +1,40 @@
+Licensing
+---------
+
+This software is covered under the following copyright:
+
+/*
+ * Copyright (c) 2003-2005  Tom Wu
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ *
+ * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following condition applies:
+ *
+ * All redistributions must retain an intact copy of this copyright notice
+ * and disclaimer.
+ */
+
+Address all questions regarding this license to:
+
+  Tom Wu
+  tjw@cs.Stanford.EDU

+ 173 - 0
node_modules/jsbn/README.md

@@ -0,0 +1,173 @@
+# jsbn: javascript big number
+
+[Tom Wu's Original Website](http://www-cs-students.stanford.edu/~tjw/jsbn/)
+
+I felt compelled to put this on github and publish to npm. I haven't tested every other big integer library out there, but the few that I have tested in comparison to this one have not even come close in performance. I am aware of the `bi` module on npm, however it has been modified and I wanted to publish the original without modifications. This is jsbn and jsbn2 from Tom Wu's original website above, with the module pattern applied to prevent global leaks and to allow for use with node.js on the server side.
+
+## usage
+
+    var BigInteger = require('jsbn').BigInteger;
+
+    var bi = new BigInteger('91823918239182398123');
+    console.log(bi.bitLength()); // 67
+
+
+## API
+
+### bi.toString()
+
+returns the base-10 number as a string
+
+### bi.negate()
+
+returns a new BigInteger equal to the negation of `bi`
+
+### bi.abs
+
+returns new BI of absolute value
+
+### bi.compareTo
+
+
+
+### bi.bitLength
+
+
+
+### bi.mod
+
+
+
+### bi.modPowInt
+
+
+
+### bi.clone
+
+
+
+### bi.intValue
+
+
+
+### bi.byteValue
+
+
+
+### bi.shortValue
+
+
+
+### bi.signum
+
+
+
+### bi.toByteArray
+
+
+
+### bi.equals
+
+
+
+### bi.min
+
+
+
+### bi.max
+
+
+
+### bi.and
+
+
+
+### bi.or
+
+
+
+### bi.xor
+
+
+
+### bi.andNot
+
+
+
+### bi.not
+
+
+
+### bi.shiftLeft
+
+
+
+### bi.shiftRight
+
+
+
+### bi.getLowestSetBit
+
+
+
+### bi.bitCount
+
+
+
+### bi.testBit
+
+
+
+### bi.setBit
+
+
+
+### bi.clearBit
+
+
+
+### bi.flipBit
+
+
+
+### bi.add
+
+
+
+### bi.subtract
+
+
+
+### bi.multiply
+
+
+
+### bi.divide
+
+
+
+### bi.remainder
+
+
+
+### bi.divideAndRemainder
+
+
+
+### bi.modPow
+
+
+
+### bi.modInverse
+
+
+
+### bi.pow
+
+
+
+### bi.gcd
+
+
+
+### bi.isProbablePrime

+ 11 - 0
node_modules/jsbn/example.html

@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title></title>
+    </head>
+    <body>
+      <script src="index.js"></script>
+      <script src="example.js"></script>
+    </body>
+</html>

+ 5 - 0
node_modules/jsbn/example.js

@@ -0,0 +1,5 @@
+(function () {
+  var BigInteger = jsbn.BigInteger;
+  var a = new BigInteger('91823918239182398123');
+  console.log(a.bitLength());
+}());

+ 1361 - 0
node_modules/jsbn/index.js

@@ -0,0 +1,1361 @@
+(function(){
+
+    // Copyright (c) 2005  Tom Wu
+    // All Rights Reserved.
+    // See "LICENSE" for details.
+
+    // Basic JavaScript BN library - subset useful for RSA encryption.
+
+    // Bits per digit
+    var dbits;
+
+    // JavaScript engine analysis
+    var canary = 0xdeadbeefcafe;
+    var j_lm = ((canary&0xffffff)==0xefcafe);
+
+    // (public) Constructor
+    function BigInteger(a,b,c) {
+      if(a != null)
+        if("number" == typeof a) this.fromNumber(a,b,c);
+        else if(b == null && "string" != typeof a) this.fromString(a,256);
+        else this.fromString(a,b);
+    }
+
+    // return new, unset BigInteger
+    function nbi() { return new BigInteger(null); }
+
+    // am: Compute w_j += (x*this_i), propagate carries,
+    // c is initial carry, returns final carry.
+    // c < 3*dvalue, x < 2*dvalue, this_i < dvalue
+    // We need to select the fastest one that works in this environment.
+
+    // am1: use a single mult and divide to get the high bits,
+    // max digit bits should be 26 because
+    // max internal value = 2*dvalue^2-2*dvalue (< 2^53)
+    function am1(i,x,w,j,c,n) {
+      while(--n >= 0) {
+        var v = x*this[i++]+w[j]+c;
+        c = Math.floor(v/0x4000000);
+        w[j++] = v&0x3ffffff;
+      }
+      return c;
+    }
+    // am2 avoids a big mult-and-extract completely.
+    // Max digit bits should be <= 30 because we do bitwise ops
+    // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
+    function am2(i,x,w,j,c,n) {
+      var xl = x&0x7fff, xh = x>>15;
+      while(--n >= 0) {
+        var l = this[i]&0x7fff;
+        var h = this[i++]>>15;
+        var m = xh*l+h*xl;
+        l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
+        c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
+        w[j++] = l&0x3fffffff;
+      }
+      return c;
+    }
+    // Alternately, set max digit bits to 28 since some
+    // browsers slow down when dealing with 32-bit numbers.
+    function am3(i,x,w,j,c,n) {
+      var xl = x&0x3fff, xh = x>>14;
+      while(--n >= 0) {
+        var l = this[i]&0x3fff;
+        var h = this[i++]>>14;
+        var m = xh*l+h*xl;
+        l = xl*l+((m&0x3fff)<<14)+w[j]+c;
+        c = (l>>28)+(m>>14)+xh*h;
+        w[j++] = l&0xfffffff;
+      }
+      return c;
+    }
+    var inBrowser = typeof navigator !== "undefined";
+    if(inBrowser && j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
+      BigInteger.prototype.am = am2;
+      dbits = 30;
+    }
+    else if(inBrowser && j_lm && (navigator.appName != "Netscape")) {
+      BigInteger.prototype.am = am1;
+      dbits = 26;
+    }
+    else { // Mozilla/Netscape seems to prefer am3
+      BigInteger.prototype.am = am3;
+      dbits = 28;
+    }
+
+    BigInteger.prototype.DB = dbits;
+    BigInteger.prototype.DM = ((1<<dbits)-1);
+    BigInteger.prototype.DV = (1<<dbits);
+
+    var BI_FP = 52;
+    BigInteger.prototype.FV = Math.pow(2,BI_FP);
+    BigInteger.prototype.F1 = BI_FP-dbits;
+    BigInteger.prototype.F2 = 2*dbits-BI_FP;
+
+    // Digit conversions
+    var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
+    var BI_RC = new Array();
+    var rr,vv;
+    rr = "0".charCodeAt(0);
+    for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
+    rr = "a".charCodeAt(0);
+    for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
+    rr = "A".charCodeAt(0);
+    for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
+
+    function int2char(n) { return BI_RM.charAt(n); }
+    function intAt(s,i) {
+      var c = BI_RC[s.charCodeAt(i)];
+      return (c==null)?-1:c;
+    }
+
+    // (protected) copy this to r
+    function bnpCopyTo(r) {
+      for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
+      r.t = this.t;
+      r.s = this.s;
+    }
+
+    // (protected) set from integer value x, -DV <= x < DV
+    function bnpFromInt(x) {
+      this.t = 1;
+      this.s = (x<0)?-1:0;
+      if(x > 0) this[0] = x;
+      else if(x < -1) this[0] = x+this.DV;
+      else this.t = 0;
+    }
+
+    // return bigint initialized to value
+    function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
+
+    // (protected) set from string and radix
+    function bnpFromString(s,b) {
+      var k;
+      if(b == 16) k = 4;
+      else if(b == 8) k = 3;
+      else if(b == 256) k = 8; // byte array
+      else if(b == 2) k = 1;
+      else if(b == 32) k = 5;
+      else if(b == 4) k = 2;
+      else { this.fromRadix(s,b); return; }
+      this.t = 0;
+      this.s = 0;
+      var i = s.length, mi = false, sh = 0;
+      while(--i >= 0) {
+        var x = (k==8)?s[i]&0xff:intAt(s,i);
+        if(x < 0) {
+          if(s.charAt(i) == "-") mi = true;
+          continue;
+        }
+        mi = false;
+        if(sh == 0)
+          this[this.t++] = x;
+        else if(sh+k > this.DB) {
+          this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
+          this[this.t++] = (x>>(this.DB-sh));
+        }
+        else
+          this[this.t-1] |= x<<sh;
+        sh += k;
+        if(sh >= this.DB) sh -= this.DB;
+      }
+      if(k == 8 && (s[0]&0x80) != 0) {
+        this.s = -1;
+        if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
+      }
+      this.clamp();
+      if(mi) BigInteger.ZERO.subTo(this,this);
+    }
+
+    // (protected) clamp off excess high words
+    function bnpClamp() {
+      var c = this.s&this.DM;
+      while(this.t > 0 && this[this.t-1] == c) --this.t;
+    }
+
+    // (public) return string representation in given radix
+    function bnToString(b) {
+      if(this.s < 0) return "-"+this.negate().toString(b);
+      var k;
+      if(b == 16) k = 4;
+      else if(b == 8) k = 3;
+      else if(b == 2) k = 1;
+      else if(b == 32) k = 5;
+      else if(b == 4) k = 2;
+      else return this.toRadix(b);
+      var km = (1<<k)-1, d, m = false, r = "", i = this.t;
+      var p = this.DB-(i*this.DB)%k;
+      if(i-- > 0) {
+        if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
+        while(i >= 0) {
+          if(p < k) {
+            d = (this[i]&((1<<p)-1))<<(k-p);
+            d |= this[--i]>>(p+=this.DB-k);
+          }
+          else {
+            d = (this[i]>>(p-=k))&km;
+            if(p <= 0) { p += this.DB; --i; }
+          }
+          if(d > 0) m = true;
+          if(m) r += int2char(d);
+        }
+      }
+      return m?r:"0";
+    }
+
+    // (public) -this
+    function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
+
+    // (public) |this|
+    function bnAbs() { return (this.s<0)?this.negate():this; }
+
+    // (public) return + if this > a, - if this < a, 0 if equal
+    function bnCompareTo(a) {
+      var r = this.s-a.s;
+      if(r != 0) return r;
+      var i = this.t;
+      r = i-a.t;
+      if(r != 0) return (this.s<0)?-r:r;
+      while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
+      return 0;
+    }
+
+    // returns bit length of the integer x
+    function nbits(x) {
+      var r = 1, t;
+      if((t=x>>>16) != 0) { x = t; r += 16; }
+      if((t=x>>8) != 0) { x = t; r += 8; }
+      if((t=x>>4) != 0) { x = t; r += 4; }
+      if((t=x>>2) != 0) { x = t; r += 2; }
+      if((t=x>>1) != 0) { x = t; r += 1; }
+      return r;
+    }
+
+    // (public) return the number of bits in "this"
+    function bnBitLength() {
+      if(this.t <= 0) return 0;
+      return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
+    }
+
+    // (protected) r = this << n*DB
+    function bnpDLShiftTo(n,r) {
+      var i;
+      for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
+      for(i = n-1; i >= 0; --i) r[i] = 0;
+      r.t = this.t+n;
+      r.s = this.s;
+    }
+
+    // (protected) r = this >> n*DB
+    function bnpDRShiftTo(n,r) {
+      for(var i = n; i < this.t; ++i) r[i-n] = this[i];
+      r.t = Math.max(this.t-n,0);
+      r.s = this.s;
+    }
+
+    // (protected) r = this << n
+    function bnpLShiftTo(n,r) {
+      var bs = n%this.DB;
+      var cbs = this.DB-bs;
+      var bm = (1<<cbs)-1;
+      var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
+      for(i = this.t-1; i >= 0; --i) {
+        r[i+ds+1] = (this[i]>>cbs)|c;
+        c = (this[i]&bm)<<bs;
+      }
+      for(i = ds-1; i >= 0; --i) r[i] = 0;
+      r[ds] = c;
+      r.t = this.t+ds+1;
+      r.s = this.s;
+      r.clamp();
+    }
+
+    // (protected) r = this >> n
+    function bnpRShiftTo(n,r) {
+      r.s = this.s;
+      var ds = Math.floor(n/this.DB);
+      if(ds >= this.t) { r.t = 0; return; }
+      var bs = n%this.DB;
+      var cbs = this.DB-bs;
+      var bm = (1<<bs)-1;
+      r[0] = this[ds]>>bs;
+      for(var i = ds+1; i < this.t; ++i) {
+        r[i-ds-1] |= (this[i]&bm)<<cbs;
+        r[i-ds] = this[i]>>bs;
+      }
+      if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
+      r.t = this.t-ds;
+      r.clamp();
+    }
+
+    // (protected) r = this - a
+    function bnpSubTo(a,r) {
+      var i = 0, c = 0, m = Math.min(a.t,this.t);
+      while(i < m) {
+        c += this[i]-a[i];
+        r[i++] = c&this.DM;
+        c >>= this.DB;
+      }
+      if(a.t < this.t) {
+        c -= a.s;
+        while(i < this.t) {
+          c += this[i];
+          r[i++] = c&this.DM;
+          c >>= this.DB;
+        }
+        c += this.s;
+      }
+      else {
+        c += this.s;
+        while(i < a.t) {
+          c -= a[i];
+          r[i++] = c&this.DM;
+          c >>= this.DB;
+        }
+        c -= a.s;
+      }
+      r.s = (c<0)?-1:0;
+      if(c < -1) r[i++] = this.DV+c;
+      else if(c > 0) r[i++] = c;
+      r.t = i;
+      r.clamp();
+    }
+
+    // (protected) r = this * a, r != this,a (HAC 14.12)
+    // "this" should be the larger one if appropriate.
+    function bnpMultiplyTo(a,r) {
+      var x = this.abs(), y = a.abs();
+      var i = x.t;
+      r.t = i+y.t;
+      while(--i >= 0) r[i] = 0;
+      for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
+      r.s = 0;
+      r.clamp();
+      if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
+    }
+
+    // (protected) r = this^2, r != this (HAC 14.16)
+    function bnpSquareTo(r) {
+      var x = this.abs();
+      var i = r.t = 2*x.t;
+      while(--i >= 0) r[i] = 0;
+      for(i = 0; i < x.t-1; ++i) {
+        var c = x.am(i,x[i],r,2*i,0,1);
+        if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
+          r[i+x.t] -= x.DV;
+          r[i+x.t+1] = 1;
+        }
+      }
+      if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
+      r.s = 0;
+      r.clamp();
+    }
+
+    // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
+    // r != q, this != m.  q or r may be null.
+    function bnpDivRemTo(m,q,r) {
+      var pm = m.abs();
+      if(pm.t <= 0) return;
+      var pt = this.abs();
+      if(pt.t < pm.t) {
+        if(q != null) q.fromInt(0);
+        if(r != null) this.copyTo(r);
+        return;
+      }
+      if(r == null) r = nbi();
+      var y = nbi(), ts = this.s, ms = m.s;
+      var nsh = this.DB-nbits(pm[pm.t-1]);   // normalize modulus
+      if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
+      else { pm.copyTo(y); pt.copyTo(r); }
+      var ys = y.t;
+      var y0 = y[ys-1];
+      if(y0 == 0) return;
+      var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
+      var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
+      var i = r.t, j = i-ys, t = (q==null)?nbi():q;
+      y.dlShiftTo(j,t);
+      if(r.compareTo(t) >= 0) {
+        r[r.t++] = 1;
+        r.subTo(t,r);
+      }
+      BigInteger.ONE.dlShiftTo(ys,t);
+      t.subTo(y,y);  // "negative" y so we can replace sub with am later
+      while(y.t < ys) y[y.t++] = 0;
+      while(--j >= 0) {
+        // Estimate quotient digit
+        var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
+        if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) {   // Try it out
+          y.dlShiftTo(j,t);
+          r.subTo(t,r);
+          while(r[i] < --qd) r.subTo(t,r);
+        }
+      }
+      if(q != null) {
+        r.drShiftTo(ys,q);
+        if(ts != ms) BigInteger.ZERO.subTo(q,q);
+      }
+      r.t = ys;
+      r.clamp();
+      if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder
+      if(ts < 0) BigInteger.ZERO.subTo(r,r);
+    }
+
+    // (public) this mod a
+    function bnMod(a) {
+      var r = nbi();
+      this.abs().divRemTo(a,null,r);
+      if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
+      return r;
+    }
+
+    // Modular reduction using "classic" algorithm
+    function Classic(m) { this.m = m; }
+    function cConvert(x) {
+      if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
+      else return x;
+    }
+    function cRevert(x) { return x; }
+    function cReduce(x) { x.divRemTo(this.m,null,x); }
+    function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
+    function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
+
+    Classic.prototype.convert = cConvert;
+    Classic.prototype.revert = cRevert;
+    Classic.prototype.reduce = cReduce;
+    Classic.prototype.mulTo = cMulTo;
+    Classic.prototype.sqrTo = cSqrTo;
+
+    // (protected) return "-1/this % 2^DB"; useful for Mont. reduction
+    // justification:
+    //         xy == 1 (mod m)
+    //         xy =  1+km
+    //   xy(2-xy) = (1+km)(1-km)
+    // x[y(2-xy)] = 1-k^2m^2
+    // x[y(2-xy)] == 1 (mod m^2)
+    // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
+    // should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
+    // JS multiply "overflows" differently from C/C++, so care is needed here.
+    function bnpInvDigit() {
+      if(this.t < 1) return 0;
+      var x = this[0];
+      if((x&1) == 0) return 0;
+      var y = x&3;       // y == 1/x mod 2^2
+      y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4
+      y = (y*(2-(x&0xff)*y))&0xff;   // y == 1/x mod 2^8
+      y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff;    // y == 1/x mod 2^16
+      // last step - calculate inverse mod DV directly;
+      // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
+      y = (y*(2-x*y%this.DV))%this.DV;       // y == 1/x mod 2^dbits
+      // we really want the negative inverse, and -DV < y < DV
+      return (y>0)?this.DV-y:-y;
+    }
+
+    // Montgomery reduction
+    function Montgomery(m) {
+      this.m = m;
+      this.mp = m.invDigit();
+      this.mpl = this.mp&0x7fff;
+      this.mph = this.mp>>15;
+      this.um = (1<<(m.DB-15))-1;
+      this.mt2 = 2*m.t;
+    }
+
+    // xR mod m
+    function montConvert(x) {
+      var r = nbi();
+      x.abs().dlShiftTo(this.m.t,r);
+      r.divRemTo(this.m,null,r);
+      if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
+      return r;
+    }
+
+    // x/R mod m
+    function montRevert(x) {
+      var r = nbi();
+      x.copyTo(r);
+      this.reduce(r);
+      return r;
+    }
+
+    // x = x/R mod m (HAC 14.32)
+    function montReduce(x) {
+      while(x.t <= this.mt2) // pad x so am has enough room later
+        x[x.t++] = 0;
+      for(var i = 0; i < this.m.t; ++i) {
+        // faster way of calculating u0 = x[i]*mp mod DV
+        var j = x[i]&0x7fff;
+        var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
+        // use am to combine the multiply-shift-add into one call
+        j = i+this.m.t;
+        x[j] += this.m.am(0,u0,x,i,0,this.m.t);
+        // propagate carry
+        while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
+      }
+      x.clamp();
+      x.drShiftTo(this.m.t,x);
+      if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
+    }
+
+    // r = "x^2/R mod m"; x != r
+    function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
+
+    // r = "xy/R mod m"; x,y != r
+    function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
+
+    Montgomery.prototype.convert = montConvert;
+    Montgomery.prototype.revert = montRevert;
+    Montgomery.prototype.reduce = montReduce;
+    Montgomery.prototype.mulTo = montMulTo;
+    Montgomery.prototype.sqrTo = montSqrTo;
+
+    // (protected) true iff this is even
+    function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
+
+    // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
+    function bnpExp(e,z) {
+      if(e > 0xffffffff || e < 1) return BigInteger.ONE;
+      var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
+      g.copyTo(r);
+      while(--i >= 0) {
+        z.sqrTo(r,r2);
+        if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
+        else { var t = r; r = r2; r2 = t; }
+      }
+      return z.revert(r);
+    }
+
+    // (public) this^e % m, 0 <= e < 2^32
+    function bnModPowInt(e,m) {
+      var z;
+      if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
+      return this.exp(e,z);
+    }
+
+    // protected
+    BigInteger.prototype.copyTo = bnpCopyTo;
+    BigInteger.prototype.fromInt = bnpFromInt;
+    BigInteger.prototype.fromString = bnpFromString;
+    BigInteger.prototype.clamp = bnpClamp;
+    BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
+    BigInteger.prototype.drShiftTo = bnpDRShiftTo;
+    BigInteger.prototype.lShiftTo = bnpLShiftTo;
+    BigInteger.prototype.rShiftTo = bnpRShiftTo;
+    BigInteger.prototype.subTo = bnpSubTo;
+    BigInteger.prototype.multiplyTo = bnpMultiplyTo;
+    BigInteger.prototype.squareTo = bnpSquareTo;
+    BigInteger.prototype.divRemTo = bnpDivRemTo;
+    BigInteger.prototype.invDigit = bnpInvDigit;
+    BigInteger.prototype.isEven = bnpIsEven;
+    BigInteger.prototype.exp = bnpExp;
+
+    // public
+    BigInteger.prototype.toString = bnToString;
+    BigInteger.prototype.negate = bnNegate;
+    BigInteger.prototype.abs = bnAbs;
+    BigInteger.prototype.compareTo = bnCompareTo;
+    BigInteger.prototype.bitLength = bnBitLength;
+    BigInteger.prototype.mod = bnMod;
+    BigInteger.prototype.modPowInt = bnModPowInt;
+
+    // "constants"
+    BigInteger.ZERO = nbv(0);
+    BigInteger.ONE = nbv(1);
+
+    // Copyright (c) 2005-2009  Tom Wu
+    // All Rights Reserved.
+    // See "LICENSE" for details.
+
+    // Extended JavaScript BN functions, required for RSA private ops.
+
+    // Version 1.1: new BigInteger("0", 10) returns "proper" zero
+    // Version 1.2: square() API, isProbablePrime fix
+
+    // (public)
+    function bnClone() { var r = nbi(); this.copyTo(r); return r; }
+
+    // (public) return value as integer
+    function bnIntValue() {
+      if(this.s < 0) {
+        if(this.t == 1) return this[0]-this.DV;
+        else if(this.t == 0) return -1;
+      }
+      else if(this.t == 1) return this[0];
+      else if(this.t == 0) return 0;
+      // assumes 16 < DB < 32
+      return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];
+    }
+
+    // (public) return value as byte
+    function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }
+
+    // (public) return value as short (assumes DB>=16)
+    function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }
+
+    // (protected) return x s.t. r^x < DV
+    function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }
+
+    // (public) 0 if this == 0, 1 if this > 0
+    function bnSigNum() {
+      if(this.s < 0) return -1;
+      else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
+      else return 1;
+    }
+
+    // (protected) convert to radix string
+    function bnpToRadix(b) {
+      if(b == null) b = 10;
+      if(this.signum() == 0 || b < 2 || b > 36) return "0";
+      var cs = this.chunkSize(b);
+      var a = Math.pow(b,cs);
+      var d = nbv(a), y = nbi(), z = nbi(), r = "";
+      this.divRemTo(d,y,z);
+      while(y.signum() > 0) {
+        r = (a+z.intValue()).toString(b).substr(1) + r;
+        y.divRemTo(d,y,z);
+      }
+      return z.intValue().toString(b) + r;
+    }
+
+    // (protected) convert from radix string
+    function bnpFromRadix(s,b) {
+      this.fromInt(0);
+      if(b == null) b = 10;
+      var cs = this.chunkSize(b);
+      var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
+      for(var i = 0; i < s.length; ++i) {
+        var x = intAt(s,i);
+        if(x < 0) {
+          if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
+          continue;
+        }
+        w = b*w+x;
+        if(++j >= cs) {
+          this.dMultiply(d);
+          this.dAddOffset(w,0);
+          j = 0;
+          w = 0;
+        }
+      }
+      if(j > 0) {
+        this.dMultiply(Math.pow(b,j));
+        this.dAddOffset(w,0);
+      }
+      if(mi) BigInteger.ZERO.subTo(this,this);
+    }
+
+    // (protected) alternate constructor
+    function bnpFromNumber(a,b,c) {
+      if("number" == typeof b) {
+        // new BigInteger(int,int,RNG)
+        if(a < 2) this.fromInt(1);
+        else {
+          this.fromNumber(a,c);
+          if(!this.testBit(a-1))    // force MSB set
+            this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);
+          if(this.isEven()) this.dAddOffset(1,0); // force odd
+          while(!this.isProbablePrime(b)) {
+            this.dAddOffset(2,0);
+            if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);
+          }
+        }
+      }
+      else {
+        // new BigInteger(int,RNG)
+        var x = new Array(), t = a&7;
+        x.length = (a>>3)+1;
+        b.nextBytes(x);
+        if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
+        this.fromString(x,256);
+      }
+    }
+
+    // (public) convert to bigendian byte array
+    function bnToByteArray() {
+      var i = this.t, r = new Array();
+      r[0] = this.s;
+      var p = this.DB-(i*this.DB)%8, d, k = 0;
+      if(i-- > 0) {
+        if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)
+          r[k++] = d|(this.s<<(this.DB-p));
+        while(i >= 0) {
+          if(p < 8) {
+            d = (this[i]&((1<<p)-1))<<(8-p);
+            d |= this[--i]>>(p+=this.DB-8);
+          }
+          else {
+            d = (this[i]>>(p-=8))&0xff;
+            if(p <= 0) { p += this.DB; --i; }
+          }
+          if((d&0x80) != 0) d |= -256;
+          if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
+          if(k > 0 || d != this.s) r[k++] = d;
+        }
+      }
+      return r;
+    }
+
+    function bnEquals(a) { return(this.compareTo(a)==0); }
+    function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
+    function bnMax(a) { return(this.compareTo(a)>0)?this:a; }
+
+    // (protected) r = this op a (bitwise)
+    function bnpBitwiseTo(a,op,r) {
+      var i, f, m = Math.min(a.t,this.t);
+      for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);
+      if(a.t < this.t) {
+        f = a.s&this.DM;
+        for(i = m; i < this.t; ++i) r[i] = op(this[i],f);
+        r.t = this.t;
+      }
+      else {
+        f = this.s&this.DM;
+        for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);
+        r.t = a.t;
+      }
+      r.s = op(this.s,a.s);
+      r.clamp();
+    }
+
+    // (public) this & a
+    function op_and(x,y) { return x&y; }
+    function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }
+
+    // (public) this | a
+    function op_or(x,y) { return x|y; }
+    function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }
+
+    // (public) this ^ a
+    function op_xor(x,y) { return x^y; }
+    function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }
+
+    // (public) this & ~a
+    function op_andnot(x,y) { return x&~y; }
+    function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }
+
+    // (public) ~this
+    function bnNot() {
+      var r = nbi();
+      for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];
+      r.t = this.t;
+      r.s = ~this.s;
+      return r;
+    }
+
+    // (public) this << n
+    function bnShiftLeft(n) {
+      var r = nbi();
+      if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);
+      return r;
+    }
+
+    // (public) this >> n
+    function bnShiftRight(n) {
+      var r = nbi();
+      if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);
+      return r;
+    }
+
+    // return index of lowest 1-bit in x, x < 2^31
+    function lbit(x) {
+      if(x == 0) return -1;
+      var r = 0;
+      if((x&0xffff) == 0) { x >>= 16; r += 16; }
+      if((x&0xff) == 0) { x >>= 8; r += 8; }
+      if((x&0xf) == 0) { x >>= 4; r += 4; }
+      if((x&3) == 0) { x >>= 2; r += 2; }
+      if((x&1) == 0) ++r;
+      return r;
+    }
+
+    // (public) returns index of lowest 1-bit (or -1 if none)
+    function bnGetLowestSetBit() {
+      for(var i = 0; i < this.t; ++i)
+        if(this[i] != 0) return i*this.DB+lbit(this[i]);
+      if(this.s < 0) return this.t*this.DB;
+      return -1;
+    }
+
+    // return number of 1 bits in x
+    function cbit(x) {
+      var r = 0;
+      while(x != 0) { x &= x-1; ++r; }
+      return r;
+    }
+
+    // (public) return number of set bits
+    function bnBitCount() {
+      var r = 0, x = this.s&this.DM;
+      for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);
+      return r;
+    }
+
+    // (public) true iff nth bit is set
+    function bnTestBit(n) {
+      var j = Math.floor(n/this.DB);
+      if(j >= this.t) return(this.s!=0);
+      return((this[j]&(1<<(n%this.DB)))!=0);
+    }
+
+    // (protected) this op (1<<n)
+    function bnpChangeBit(n,op) {
+      var r = BigInteger.ONE.shiftLeft(n);
+      this.bitwiseTo(r,op,r);
+      return r;
+    }
+
+    // (public) this | (1<<n)
+    function bnSetBit(n) { return this.changeBit(n,op_or); }
+
+    // (public) this & ~(1<<n)
+    function bnClearBit(n) { return this.changeBit(n,op_andnot); }
+
+    // (public) this ^ (1<<n)
+    function bnFlipBit(n) { return this.changeBit(n,op_xor); }
+
+    // (protected) r = this + a
+    function bnpAddTo(a,r) {
+      var i = 0, c = 0, m = Math.min(a.t,this.t);
+      while(i < m) {
+        c += this[i]+a[i];
+        r[i++] = c&this.DM;
+        c >>= this.DB;
+      }
+      if(a.t < this.t) {
+        c += a.s;
+        while(i < this.t) {
+          c += this[i];
+          r[i++] = c&this.DM;
+          c >>= this.DB;
+        }
+        c += this.s;
+      }
+      else {
+        c += this.s;
+        while(i < a.t) {
+          c += a[i];
+          r[i++] = c&this.DM;
+          c >>= this.DB;
+        }
+        c += a.s;
+      }
+      r.s = (c<0)?-1:0;
+      if(c > 0) r[i++] = c;
+      else if(c < -1) r[i++] = this.DV+c;
+      r.t = i;
+      r.clamp();
+    }
+
+    // (public) this + a
+    function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }
+
+    // (public) this - a
+    function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }
+
+    // (public) this * a
+    function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }
+
+    // (public) this^2
+    function bnSquare() { var r = nbi(); this.squareTo(r); return r; }
+
+    // (public) this / a
+    function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }
+
+    // (public) this % a
+    function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }
+
+    // (public) [this/a,this%a]
+    function bnDivideAndRemainder(a) {
+      var q = nbi(), r = nbi();
+      this.divRemTo(a,q,r);
+      return new Array(q,r);
+    }
+
+    // (protected) this *= n, this >= 0, 1 < n < DV
+    function bnpDMultiply(n) {
+      this[this.t] = this.am(0,n-1,this,0,0,this.t);
+      ++this.t;
+      this.clamp();
+    }
+
+    // (protected) this += n << w words, this >= 0
+    function bnpDAddOffset(n,w) {
+      if(n == 0) return;
+      while(this.t <= w) this[this.t++] = 0;
+      this[w] += n;
+      while(this[w] >= this.DV) {
+        this[w] -= this.DV;
+        if(++w >= this.t) this[this.t++] = 0;
+        ++this[w];
+      }
+    }
+
+    // A "null" reducer
+    function NullExp() {}
+    function nNop(x) { return x; }
+    function nMulTo(x,y,r) { x.multiplyTo(y,r); }
+    function nSqrTo(x,r) { x.squareTo(r); }
+
+    NullExp.prototype.convert = nNop;
+    NullExp.prototype.revert = nNop;
+    NullExp.prototype.mulTo = nMulTo;
+    NullExp.prototype.sqrTo = nSqrTo;
+
+    // (public) this^e
+    function bnPow(e) { return this.exp(e,new NullExp()); }
+
+    // (protected) r = lower n words of "this * a", a.t <= n
+    // "this" should be the larger one if appropriate.
+    function bnpMultiplyLowerTo(a,n,r) {
+      var i = Math.min(this.t+a.t,n);
+      r.s = 0; // assumes a,this >= 0
+      r.t = i;
+      while(i > 0) r[--i] = 0;
+      var j;
+      for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);
+      for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);
+      r.clamp();
+    }
+
+    // (protected) r = "this * a" without lower n words, n > 0
+    // "this" should be the larger one if appropriate.
+    function bnpMultiplyUpperTo(a,n,r) {
+      --n;
+      var i = r.t = this.t+a.t-n;
+      r.s = 0; // assumes a,this >= 0
+      while(--i >= 0) r[i] = 0;
+      for(i = Math.max(n-this.t,0); i < a.t; ++i)
+        r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);
+      r.clamp();
+      r.drShiftTo(1,r);
+    }
+
+    // Barrett modular reduction
+    function Barrett(m) {
+      // setup Barrett
+      this.r2 = nbi();
+      this.q3 = nbi();
+      BigInteger.ONE.dlShiftTo(2*m.t,this.r2);
+      this.mu = this.r2.divide(m);
+      this.m = m;
+    }
+
+    function barrettConvert(x) {
+      if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);
+      else if(x.compareTo(this.m) < 0) return x;
+      else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
+    }
+
+    function barrettRevert(x) { return x; }
+
+    // x = x mod m (HAC 14.42)
+    function barrettReduce(x) {
+      x.drShiftTo(this.m.t-1,this.r2);
+      if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }
+      this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);
+      this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);
+      while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);
+      x.subTo(this.r2,x);
+      while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
+    }
+
+    // r = x^2 mod m; x != r
+    function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
+
+    // r = x*y mod m; x,y != r
+    function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
+
+    Barrett.prototype.convert = barrettConvert;
+    Barrett.prototype.revert = barrettRevert;
+    Barrett.prototype.reduce = barrettReduce;
+    Barrett.prototype.mulTo = barrettMulTo;
+    Barrett.prototype.sqrTo = barrettSqrTo;
+
+    // (public) this^e % m (HAC 14.85)
+    function bnModPow(e,m) {
+      var i = e.bitLength(), k, r = nbv(1), z;
+      if(i <= 0) return r;
+      else if(i < 18) k = 1;
+      else if(i < 48) k = 3;
+      else if(i < 144) k = 4;
+      else if(i < 768) k = 5;
+      else k = 6;
+      if(i < 8)
+        z = new Classic(m);
+      else if(m.isEven())
+        z = new Barrett(m);
+      else
+        z = new Montgomery(m);
+
+      // precomputation
+      var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;
+      g[1] = z.convert(this);
+      if(k > 1) {
+        var g2 = nbi();
+        z.sqrTo(g[1],g2);
+        while(n <= km) {
+          g[n] = nbi();
+          z.mulTo(g2,g[n-2],g[n]);
+          n += 2;
+        }
+      }
+
+      var j = e.t-1, w, is1 = true, r2 = nbi(), t;
+      i = nbits(e[j])-1;
+      while(j >= 0) {
+        if(i >= k1) w = (e[j]>>(i-k1))&km;
+        else {
+          w = (e[j]&((1<<(i+1))-1))<<(k1-i);
+          if(j > 0) w |= e[j-1]>>(this.DB+i-k1);
+        }
+
+        n = k;
+        while((w&1) == 0) { w >>= 1; --n; }
+        if((i -= n) < 0) { i += this.DB; --j; }
+        if(is1) {    // ret == 1, don't bother squaring or multiplying it
+          g[w].copyTo(r);
+          is1 = false;
+        }
+        else {
+          while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }
+          if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }
+          z.mulTo(r2,g[w],r);
+        }
+
+        while(j >= 0 && (e[j]&(1<<i)) == 0) {
+          z.sqrTo(r,r2); t = r; r = r2; r2 = t;
+          if(--i < 0) { i = this.DB-1; --j; }
+        }
+      }
+      return z.revert(r);
+    }
+
+    // (public) gcd(this,a) (HAC 14.54)
+    function bnGCD(a) {
+      var x = (this.s<0)?this.negate():this.clone();
+      var y = (a.s<0)?a.negate():a.clone();
+      if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }
+      var i = x.getLowestSetBit(), g = y.getLowestSetBit();
+      if(g < 0) return x;
+      if(i < g) g = i;
+      if(g > 0) {
+        x.rShiftTo(g,x);
+        y.rShiftTo(g,y);
+      }
+      while(x.signum() > 0) {
+        if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);
+        if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);
+        if(x.compareTo(y) >= 0) {
+          x.subTo(y,x);
+          x.rShiftTo(1,x);
+        }
+        else {
+          y.subTo(x,y);
+          y.rShiftTo(1,y);
+        }
+      }
+      if(g > 0) y.lShiftTo(g,y);
+      return y;
+    }
+
+    // (protected) this % n, n < 2^26
+    function bnpModInt(n) {
+      if(n <= 0) return 0;
+      var d = this.DV%n, r = (this.s<0)?n-1:0;
+      if(this.t > 0)
+        if(d == 0) r = this[0]%n;
+        else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;
+      return r;
+    }
+
+    // (public) 1/this % m (HAC 14.61)
+    function bnModInverse(m) {
+      var ac = m.isEven();
+      if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
+      var u = m.clone(), v = this.clone();
+      var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
+      while(u.signum() != 0) {
+        while(u.isEven()) {
+          u.rShiftTo(1,u);
+          if(ac) {
+            if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
+            a.rShiftTo(1,a);
+          }
+          else if(!b.isEven()) b.subTo(m,b);
+          b.rShiftTo(1,b);
+        }
+        while(v.isEven()) {
+          v.rShiftTo(1,v);
+          if(ac) {
+            if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
+            c.rShiftTo(1,c);
+          }
+          else if(!d.isEven()) d.subTo(m,d);
+          d.rShiftTo(1,d);
+        }
+        if(u.compareTo(v) >= 0) {
+          u.subTo(v,u);
+          if(ac) a.subTo(c,a);
+          b.subTo(d,b);
+        }
+        else {
+          v.subTo(u,v);
+          if(ac) c.subTo(a,c);
+          d.subTo(b,d);
+        }
+      }
+      if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
+      if(d.compareTo(m) >= 0) return d.subtract(m);
+      if(d.signum() < 0) d.addTo(m,d); else return d;
+      if(d.signum() < 0) return d.add(m); else return d;
+    }
+
+    var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997];
+    var lplim = (1<<26)/lowprimes[lowprimes.length-1];
+
+    // (public) test primality with certainty >= 1-.5^t
+    function bnIsProbablePrime(t) {
+      var i, x = this.abs();
+      if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {
+        for(i = 0; i < lowprimes.length; ++i)
+          if(x[0] == lowprimes[i]) return true;
+        return false;
+      }
+      if(x.isEven()) return false;
+      i = 1;
+      while(i < lowprimes.length) {
+        var m = lowprimes[i], j = i+1;
+        while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];
+        m = x.modInt(m);
+        while(i < j) if(m%lowprimes[i++] == 0) return false;
+      }
+      return x.millerRabin(t);
+    }
+
+    // (protected) true if probably prime (HAC 4.24, Miller-Rabin)
+    function bnpMillerRabin(t) {
+      var n1 = this.subtract(BigInteger.ONE);
+      var k = n1.getLowestSetBit();
+      if(k <= 0) return false;
+      var r = n1.shiftRight(k);
+      t = (t+1)>>1;
+      if(t > lowprimes.length) t = lowprimes.length;
+      var a = nbi();
+      for(var i = 0; i < t; ++i) {
+        //Pick bases at random, instead of starting at 2
+        a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);
+        var y = a.modPow(r,this);
+        if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
+          var j = 1;
+          while(j++ < k && y.compareTo(n1) != 0) {
+            y = y.modPowInt(2,this);
+            if(y.compareTo(BigInteger.ONE) == 0) return false;
+          }
+          if(y.compareTo(n1) != 0) return false;
+        }
+      }
+      return true;
+    }
+
+    // protected
+    BigInteger.prototype.chunkSize = bnpChunkSize;
+    BigInteger.prototype.toRadix = bnpToRadix;
+    BigInteger.prototype.fromRadix = bnpFromRadix;
+    BigInteger.prototype.fromNumber = bnpFromNumber;
+    BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
+    BigInteger.prototype.changeBit = bnpChangeBit;
+    BigInteger.prototype.addTo = bnpAddTo;
+    BigInteger.prototype.dMultiply = bnpDMultiply;
+    BigInteger.prototype.dAddOffset = bnpDAddOffset;
+    BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
+    BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
+    BigInteger.prototype.modInt = bnpModInt;
+    BigInteger.prototype.millerRabin = bnpMillerRabin;
+
+    // public
+    BigInteger.prototype.clone = bnClone;
+    BigInteger.prototype.intValue = bnIntValue;
+    BigInteger.prototype.byteValue = bnByteValue;
+    BigInteger.prototype.shortValue = bnShortValue;
+    BigInteger.prototype.signum = bnSigNum;
+    BigInteger.prototype.toByteArray = bnToByteArray;
+    BigInteger.prototype.equals = bnEquals;
+    BigInteger.prototype.min = bnMin;
+    BigInteger.prototype.max = bnMax;
+    BigInteger.prototype.and = bnAnd;
+    BigInteger.prototype.or = bnOr;
+    BigInteger.prototype.xor = bnXor;
+    BigInteger.prototype.andNot = bnAndNot;
+    BigInteger.prototype.not = bnNot;
+    BigInteger.prototype.shiftLeft = bnShiftLeft;
+    BigInteger.prototype.shiftRight = bnShiftRight;
+    BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
+    BigInteger.prototype.bitCount = bnBitCount;
+    BigInteger.prototype.testBit = bnTestBit;
+    BigInteger.prototype.setBit = bnSetBit;
+    BigInteger.prototype.clearBit = bnClearBit;
+    BigInteger.prototype.flipBit = bnFlipBit;
+    BigInteger.prototype.add = bnAdd;
+    BigInteger.prototype.subtract = bnSubtract;
+    BigInteger.prototype.multiply = bnMultiply;
+    BigInteger.prototype.divide = bnDivide;
+    BigInteger.prototype.remainder = bnRemainder;
+    BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
+    BigInteger.prototype.modPow = bnModPow;
+    BigInteger.prototype.modInverse = bnModInverse;
+    BigInteger.prototype.pow = bnPow;
+    BigInteger.prototype.gcd = bnGCD;
+    BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
+
+    // JSBN-specific extension
+    BigInteger.prototype.square = bnSquare;
+
+    // Expose the Barrett function
+    BigInteger.prototype.Barrett = Barrett
+
+    // BigInteger interfaces not implemented in jsbn:
+
+    // BigInteger(int signum, byte[] magnitude)
+    // double doubleValue()
+    // float floatValue()
+    // int hashCode()
+    // long longValue()
+    // static BigInteger valueOf(long val)
+
+    // Random number generator - requires a PRNG backend, e.g. prng4.js
+
+    // For best results, put code like
+    // <body onClick='rng_seed_time();' onKeyPress='rng_seed_time();'>
+    // in your main HTML document.
+
+    var rng_state;
+    var rng_pool;
+    var rng_pptr;
+
+    // Mix in a 32-bit integer into the pool
+    function rng_seed_int(x) {
+      rng_pool[rng_pptr++] ^= x & 255;
+      rng_pool[rng_pptr++] ^= (x >> 8) & 255;
+      rng_pool[rng_pptr++] ^= (x >> 16) & 255;
+      rng_pool[rng_pptr++] ^= (x >> 24) & 255;
+      if(rng_pptr >= rng_psize) rng_pptr -= rng_psize;
+    }
+
+    // Mix in the current time (w/milliseconds) into the pool
+    function rng_seed_time() {
+      rng_seed_int(new Date().getTime());
+    }
+
+    // Initialize the pool with junk if needed.
+    if(rng_pool == null) {
+      rng_pool = new Array();
+      rng_pptr = 0;
+      var t;
+      if(typeof window !== "undefined" && window.crypto) {
+        if (window.crypto.getRandomValues) {
+          // Use webcrypto if available
+          var ua = new Uint8Array(32);
+          window.crypto.getRandomValues(ua);
+          for(t = 0; t < 32; ++t)
+            rng_pool[rng_pptr++] = ua[t];
+        }
+        else if(navigator.appName == "Netscape" && navigator.appVersion < "5") {
+          // Extract entropy (256 bits) from NS4 RNG if available
+          var z = window.crypto.random(32);
+          for(t = 0; t < z.length; ++t)
+            rng_pool[rng_pptr++] = z.charCodeAt(t) & 255;
+        }
+      }
+      while(rng_pptr < rng_psize) {  // extract some randomness from Math.random()
+        t = Math.floor(65536 * Math.random());
+        rng_pool[rng_pptr++] = t >>> 8;
+        rng_pool[rng_pptr++] = t & 255;
+      }
+      rng_pptr = 0;
+      rng_seed_time();
+      //rng_seed_int(window.screenX);
+      //rng_seed_int(window.screenY);
+    }
+
+    function rng_get_byte() {
+      if(rng_state == null) {
+        rng_seed_time();
+        rng_state = prng_newstate();
+        rng_state.init(rng_pool);
+        for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr)
+          rng_pool[rng_pptr] = 0;
+        rng_pptr = 0;
+        //rng_pool = null;
+      }
+      // TODO: allow reseeding after first request
+      return rng_state.next();
+    }
+
+    function rng_get_bytes(ba) {
+      var i;
+      for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte();
+    }
+
+    function SecureRandom() {}
+
+    SecureRandom.prototype.nextBytes = rng_get_bytes;
+
+    // prng4.js - uses Arcfour as a PRNG
+
+    function Arcfour() {
+      this.i = 0;
+      this.j = 0;
+      this.S = new Array();
+    }
+
+    // Initialize arcfour context from key, an array of ints, each from [0..255]
+    function ARC4init(key) {
+      var i, j, t;
+      for(i = 0; i < 256; ++i)
+        this.S[i] = i;
+      j = 0;
+      for(i = 0; i < 256; ++i) {
+        j = (j + this.S[i] + key[i % key.length]) & 255;
+        t = this.S[i];
+        this.S[i] = this.S[j];
+        this.S[j] = t;
+      }
+      this.i = 0;
+      this.j = 0;
+    }
+
+    function ARC4next() {
+      var t;
+      this.i = (this.i + 1) & 255;
+      this.j = (this.j + this.S[this.i]) & 255;
+      t = this.S[this.i];
+      this.S[this.i] = this.S[this.j];
+      this.S[this.j] = t;
+      return this.S[(t + this.S[this.i]) & 255];
+    }
+
+    Arcfour.prototype.init = ARC4init;
+    Arcfour.prototype.next = ARC4next;
+
+    // Plug in your RNG constructor here
+    function prng_newstate() {
+      return new Arcfour();
+    }
+
+    // Pool size must be a multiple of 4 and greater than 32.
+    // An array of bytes the size of the pool will be passed to init()
+    var rng_psize = 256;
+
+    if (typeof exports !== 'undefined') {
+        exports = module.exports = {
+            default: BigInteger,
+            BigInteger: BigInteger,
+            SecureRandom: SecureRandom,
+        };
+    } else {
+        this.jsbn = {
+          BigInteger: BigInteger,
+          SecureRandom: SecureRandom
+        };
+    }
+
+}).call(this);

+ 21 - 0
node_modules/jsbn/package.json

@@ -0,0 +1,21 @@
+{
+  "name": "jsbn",
+  "version": "1.1.0",
+  "description": "The jsbn library is a fast, portable implementation of large-number math in pure JavaScript, enabling public-key crypto and other applications on desktop and mobile browsers.",
+  "main": "index.js",
+  "scripts": {
+    "test": "mocha test.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/andyperlitch/jsbn.git"
+  },
+  "keywords": [
+    "biginteger",
+    "bignumber",
+    "big",
+    "integer"
+  ],
+  "author": "Tom Wu",
+  "license": "MIT"
+}

+ 3 - 0
node_modules/jsbn/test/es6-import.js

@@ -0,0 +1,3 @@
+import {BigInteger} from '../';
+
+console.log(typeof BigInteger)

+ 11 - 0
node_modules/miniprogram-sm-crypto/.babelrc

@@ -0,0 +1,11 @@
+{
+    "plugins": [
+        ["module-resolver", {
+            "root": ["./src"],
+            "alias": {}
+        }]
+    ],
+    "presets": [
+        ["env", {"loose": true, "modules": "commonjs"}]
+    ]
+}

+ 97 - 0
node_modules/miniprogram-sm-crypto/.eslintrc.js

@@ -0,0 +1,97 @@
+module.exports = {
+  'extends': [
+    'airbnb-base',
+    'plugin:promise/recommended'
+  ],
+  'parserOptions': {
+    'ecmaVersion': 9,
+    'ecmaFeatures': {
+      'jsx': false
+    },
+    'sourceType': 'module'
+  },
+  'env': {
+    'es6': true,
+    'node': true,
+    'jest': true
+  },
+  'plugins': [
+    'import',
+    'node',
+    'promise'
+  ],
+  'rules': {
+    'arrow-parens': 'off',
+    'comma-dangle': [
+      'error',
+      'only-multiline'
+    ],
+    'complexity': ['error', 20],
+    'func-names': 'off',
+    'global-require': 'off',
+    'handle-callback-err': [
+      'error',
+      '^(err|error)$'
+    ],
+    'import/no-unresolved': [
+      'error',
+      {
+        'caseSensitive': true,
+        'commonjs': true,
+        'ignore': ['^[^.]']
+      }
+    ],
+    'import/prefer-default-export': 'off',
+    'linebreak-style': 'off',
+    'no-catch-shadow': 'error',
+    'no-continue': 'off',
+    'no-div-regex': 'warn',
+    'no-else-return': 'off',
+    'no-param-reassign': 'off',
+    'no-plusplus': 'off',
+    'no-shadow': 'off',
+    'no-multi-assign': 'off',
+    'no-underscore-dangle': 'off',
+    'node/no-deprecated-api': 'error',
+    'node/process-exit-as-throw': 'error',
+    'object-curly-spacing': [
+      'error',
+      'never'
+    ],
+    'operator-linebreak': [
+      'error',
+      'after',
+      {
+        'overrides': {
+          ':': 'before',
+          '?': 'before'
+        }
+      }
+    ],
+    'prefer-arrow-callback': 'off',
+    'prefer-destructuring': 'off',
+    'prefer-template': 'off',
+    'quote-props': [
+      1,
+      'as-needed',
+      {
+        'unnecessary': true
+      }
+    ],
+    'semi': [
+      'error',
+      'never'
+    ],
+    'max-len': 'off',
+    'no-bitwise': 'off',
+    'no-mixed-operators': 'off',
+  },
+  'globals': {
+    'window': true,
+    'document': true,
+    'App': true,
+    'Page': true,
+    'Component': true,
+    'Behavior': true
+  }
+}

+ 21 - 0
node_modules/miniprogram-sm-crypto/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018 
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 168 - 0
node_modules/miniprogram-sm-crypto/README.md

@@ -0,0 +1,168 @@
+# sm-crypto
+
+小程序 js 库。国密算法 sm2、sm3 和 sm4 的实现。
+
+> 使用此组件需要依赖小程序基础库 2.2.1 以上版本,同时依赖开发者工具的 npm 构建。具体详情可查阅[官方 npm 文档](https://developers.weixin.qq.com/miniprogram/dev/devtools/npm.html)。
+
+## 安装
+
+```bash
+npm install --save miniprogram-sm-crypto
+```
+
+## sm2
+
+### 获取密钥对
+
+```js
+const sm2 = require('miniprogram-sm-crypto').sm2
+
+let keypair = sm2.generateKeyPairHex()
+
+publicKey = keypair.publicKey // 公钥
+privateKey = keypair.privateKey // 私钥
+
+// 默认生成公钥 130 位太长,可以压缩公钥到 66 位
+const compressedPublicKey = sm2.compressPublicKeyHex(publicKey) // compressedPublicKey 和 publicKey 等价
+sm2.comparePublicKeyHex(publicKey, compressedPublicKey) // 判断公钥是否等价
+
+// 自定义随机数,参数会直接透传给 jsbn 库的 BigInteger 构造器
+// 注意:开发者使用自定义随机数,需要自行确保传入的随机数符合密码学安全
+let keypair2 = sm2.generateKeyPairHex('123123123123123')
+let keypair3 = sm2.generateKeyPairHex(256, SecureRandom)
+
+let verifyResult = sm2.verifyPublicKey(publicKey) // 验证公钥
+verifyResult = sm2.verifyPublicKey(compressedPublicKey) // 验证公钥
+```
+
+### 加密解密
+
+```js
+const sm2 = require('miniprogram-sm-crypto').sm2
+const cipherMode = 1 // 1 - C1C3C2,0 - C1C2C3,默认为1
+
+let encryptData = sm2.doEncrypt(msgString, publicKey, cipherMode) // 加密结果
+let decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode) // 解密结果
+
+encryptData = sm2.doEncrypt(msgArray, publicKey, cipherMode) // 加密结果,输入数组
+decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode, {output: 'array'}) // 解密结果,输出数组
+```
+
+> ps:密文会在解密时自动补充 `04`,如遇到其他工具补充的 `04` 需手动去除再传入。
+
+### 签名验签
+
+> ps:理论上来说,只做纯签名是最快的。
+
+```js
+const sm2 = require('miniprogram-sm-crypto').sm2
+
+// 纯签名 + 生成椭圆曲线点
+let sigValueHex = sm2.doSignature(msg, privateKey) // 签名
+let verifyResult = sm2.doVerifySignature(msg, sigValueHex, publicKey) // 验签结果
+
+// 纯签名
+let sigValueHex2 = sm2.doSignature(msg, privateKey, {
+    pointPool: [sm2.getPoint(), sm2.getPoint(), sm2.getPoint(), sm2.getPoint()], // 传入事先已生成好的椭圆曲线点,可加快签名速度
+}) // 签名
+let verifyResult2 = sm2.doVerifySignature(msg, sigValueHex2, publicKey) // 验签结果
+
+// 纯签名 + 生成椭圆曲线点 + der编解码
+let sigValueHex3 = sm2.doSignature(msg, privateKey, {
+    der: true,
+}) // 签名
+let verifyResult3 = sm2.doVerifySignature(msg, sigValueHex3, publicKey, {
+    der: true,
+}) // 验签结果
+
+// 纯签名 + 生成椭圆曲线点 + sm3杂凑
+let sigValueHex4 = sm2.doSignature(msg, privateKey, {
+    hash: true,
+}) // 签名
+let verifyResult4 = sm2.doVerifySignature(msg, sigValueHex4, publicKey, {
+    hash: true,
+}) // 验签结果
+
+// 纯签名 + 生成椭圆曲线点 + sm3杂凑(不做公钥推导)
+let sigValueHex5 = sm2.doSignature(msg, privateKey, {
+    hash: true,
+    publicKey, // 传入公钥的话,可以去掉sm3杂凑中推导公钥的过程,速度会比纯签名 + 生成椭圆曲线点 + sm3杂凑快
+})
+let verifyResult5 = sm2.doVerifySignature(msg, sigValueHex5, publicKey, {
+    hash: true,
+    publicKey,
+})
+
+// 纯签名 + 生成椭圆曲线点 + sm3杂凑 + 不做公钥推 + 添加 userId(长度小于 8192)
+// 默认 userId 值为 1234567812345678
+let sigValueHex6 = sm2.doSignature(msgString, privateKey, {
+    hash: true,
+    publicKey,
+    userId: 'testUserId',
+})
+let verifyResult6 = sm2.doVerifySignature(msgString, sigValueHex6, publicKey, {
+    hash: true,
+    userId: 'testUserId',
+})
+```
+
+### 获取椭圆曲线点
+
+```js
+const sm2 = require('miniprogram-sm-crypto').sm2
+
+let point = sm2.getPoint() // 获取一个椭圆曲线点,可在sm2签名时传入
+```
+
+### 根据私钥获取公钥
+
+```js
+const sm2 = require('sm-crypto).sm2
+
+let publicKey = sm2.getPublicKeyFromPrivateKey(privateKey)
+```
+
+## sm3
+
+```js
+const sm3 = require('miniprogram-sm-crypto').sm3
+
+let hashData = sm3('abc') // 杂凑
+
+// hmac
+hashData = sm3('abc', {
+    key: 'daac25c1512fe50f79b0e4526b93f5c0e1460cef40b6dd44af13caec62e8c60e0d885f3c6d6fb51e530889e6fd4ac743a6d332e68a0f2a3923f42585dceb93e9', // 要求为 16 进制串或字节数组
+})
+```
+
+## sm4
+
+### 加密
+
+```js
+const sm4 = require('miniprogram-sm-crypto').sm4
+const msg = 'hello world! 我是 juneandgreen.' // 可以为 utf8 串或字节数组
+const key = '0123456789abcdeffedcba9876543210' // 可以为 16 进制串或字节数组,要求为 128 比特
+
+let encryptData = sm4.encrypt(msg, key) // 加密,默认输出 16 进制字符串,默认使用 pkcs#7 填充(传 pkcs#5 也会走 pkcs#7 填充)
+let encryptData = sm4.encrypt(msg, key, {padding: 'none'}) // 加密,不使用 padding
+let encryptData = sm4.encrypt(msg, key, {padding: 'none', output: 'array'}) // 加密,不使用 padding,输出为字节数组
+let encryptData = sm4.encrypt(msg, key, {mode: 'cbc', iv: 'fedcba98765432100123456789abcdef'}) // 加密,cbc 模式
+```
+
+### 解密
+
+```js
+const sm4 = require('miniprogram-sm-crypto').sm4
+const encryptData = '0e395deb10f6e8a17e17823e1fd9bd98a1bff1df508b5b8a1efb79ec633d1bb129432ac1b74972dbe97bab04f024e89c' // 可以为 16 进制串或字节数组
+const key = '0123456789abcdeffedcba9876543210' // 可以为 16 进制串或字节数组,要求为 128 比特
+
+let decryptData = sm4.decrypt(encryptData, key) // 解密,默认输出 utf8 字符串,默认使用 pkcs#7 填充(传 pkcs#5 也会走 pkcs#7 填充)
+let decryptData = sm4.decrypt(encryptData, key, {padding: 'none'}) // 解密,不使用 padding
+let decryptData = sm4.decrypt(encryptData, key, {padding: 'none', output: 'array'}) // 解密,不使用 padding,输出为字节数组
+let decryptData = sm4.decrypt(encryptData, key, {mode: 'cbc', iv: 'fedcba98765432100123456789abcdef'}) // 解密,cbc 模式
+```
+
+## 协议
+
+MIT

+ 92 - 0
node_modules/miniprogram-sm-crypto/UPDATE.md

@@ -0,0 +1,92 @@
+## 0.3.13
+
+* 支持根据私钥获取公钥
+
+## 0.3.12
+
+* 优化 sm3 运行性能
+
+## 0.3.11
+
+* sm2 支持压缩公钥
+
+## 0.3.10
+
+* 支持 sm3 hmac 模式
+
+## 0.3.9
+
+* 补充 sm4 解密时的 padding 判断
+
+## 0.3.8
+
+* sm2 解密时兼容密文可能是大写的情况
+
+## 0.3.7
+
+* 默认填充改为 pkcs#7,如传入 pkcs#5 也转到 pkcs#7 逻辑
+
+## 0.3.6
+
+* sm2 加解密支持二进制数据
+
+## 0.3.5
+
+* sm2.generateKeyPairHex 支持完整的 BigInteger 入参
+
+## 0.3.4
+
+* sm2 支持验证公钥接口
+* sm2 生成密钥时支持自定义随机数
+
+## 0.3.2
+
+* 修复 sm2 在 userId 长度大于 31 时新旧版本验签不通过的问题
+
+## 0.3.0
+
+* sm2、sm3 重构
+* sm4 支持 cbc 模式
+
+## 0.2.7
+
+* 优化 sm3 性能
+
+## 0.2.5
+
+* sm3 支持字节数组输入
+
+## 0.2.4
+
+* 修复 sm4 四字节字符输出编码
+
+## 0.2.3
+
+* sm3/sm4 支持输入四字节字符
+
+## 0.2.2
+
+* sm3 支持中文输入
+
+## 0.2.0
+
+* 修复 sm2 点 16 进制串可能不满 64 位的问题
+* sm4 默认支持 pkcs#5 填充方式
+* sm4 支持输入输出为字符串
+
+## 0.1.3
+
+* 支持用户传入 userId
+
+## 0.1.0
+
+* 修复 sm2 中 z 值数组可能包含 256 的问题。
+
+## 0.0.6
+
+* 修复加解密偶现失败的情况。
+
+## 0.0.5
+
+* 修复签名时如果使用 hash,会执行两次 utf8 转 hex 的问题。
+* 修复 sm2/utils/js 中当传入 hex 为奇数位串会导致出错的问题。

+ 28 - 0
node_modules/miniprogram-sm-crypto/gulpfile.js

@@ -0,0 +1,28 @@
+const gulp = require('gulp');
+const clean = require('gulp-clean');
+
+const config = require('./tools/config');
+const BuildTask = require('./tools/build');
+const id = require('./package.json').name || 'miniprogram-custom-component';
+
+// build task instance
+new BuildTask(id, config.entry);
+
+// clean the generated folders and files
+gulp.task('clean', gulp.series(() => {
+    return gulp.src(config.distPath, { read: false, allowEmpty: true })
+        .pipe(clean())
+}, done => {
+    if (config.isDev) {
+        return gulp.src(config.demoDist, { read: false, allowEmpty: true })
+            .pipe(clean());
+    }
+
+    done();
+}));
+// watch files and build
+gulp.task('watch', gulp.series(`${id}-watch`));
+// build for develop
+gulp.task('dev', gulp.series(`${id}-dev`));
+// build for publish
+gulp.task('default', gulp.series(`${id}-default`));

+ 1837 - 0
node_modules/miniprogram-sm-crypto/miniprogram_dist/index.js

@@ -0,0 +1,1837 @@
+module.exports =
+/******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// define __esModule on exports
+/******/ 	__webpack_require__.r = function(exports) {
+/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 		}
+/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 	};
+/******/
+/******/ 	// create a fake namespace object
+/******/ 	// mode & 1: value is a module id, require it
+/******/ 	// mode & 2: merge all properties of value into the ns
+/******/ 	// mode & 4: return value when already ns object
+/******/ 	// mode & 8|1: behave like require
+/******/ 	__webpack_require__.t = function(value, mode) {
+/******/ 		if(mode & 1) value = __webpack_require__(value);
+/******/ 		if(mode & 8) return value;
+/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ 		var ns = Object.create(null);
+/******/ 		__webpack_require__.r(ns);
+/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ 		return ns;
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+/******/
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = 2);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports) {
+
+module.exports = require("jsbn");
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+// 消息扩展
+var W = new Uint32Array(68);
+var M = new Uint32Array(64); // W'
+
+/**
+ * 循环左移
+ */
+function rotl(x, n) {
+  var s = n & 31;
+  return x << s | x >>> 32 - s;
+}
+
+/**
+ * 二进制异或运算
+ */
+function xor(x, y) {
+  var result = [];
+  for (var i = x.length - 1; i >= 0; i--) {
+    result[i] = (x[i] ^ y[i]) & 0xff;
+  }return result;
+}
+
+/**
+ * 压缩函数中的置换函数 P0(X) = X xor (X <<< 9) xor (X <<< 17)
+ */
+function P0(X) {
+  return X ^ rotl(X, 9) ^ rotl(X, 17);
+}
+
+/**
+ * 消息扩展中的置换函数 P1(X) = X xor (X <<< 15) xor (X <<< 23)
+ */
+function P1(X) {
+  return X ^ rotl(X, 15) ^ rotl(X, 23);
+}
+
+/**
+ * sm3 本体
+ */
+function sm3(array) {
+  var len = array.length * 8;
+
+  // k 是满足 len + 1 + k = 448mod512 的最小的非负整数
+  var k = len % 512;
+  // 如果 448 <= (512 % len) < 512,需要多补充 (len % 448) 比特'0'以满足总比特长度为512的倍数
+  k = k >= 448 ? 512 - k % 448 - 1 : 448 - k - 1;
+
+  // 填充
+  var kArr = new Array((k - 7) / 8);
+  var lenArr = new Array(8);
+  for (var i = 0, _len = kArr.length; i < _len; i++) {
+    kArr[i] = 0;
+  }for (var _i = 0, _len2 = lenArr.length; _i < _len2; _i++) {
+    lenArr[_i] = 0;
+  }len = len.toString(2);
+  for (var _i2 = 7; _i2 >= 0; _i2--) {
+    if (len.length > 8) {
+      var start = len.length - 8;
+      lenArr[_i2] = parseInt(len.substr(start), 2);
+      len = len.substr(0, start);
+    } else if (len.length > 0) {
+      lenArr[_i2] = parseInt(len, 2);
+      len = '';
+    }
+  }
+  var m = new Uint8Array([].concat(array, [0x80], kArr, lenArr));
+  var dataView = new DataView(m.buffer, 0);
+
+  // 迭代压缩
+  var n = m.length / 64;
+  var V = new Uint32Array([0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e]);
+  for (var _i3 = 0; _i3 < n; _i3++) {
+    W.fill(0);
+    M.fill(0);
+
+    // 将消息分组B划分为 16 个字 W0, W1,……,W15
+    var _start = 16 * _i3;
+    for (var j = 0; j < 16; j++) {
+      W[j] = dataView.getUint32((_start + j) * 4, false);
+    }
+
+    // W16 ~ W67:W[j] <- P1(W[j−16] xor W[j−9] xor (W[j−3] <<< 15)) xor (W[j−13] <<< 7) xor W[j−6]
+    for (var _j = 16; _j < 68; _j++) {
+      W[_j] = P1(W[_j - 16] ^ W[_j - 9] ^ rotl(W[_j - 3], 15)) ^ rotl(W[_j - 13], 7) ^ W[_j - 6];
+    }
+
+    // W′0 ~ W′63:W′[j] = W[j] xor W[j+4]
+    for (var _j2 = 0; _j2 < 64; _j2++) {
+      M[_j2] = W[_j2] ^ W[_j2 + 4];
+    }
+
+    // 压缩
+    var T1 = 0x79cc4519;
+    var T2 = 0x7a879d8a;
+    // 字寄存器
+    var A = V[0];
+    var B = V[1];
+    var C = V[2];
+    var D = V[3];
+    var E = V[4];
+    var F = V[5];
+    var G = V[6];
+    var H = V[7];
+    // 中间变量
+    var SS1 = void 0;
+    var SS2 = void 0;
+    var TT1 = void 0;
+    var TT2 = void 0;
+    var T = void 0;
+    for (var _j3 = 0; _j3 < 64; _j3++) {
+      T = _j3 >= 0 && _j3 <= 15 ? T1 : T2;
+      SS1 = rotl(rotl(A, 12) + E + rotl(T, _j3), 7);
+      SS2 = SS1 ^ rotl(A, 12);
+
+      TT1 = (_j3 >= 0 && _j3 <= 15 ? A ^ B ^ C : A & B | A & C | B & C) + D + SS2 + M[_j3];
+      TT2 = (_j3 >= 0 && _j3 <= 15 ? E ^ F ^ G : E & F | ~E & G) + H + SS1 + W[_j3];
+
+      D = C;
+      C = rotl(B, 9);
+      B = A;
+      A = TT1;
+      H = G;
+      G = rotl(F, 19);
+      F = E;
+      E = P0(TT2);
+    }
+
+    V[0] ^= A;
+    V[1] ^= B;
+    V[2] ^= C;
+    V[3] ^= D;
+    V[4] ^= E;
+    V[5] ^= F;
+    V[6] ^= G;
+    V[7] ^= H;
+  }
+
+  // 转回 uint8
+  var result = [];
+  for (var _i4 = 0, _len3 = V.length; _i4 < _len3; _i4++) {
+    var word = V[_i4];
+    result.push((word & 0xff000000) >>> 24, (word & 0xff0000) >>> 16, (word & 0xff00) >>> 8, word & 0xff);
+  }
+
+  return result;
+}
+
+/**
+ * hmac 实现
+ */
+var blockLen = 64;
+var iPad = new Uint8Array(blockLen);
+var oPad = new Uint8Array(blockLen);
+for (var i = 0; i < blockLen; i++) {
+  iPad[i] = 0x36;
+  oPad[i] = 0x5c;
+}
+function hmac(input, key) {
+  // 密钥填充
+  if (key.length > blockLen) key = sm3(key);
+  while (key.length < blockLen) {
+    key.push(0);
+  }var iPadKey = xor(key, iPad);
+  var oPadKey = xor(key, oPad);
+
+  var hash = sm3([].concat(iPadKey, input));
+  return sm3([].concat(oPadKey, hash));
+}
+
+module.exports = {
+  sm3: sm3,
+  hmac: hmac
+};
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+module.exports = {
+  sm2: __webpack_require__(3),
+  sm3: __webpack_require__(7),
+  sm4: __webpack_require__(8)
+};
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+/* eslint-disable no-use-before-define */
+var _require = __webpack_require__(0),
+    BigInteger = _require.BigInteger;
+
+var _require2 = __webpack_require__(4),
+    encodeDer = _require2.encodeDer,
+    decodeDer = _require2.decodeDer;
+
+var _ = __webpack_require__(5);
+var sm3 = __webpack_require__(1).sm3;
+
+var _$generateEcparam = _.generateEcparam(),
+    G = _$generateEcparam.G,
+    curve = _$generateEcparam.curve,
+    n = _$generateEcparam.n;
+
+var C1C2C3 = 0;
+
+/**
+ * 加密
+ */
+function doEncrypt(msg, publicKey) {
+  var cipherMode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
+
+  msg = typeof msg === 'string' ? _.hexToArray(_.utf8ToHex(msg)) : Array.prototype.slice.call(msg);
+  publicKey = _.getGlobalCurve().decodePointHex(publicKey); // 先将公钥转成点
+
+  var keypair = _.generateKeyPairHex();
+  var k = new BigInteger(keypair.privateKey, 16); // 随机数 k
+
+  // c1 = k * G
+  var c1 = keypair.publicKey;
+  if (c1.length > 128) c1 = c1.substr(c1.length - 128);
+
+  // (x2, y2) = k * publicKey
+  var p = publicKey.multiply(k);
+  var x2 = _.hexToArray(_.leftPad(p.getX().toBigInteger().toRadix(16), 64));
+  var y2 = _.hexToArray(_.leftPad(p.getY().toBigInteger().toRadix(16), 64));
+
+  // c3 = hash(x2 || msg || y2)
+  var c3 = _.arrayToHex(sm3([].concat(x2, msg, y2)));
+
+  var ct = 1;
+  var offset = 0;
+  var t = []; // 256 位
+  var z = [].concat(x2, y2);
+  var nextT = function nextT() {
+    // (1) Hai = hash(z || ct)
+    // (2) ct++
+    t = sm3([].concat(z, [ct >> 24 & 0x00ff, ct >> 16 & 0x00ff, ct >> 8 & 0x00ff, ct & 0x00ff]));
+    ct++;
+    offset = 0;
+  };
+  nextT(); // 先生成 Ha1
+
+  for (var i = 0, len = msg.length; i < len; i++) {
+    // t = Ha1 || Ha2 || Ha3 || Ha4
+    if (offset === t.length) nextT();
+
+    // c2 = msg ^ t
+    msg[i] ^= t[offset++] & 0xff;
+  }
+  var c2 = _.arrayToHex(msg);
+
+  return cipherMode === C1C2C3 ? c1 + c2 + c3 : c1 + c3 + c2;
+}
+
+/**
+ * 解密
+ */
+function doDecrypt(encryptData, privateKey) {
+  var cipherMode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
+
+  var _ref = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {},
+      _ref$output = _ref.output,
+      output = _ref$output === undefined ? 'string' : _ref$output;
+
+  privateKey = new BigInteger(privateKey, 16);
+
+  var c3 = encryptData.substr(128, 64);
+  var c2 = encryptData.substr(128 + 64);
+
+  if (cipherMode === C1C2C3) {
+    c3 = encryptData.substr(encryptData.length - 64);
+    c2 = encryptData.substr(128, encryptData.length - 128 - 64);
+  }
+
+  var msg = _.hexToArray(c2);
+  var c1 = _.getGlobalCurve().decodePointHex('04' + encryptData.substr(0, 128));
+
+  var p = c1.multiply(privateKey);
+  var x2 = _.hexToArray(_.leftPad(p.getX().toBigInteger().toRadix(16), 64));
+  var y2 = _.hexToArray(_.leftPad(p.getY().toBigInteger().toRadix(16), 64));
+
+  var ct = 1;
+  var offset = 0;
+  var t = []; // 256 位
+  var z = [].concat(x2, y2);
+  var nextT = function nextT() {
+    // (1) Hai = hash(z || ct)
+    // (2) ct++
+    t = sm3([].concat(z, [ct >> 24 & 0x00ff, ct >> 16 & 0x00ff, ct >> 8 & 0x00ff, ct & 0x00ff]));
+    ct++;
+    offset = 0;
+  };
+  nextT(); // 先生成 Ha1
+
+  for (var i = 0, len = msg.length; i < len; i++) {
+    // t = Ha1 || Ha2 || Ha3 || Ha4
+    if (offset === t.length) nextT();
+
+    // c2 = msg ^ t
+    msg[i] ^= t[offset++] & 0xff;
+  }
+
+  // c3 = hash(x2 || msg || y2)
+  var checkC3 = _.arrayToHex(sm3([].concat(x2, msg, y2)));
+
+  if (checkC3 === c3.toLowerCase()) {
+    return output === 'array' ? msg : _.arrayToUtf8(msg);
+  } else {
+    return output === 'array' ? [] : '';
+  }
+}
+
+/**
+ * 签名
+ */
+function doSignature(msg, privateKey) {
+  var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
+      pointPool = _ref2.pointPool,
+      der = _ref2.der,
+      hash = _ref2.hash,
+      publicKey = _ref2.publicKey,
+      userId = _ref2.userId;
+
+  var hashHex = typeof msg === 'string' ? _.utf8ToHex(msg) : _.arrayToHex(msg);
+
+  if (hash) {
+    // sm3杂凑
+    publicKey = publicKey || getPublicKeyFromPrivateKey(privateKey);
+    hashHex = getHash(hashHex, publicKey, userId);
+  }
+
+  var dA = new BigInteger(privateKey, 16);
+  var e = new BigInteger(hashHex, 16);
+
+  // k
+  var k = null;
+  var r = null;
+  var s = null;
+
+  do {
+    do {
+      var point = void 0;
+      if (pointPool && pointPool.length) {
+        point = pointPool.pop();
+      } else {
+        point = getPoint();
+      }
+      k = point.k;
+
+      // r = (e + x1) mod n
+      r = e.add(point.x1).mod(n);
+    } while (r.equals(BigInteger.ZERO) || r.add(k).equals(n));
+
+    // s = ((1 + dA)^-1 * (k - r * dA)) mod n
+    s = dA.add(BigInteger.ONE).modInverse(n).multiply(k.subtract(r.multiply(dA))).mod(n);
+  } while (s.equals(BigInteger.ZERO));
+
+  if (der) return encodeDer(r, s); // asn.1 der 编码
+
+  return _.leftPad(r.toString(16), 64) + _.leftPad(s.toString(16), 64);
+}
+
+/**
+ * 验签
+ */
+function doVerifySignature(msg, signHex, publicKey) {
+  var _ref3 = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {},
+      der = _ref3.der,
+      hash = _ref3.hash,
+      userId = _ref3.userId;
+
+  var hashHex = typeof msg === 'string' ? _.utf8ToHex(msg) : _.arrayToHex(msg);
+
+  if (hash) {
+    // sm3杂凑
+    hashHex = getHash(hashHex, publicKey, userId);
+  }
+
+  var r = void 0;var s = void 0;
+  if (der) {
+    var decodeDerObj = decodeDer(signHex); // asn.1 der 解码
+    r = decodeDerObj.r;
+    s = decodeDerObj.s;
+  } else {
+    r = new BigInteger(signHex.substring(0, 64), 16);
+    s = new BigInteger(signHex.substring(64), 16);
+  }
+
+  var PA = curve.decodePointHex(publicKey);
+  var e = new BigInteger(hashHex, 16);
+
+  // t = (r + s) mod n
+  var t = r.add(s).mod(n);
+
+  if (t.equals(BigInteger.ZERO)) return false;
+
+  // x1y1 = s * G + t * PA
+  var x1y1 = G.multiply(s).add(PA.multiply(t));
+
+  // R = (e + x1) mod n
+  var R = e.add(x1y1.getX().toBigInteger()).mod(n);
+
+  return r.equals(R);
+}
+
+/**
+ * sm3杂凑算法
+ */
+function getHash(hashHex, publicKey) {
+  var userId = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '1234567812345678';
+
+  // z = hash(entl || userId || a || b || gx || gy || px || py)
+  userId = _.utf8ToHex(userId);
+  var a = _.leftPad(G.curve.a.toBigInteger().toRadix(16), 64);
+  var b = _.leftPad(G.curve.b.toBigInteger().toRadix(16), 64);
+  var gx = _.leftPad(G.getX().toBigInteger().toRadix(16), 64);
+  var gy = _.leftPad(G.getY().toBigInteger().toRadix(16), 64);
+  var px = void 0;
+  var py = void 0;
+  if (publicKey.length === 128) {
+    px = publicKey.substr(0, 64);
+    py = publicKey.substr(64, 64);
+  } else {
+    var point = G.curve.decodePointHex(publicKey);
+    px = _.leftPad(point.getX().toBigInteger().toRadix(16), 64);
+    py = _.leftPad(point.getY().toBigInteger().toRadix(16), 64);
+  }
+  var data = _.hexToArray(userId + a + b + gx + gy + px + py);
+
+  var entl = userId.length * 4;
+  data.unshift(entl & 0x00ff);
+  data.unshift(entl >> 8 & 0x00ff);
+
+  var z = sm3(data);
+
+  // e = hash(z || msg)
+  return _.arrayToHex(sm3(z.concat(_.hexToArray(hashHex))));
+}
+
+/**
+ * 计算公钥
+ */
+function getPublicKeyFromPrivateKey(privateKey) {
+  var PA = G.multiply(new BigInteger(privateKey, 16));
+  var x = _.leftPad(PA.getX().toBigInteger().toString(16), 64);
+  var y = _.leftPad(PA.getY().toBigInteger().toString(16), 64);
+  return '04' + x + y;
+}
+
+/**
+ * 获取椭圆曲线点
+ */
+function getPoint() {
+  var keypair = _.generateKeyPairHex();
+  var PA = curve.decodePointHex(keypair.publicKey);
+
+  keypair.k = new BigInteger(keypair.privateKey, 16);
+  keypair.x1 = PA.getX().toBigInteger();
+
+  return keypair;
+}
+
+module.exports = {
+  generateKeyPairHex: _.generateKeyPairHex,
+  compressPublicKeyHex: _.compressPublicKeyHex,
+  comparePublicKeyHex: _.comparePublicKeyHex,
+  doEncrypt: doEncrypt,
+  doDecrypt: doDecrypt,
+  doSignature: doSignature,
+  doVerifySignature: doVerifySignature,
+  getPublicKeyFromPrivateKey: getPublicKeyFromPrivateKey,
+  getPoint: getPoint,
+  verifyPublicKey: _.verifyPublicKey
+};
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/* eslint-disable class-methods-use-this */
+var _require = __webpack_require__(0),
+    BigInteger = _require.BigInteger;
+
+function bigintToValue(bigint) {
+  var h = bigint.toString(16);
+  if (h[0] !== '-') {
+    // 正数
+    if (h.length % 2 === 1) h = '0' + h; // 补齐到整字节
+    else if (!h.match(/^[0-7]/)) h = '00' + h; // 非0开头,则补一个全0字节
+  } else {
+    // 负数
+    h = h.substr(1);
+
+    var len = h.length;
+    if (len % 2 === 1) len += 1; // 补齐到整字节
+    else if (!h.match(/^[0-7]/)) len += 2; // 非0开头,则补一个全0字节
+
+    var mask = '';
+    for (var i = 0; i < len; i++) {
+      mask += 'f';
+    }mask = new BigInteger(mask, 16);
+
+    // 对绝对值取反,加1
+    h = mask.xor(bigint).add(BigInteger.ONE);
+    h = h.toString(16).replace(/^-/, '');
+  }
+  return h;
+}
+
+var ASN1Object = function () {
+  function ASN1Object() {
+    _classCallCheck(this, ASN1Object);
+
+    this.tlv = null;
+    this.t = '00';
+    this.l = '00';
+    this.v = '';
+  }
+
+  /**
+   * 获取 der 编码比特流16进制串
+   */
+
+
+  ASN1Object.prototype.getEncodedHex = function getEncodedHex() {
+    if (!this.tlv) {
+      this.v = this.getValue();
+      this.l = this.getLength();
+      this.tlv = this.t + this.l + this.v;
+    }
+    return this.tlv;
+  };
+
+  ASN1Object.prototype.getLength = function getLength() {
+    var n = this.v.length / 2; // 字节数
+    var nHex = n.toString(16);
+    if (nHex.length % 2 === 1) nHex = '0' + nHex; // 补齐到整字节
+
+    if (n < 128) {
+      // 短格式,以 0 开头
+      return nHex;
+    } else {
+      // 长格式,以 1 开头
+      var head = 128 + nHex.length / 2; // 1(1位) + 真正的长度占用字节数(7位) + 真正的长度
+      return head.toString(16) + nHex;
+    }
+  };
+
+  ASN1Object.prototype.getValue = function getValue() {
+    return '';
+  };
+
+  return ASN1Object;
+}();
+
+var DERInteger = function (_ASN1Object) {
+  _inherits(DERInteger, _ASN1Object);
+
+  function DERInteger(bigint) {
+    _classCallCheck(this, DERInteger);
+
+    var _this = _possibleConstructorReturn(this, _ASN1Object.call(this));
+
+    _this.t = '02'; // 整型标签说明
+    if (bigint) _this.v = bigintToValue(bigint);
+    return _this;
+  }
+
+  DERInteger.prototype.getValue = function getValue() {
+    return this.v;
+  };
+
+  return DERInteger;
+}(ASN1Object);
+
+var DERSequence = function (_ASN1Object2) {
+  _inherits(DERSequence, _ASN1Object2);
+
+  function DERSequence(asn1Array) {
+    _classCallCheck(this, DERSequence);
+
+    var _this2 = _possibleConstructorReturn(this, _ASN1Object2.call(this));
+
+    _this2.t = '30'; // 序列标签说明
+    _this2.asn1Array = asn1Array;
+    return _this2;
+  }
+
+  DERSequence.prototype.getValue = function getValue() {
+    this.v = this.asn1Array.map(function (asn1Object) {
+      return asn1Object.getEncodedHex();
+    }).join('');
+    return this.v;
+  };
+
+  return DERSequence;
+}(ASN1Object);
+
+/**
+ * 获取 l 占用字节数
+ */
+
+
+function getLenOfL(str, start) {
+  if (+str[start + 2] < 8) return 1; // l 以0开头,则表示短格式,只占一个字节
+  return +str.substr(start + 2, 2) & 0x7f + 1; // 长格式,取第一个字节后7位作为长度真正占用字节数,再加上本身
+}
+
+/**
+ * 获取 l
+ */
+function getL(str, start) {
+  // 获取 l
+  var len = getLenOfL(str, start);
+  var l = str.substr(start + 2, len * 2);
+
+  if (!l) return -1;
+  var bigint = +l[0] < 8 ? new BigInteger(l, 16) : new BigInteger(l.substr(2), 16);
+
+  return bigint.intValue();
+}
+
+/**
+ * 获取 v 的位置
+ */
+function getStartOfV(str, start) {
+  var len = getLenOfL(str, start);
+  return start + (len + 1) * 2;
+}
+
+module.exports = {
+  /**
+   * ASN.1 der 编码,针对 sm2 签名
+   */
+  encodeDer: function encodeDer(r, s) {
+    var derR = new DERInteger(r);
+    var derS = new DERInteger(s);
+    var derSeq = new DERSequence([derR, derS]);
+
+    return derSeq.getEncodedHex();
+  },
+
+
+  /**
+   * 解析 ASN.1 der,针对 sm2 验签
+   */
+  decodeDer: function decodeDer(input) {
+    // 结构:
+    // input = | tSeq | lSeq | vSeq |
+    // vSeq = | tR | lR | vR | tS | lS | vS |
+    var start = getStartOfV(input, 0);
+
+    var vIndexR = getStartOfV(input, start);
+    var lR = getL(input, start);
+    var vR = input.substr(vIndexR, lR * 2);
+
+    var nextStart = vIndexR + vR.length;
+    var vIndexS = getStartOfV(input, nextStart);
+    var lS = getL(input, nextStart);
+    var vS = input.substr(vIndexS, lS * 2);
+
+    var r = new BigInteger(vR, 16);
+    var s = new BigInteger(vS, 16);
+
+    return { r: r, s: s };
+  }
+};
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+/* eslint-disable no-bitwise, no-mixed-operators, no-use-before-define, max-len */
+var _require = __webpack_require__(0),
+    BigInteger = _require.BigInteger,
+    SecureRandom = _require.SecureRandom;
+
+var _require2 = __webpack_require__(6),
+    ECCurveFp = _require2.ECCurveFp;
+
+var rng = new SecureRandom();
+
+var _generateEcparam = generateEcparam(),
+    curve = _generateEcparam.curve,
+    G = _generateEcparam.G,
+    n = _generateEcparam.n;
+
+/**
+ * 获取公共椭圆曲线
+ */
+
+
+function getGlobalCurve() {
+  return curve;
+}
+
+/**
+ * 生成ecparam
+ */
+function generateEcparam() {
+  // 椭圆曲线
+  var p = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16);
+  var a = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16);
+  var b = new BigInteger('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93', 16);
+  var curve = new ECCurveFp(p, a, b);
+
+  // 基点
+  var gxHex = '32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7';
+  var gyHex = 'BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0';
+  var G = curve.decodePointHex('04' + gxHex + gyHex);
+
+  var n = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123', 16);
+
+  return { curve: curve, G: G, n: n };
+}
+
+/**
+ * 生成密钥对:publicKey = privateKey * G
+ */
+function generateKeyPairHex(a, b, c) {
+  var random = a ? new BigInteger(a, b, c) : new BigInteger(n.bitLength(), rng);
+  var d = random.mod(n.subtract(BigInteger.ONE)).add(BigInteger.ONE); // 随机数
+  var privateKey = leftPad(d.toString(16), 64);
+
+  var P = G.multiply(d); // P = dG,p 为公钥,d 为私钥
+  var Px = leftPad(P.getX().toBigInteger().toString(16), 64);
+  var Py = leftPad(P.getY().toBigInteger().toString(16), 64);
+  var publicKey = '04' + Px + Py;
+
+  return { privateKey: privateKey, publicKey: publicKey };
+}
+
+/**
+ * 生成压缩公钥
+ */
+function compressPublicKeyHex(s) {
+  if (s.length !== 130) throw new Error('Invalid public key to compress');
+
+  var len = (s.length - 2) / 2;
+  var xHex = s.substr(2, len);
+  var y = new BigInteger(s.substr(len + 2, len), 16);
+
+  var prefix = '03';
+  if (y.mod(new BigInteger('2')).equals(BigInteger.ZERO)) prefix = '02';
+
+  return prefix + xHex;
+}
+
+/**
+ * utf8串转16进制串
+ */
+function utf8ToHex(input) {
+  input = unescape(encodeURIComponent(input));
+
+  var length = input.length;
+
+  // 转换到字数组
+  var words = [];
+  for (var i = 0; i < length; i++) {
+    words[i >>> 2] |= (input.charCodeAt(i) & 0xff) << 24 - i % 4 * 8;
+  }
+
+  // 转换到16进制
+  var hexChars = [];
+  for (var _i = 0; _i < length; _i++) {
+    var bite = words[_i >>> 2] >>> 24 - _i % 4 * 8 & 0xff;
+    hexChars.push((bite >>> 4).toString(16));
+    hexChars.push((bite & 0x0f).toString(16));
+  }
+
+  return hexChars.join('');
+}
+
+/**
+ * 补全16进制字符串
+ */
+function leftPad(input, num) {
+  if (input.length >= num) return input;
+
+  return new Array(num - input.length + 1).join('0') + input;
+}
+
+/**
+ * 转成16进制串
+ */
+function arrayToHex(arr) {
+  return arr.map(function (item) {
+    item = item.toString(16);
+    return item.length === 1 ? '0' + item : item;
+  }).join('');
+}
+
+/**
+ * 转成utf8串
+ */
+function arrayToUtf8(arr) {
+  var words = [];
+  var j = 0;
+  for (var i = 0; i < arr.length * 2; i += 2) {
+    words[i >>> 3] |= parseInt(arr[j], 10) << 24 - i % 8 * 4;
+    j++;
+  }
+
+  try {
+    var latin1Chars = [];
+
+    for (var _i2 = 0; _i2 < arr.length; _i2++) {
+      var bite = words[_i2 >>> 2] >>> 24 - _i2 % 4 * 8 & 0xff;
+      latin1Chars.push(String.fromCharCode(bite));
+    }
+
+    return decodeURIComponent(escape(latin1Chars.join('')));
+  } catch (e) {
+    throw new Error('Malformed UTF-8 data');
+  }
+}
+
+/**
+ * 转成字节数组
+ */
+function hexToArray(hexStr) {
+  var words = [];
+  var hexStrLength = hexStr.length;
+
+  if (hexStrLength % 2 !== 0) {
+    hexStr = leftPad(hexStr, hexStrLength + 1);
+  }
+
+  hexStrLength = hexStr.length;
+
+  for (var i = 0; i < hexStrLength; i += 2) {
+    words.push(parseInt(hexStr.substr(i, 2), 16));
+  }
+  return words;
+}
+
+/**
+ * 验证公钥是否为椭圆曲线上的点
+ */
+function verifyPublicKey(publicKey) {
+  var point = curve.decodePointHex(publicKey);
+  if (!point) return false;
+
+  var x = point.getX();
+  var y = point.getY();
+
+  // 验证 y^2 是否等于 x^3 + ax + b
+  return y.square().equals(x.multiply(x.square()).add(x.multiply(curve.a)).add(curve.b));
+}
+
+/**
+ * 验证公钥是否等价,等价返回true
+ */
+function comparePublicKeyHex(publicKey1, publicKey2) {
+  var point1 = curve.decodePointHex(publicKey1);
+  if (!point1) return false;
+
+  var point2 = curve.decodePointHex(publicKey2);
+  if (!point2) return false;
+
+  return point1.equals(point2);
+}
+
+module.exports = {
+  getGlobalCurve: getGlobalCurve,
+  generateEcparam: generateEcparam,
+  generateKeyPairHex: generateKeyPairHex,
+  compressPublicKeyHex: compressPublicKeyHex,
+  utf8ToHex: utf8ToHex,
+  leftPad: leftPad,
+  arrayToHex: arrayToHex,
+  arrayToUtf8: arrayToUtf8,
+  hexToArray: hexToArray,
+  verifyPublicKey: verifyPublicKey,
+  comparePublicKeyHex: comparePublicKeyHex
+};
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/* eslint-disable no-case-declarations, max-len */
+var _require = __webpack_require__(0),
+    BigInteger = _require.BigInteger;
+
+/**
+ * thanks for Tom Wu : http://www-cs-students.stanford.edu/~tjw/jsbn/
+ *
+ * Basic Javascript Elliptic Curve implementation
+ * Ported loosely from BouncyCastle's Java EC code
+ * Only Fp curves implemented for now
+ */
+
+var TWO = new BigInteger('2');
+var THREE = new BigInteger('3');
+
+/**
+ * 椭圆曲线域元素
+ */
+
+var ECFieldElementFp = function () {
+  function ECFieldElementFp(q, x) {
+    _classCallCheck(this, ECFieldElementFp);
+
+    this.x = x;
+    this.q = q;
+    // TODO if (x.compareTo(q) >= 0) error
+  }
+
+  /**
+   * 判断相等
+   */
+
+
+  ECFieldElementFp.prototype.equals = function equals(other) {
+    if (other === this) return true;
+    return this.q.equals(other.q) && this.x.equals(other.x);
+  };
+
+  /**
+   * 返回具体数值
+   */
+
+
+  ECFieldElementFp.prototype.toBigInteger = function toBigInteger() {
+    return this.x;
+  };
+
+  /**
+   * 取反
+   */
+
+
+  ECFieldElementFp.prototype.negate = function negate() {
+    return new ECFieldElementFp(this.q, this.x.negate().mod(this.q));
+  };
+
+  /**
+   * 相加
+   */
+
+
+  ECFieldElementFp.prototype.add = function add(b) {
+    return new ECFieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q));
+  };
+
+  /**
+   * 相减
+   */
+
+
+  ECFieldElementFp.prototype.subtract = function subtract(b) {
+    return new ECFieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q));
+  };
+
+  /**
+   * 相乘
+   */
+
+
+  ECFieldElementFp.prototype.multiply = function multiply(b) {
+    return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q));
+  };
+
+  /**
+   * 相除
+   */
+
+
+  ECFieldElementFp.prototype.divide = function divide(b) {
+    return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger().modInverse(this.q)).mod(this.q));
+  };
+
+  /**
+   * 平方
+   */
+
+
+  ECFieldElementFp.prototype.square = function square() {
+    return new ECFieldElementFp(this.q, this.x.square().mod(this.q));
+  };
+
+  return ECFieldElementFp;
+}();
+
+var ECPointFp = function () {
+  function ECPointFp(curve, x, y, z) {
+    _classCallCheck(this, ECPointFp);
+
+    this.curve = curve;
+    this.x = x;
+    this.y = y;
+    // 标准射影坐标系:zinv == null 或 z * zinv == 1
+    this.z = z == null ? BigInteger.ONE : z;
+    this.zinv = null;
+    // TODO: compression flag
+  }
+
+  ECPointFp.prototype.getX = function getX() {
+    if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q);
+
+    return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q));
+  };
+
+  ECPointFp.prototype.getY = function getY() {
+    if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q);
+
+    return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q));
+  };
+
+  /**
+   * 判断相等
+   */
+
+
+  ECPointFp.prototype.equals = function equals(other) {
+    if (other === this) return true;
+    if (this.isInfinity()) return other.isInfinity();
+    if (other.isInfinity()) return this.isInfinity();
+
+    // u = y2 * z1 - y1 * z2
+    var u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q);
+    if (!u.equals(BigInteger.ZERO)) return false;
+
+    // v = x2 * z1 - x1 * z2
+    var v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q);
+    return v.equals(BigInteger.ZERO);
+  };
+
+  /**
+   * 是否是无穷远点
+   */
+
+
+  ECPointFp.prototype.isInfinity = function isInfinity() {
+    if (this.x === null && this.y === null) return true;
+    return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO);
+  };
+
+  /**
+   * 取反,x 轴对称点
+   */
+
+
+  ECPointFp.prototype.negate = function negate() {
+    return new ECPointFp(this.curve, this.x, this.y.negate(), this.z);
+  };
+
+  /**
+   * 相加
+   *
+   * 标准射影坐标系:
+   *
+   * λ1 = x1 * z2
+   * λ2 = x2 * z1
+   * λ3 = λ1 − λ2
+   * λ4 = y1 * z2
+   * λ5 = y2 * z1
+   * λ6 = λ4 − λ5
+   * λ7 = λ1 + λ2
+   * λ8 = z1 * z2
+   * λ9 = λ3^2
+   * λ10 = λ3 * λ9
+   * λ11 = λ8 * λ6^2 − λ7 * λ9
+   * x3 = λ3 * λ11
+   * y3 = λ6 * (λ9 * λ1 − λ11) − λ4 * λ10
+   * z3 = λ10 * λ8
+   */
+
+
+  ECPointFp.prototype.add = function add(b) {
+    if (this.isInfinity()) return b;
+    if (b.isInfinity()) return this;
+
+    var x1 = this.x.toBigInteger();
+    var y1 = this.y.toBigInteger();
+    var z1 = this.z;
+    var x2 = b.x.toBigInteger();
+    var y2 = b.y.toBigInteger();
+    var z2 = b.z;
+    var q = this.curve.q;
+
+    var w1 = x1.multiply(z2).mod(q);
+    var w2 = x2.multiply(z1).mod(q);
+    var w3 = w1.subtract(w2);
+    var w4 = y1.multiply(z2).mod(q);
+    var w5 = y2.multiply(z1).mod(q);
+    var w6 = w4.subtract(w5);
+
+    if (BigInteger.ZERO.equals(w3)) {
+      if (BigInteger.ZERO.equals(w6)) {
+        return this.twice(); // this == b,计算自加
+      }
+      return this.curve.infinity; // this == -b,则返回无穷远点
+    }
+
+    var w7 = w1.add(w2);
+    var w8 = z1.multiply(z2).mod(q);
+    var w9 = w3.square().mod(q);
+    var w10 = w3.multiply(w9).mod(q);
+    var w11 = w8.multiply(w6.square()).subtract(w7.multiply(w9)).mod(q);
+
+    var x3 = w3.multiply(w11).mod(q);
+    var y3 = w6.multiply(w9.multiply(w1).subtract(w11)).subtract(w4.multiply(w10)).mod(q);
+    var z3 = w10.multiply(w8).mod(q);
+
+    return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3);
+  };
+
+  /**
+   * 自加
+   *
+   * 标准射影坐标系:
+   *
+   * λ1 = 3 * x1^2 + a * z1^2
+   * λ2 = 2 * y1 * z1
+   * λ3 = y1^2
+   * λ4 = λ3 * x1 * z1
+   * λ5 = λ2^2
+   * λ6 = λ1^2 − 8 * λ4
+   * x3 = λ2 * λ6
+   * y3 = λ1 * (4 * λ4 − λ6) − 2 * λ5 * λ3
+   * z3 = λ2 * λ5
+   */
+
+
+  ECPointFp.prototype.twice = function twice() {
+    if (this.isInfinity()) return this;
+    if (!this.y.toBigInteger().signum()) return this.curve.infinity;
+
+    var x1 = this.x.toBigInteger();
+    var y1 = this.y.toBigInteger();
+    var z1 = this.z;
+    var q = this.curve.q;
+    var a = this.curve.a.toBigInteger();
+
+    var w1 = x1.square().multiply(THREE).add(a.multiply(z1.square())).mod(q);
+    var w2 = y1.shiftLeft(1).multiply(z1).mod(q);
+    var w3 = y1.square().mod(q);
+    var w4 = w3.multiply(x1).multiply(z1).mod(q);
+    var w5 = w2.square().mod(q);
+    var w6 = w1.square().subtract(w4.shiftLeft(3)).mod(q);
+
+    var x3 = w2.multiply(w6).mod(q);
+    var y3 = w1.multiply(w4.shiftLeft(2).subtract(w6)).subtract(w5.shiftLeft(1).multiply(w3)).mod(q);
+    var z3 = w2.multiply(w5).mod(q);
+
+    return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3);
+  };
+
+  /**
+   * 倍点计算
+   */
+
+
+  ECPointFp.prototype.multiply = function multiply(k) {
+    if (this.isInfinity()) return this;
+    if (!k.signum()) return this.curve.infinity;
+
+    // 使用加减法
+    var k3 = k.multiply(THREE);
+    var neg = this.negate();
+    var Q = this;
+
+    for (var i = k3.bitLength() - 2; i > 0; i--) {
+      Q = Q.twice();
+
+      var k3Bit = k3.testBit(i);
+      var kBit = k.testBit(i);
+
+      if (k3Bit !== kBit) {
+        Q = Q.add(k3Bit ? this : neg);
+      }
+    }
+
+    return Q;
+  };
+
+  return ECPointFp;
+}();
+
+/**
+ * 椭圆曲线 y^2 = x^3 + ax + b
+ */
+
+
+var ECCurveFp = function () {
+  function ECCurveFp(q, a, b) {
+    _classCallCheck(this, ECCurveFp);
+
+    this.q = q;
+    this.a = this.fromBigInteger(a);
+    this.b = this.fromBigInteger(b);
+    this.infinity = new ECPointFp(this, null, null); // 无穷远点
+  }
+
+  /**
+   * 判断两个椭圆曲线是否相等
+   */
+
+
+  ECCurveFp.prototype.equals = function equals(other) {
+    if (other === this) return true;
+    return this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b);
+  };
+
+  /**
+   * 生成椭圆曲线域元素
+   */
+
+
+  ECCurveFp.prototype.fromBigInteger = function fromBigInteger(x) {
+    return new ECFieldElementFp(this.q, x);
+  };
+
+  /**
+   * 解析 16 进制串为椭圆曲线点
+   */
+
+
+  ECCurveFp.prototype.decodePointHex = function decodePointHex(s) {
+    switch (parseInt(s.substr(0, 2), 16)) {
+      // 第一个字节
+      case 0:
+        return this.infinity;
+      case 2:
+      case 3:
+        // 压缩
+        var x = this.fromBigInteger(new BigInteger(s.substr(2), 16));
+        // 对 p ≡ 3 (mod4),即存在正整数 u,使得 p = 4u + 3
+        // 计算 y = (√ (x^3 + ax + b) % p)^(u + 1) modp
+        var y = this.fromBigInteger(x.multiply(x.square()).add(x.multiply(this.a)).add(this.b).toBigInteger().modPow(this.q.divide(new BigInteger('4')).add(BigInteger.ONE), this.q));
+        // 算出结果 2 进制最后 1 位不等于第 1 个字节减 2 则取反
+        if (!y.toBigInteger().mod(TWO).equals(new BigInteger(s.substr(0, 2), 16).subtract(TWO))) {
+          y = y.negate();
+        }
+        return new ECPointFp(this, x, y);
+      case 4:
+      case 6:
+      case 7:
+        var len = (s.length - 2) / 2;
+        var xHex = s.substr(2, len);
+        var yHex = s.substr(len + 2, len);
+
+        return new ECPointFp(this, this.fromBigInteger(new BigInteger(xHex, 16)), this.fromBigInteger(new BigInteger(yHex, 16)));
+      default:
+        // 不支持
+        return null;
+    }
+  };
+
+  return ECCurveFp;
+}();
+
+module.exports = {
+  ECPointFp: ECPointFp,
+  ECCurveFp: ECCurveFp
+};
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var _require = __webpack_require__(1),
+    sm3 = _require.sm3,
+    hmac = _require.hmac;
+
+/**
+ * 补全16进制字符串
+ */
+
+
+function leftPad(input, num) {
+  if (input.length >= num) return input;
+
+  return new Array(num - input.length + 1).join('0') + input;
+}
+
+/**
+ * 字节数组转 16 进制串
+ */
+function ArrayToHex(arr) {
+  return arr.map(function (item) {
+    item = item.toString(16);
+    return item.length === 1 ? '0' + item : item;
+  }).join('');
+}
+
+/**
+ * 转成字节数组
+ */
+function hexToArray(hexStr) {
+  var words = [];
+  var hexStrLength = hexStr.length;
+
+  if (hexStrLength % 2 !== 0) {
+    hexStr = leftPad(hexStr, hexStrLength + 1);
+  }
+
+  hexStrLength = hexStr.length;
+
+  for (var i = 0; i < hexStrLength; i += 2) {
+    words.push(parseInt(hexStr.substr(i, 2), 16));
+  }
+  return words;
+}
+
+/**
+ * utf8 串转字节数组
+ */
+function utf8ToArray(str) {
+  var arr = [];
+
+  for (var i = 0, len = str.length; i < len; i++) {
+    var point = str.codePointAt(i);
+
+    if (point <= 0x007f) {
+      // 单字节,标量值:00000000 00000000 0zzzzzzz
+      arr.push(point);
+    } else if (point <= 0x07ff) {
+      // 双字节,标量值:00000000 00000yyy yyzzzzzz
+      arr.push(0xc0 | point >>> 6); // 110yyyyy(0xc0-0xdf)
+      arr.push(0x80 | point & 0x3f); // 10zzzzzz(0x80-0xbf)
+    } else if (point <= 0xD7FF || point >= 0xE000 && point <= 0xFFFF) {
+      // 三字节:标量值:00000000 xxxxyyyy yyzzzzzz
+      arr.push(0xe0 | point >>> 12); // 1110xxxx(0xe0-0xef)
+      arr.push(0x80 | point >>> 6 & 0x3f); // 10yyyyyy(0x80-0xbf)
+      arr.push(0x80 | point & 0x3f); // 10zzzzzz(0x80-0xbf)
+    } else if (point >= 0x010000 && point <= 0x10FFFF) {
+      // 四字节:标量值:000wwwxx xxxxyyyy yyzzzzzz
+      i++;
+      arr.push(0xf0 | point >>> 18 & 0x1c); // 11110www(0xf0-0xf7)
+      arr.push(0x80 | point >>> 12 & 0x3f); // 10xxxxxx(0x80-0xbf)
+      arr.push(0x80 | point >>> 6 & 0x3f); // 10yyyyyy(0x80-0xbf)
+      arr.push(0x80 | point & 0x3f); // 10zzzzzz(0x80-0xbf)
+    } else {
+      // 五、六字节,暂时不支持
+      arr.push(point);
+      throw new Error('input is not supported');
+    }
+  }
+
+  return arr;
+}
+
+module.exports = function (input, options) {
+  input = typeof input === 'string' ? utf8ToArray(input) : Array.prototype.slice.call(input);
+
+  if (options) {
+    var mode = options.mode || 'hmac';
+    if (mode !== 'hmac') throw new Error('invalid mode');
+
+    var key = options.key;
+    if (!key) throw new Error('invalid key');
+
+    key = typeof key === 'string' ? hexToArray(key) : Array.prototype.slice.call(key);
+    return ArrayToHex(hmac(input, key));
+  }
+
+  return ArrayToHex(sm3(input));
+};
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+/* eslint-disable no-bitwise, no-mixed-operators, complexity */
+var DECRYPT = 0;
+var ROUND = 32;
+var BLOCK = 16;
+
+var Sbox = [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 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];
+
+/**
+ * 16 进制串转字节数组
+ */
+function hexToArray(str) {
+  var arr = [];
+  for (var i = 0, len = str.length; i < len; i += 2) {
+    arr.push(parseInt(str.substr(i, 2), 16));
+  }
+  return arr;
+}
+
+/**
+ * 字节数组转 16 进制串
+ */
+function ArrayToHex(arr) {
+  return arr.map(function (item) {
+    item = item.toString(16);
+    return item.length === 1 ? '0' + item : item;
+  }).join('');
+}
+
+/**
+ * utf8 串转字节数组
+ */
+function utf8ToArray(str) {
+  var arr = [];
+
+  for (var i = 0, len = str.length; i < len; i++) {
+    var point = str.codePointAt(i);
+
+    if (point <= 0x007f) {
+      // 单字节,标量值:00000000 00000000 0zzzzzzz
+      arr.push(point);
+    } else if (point <= 0x07ff) {
+      // 双字节,标量值:00000000 00000yyy yyzzzzzz
+      arr.push(0xc0 | point >>> 6); // 110yyyyy(0xc0-0xdf)
+      arr.push(0x80 | point & 0x3f); // 10zzzzzz(0x80-0xbf)
+    } else if (point <= 0xD7FF || point >= 0xE000 && point <= 0xFFFF) {
+      // 三字节:标量值:00000000 xxxxyyyy yyzzzzzz
+      arr.push(0xe0 | point >>> 12); // 1110xxxx(0xe0-0xef)
+      arr.push(0x80 | point >>> 6 & 0x3f); // 10yyyyyy(0x80-0xbf)
+      arr.push(0x80 | point & 0x3f); // 10zzzzzz(0x80-0xbf)
+    } else if (point >= 0x010000 && point <= 0x10FFFF) {
+      // 四字节:标量值:000wwwxx xxxxyyyy yyzzzzzz
+      i++;
+      arr.push(0xf0 | point >>> 18 & 0x1c); // 11110www(0xf0-0xf7)
+      arr.push(0x80 | point >>> 12 & 0x3f); // 10xxxxxx(0x80-0xbf)
+      arr.push(0x80 | point >>> 6 & 0x3f); // 10yyyyyy(0x80-0xbf)
+      arr.push(0x80 | point & 0x3f); // 10zzzzzz(0x80-0xbf)
+    } else {
+      // 五、六字节,暂时不支持
+      arr.push(point);
+      throw new Error('input is not supported');
+    }
+  }
+
+  return arr;
+}
+
+/**
+ * 字节数组转 utf8 串
+ */
+function arrayToUtf8(arr) {
+  var str = [];
+  for (var i = 0, len = arr.length; i < len; i++) {
+    if (arr[i] >= 0xf0 && arr[i] <= 0xf7) {
+      // 四字节
+      str.push(String.fromCodePoint(((arr[i] & 0x07) << 18) + ((arr[i + 1] & 0x3f) << 12) + ((arr[i + 2] & 0x3f) << 6) + (arr[i + 3] & 0x3f)));
+      i += 3;
+    } else if (arr[i] >= 0xe0 && arr[i] <= 0xef) {
+      // 三字节
+      str.push(String.fromCodePoint(((arr[i] & 0x0f) << 12) + ((arr[i + 1] & 0x3f) << 6) + (arr[i + 2] & 0x3f)));
+      i += 2;
+    } else if (arr[i] >= 0xc0 && arr[i] <= 0xdf) {
+      // 双字节
+      str.push(String.fromCodePoint(((arr[i] & 0x1f) << 6) + (arr[i + 1] & 0x3f)));
+      i++;
+    } else {
+      // 单字节
+      str.push(String.fromCodePoint(arr[i]));
+    }
+  }
+
+  return str.join('');
+}
+
+/**
+ * 32 比特循环左移
+ */
+function rotl(x, n) {
+  var s = n & 31;
+  return x << s | x >>> 32 - s;
+}
+
+/**
+ * 非线性变换
+ */
+function byteSub(a) {
+  return (Sbox[a >>> 24 & 0xFF] & 0xFF) << 24 | (Sbox[a >>> 16 & 0xFF] & 0xFF) << 16 | (Sbox[a >>> 8 & 0xFF] & 0xFF) << 8 | Sbox[a & 0xFF] & 0xFF;
+}
+
+/**
+ * 线性变换,加密/解密用
+ */
+function l1(b) {
+  return b ^ rotl(b, 2) ^ rotl(b, 10) ^ rotl(b, 18) ^ rotl(b, 24);
+}
+
+/**
+ * 线性变换,生成轮密钥用
+ */
+function l2(b) {
+  return b ^ rotl(b, 13) ^ rotl(b, 23);
+}
+
+/**
+ * 以一组 128 比特进行加密/解密操作
+ */
+function sms4Crypt(input, output, roundKey) {
+  var x = new Array(4);
+
+  // 字节数组转成字数组(此处 1 字 = 32 比特)
+  var tmp = new Array(4);
+  for (var i = 0; i < 4; i++) {
+    tmp[0] = input[4 * i] & 0xff;
+    tmp[1] = input[4 * i + 1] & 0xff;
+    tmp[2] = input[4 * i + 2] & 0xff;
+    tmp[3] = input[4 * i + 3] & 0xff;
+    x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
+  }
+
+  // x[i + 4] = x[i] ^ l1(byteSub(x[i + 1] ^ x[i + 2] ^ x[i + 3] ^ roundKey[i]))
+  for (var r = 0, mid; r < 32; r += 4) {
+    mid = x[1] ^ x[2] ^ x[3] ^ roundKey[r + 0];
+    x[0] ^= l1(byteSub(mid)); // x[4]
+
+    mid = x[2] ^ x[3] ^ x[0] ^ roundKey[r + 1];
+    x[1] ^= l1(byteSub(mid)); // x[5]
+
+    mid = x[3] ^ x[0] ^ x[1] ^ roundKey[r + 2];
+    x[2] ^= l1(byteSub(mid)); // x[6]
+
+    mid = x[0] ^ x[1] ^ x[2] ^ roundKey[r + 3];
+    x[3] ^= l1(byteSub(mid)); // x[7]
+  }
+
+  // 反序变换
+  for (var j = 0; j < 16; j += 4) {
+    output[j] = x[3 - j / 4] >>> 24 & 0xff;
+    output[j + 1] = x[3 - j / 4] >>> 16 & 0xff;
+    output[j + 2] = x[3 - j / 4] >>> 8 & 0xff;
+    output[j + 3] = x[3 - j / 4] & 0xff;
+  }
+}
+
+/**
+ * 密钥扩展算法
+ */
+function sms4KeyExt(key, roundKey, cryptFlag) {
+  var x = new Array(4);
+
+  // 字节数组转成字数组(此处 1 字 = 32 比特)
+  var tmp = new Array(4);
+  for (var i = 0; i < 4; i++) {
+    tmp[0] = key[0 + 4 * i] & 0xff;
+    tmp[1] = key[1 + 4 * i] & 0xff;
+    tmp[2] = key[2 + 4 * i] & 0xff;
+    tmp[3] = key[3 + 4 * i] & 0xff;
+    x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
+  }
+
+  // 与系统参数做异或
+  x[0] ^= 0xa3b1bac6;
+  x[1] ^= 0x56aa3350;
+  x[2] ^= 0x677d9197;
+  x[3] ^= 0xb27022dc;
+
+  // roundKey[i] = x[i + 4] = x[i] ^ l2(byteSub(x[i + 1] ^ x[i + 2] ^ x[i + 3] ^ CK[i]))
+  for (var r = 0, mid; r < 32; r += 4) {
+    mid = x[1] ^ x[2] ^ x[3] ^ CK[r + 0];
+    roundKey[r + 0] = x[0] ^= l2(byteSub(mid)); // x[4]
+
+    mid = x[2] ^ x[3] ^ x[0] ^ CK[r + 1];
+    roundKey[r + 1] = x[1] ^= l2(byteSub(mid)); // x[5]
+
+    mid = x[3] ^ x[0] ^ x[1] ^ CK[r + 2];
+    roundKey[r + 2] = x[2] ^= l2(byteSub(mid)); // x[6]
+
+    mid = x[0] ^ x[1] ^ x[2] ^ CK[r + 3];
+    roundKey[r + 3] = x[3] ^= l2(byteSub(mid)); // x[7]
+  }
+
+  // 解密时使用反序的轮密钥
+  if (cryptFlag === DECRYPT) {
+    for (var _r = 0, _mid; _r < 16; _r++) {
+      _mid = roundKey[_r];
+      roundKey[_r] = roundKey[31 - _r];
+      roundKey[31 - _r] = _mid;
+    }
+  }
+}
+
+function sm4(inArray, key, cryptFlag) {
+  var _ref = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {},
+      _ref$padding = _ref.padding,
+      padding = _ref$padding === undefined ? 'pkcs#7' : _ref$padding,
+      mode = _ref.mode,
+      _ref$iv = _ref.iv,
+      iv = _ref$iv === undefined ? [] : _ref$iv,
+      _ref$output = _ref.output,
+      output = _ref$output === undefined ? 'string' : _ref$output;
+
+  if (mode === 'cbc') {
+    // CBC 模式,默认走 ECB 模式
+    if (typeof iv === 'string') iv = hexToArray(iv);
+    if (iv.length !== 128 / 8) {
+      // iv 不是 128 比特
+      throw new Error('iv is invalid');
+    }
+  }
+
+  // 检查 key
+  if (typeof key === 'string') key = hexToArray(key);
+  if (key.length !== 128 / 8) {
+    // key 不是 128 比特
+    throw new Error('key is invalid');
+  }
+
+  // 检查输入
+  if (typeof inArray === 'string') {
+    if (cryptFlag !== DECRYPT) {
+      // 加密,输入为 utf8 串
+      inArray = utf8ToArray(inArray);
+    } else {
+      // 解密,输入为 16 进制串
+      inArray = hexToArray(inArray);
+    }
+  } else {
+    inArray = [].concat(inArray);
+  }
+
+  // 新增填充,sm4 是 16 个字节一个分组,所以统一走到 pkcs#7
+  if ((padding === 'pkcs#5' || padding === 'pkcs#7') && cryptFlag !== DECRYPT) {
+    var paddingCount = BLOCK - inArray.length % BLOCK;
+    for (var i = 0; i < paddingCount; i++) {
+      inArray.push(paddingCount);
+    }
+  }
+
+  // 生成轮密钥
+  var roundKey = new Array(ROUND);
+  sms4KeyExt(key, roundKey, cryptFlag);
+
+  var outArray = [];
+  var lastVector = iv;
+  var restLen = inArray.length;
+  var point = 0;
+  while (restLen >= BLOCK) {
+    var input = inArray.slice(point, point + 16);
+    var _output = new Array(16);
+
+    if (mode === 'cbc') {
+      for (var _i = 0; _i < BLOCK; _i++) {
+        if (cryptFlag !== DECRYPT) {
+          // 加密过程在组加密前进行异或
+          input[_i] ^= lastVector[_i];
+        }
+      }
+    }
+
+    sms4Crypt(input, _output, roundKey);
+
+    for (var _i2 = 0; _i2 < BLOCK; _i2++) {
+      if (mode === 'cbc') {
+        if (cryptFlag === DECRYPT) {
+          // 解密过程在组解密后进行异或
+          _output[_i2] ^= lastVector[_i2];
+        }
+      }
+
+      outArray[point + _i2] = _output[_i2];
+    }
+
+    if (mode === 'cbc') {
+      if (cryptFlag !== DECRYPT) {
+        // 使用上一次输出作为加密向量
+        lastVector = _output;
+      } else {
+        // 使用上一次输入作为解密向量
+        lastVector = input;
+      }
+    }
+
+    restLen -= BLOCK;
+    point += BLOCK;
+  }
+
+  // 去除填充,sm4 是 16 个字节一个分组,所以统一走到 pkcs#7
+  if ((padding === 'pkcs#5' || padding === 'pkcs#7') && cryptFlag === DECRYPT) {
+    var len = outArray.length;
+    var _paddingCount = outArray[len - 1];
+    for (var _i3 = 1; _i3 <= _paddingCount; _i3++) {
+      if (outArray[len - _i3] !== _paddingCount) throw new Error('padding is invalid');
+    }
+    outArray.splice(len - _paddingCount, _paddingCount);
+  }
+
+  // 调整输出
+  if (output !== 'array') {
+    if (cryptFlag !== DECRYPT) {
+      // 加密,输出转 16 进制串
+      return ArrayToHex(outArray);
+    } else {
+      // 解密,输出转 utf8 串
+      return arrayToUtf8(outArray);
+    }
+  } else {
+    return outArray;
+  }
+}
+
+module.exports = {
+  encrypt: function encrypt(inArray, key, options) {
+    return sm4(inArray, key, 1, options);
+  },
+  decrypt: function decrypt(inArray, key, options) {
+    return sm4(inArray, key, 0, options);
+  }
+};
+
+/***/ })
+/******/ ]);

+ 65 - 0
node_modules/miniprogram-sm-crypto/package.json

@@ -0,0 +1,65 @@
+{
+	"name": "miniprogram-sm-crypto",
+	"version": "0.3.13",
+	"description": "miniprogram js library",
+	"main": "miniprogram_dist/index.js",
+	"scripts": {
+		"prepublish": "npm run build",
+		"dev": "gulp dev --develop",
+		"watch": "gulp watch --develop --watch",
+		"build": "gulp",
+		"dist": "npm run build",
+		"clean-dev": "gulp clean --develop",
+		"clean": "gulp clean",
+		"test": "jest ./test/* --silent --bail",
+		"coverage": "jest ./test/* --coverage --bail",
+		"lint": "eslint \"src/**/*.js\" --fix",
+		"lint-tools": "eslint \"tools/**/*.js\" --rule \"import/no-extraneous-dependencies: false\""
+	},
+	"miniprogram": "miniprogram_dist",
+	"repository": {
+		"type": "git",
+		"url": "https://github.com/wechat-miniprogram/sm-crypto.git"
+	},
+	"author": "wechat-miniprogram",
+	"license": "MIT",
+	"devDependencies": {
+		"babel-core": "^6.26.3",
+		"babel-loader": "^7.1.5",
+		"babel-plugin-module-resolver": "^3.1.1",
+		"babel-preset-env": "^1.7.0",
+		"colors": "^1.3.1",
+		"eslint": "^5.3.0",
+		"eslint-loader": "^2.1.0",
+		"gulp": "^4.0.0",
+		"gulp-clean": "^0.4.0",
+		"gulp-if": "^2.0.2",
+		"gulp-install": "^1.1.0",
+		"gulp-less": "^3.5.0",
+		"gulp-rename": "^1.4.0",
+		"gulp-sourcemaps": "^2.6.4",
+		"j-component": "git+https://github.com/JuneAndGreen/j-component.git",
+		"jest": "^23.5.0",
+		"through2": "^2.0.3",
+		"webpack": "^4.16.5",
+		"webpack-node-externals": "^1.7.2",
+		"eslint-config-airbnb-base": "13.1.0",
+		"eslint-plugin-import": "^2.14.0",
+		"eslint-plugin-node": "^7.0.1",
+		"eslint-plugin-promise": "^3.8.0"
+	},
+	"dependencies": {
+		"jsbn": "^1.1.0"
+	},
+	"jest": {
+		"testEnvironment": "jsdom",
+		"testURL": "https://jest.test",
+		"collectCoverageFrom": [
+			"src/**/*.js"
+		],
+		"moduleDirectories": [
+			"node_modules",
+			"src"
+		]
+	}
+}

+ 5 - 0
node_modules/miniprogram-sm-crypto/src/index.js

@@ -0,0 +1,5 @@
+module.exports = {
+  sm2: require('./sm2/index'),
+  sm3: require('./sm3/index'),
+  sm4: require('./sm4/index'),
+}

+ 161 - 0
node_modules/miniprogram-sm-crypto/src/sm2/asn1.js

@@ -0,0 +1,161 @@
+/* eslint-disable class-methods-use-this */
+const {BigInteger} = require('jsbn')
+
+function bigintToValue(bigint) {
+  let h = bigint.toString(16)
+  if (h[0] !== '-') {
+    // 正数
+    if (h.length % 2 === 1) h = '0' + h // 补齐到整字节
+    else if (!h.match(/^[0-7]/)) h = '00' + h // 非0开头,则补一个全0字节
+  } else {
+    // 负数
+    h = h.substr(1)
+
+    let len = h.length
+    if (len % 2 === 1) len += 1 // 补齐到整字节
+    else if (!h.match(/^[0-7]/)) len += 2 // 非0开头,则补一个全0字节
+
+    let mask = ''
+    for (let i = 0; i < len; i++) mask += 'f'
+    mask = new BigInteger(mask, 16)
+
+    // 对绝对值取反,加1
+    h = mask.xor(bigint).add(BigInteger.ONE)
+    h = h.toString(16).replace(/^-/, '')
+  }
+  return h
+}
+
+class ASN1Object {
+  constructor() {
+    this.tlv = null
+    this.t = '00'
+    this.l = '00'
+    this.v = ''
+  }
+
+  /**
+   * 获取 der 编码比特流16进制串
+   */
+  getEncodedHex() {
+    if (!this.tlv) {
+      this.v = this.getValue()
+      this.l = this.getLength()
+      this.tlv = this.t + this.l + this.v
+    }
+    return this.tlv
+  }
+
+  getLength() {
+    const n = this.v.length / 2 // 字节数
+    let nHex = n.toString(16)
+    if (nHex.length % 2 === 1) nHex = '0' + nHex // 补齐到整字节
+
+    if (n < 128) {
+      // 短格式,以 0 开头
+      return nHex
+    } else {
+      // 长格式,以 1 开头
+      const head = 128 + nHex.length / 2 // 1(1位) + 真正的长度占用字节数(7位) + 真正的长度
+      return head.toString(16) + nHex
+    }
+  }
+
+  getValue() {
+    return ''
+  }
+}
+
+class DERInteger extends ASN1Object {
+  constructor(bigint) {
+    super()
+
+    this.t = '02' // 整型标签说明
+    if (bigint) this.v = bigintToValue(bigint)
+  }
+
+  getValue() {
+    return this.v
+  }
+}
+
+class DERSequence extends ASN1Object {
+  constructor(asn1Array) {
+    super()
+
+    this.t = '30' // 序列标签说明
+    this.asn1Array = asn1Array
+  }
+
+  getValue() {
+    this.v = this.asn1Array.map(asn1Object => asn1Object.getEncodedHex()).join('')
+    return this.v
+  }
+}
+
+/**
+ * 获取 l 占用字节数
+ */
+function getLenOfL(str, start) {
+  if (+str[start + 2] < 8) return 1 // l 以0开头,则表示短格式,只占一个字节
+  return +str.substr(start + 2, 2) & 0x7f + 1 // 长格式,取第一个字节后7位作为长度真正占用字节数,再加上本身
+}
+
+/**
+ * 获取 l
+ */
+function getL(str, start) {
+  // 获取 l
+  const len = getLenOfL(str, start)
+  const l = str.substr(start + 2, len * 2)
+
+  if (!l) return -1
+  const bigint = +l[0] < 8 ? new BigInteger(l, 16) : new BigInteger(l.substr(2), 16)
+
+  return bigint.intValue()
+}
+
+/**
+ * 获取 v 的位置
+ */
+function getStartOfV(str, start) {
+  const len = getLenOfL(str, start)
+  return start + (len + 1) * 2
+}
+
+module.exports = {
+  /**
+   * ASN.1 der 编码,针对 sm2 签名
+   */
+  encodeDer(r, s) {
+    const derR = new DERInteger(r)
+    const derS = new DERInteger(s)
+    const derSeq = new DERSequence([derR, derS])
+
+    return derSeq.getEncodedHex()
+  },
+
+  /**
+   * 解析 ASN.1 der,针对 sm2 验签
+   */
+  decodeDer(input) {
+    // 结构:
+    // input = | tSeq | lSeq | vSeq |
+    // vSeq = | tR | lR | vR | tS | lS | vS |
+    const start = getStartOfV(input, 0)
+
+    const vIndexR = getStartOfV(input, start)
+    const lR = getL(input, start)
+    const vR = input.substr(vIndexR, lR * 2)
+
+    const nextStart = vIndexR + vR.length
+    const vIndexS = getStartOfV(input, nextStart)
+    const lS = getL(input, nextStart)
+    const vS = input.substr(vIndexS, lS * 2)
+
+    const r = new BigInteger(vR, 16)
+    const s = new BigInteger(vS, 16)
+
+    return {r, s}
+  }
+}

+ 332 - 0
node_modules/miniprogram-sm-crypto/src/sm2/ec.js

@@ -0,0 +1,332 @@
+/* eslint-disable no-case-declarations, max-len */
+const {BigInteger} = require('jsbn')
+
+/**
+ * thanks for Tom Wu : http://www-cs-students.stanford.edu/~tjw/jsbn/
+ *
+ * Basic Javascript Elliptic Curve implementation
+ * Ported loosely from BouncyCastle's Java EC code
+ * Only Fp curves implemented for now
+ */
+
+const TWO = new BigInteger('2')
+const THREE = new BigInteger('3')
+
+/**
+ * 椭圆曲线域元素
+ */
+class ECFieldElementFp {
+  constructor(q, x) {
+    this.x = x
+    this.q = q
+    // TODO if (x.compareTo(q) >= 0) error
+  }
+
+  /**
+   * 判断相等
+   */
+  equals(other) {
+    if (other === this) return true
+    return (this.q.equals(other.q) && this.x.equals(other.x))
+  }
+
+  /**
+   * 返回具体数值
+   */
+  toBigInteger() {
+    return this.x
+  }
+
+  /**
+   * 取反
+   */
+  negate() {
+    return new ECFieldElementFp(this.q, this.x.negate().mod(this.q))
+  }
+
+  /**
+   * 相加
+   */
+  add(b) {
+    return new ECFieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q))
+  }
+
+  /**
+   * 相减
+   */
+  subtract(b) {
+    return new ECFieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q))
+  }
+
+  /**
+   * 相乘
+   */
+  multiply(b) {
+    return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q))
+  }
+
+  /**
+   * 相除
+   */
+  divide(b) {
+    return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger().modInverse(this.q)).mod(this.q))
+  }
+
+  /**
+   * 平方
+   */
+  square() {
+    return new ECFieldElementFp(this.q, this.x.square().mod(this.q))
+  }
+}
+
+class ECPointFp {
+  constructor(curve, x, y, z) {
+    this.curve = curve
+    this.x = x
+    this.y = y
+    // 标准射影坐标系:zinv == null 或 z * zinv == 1
+    this.z = z == null ? BigInteger.ONE : z
+    this.zinv = null
+    // TODO: compression flag
+  }
+
+  getX() {
+    if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q)
+
+    return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q))
+  }
+
+  getY() {
+    if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q)
+
+    return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q))
+  }
+
+  /**
+   * 判断相等
+   */
+  equals(other) {
+    if (other === this) return true
+    if (this.isInfinity()) return other.isInfinity()
+    if (other.isInfinity()) return this.isInfinity()
+
+    // u = y2 * z1 - y1 * z2
+    const u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q)
+    if (!u.equals(BigInteger.ZERO)) return false
+
+    // v = x2 * z1 - x1 * z2
+    const v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q)
+    return v.equals(BigInteger.ZERO)
+  }
+
+  /**
+   * 是否是无穷远点
+   */
+  isInfinity() {
+    if ((this.x === null) && (this.y === null)) return true
+    return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO)
+  }
+
+  /**
+   * 取反,x 轴对称点
+   */
+  negate() {
+    return new ECPointFp(this.curve, this.x, this.y.negate(), this.z)
+  }
+
+  /**
+   * 相加
+   *
+   * 标准射影坐标系:
+   *
+   * λ1 = x1 * z2
+   * λ2 = x2 * z1
+   * λ3 = λ1 − λ2
+   * λ4 = y1 * z2
+   * λ5 = y2 * z1
+   * λ6 = λ4 − λ5
+   * λ7 = λ1 + λ2
+   * λ8 = z1 * z2
+   * λ9 = λ3^2
+   * λ10 = λ3 * λ9
+   * λ11 = λ8 * λ6^2 − λ7 * λ9
+   * x3 = λ3 * λ11
+   * y3 = λ6 * (λ9 * λ1 − λ11) − λ4 * λ10
+   * z3 = λ10 * λ8
+   */
+  add(b) {
+    if (this.isInfinity()) return b
+    if (b.isInfinity()) return this
+
+    const x1 = this.x.toBigInteger()
+    const y1 = this.y.toBigInteger()
+    const z1 = this.z
+    const x2 = b.x.toBigInteger()
+    const y2 = b.y.toBigInteger()
+    const z2 = b.z
+    const q = this.curve.q
+
+    const w1 = x1.multiply(z2).mod(q)
+    const w2 = x2.multiply(z1).mod(q)
+    const w3 = w1.subtract(w2)
+    const w4 = y1.multiply(z2).mod(q)
+    const w5 = y2.multiply(z1).mod(q)
+    const w6 = w4.subtract(w5)
+
+    if (BigInteger.ZERO.equals(w3)) {
+      if (BigInteger.ZERO.equals(w6)) {
+        return this.twice() // this == b,计算自加
+      }
+      return this.curve.infinity // this == -b,则返回无穷远点
+    }
+
+    const w7 = w1.add(w2)
+    const w8 = z1.multiply(z2).mod(q)
+    const w9 = w3.square().mod(q)
+    const w10 = w3.multiply(w9).mod(q)
+    const w11 = w8.multiply(w6.square()).subtract(w7.multiply(w9)).mod(q)
+
+    const x3 = w3.multiply(w11).mod(q)
+    const y3 = w6.multiply(w9.multiply(w1).subtract(w11)).subtract(w4.multiply(w10)).mod(q)
+    const z3 = w10.multiply(w8).mod(q)
+
+    return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3)
+  }
+
+  /**
+   * 自加
+   *
+   * 标准射影坐标系:
+   *
+   * λ1 = 3 * x1^2 + a * z1^2
+   * λ2 = 2 * y1 * z1
+   * λ3 = y1^2
+   * λ4 = λ3 * x1 * z1
+   * λ5 = λ2^2
+   * λ6 = λ1^2 − 8 * λ4
+   * x3 = λ2 * λ6
+   * y3 = λ1 * (4 * λ4 − λ6) − 2 * λ5 * λ3
+   * z3 = λ2 * λ5
+   */
+  twice() {
+    if (this.isInfinity()) return this
+    if (!this.y.toBigInteger().signum()) return this.curve.infinity
+
+    const x1 = this.x.toBigInteger()
+    const y1 = this.y.toBigInteger()
+    const z1 = this.z
+    const q = this.curve.q
+    const a = this.curve.a.toBigInteger()
+
+    const w1 = x1.square().multiply(THREE).add(a.multiply(z1.square())).mod(q)
+    const w2 = y1.shiftLeft(1).multiply(z1).mod(q)
+    const w3 = y1.square().mod(q)
+    const w4 = w3.multiply(x1).multiply(z1).mod(q)
+    const w5 = w2.square().mod(q)
+    const w6 = w1.square().subtract(w4.shiftLeft(3)).mod(q)
+
+    const x3 = w2.multiply(w6).mod(q)
+    const y3 = w1.multiply(w4.shiftLeft(2).subtract(w6)).subtract(w5.shiftLeft(1).multiply(w3)).mod(q)
+    const z3 = w2.multiply(w5).mod(q)
+
+    return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3)
+  }
+
+  /**
+   * 倍点计算
+   */
+  multiply(k) {
+    if (this.isInfinity()) return this
+    if (!k.signum()) return this.curve.infinity
+
+    // 使用加减法
+    const k3 = k.multiply(THREE)
+    const neg = this.negate()
+    let Q = this
+
+    for (let i = k3.bitLength() - 2; i > 0; i--) {
+      Q = Q.twice()
+
+      const k3Bit = k3.testBit(i)
+      const kBit = k.testBit(i)
+
+      if (k3Bit !== kBit) {
+        Q = Q.add(k3Bit ? this : neg)
+      }
+    }
+
+    return Q
+  }
+}
+
+/**
+ * 椭圆曲线 y^2 = x^3 + ax + b
+ */
+class ECCurveFp {
+  constructor(q, a, b) {
+    this.q = q
+    this.a = this.fromBigInteger(a)
+    this.b = this.fromBigInteger(b)
+    this.infinity = new ECPointFp(this, null, null) // 无穷远点
+  }
+
+  /**
+   * 判断两个椭圆曲线是否相等
+   */
+  equals(other) {
+    if (other === this) return true
+    return (this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b))
+  }
+
+  /**
+   * 生成椭圆曲线域元素
+   */
+  fromBigInteger(x) {
+    return new ECFieldElementFp(this.q, x)
+  }
+
+  /**
+   * 解析 16 进制串为椭圆曲线点
+   */
+  decodePointHex(s) {
+    switch (parseInt(s.substr(0, 2), 16)) {
+      // 第一个字节
+      case 0:
+        return this.infinity
+      case 2:
+      case 3:
+        // 压缩
+        const x = this.fromBigInteger(new BigInteger(s.substr(2), 16))
+        // 对 p ≡ 3 (mod4),即存在正整数 u,使得 p = 4u + 3
+        // 计算 y = (√ (x^3 + ax + b) % p)^(u + 1) modp
+        let y = this.fromBigInteger(x.multiply(x.square()).add(
+          x.multiply(this.a)
+        ).add(this.b).toBigInteger()
+          .modPow(
+            this.q.divide(new BigInteger('4')).add(BigInteger.ONE), this.q
+          ))
+        // 算出结果 2 进制最后 1 位不等于第 1 个字节减 2 则取反
+        if (!y.toBigInteger().mod(TWO).equals(new BigInteger(s.substr(0, 2), 16).subtract(TWO))) {
+          y = y.negate()
+        }
+        return new ECPointFp(this, x, y)
+      case 4:
+      case 6:
+      case 7:
+        const len = (s.length - 2) / 2
+        const xHex = s.substr(2, len)
+        const yHex = s.substr(len + 2, len)
+
+        return new ECPointFp(this, this.fromBigInteger(new BigInteger(xHex, 16)), this.fromBigInteger(new BigInteger(yHex, 16)))
+      default:
+        // 不支持
+        return null
+    }
+  }
+}
+
+module.exports = {
+  ECPointFp,
+  ECCurveFp,
+}

+ 261 - 0
node_modules/miniprogram-sm-crypto/src/sm2/index.js

@@ -0,0 +1,261 @@
+/* eslint-disable no-use-before-define */
+const {BigInteger} = require('jsbn')
+const {encodeDer, decodeDer} = require('./asn1')
+const _ = require('./utils')
+const sm3 = require('./sm3').sm3
+
+const {G, curve, n} = _.generateEcparam()
+const C1C2C3 = 0
+
+/**
+ * 加密
+ */
+function doEncrypt(msg, publicKey, cipherMode = 1) {
+  msg = typeof msg === 'string' ? _.hexToArray(_.utf8ToHex(msg)) : Array.prototype.slice.call(msg)
+  publicKey = _.getGlobalCurve().decodePointHex(publicKey) // 先将公钥转成点
+
+  const keypair = _.generateKeyPairHex()
+  const k = new BigInteger(keypair.privateKey, 16) // 随机数 k
+
+  // c1 = k * G
+  let c1 = keypair.publicKey
+  if (c1.length > 128) c1 = c1.substr(c1.length - 128)
+
+  // (x2, y2) = k * publicKey
+  const p = publicKey.multiply(k)
+  const x2 = _.hexToArray(_.leftPad(p.getX().toBigInteger().toRadix(16), 64))
+  const y2 = _.hexToArray(_.leftPad(p.getY().toBigInteger().toRadix(16), 64))
+
+  // c3 = hash(x2 || msg || y2)
+  const c3 = _.arrayToHex(sm3([].concat(x2, msg, y2)))
+
+  let ct = 1
+  let offset = 0
+  let t = [] // 256 位
+  const z = [].concat(x2, y2)
+  const nextT = () => {
+    // (1) Hai = hash(z || ct)
+    // (2) ct++
+    t = sm3([...z, ct >> 24 & 0x00ff, ct >> 16 & 0x00ff, ct >> 8 & 0x00ff, ct & 0x00ff])
+    ct++
+    offset = 0
+  }
+  nextT() // 先生成 Ha1
+
+  for (let i = 0, len = msg.length; i < len; i++) {
+    // t = Ha1 || Ha2 || Ha3 || Ha4
+    if (offset === t.length) nextT()
+
+    // c2 = msg ^ t
+    msg[i] ^= t[offset++] & 0xff
+  }
+  const c2 = _.arrayToHex(msg)
+
+  return cipherMode === C1C2C3 ? c1 + c2 + c3 : c1 + c3 + c2
+}
+
+/**
+ * 解密
+ */
+function doDecrypt(encryptData, privateKey, cipherMode = 1, {
+  output = 'string',
+} = {}) {
+  privateKey = new BigInteger(privateKey, 16)
+
+  let c3 = encryptData.substr(128, 64)
+  let c2 = encryptData.substr(128 + 64)
+
+  if (cipherMode === C1C2C3) {
+    c3 = encryptData.substr(encryptData.length - 64)
+    c2 = encryptData.substr(128, encryptData.length - 128 - 64)
+  }
+
+  const msg = _.hexToArray(c2)
+  const c1 = _.getGlobalCurve().decodePointHex('04' + encryptData.substr(0, 128))
+
+  const p = c1.multiply(privateKey)
+  const x2 = _.hexToArray(_.leftPad(p.getX().toBigInteger().toRadix(16), 64))
+  const y2 = _.hexToArray(_.leftPad(p.getY().toBigInteger().toRadix(16), 64))
+
+  let ct = 1
+  let offset = 0
+  let t = [] // 256 位
+  const z = [].concat(x2, y2)
+  const nextT = () => {
+    // (1) Hai = hash(z || ct)
+    // (2) ct++
+    t = sm3([...z, ct >> 24 & 0x00ff, ct >> 16 & 0x00ff, ct >> 8 & 0x00ff, ct & 0x00ff])
+    ct++
+    offset = 0
+  }
+  nextT() // 先生成 Ha1
+
+  for (let i = 0, len = msg.length; i < len; i++) {
+    // t = Ha1 || Ha2 || Ha3 || Ha4
+    if (offset === t.length) nextT()
+
+    // c2 = msg ^ t
+    msg[i] ^= t[offset++] & 0xff
+  }
+
+  // c3 = hash(x2 || msg || y2)
+  const checkC3 = _.arrayToHex(sm3([].concat(x2, msg, y2)))
+
+  if (checkC3 === c3.toLowerCase()) {
+    return output === 'array' ? msg : _.arrayToUtf8(msg)
+  } else {
+    return output === 'array' ? [] : ''
+  }
+}
+
+/**
+ * 签名
+ */
+function doSignature(msg, privateKey, {
+  pointPool, der, hash, publicKey, userId
+} = {}) {
+  let hashHex = typeof msg === 'string' ? _.utf8ToHex(msg) : _.arrayToHex(msg)
+
+  if (hash) {
+    // sm3杂凑
+    publicKey = publicKey || getPublicKeyFromPrivateKey(privateKey)
+    hashHex = getHash(hashHex, publicKey, userId)
+  }
+
+  const dA = new BigInteger(privateKey, 16)
+  const e = new BigInteger(hashHex, 16)
+
+  // k
+  let k = null
+  let r = null
+  let s = null
+
+  do {
+    do {
+      let point
+      if (pointPool && pointPool.length) {
+        point = pointPool.pop()
+      } else {
+        point = getPoint()
+      }
+      k = point.k
+
+      // r = (e + x1) mod n
+      r = e.add(point.x1).mod(n)
+    } while (r.equals(BigInteger.ZERO) || r.add(k).equals(n))
+
+    // s = ((1 + dA)^-1 * (k - r * dA)) mod n
+    s = dA.add(BigInteger.ONE).modInverse(n).multiply(k.subtract(r.multiply(dA))).mod(n)
+  } while (s.equals(BigInteger.ZERO))
+
+  if (der) return encodeDer(r, s) // asn.1 der 编码
+
+  return _.leftPad(r.toString(16), 64) + _.leftPad(s.toString(16), 64)
+}
+
+/**
+ * 验签
+ */
+function doVerifySignature(msg, signHex, publicKey, {der, hash, userId} = {}) {
+  let hashHex = typeof msg === 'string' ? _.utf8ToHex(msg) : _.arrayToHex(msg)
+
+  if (hash) {
+    // sm3杂凑
+    hashHex = getHash(hashHex, publicKey, userId)
+  }
+
+  let r; let
+    s
+  if (der) {
+    const decodeDerObj = decodeDer(signHex) // asn.1 der 解码
+    r = decodeDerObj.r
+    s = decodeDerObj.s
+  } else {
+    r = new BigInteger(signHex.substring(0, 64), 16)
+    s = new BigInteger(signHex.substring(64), 16)
+  }
+
+  const PA = curve.decodePointHex(publicKey)
+  const e = new BigInteger(hashHex, 16)
+
+  // t = (r + s) mod n
+  const t = r.add(s).mod(n)
+
+  if (t.equals(BigInteger.ZERO)) return false
+
+  // x1y1 = s * G + t * PA
+  const x1y1 = G.multiply(s).add(PA.multiply(t))
+
+  // R = (e + x1) mod n
+  const R = e.add(x1y1.getX().toBigInteger()).mod(n)
+
+  return r.equals(R)
+}
+
+/**
+ * sm3杂凑算法
+ */
+function getHash(hashHex, publicKey, userId = '1234567812345678') {
+  // z = hash(entl || userId || a || b || gx || gy || px || py)
+  userId = _.utf8ToHex(userId)
+  const a = _.leftPad(G.curve.a.toBigInteger().toRadix(16), 64)
+  const b = _.leftPad(G.curve.b.toBigInteger().toRadix(16), 64)
+  const gx = _.leftPad(G.getX().toBigInteger().toRadix(16), 64)
+  const gy = _.leftPad(G.getY().toBigInteger().toRadix(16), 64)
+  let px
+  let py
+  if (publicKey.length === 128) {
+    px = publicKey.substr(0, 64)
+    py = publicKey.substr(64, 64)
+  } else {
+    const point = G.curve.decodePointHex(publicKey)
+    px = _.leftPad(point.getX().toBigInteger().toRadix(16), 64)
+    py = _.leftPad(point.getY().toBigInteger().toRadix(16), 64)
+  }
+  const data = _.hexToArray(userId + a + b + gx + gy + px + py)
+
+  const entl = userId.length * 4
+  data.unshift(entl & 0x00ff)
+  data.unshift(entl >> 8 & 0x00ff)
+
+  const z = sm3(data)
+
+  // e = hash(z || msg)
+  return _.arrayToHex(sm3(z.concat(_.hexToArray(hashHex))))
+}
+
+/**
+ * 计算公钥
+ */
+function getPublicKeyFromPrivateKey(privateKey) {
+  const PA = G.multiply(new BigInteger(privateKey, 16))
+  const x = _.leftPad(PA.getX().toBigInteger().toString(16), 64)
+  const y = _.leftPad(PA.getY().toBigInteger().toString(16), 64)
+  return '04' + x + y
+}
+
+/**
+ * 获取椭圆曲线点
+ */
+function getPoint() {
+  const keypair = _.generateKeyPairHex()
+  const PA = curve.decodePointHex(keypair.publicKey)
+
+  keypair.k = new BigInteger(keypair.privateKey, 16)
+  keypair.x1 = PA.getX().toBigInteger()
+
+  return keypair
+}
+
+module.exports = {
+  generateKeyPairHex: _.generateKeyPairHex,
+  compressPublicKeyHex: _.compressPublicKeyHex,
+  comparePublicKeyHex: _.comparePublicKeyHex,
+  doEncrypt,
+  doDecrypt,
+  doSignature,
+  doVerifySignature,
+  getPublicKeyFromPrivateKey,
+  getPoint,
+  verifyPublicKey: _.verifyPublicKey,
+}

+ 170 - 0
node_modules/miniprogram-sm-crypto/src/sm2/sm3.js

@@ -0,0 +1,170 @@
+// 消息扩展
+const W = new Uint32Array(68)
+const M = new Uint32Array(64) // W'
+
+/**
+ * 循环左移
+ */
+function rotl(x, n) {
+  const s = n & 31
+  return (x << s) | (x >>> (32 - s))
+}
+
+/**
+ * 二进制异或运算
+ */
+function xor(x, y) {
+  const result = []
+  for (let i = x.length - 1; i >= 0; i--) result[i] = (x[i] ^ y[i]) & 0xff
+  return result
+}
+
+/**
+ * 压缩函数中的置换函数 P0(X) = X xor (X <<< 9) xor (X <<< 17)
+ */
+function P0(X) {
+  return (X ^ rotl(X, 9)) ^ rotl(X, 17)
+}
+
+/**
+ * 消息扩展中的置换函数 P1(X) = X xor (X <<< 15) xor (X <<< 23)
+ */
+function P1(X) {
+  return (X ^ rotl(X, 15)) ^ rotl(X, 23)
+}
+
+/**
+ * sm3 本体
+ */
+function sm3(array) {
+  let len = array.length * 8
+
+  // k 是满足 len + 1 + k = 448mod512 的最小的非负整数
+  let k = len % 512
+  // 如果 448 <= (512 % len) < 512,需要多补充 (len % 448) 比特'0'以满足总比特长度为512的倍数
+  k = k >= 448 ? 512 - (k % 448) - 1 : 448 - k - 1
+
+  // 填充
+  const kArr = new Array((k - 7) / 8)
+  const lenArr = new Array(8)
+  for (let i = 0, len = kArr.length; i < len; i++) kArr[i] = 0
+  for (let i = 0, len = lenArr.length; i < len; i++) lenArr[i] = 0
+  len = len.toString(2)
+  for (let i = 7; i >= 0; i--) {
+    if (len.length > 8) {
+      const start = len.length - 8
+      lenArr[i] = parseInt(len.substr(start), 2)
+      len = len.substr(0, start)
+    } else if (len.length > 0) {
+      lenArr[i] = parseInt(len, 2)
+      len = ''
+    }
+  }
+  const m = new Uint8Array([...array, 0x80, ...kArr, ...lenArr])
+  const dataView = new DataView(m.buffer, 0)
+
+  // 迭代压缩
+  const n = m.length / 64
+  const V = new Uint32Array([0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e])
+  for (let i = 0; i < n; i++) {
+    W.fill(0)
+    M.fill(0)
+
+    // 将消息分组B划分为 16 个字 W0, W1,……,W15
+    const start = 16 * i
+    for (let j = 0; j < 16; j++) {
+      W[j] = dataView.getUint32((start + j) * 4, false)
+    }
+
+    // W16 ~ W67:W[j] <- P1(W[j−16] xor W[j−9] xor (W[j−3] <<< 15)) xor (W[j−13] <<< 7) xor W[j−6]
+    for (let j = 16; j < 68; j++) {
+      W[j] = (P1((W[j - 16] ^ W[j - 9]) ^ rotl(W[j - 3], 15)) ^ rotl(W[j - 13], 7)) ^ W[j - 6]
+    }
+
+    // W′0 ~ W′63:W′[j] = W[j] xor W[j+4]
+    for (let j = 0; j < 64; j++) {
+      M[j] = W[j] ^ W[j + 4]
+    }
+
+    // 压缩
+    const T1 = 0x79cc4519
+    const T2 = 0x7a879d8a
+    // 字寄存器
+    let A = V[0]
+    let B = V[1]
+    let C = V[2]
+    let D = V[3]
+    let E = V[4]
+    let F = V[5]
+    let G = V[6]
+    let H = V[7]
+    // 中间变量
+    let SS1
+    let SS2
+    let TT1
+    let TT2
+    let T
+    for (let j = 0; j < 64; j++) {
+      T = j >= 0 && j <= 15 ? T1 : T2
+      SS1 = rotl(rotl(A, 12) + E + rotl(T, j), 7)
+      SS2 = SS1 ^ rotl(A, 12)
+
+      TT1 = (j >= 0 && j <= 15 ? ((A ^ B) ^ C) : (((A & B) | (A & C)) | (B & C))) + D + SS2 + M[j]
+      TT2 = (j >= 0 && j <= 15 ? ((E ^ F) ^ G) : ((E & F) | ((~E) & G))) + H + SS1 + W[j]
+
+      D = C
+      C = rotl(B, 9)
+      B = A
+      A = TT1
+      H = G
+      G = rotl(F, 19)
+      F = E
+      E = P0(TT2)
+    }
+
+    V[0] ^= A
+    V[1] ^= B
+    V[2] ^= C
+    V[3] ^= D
+    V[4] ^= E
+    V[5] ^= F
+    V[6] ^= G
+    V[7] ^= H
+  }
+
+  // 转回 uint8
+  const result = []
+  for (let i = 0, len = V.length; i < len; i++) {
+    const word = V[i]
+    result.push((word & 0xff000000) >>> 24, (word & 0xff0000) >>> 16, (word & 0xff00) >>> 8, word & 0xff)
+  }
+
+  return result
+}
+
+/**
+ * hmac 实现
+ */
+const blockLen = 64
+const iPad = new Uint8Array(blockLen)
+const oPad = new Uint8Array(blockLen)
+for (let i = 0; i < blockLen; i++) {
+  iPad[i] = 0x36
+  oPad[i] = 0x5c
+}
+function hmac(input, key) {
+  // 密钥填充
+  if (key.length > blockLen) key = sm3(key)
+  while (key.length < blockLen) key.push(0)
+
+  const iPadKey = xor(key, iPad)
+  const oPadKey = xor(key, oPad)
+
+  const hash = sm3([...iPadKey, ...input])
+  return sm3([...oPadKey, ...hash])
+}
+
+module.exports = {
+  sm3,
+  hmac,
+}

+ 194 - 0
node_modules/miniprogram-sm-crypto/src/sm2/utils.js

@@ -0,0 +1,194 @@
+/* eslint-disable no-bitwise, no-mixed-operators, no-use-before-define, max-len */
+const {BigInteger, SecureRandom} = require('jsbn')
+const {ECCurveFp} = require('./ec')
+
+const rng = new SecureRandom()
+const {curve, G, n} = generateEcparam()
+
+/**
+ * 获取公共椭圆曲线
+ */
+function getGlobalCurve() {
+  return curve
+}
+
+/**
+ * 生成ecparam
+ */
+function generateEcparam() {
+  // 椭圆曲线
+  const p = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16)
+  const a = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16)
+  const b = new BigInteger('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93', 16)
+  const curve = new ECCurveFp(p, a, b)
+
+  // 基点
+  const gxHex = '32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7'
+  const gyHex = 'BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0'
+  const G = curve.decodePointHex('04' + gxHex + gyHex)
+
+  const n = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123', 16)
+
+  return {curve, G, n}
+}
+
+/**
+ * 生成密钥对:publicKey = privateKey * G
+ */
+function generateKeyPairHex(a, b, c) {
+  const random = a ? new BigInteger(a, b, c) : new BigInteger(n.bitLength(), rng)
+  const d = random.mod(n.subtract(BigInteger.ONE)).add(BigInteger.ONE) // 随机数
+  const privateKey = leftPad(d.toString(16), 64)
+
+  const P = G.multiply(d) // P = dG,p 为公钥,d 为私钥
+  const Px = leftPad(P.getX().toBigInteger().toString(16), 64)
+  const Py = leftPad(P.getY().toBigInteger().toString(16), 64)
+  const publicKey = '04' + Px + Py
+
+  return {privateKey, publicKey}
+}
+
+/**
+ * 生成压缩公钥
+ */
+function compressPublicKeyHex(s) {
+  if (s.length !== 130) throw new Error('Invalid public key to compress')
+
+  const len = (s.length - 2) / 2
+  const xHex = s.substr(2, len)
+  const y = new BigInteger(s.substr(len + 2, len), 16)
+
+  let prefix = '03'
+  if (y.mod(new BigInteger('2')).equals(BigInteger.ZERO)) prefix = '02'
+
+  return prefix + xHex
+}
+
+/**
+ * utf8串转16进制串
+ */
+function utf8ToHex(input) {
+  input = unescape(encodeURIComponent(input))
+
+  const length = input.length
+
+  // 转换到字数组
+  const words = []
+  for (let i = 0; i < length; i++) {
+    words[i >>> 2] |= (input.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8)
+  }
+
+  // 转换到16进制
+  const hexChars = []
+  for (let i = 0; i < length; i++) {
+    const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff
+    hexChars.push((bite >>> 4).toString(16))
+    hexChars.push((bite & 0x0f).toString(16))
+  }
+
+  return hexChars.join('')
+}
+
+/**
+ * 补全16进制字符串
+ */
+function leftPad(input, num) {
+  if (input.length >= num) return input
+
+  return (new Array(num - input.length + 1)).join('0') + input
+}
+
+/**
+ * 转成16进制串
+ */
+function arrayToHex(arr) {
+  return arr.map(item => {
+    item = item.toString(16)
+    return item.length === 1 ? '0' + item : item
+  }).join('')
+}
+
+/**
+ * 转成utf8串
+ */
+function arrayToUtf8(arr) {
+  const words = []
+  let j = 0
+  for (let i = 0; i < arr.length * 2; i += 2) {
+    words[i >>> 3] |= parseInt(arr[j], 10) << (24 - (i % 8) * 4)
+    j++
+  }
+
+  try {
+    const latin1Chars = []
+
+    for (let i = 0; i < arr.length; i++) {
+      const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff
+      latin1Chars.push(String.fromCharCode(bite))
+    }
+
+    return decodeURIComponent(escape(latin1Chars.join('')))
+  } catch (e) {
+    throw new Error('Malformed UTF-8 data')
+  }
+}
+
+/**
+ * 转成字节数组
+ */
+function hexToArray(hexStr) {
+  const words = []
+  let hexStrLength = hexStr.length
+
+  if (hexStrLength % 2 !== 0) {
+    hexStr = leftPad(hexStr, hexStrLength + 1)
+  }
+
+  hexStrLength = hexStr.length
+
+  for (let i = 0; i < hexStrLength; i += 2) {
+    words.push(parseInt(hexStr.substr(i, 2), 16))
+  }
+  return words
+}
+
+/**
+ * 验证公钥是否为椭圆曲线上的点
+ */
+function verifyPublicKey(publicKey) {
+  const point = curve.decodePointHex(publicKey)
+  if (!point) return false
+
+  const x = point.getX()
+  const y = point.getY()
+
+  // 验证 y^2 是否等于 x^3 + ax + b
+  return y.square().equals(x.multiply(x.square()).add(x.multiply(curve.a)).add(curve.b))
+}
+
+/**
+ * 验证公钥是否等价,等价返回true
+ */
+function comparePublicKeyHex(publicKey1, publicKey2) {
+  const point1 = curve.decodePointHex(publicKey1)
+  if (!point1) return false
+
+  const point2 = curve.decodePointHex(publicKey2)
+  if (!point2) return false
+
+  return point1.equals(point2)
+}
+
+module.exports = {
+  getGlobalCurve,
+  generateEcparam,
+  generateKeyPairHex,
+  compressPublicKeyHex,
+  utf8ToHex,
+  leftPad,
+  arrayToHex,
+  arrayToUtf8,
+  hexToArray,
+  verifyPublicKey,
+  comparePublicKeyHex,
+}

+ 94 - 0
node_modules/miniprogram-sm-crypto/src/sm3/index.js

@@ -0,0 +1,94 @@
+const {sm3, hmac} = require('../sm2/sm3')
+
+/**
+ * 补全16进制字符串
+ */
+function leftPad(input, num) {
+  if (input.length >= num) return input
+
+  return (new Array(num - input.length + 1)).join('0') + input
+}
+
+/**
+ * 字节数组转 16 进制串
+ */
+function ArrayToHex(arr) {
+  return arr.map(item => {
+    item = item.toString(16)
+    return item.length === 1 ? '0' + item : item
+  }).join('')
+}
+
+/**
+ * 转成字节数组
+ */
+function hexToArray(hexStr) {
+  const words = []
+  let hexStrLength = hexStr.length
+
+  if (hexStrLength % 2 !== 0) {
+    hexStr = leftPad(hexStr, hexStrLength + 1)
+  }
+
+  hexStrLength = hexStr.length
+
+  for (let i = 0; i < hexStrLength; i += 2) {
+    words.push(parseInt(hexStr.substr(i, 2), 16))
+  }
+  return words
+}
+
+/**
+ * utf8 串转字节数组
+ */
+function utf8ToArray(str) {
+  const arr = []
+
+  for (let i = 0, len = str.length; i < len; i++) {
+    const point = str.codePointAt(i)
+
+    if (point <= 0x007f) {
+      // 单字节,标量值:00000000 00000000 0zzzzzzz
+      arr.push(point)
+    } else if (point <= 0x07ff) {
+      // 双字节,标量值:00000000 00000yyy yyzzzzzz
+      arr.push(0xc0 | (point >>> 6)) // 110yyyyy(0xc0-0xdf)
+      arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
+    } else if (point <= 0xD7FF || (point >= 0xE000 && point <= 0xFFFF)) {
+      // 三字节:标量值:00000000 xxxxyyyy yyzzzzzz
+      arr.push(0xe0 | (point >>> 12)) // 1110xxxx(0xe0-0xef)
+      arr.push(0x80 | ((point >>> 6) & 0x3f)) // 10yyyyyy(0x80-0xbf)
+      arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
+    } else if (point >= 0x010000 && point <= 0x10FFFF) {
+      // 四字节:标量值:000wwwxx xxxxyyyy yyzzzzzz
+      i++
+      arr.push((0xf0 | (point >>> 18) & 0x1c)) // 11110www(0xf0-0xf7)
+      arr.push((0x80 | ((point >>> 12) & 0x3f))) // 10xxxxxx(0x80-0xbf)
+      arr.push((0x80 | ((point >>> 6) & 0x3f))) // 10yyyyyy(0x80-0xbf)
+      arr.push((0x80 | (point & 0x3f))) // 10zzzzzz(0x80-0xbf)
+    } else {
+      // 五、六字节,暂时不支持
+      arr.push(point)
+      throw new Error('input is not supported')
+    }
+  }
+
+  return arr
+}
+
+module.exports = function (input, options) {
+  input = typeof input === 'string' ? utf8ToArray(input) : Array.prototype.slice.call(input)
+
+  if (options) {
+    const mode = options.mode || 'hmac'
+    if (mode !== 'hmac') throw new Error('invalid mode')
+
+    let key = options.key
+    if (!key) throw new Error('invalid key')
+
+    key = typeof key === 'string' ? hexToArray(key) : Array.prototype.slice.call(key)
+    return ArrayToHex(hmac(input, key))
+  }
+
+  return ArrayToHex(sm3(input))
+}

+ 359 - 0
node_modules/miniprogram-sm-crypto/src/sm4/index.js

@@ -0,0 +1,359 @@
+/* eslint-disable no-bitwise, no-mixed-operators, complexity */
+const DECRYPT = 0
+const ROUND = 32
+const BLOCK = 16
+
+const Sbox = [
+  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
+]
+
+const 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
+]
+
+/**
+ * 16 进制串转字节数组
+ */
+function hexToArray(str) {
+  const arr = []
+  for (let i = 0, len = str.length; i < len; i += 2) {
+    arr.push(parseInt(str.substr(i, 2), 16))
+  }
+  return arr
+}
+
+/**
+ * 字节数组转 16 进制串
+ */
+function ArrayToHex(arr) {
+  return arr.map(item => {
+    item = item.toString(16)
+    return item.length === 1 ? '0' + item : item
+  }).join('')
+}
+
+/**
+ * utf8 串转字节数组
+ */
+function utf8ToArray(str) {
+  const arr = []
+
+  for (let i = 0, len = str.length; i < len; i++) {
+    const point = str.codePointAt(i)
+
+    if (point <= 0x007f) {
+      // 单字节,标量值:00000000 00000000 0zzzzzzz
+      arr.push(point)
+    } else if (point <= 0x07ff) {
+      // 双字节,标量值:00000000 00000yyy yyzzzzzz
+      arr.push(0xc0 | (point >>> 6)) // 110yyyyy(0xc0-0xdf)
+      arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
+    } else if (point <= 0xD7FF || (point >= 0xE000 && point <= 0xFFFF)) {
+      // 三字节:标量值:00000000 xxxxyyyy yyzzzzzz
+      arr.push(0xe0 | (point >>> 12)) // 1110xxxx(0xe0-0xef)
+      arr.push(0x80 | ((point >>> 6) & 0x3f)) // 10yyyyyy(0x80-0xbf)
+      arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
+    } else if (point >= 0x010000 && point <= 0x10FFFF) {
+      // 四字节:标量值:000wwwxx xxxxyyyy yyzzzzzz
+      i++
+      arr.push((0xf0 | (point >>> 18) & 0x1c)) // 11110www(0xf0-0xf7)
+      arr.push((0x80 | ((point >>> 12) & 0x3f))) // 10xxxxxx(0x80-0xbf)
+      arr.push((0x80 | ((point >>> 6) & 0x3f))) // 10yyyyyy(0x80-0xbf)
+      arr.push((0x80 | (point & 0x3f))) // 10zzzzzz(0x80-0xbf)
+    } else {
+      // 五、六字节,暂时不支持
+      arr.push(point)
+      throw new Error('input is not supported')
+    }
+  }
+
+  return arr
+}
+
+/**
+ * 字节数组转 utf8 串
+ */
+function arrayToUtf8(arr) {
+  const str = []
+  for (let i = 0, len = arr.length; i < len; i++) {
+    if (arr[i] >= 0xf0 && arr[i] <= 0xf7) {
+      // 四字节
+      str.push(String.fromCodePoint(((arr[i] & 0x07) << 18) + ((arr[i + 1] & 0x3f) << 12) + ((arr[i + 2] & 0x3f) << 6) + (arr[i + 3] & 0x3f)))
+      i += 3
+    } else if (arr[i] >= 0xe0 && arr[i] <= 0xef) {
+      // 三字节
+      str.push(String.fromCodePoint(((arr[i] & 0x0f) << 12) + ((arr[i + 1] & 0x3f) << 6) + (arr[i + 2] & 0x3f)))
+      i += 2
+    } else if (arr[i] >= 0xc0 && arr[i] <= 0xdf) {
+      // 双字节
+      str.push(String.fromCodePoint(((arr[i] & 0x1f) << 6) + (arr[i + 1] & 0x3f)))
+      i++
+    } else {
+      // 单字节
+      str.push(String.fromCodePoint(arr[i]))
+    }
+  }
+
+  return str.join('')
+}
+
+/**
+ * 32 比特循环左移
+ */
+function rotl(x, n) {
+  const s = n & 31
+  return (x << s) | (x >>> (32 - s))
+}
+
+/**
+ * 非线性变换
+ */
+function byteSub(a) {
+  return (Sbox[a >>> 24 & 0xFF] & 0xFF) << 24 |
+    (Sbox[a >>> 16 & 0xFF] & 0xFF) << 16 |
+    (Sbox[a >>> 8 & 0xFF] & 0xFF) << 8 |
+    (Sbox[a & 0xFF] & 0xFF)
+}
+
+/**
+ * 线性变换,加密/解密用
+ */
+function l1(b) {
+  return b ^ rotl(b, 2) ^ rotl(b, 10) ^ rotl(b, 18) ^ rotl(b, 24)
+}
+
+/**
+ * 线性变换,生成轮密钥用
+ */
+function l2(b) {
+  return b ^ rotl(b, 13) ^ rotl(b, 23)
+}
+
+/**
+ * 以一组 128 比特进行加密/解密操作
+ */
+function sms4Crypt(input, output, roundKey) {
+  const x = new Array(4)
+
+  // 字节数组转成字数组(此处 1 字 = 32 比特)
+  const tmp = new Array(4)
+  for (let i = 0; i < 4; i++) {
+    tmp[0] = input[4 * i] & 0xff
+    tmp[1] = input[4 * i + 1] & 0xff
+    tmp[2] = input[4 * i + 2] & 0xff
+    tmp[3] = input[4 * i + 3] & 0xff
+    x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3]
+  }
+
+  // x[i + 4] = x[i] ^ l1(byteSub(x[i + 1] ^ x[i + 2] ^ x[i + 3] ^ roundKey[i]))
+  for (let r = 0, mid; r < 32; r += 4) {
+    mid = x[1] ^ x[2] ^ x[3] ^ roundKey[r + 0]
+    x[0] ^= l1(byteSub(mid)) // x[4]
+
+    mid = x[2] ^ x[3] ^ x[0] ^ roundKey[r + 1]
+    x[1] ^= l1(byteSub(mid)) // x[5]
+
+    mid = x[3] ^ x[0] ^ x[1] ^ roundKey[r + 2]
+    x[2] ^= l1(byteSub(mid)) // x[6]
+
+    mid = x[0] ^ x[1] ^ x[2] ^ roundKey[r + 3]
+    x[3] ^= l1(byteSub(mid)) // x[7]
+  }
+
+  // 反序变换
+  for (let j = 0; j < 16; j += 4) {
+    output[j] = x[3 - j / 4] >>> 24 & 0xff
+    output[j + 1] = x[3 - j / 4] >>> 16 & 0xff
+    output[j + 2] = x[3 - j / 4] >>> 8 & 0xff
+    output[j + 3] = x[3 - j / 4] & 0xff
+  }
+}
+
+/**
+ * 密钥扩展算法
+ */
+function sms4KeyExt(key, roundKey, cryptFlag) {
+  const x = new Array(4)
+
+  // 字节数组转成字数组(此处 1 字 = 32 比特)
+  const tmp = new Array(4)
+  for (let i = 0; i < 4; i++) {
+    tmp[0] = key[0 + 4 * i] & 0xff
+    tmp[1] = key[1 + 4 * i] & 0xff
+    tmp[2] = key[2 + 4 * i] & 0xff
+    tmp[3] = key[3 + 4 * i] & 0xff
+    x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3]
+  }
+
+  // 与系统参数做异或
+  x[0] ^= 0xa3b1bac6
+  x[1] ^= 0x56aa3350
+  x[2] ^= 0x677d9197
+  x[3] ^= 0xb27022dc
+
+  // roundKey[i] = x[i + 4] = x[i] ^ l2(byteSub(x[i + 1] ^ x[i + 2] ^ x[i + 3] ^ CK[i]))
+  for (let r = 0, mid; r < 32; r += 4) {
+    mid = x[1] ^ x[2] ^ x[3] ^ CK[r + 0]
+    roundKey[r + 0] = x[0] ^= l2(byteSub(mid)) // x[4]
+
+    mid = x[2] ^ x[3] ^ x[0] ^ CK[r + 1]
+    roundKey[r + 1] = x[1] ^= l2(byteSub(mid)) // x[5]
+
+    mid = x[3] ^ x[0] ^ x[1] ^ CK[r + 2]
+    roundKey[r + 2] = x[2] ^= l2(byteSub(mid)) // x[6]
+
+    mid = x[0] ^ x[1] ^ x[2] ^ CK[r + 3]
+    roundKey[r + 3] = x[3] ^= l2(byteSub(mid)) // x[7]
+  }
+
+  // 解密时使用反序的轮密钥
+  if (cryptFlag === DECRYPT) {
+    for (let r = 0, mid; r < 16; r++) {
+      mid = roundKey[r]
+      roundKey[r] = roundKey[31 - r]
+      roundKey[31 - r] = mid
+    }
+  }
+}
+
+function sm4(inArray, key, cryptFlag, {
+  padding = 'pkcs#7', mode, iv = [], output = 'string'
+} = {}) {
+  if (mode === 'cbc') {
+    // CBC 模式,默认走 ECB 模式
+    if (typeof iv === 'string') iv = hexToArray(iv)
+    if (iv.length !== (128 / 8)) {
+      // iv 不是 128 比特
+      throw new Error('iv is invalid')
+    }
+  }
+
+  // 检查 key
+  if (typeof key === 'string') key = hexToArray(key)
+  if (key.length !== (128 / 8)) {
+    // key 不是 128 比特
+    throw new Error('key is invalid')
+  }
+
+  // 检查输入
+  if (typeof inArray === 'string') {
+    if (cryptFlag !== DECRYPT) {
+      // 加密,输入为 utf8 串
+      inArray = utf8ToArray(inArray)
+    } else {
+      // 解密,输入为 16 进制串
+      inArray = hexToArray(inArray)
+    }
+  } else {
+    inArray = [...inArray]
+  }
+
+  // 新增填充,sm4 是 16 个字节一个分组,所以统一走到 pkcs#7
+  if ((padding === 'pkcs#5' || padding === 'pkcs#7') && cryptFlag !== DECRYPT) {
+    const paddingCount = BLOCK - inArray.length % BLOCK
+    for (let i = 0; i < paddingCount; i++) inArray.push(paddingCount)
+  }
+
+  // 生成轮密钥
+  const roundKey = new Array(ROUND)
+  sms4KeyExt(key, roundKey, cryptFlag)
+
+  const outArray = []
+  let lastVector = iv
+  let restLen = inArray.length
+  let point = 0
+  while (restLen >= BLOCK) {
+    const input = inArray.slice(point, point + 16)
+    const output = new Array(16)
+
+    if (mode === 'cbc') {
+      for (let i = 0; i < BLOCK; i++) {
+        if (cryptFlag !== DECRYPT) {
+          // 加密过程在组加密前进行异或
+          input[i] ^= lastVector[i]
+        }
+      }
+    }
+
+    sms4Crypt(input, output, roundKey)
+
+
+    for (let i = 0; i < BLOCK; i++) {
+      if (mode === 'cbc') {
+        if (cryptFlag === DECRYPT) {
+          // 解密过程在组解密后进行异或
+          output[i] ^= lastVector[i]
+        }
+      }
+
+      outArray[point + i] = output[i]
+    }
+
+    if (mode === 'cbc') {
+      if (cryptFlag !== DECRYPT) {
+        // 使用上一次输出作为加密向量
+        lastVector = output
+      } else {
+        // 使用上一次输入作为解密向量
+        lastVector = input
+      }
+    }
+
+    restLen -= BLOCK
+    point += BLOCK
+  }
+
+  // 去除填充,sm4 是 16 个字节一个分组,所以统一走到 pkcs#7
+  if ((padding === 'pkcs#5' || padding === 'pkcs#7') && cryptFlag === DECRYPT) {
+    const len = outArray.length
+    const paddingCount = outArray[len - 1]
+    for (let i = 1; i <= paddingCount; i++) {
+      if (outArray[len - i] !== paddingCount) throw new Error('padding is invalid')
+    }
+    outArray.splice(len - paddingCount, paddingCount)
+  }
+
+  // 调整输出
+  if (output !== 'array') {
+    if (cryptFlag !== DECRYPT) {
+      // 加密,输出转 16 进制串
+      return ArrayToHex(outArray)
+    } else {
+      // 解密,输出转 utf8 串
+      return arrayToUtf8(outArray)
+    }
+  } else {
+    return outArray
+  }
+}
+
+module.exports = {
+  encrypt(inArray, key, options) {
+    return sm4(inArray, key, 1, options)
+  },
+  decrypt(inArray, key, options) {
+    return sm4(inArray, key, 0, options)
+  }
+}

+ 3 - 0
node_modules/sm-crypto/.babelrc

@@ -0,0 +1,3 @@
+{
+    "presets": ["es2015"]
+}

+ 97 - 0
node_modules/sm-crypto/.eslintrc.js

@@ -0,0 +1,97 @@
+module.exports = {
+  'extends': [
+    'airbnb-base',
+    'plugin:promise/recommended'
+  ],
+  'parserOptions': {
+    'ecmaVersion': 9,
+    'ecmaFeatures': {
+      'jsx': false
+    },
+    'sourceType': 'module'
+  },
+  'env': {
+    'es6': true,
+    'node': true,
+    'jest': true
+  },
+  'plugins': [
+    'import',
+    'node',
+    'promise'
+  ],
+  'rules': {
+    'arrow-parens': 'off',
+    'comma-dangle': [
+      'error',
+      'only-multiline'
+    ],
+    'complexity': ['error', 20],
+    'func-names': 'off',
+    'global-require': 'off',
+    'handle-callback-err': [
+      'error',
+      '^(err|error)$'
+    ],
+    'import/no-unresolved': [
+      'error',
+      {
+        'caseSensitive': true,
+        'commonjs': true,
+        'ignore': ['^[^.]']
+      }
+    ],
+    'import/prefer-default-export': 'off',
+    'linebreak-style': 'off',
+    'no-catch-shadow': 'error',
+    'no-continue': 'off',
+    'no-div-regex': 'warn',
+    'no-else-return': 'off',
+    'no-param-reassign': 'off',
+    'no-plusplus': 'off',
+    'no-shadow': 'off',
+    'no-multi-assign': 'off',
+    'no-underscore-dangle': 'off',
+    'node/no-deprecated-api': 'error',
+    'node/process-exit-as-throw': 'error',
+    'object-curly-spacing': [
+      'error',
+      'never'
+    ],
+    'operator-linebreak': [
+      'error',
+      'after',
+      {
+        'overrides': {
+          ':': 'before',
+          '?': 'before'
+        }
+      }
+    ],
+    'prefer-arrow-callback': 'off',
+    'prefer-destructuring': 'off',
+    'prefer-template': 'off',
+    'quote-props': [
+      1,
+      'as-needed',
+      {
+        'unnecessary': true
+      }
+    ],
+    'semi': [
+      'error',
+      'never'
+    ],
+    'max-len': 'off',
+    'no-bitwise': 'off',
+    'no-mixed-operators': 'off',
+  },
+  'globals': {
+    'window': true,
+    'document': true,
+    'App': true,
+    'Page': true,
+    'Component': true,
+    'Behavior': true
+  }
+}

+ 82 - 0
node_modules/sm-crypto/CHANGELOG.md

@@ -0,0 +1,82 @@
+## 0.3.13
+
+* 支持根据私钥获取公钥
+
+## 0.3.12
+
+* 优化 sm3 运行性能
+
+## 0.3.11
+
+* sm2 支持压缩公钥
+
+## 0.3.10
+
+* 支持 sm3 hmac 模式
+
+
+## 0.3.9
+
+* 补充 sm4 解密时的 padding 判断
+
+## 0.3.8
+
+* sm2 解密时兼容密文可能是大写的情况
+
+## 0.3.7
+
+* 默认填充改为 pkcs#7,如传入 pkcs#5 也转到 pkcs#7 逻辑
+
+## 0.3.6
+
+* sm2 加解密支持二进制数据
+
+## 0.3.5
+
+* sm2.generateKeyPairHex 支持完整的 BigInteger 入参
+
+## 0.3.4
+
+* sm2 支持验证公钥接口
+* sm2 生成密钥时支持自定义随机数
+
+## 0.3.3
+
+* dist 输出改成 umd 模式
+
+## 0.3.2
+
+* 修复 sm2 在 userId 长度大于 31 时新旧版本验签不通过的问题
+## 0.3.0
+
+* sm2、sm3 重构
+* sm4 支持 cbc 模式
+
+## 0.2.7
+
+* 优化 sm3 性能
+
+## 0.2.5
+
+* sm3 支持字节数组输入
+
+## 0.2.4
+
+* 修复 sm4 四字节字符输出编码
+
+## 0.2.3
+
+* sm3/sm4 支持输入四字节字符
+
+## 0.2.2
+
+* sm3 支持中文输入
+
+## 0.2.1
+
+* 修复 sm2 点 16 进制串可能不满 64 位的问题
+
+## 0.2.0
+
+* sm4 默认支持 pkcs#5 填充方式
+* sm4 支持输入输出为字符串

+ 7 - 0
node_modules/sm-crypto/LICENCE_MIT

@@ -0,0 +1,7 @@
+Copyright © 2018 june01
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 171 - 0
node_modules/sm-crypto/README.md

@@ -0,0 +1,171 @@
+# sm-crypto
+
+国密算法sm2、sm3和sm4的js实现。
+
+## 安装
+
+```bash
+npm install --save sm-crypto
+```
+
+## sm2
+
+### 获取密钥对
+
+```js
+const sm2 = require('sm-crypto').sm2
+
+let keypair = sm2.generateKeyPairHex()
+
+publicKey = keypair.publicKey // 公钥
+privateKey = keypair.privateKey // 私钥
+
+// 默认生成公钥 130 位太长,可以压缩公钥到 66 位
+const compressedPublicKey = sm2.compressPublicKeyHex(publicKey) // compressedPublicKey 和 publicKey 等价
+sm2.comparePublicKeyHex(publicKey, compressedPublicKey) // 判断公钥是否等价
+
+// 自定义随机数,参数会直接透传给 jsbn 库的 BigInteger 构造器
+// 注意:开发者使用自定义随机数,需要自行确保传入的随机数符合密码学安全
+let keypair2 = sm2.generateKeyPairHex('123123123123123')
+let keypair3 = sm2.generateKeyPairHex(256, SecureRandom)
+
+let verifyResult = sm2.verifyPublicKey(publicKey) // 验证公钥
+verifyResult = sm2.verifyPublicKey(compressedPublicKey) // 验证公钥
+```
+
+### 加密解密
+
+```js
+const sm2 = require('sm-crypto').sm2
+const cipherMode = 1 // 1 - C1C3C2,0 - C1C2C3,默认为1
+
+let encryptData = sm2.doEncrypt(msgString, publicKey, cipherMode) // 加密结果
+let decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode) // 解密结果
+
+encryptData = sm2.doEncrypt(msgArray, publicKey, cipherMode) // 加密结果,输入数组
+decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode, {output: 'array'}) // 解密结果,输出数组
+```
+
+> ps:密文会在解密时自动补充 `04`,如遇到其他工具补充的 `04` 需手动去除再传入。
+
+### 签名验签
+
+> ps:理论上来说,只做纯签名是最快的。
+
+```js
+const sm2 = require('sm-crypto').sm2
+
+// 纯签名 + 生成椭圆曲线点
+let sigValueHex = sm2.doSignature(msg, privateKey) // 签名
+let verifyResult = sm2.doVerifySignature(msg, sigValueHex, publicKey) // 验签结果
+
+// 纯签名
+let sigValueHex2 = sm2.doSignature(msg, privateKey, {
+    pointPool: [sm2.getPoint(), sm2.getPoint(), sm2.getPoint(), sm2.getPoint()], // 传入事先已生成好的椭圆曲线点,可加快签名速度
+}) // 签名
+let verifyResult2 = sm2.doVerifySignature(msg, sigValueHex2, publicKey) // 验签结果
+
+// 纯签名 + 生成椭圆曲线点 + der编解码
+let sigValueHex3 = sm2.doSignature(msg, privateKey, {
+    der: true,
+}) // 签名
+let verifyResult3 = sm2.doVerifySignature(msg, sigValueHex3, publicKey, {
+    der: true,
+}) // 验签结果
+
+// 纯签名 + 生成椭圆曲线点 + sm3杂凑
+let sigValueHex4 = sm2.doSignature(msg, privateKey, {
+    hash: true,
+}) // 签名
+let verifyResult4 = sm2.doVerifySignature(msg, sigValueHex4, publicKey, {
+    hash: true,
+}) // 验签结果
+
+// 纯签名 + 生成椭圆曲线点 + sm3杂凑(不做公钥推导)
+let sigValueHex5 = sm2.doSignature(msg, privateKey, {
+    hash: true,
+    publicKey, // 传入公钥的话,可以去掉sm3杂凑中推导公钥的过程,速度会比纯签名 + 生成椭圆曲线点 + sm3杂凑快
+})
+let verifyResult5 = sm2.doVerifySignature(msg, sigValueHex5, publicKey, {
+    hash: true,
+    publicKey,
+})
+
+// 纯签名 + 生成椭圆曲线点 + sm3杂凑 + 不做公钥推 + 添加 userId(长度小于 8192)
+// 默认 userId 值为 1234567812345678
+let sigValueHex6 = sm2.doSignature(msgString, privateKey, {
+    hash: true,
+    publicKey,
+    userId: 'testUserId',
+})
+let verifyResult6 = sm2.doVerifySignature(msgString, sigValueHex6, publicKey, {
+    hash: true,
+    userId: 'testUserId',
+})
+```
+
+### 获取椭圆曲线点
+
+```js
+const sm2 = require('sm-crypto').sm2
+
+let point = sm2.getPoint() // 获取一个椭圆曲线点,可在sm2签名时传入
+```
+
+### 根据私钥获取公钥
+
+```js
+const sm2 = require('sm-crypto).sm2
+
+let publicKey = sm2.getPublicKeyFromPrivateKey(privateKey)
+```
+
+## sm3
+
+```js
+const sm3 = require('sm-crypto').sm3
+
+let hashData = sm3('abc') // 杂凑
+
+// hmac
+hashData = sm3('abc', {
+    key: 'daac25c1512fe50f79b0e4526b93f5c0e1460cef40b6dd44af13caec62e8c60e0d885f3c6d6fb51e530889e6fd4ac743a6d332e68a0f2a3923f42585dceb93e9', // 要求为 16 进制串或字节数组
+})
+```
+
+## sm4
+
+### 加密
+
+```js
+const sm4 = require('sm-crypto').sm4
+const msg = 'hello world! 我是 juneandgreen.' // 可以为 utf8 串或字节数组
+const key = '0123456789abcdeffedcba9876543210' // 可以为 16 进制串或字节数组,要求为 128 比特
+
+let encryptData = sm4.encrypt(msg, key) // 加密,默认输出 16 进制字符串,默认使用 pkcs#7 填充(传 pkcs#5 也会走 pkcs#7 填充)
+let encryptData = sm4.encrypt(msg, key, {padding: 'none'}) // 加密,不使用 padding
+let encryptData = sm4.encrypt(msg, key, {padding: 'none', output: 'array'}) // 加密,不使用 padding,输出为字节数组
+let encryptData = sm4.encrypt(msg, key, {mode: 'cbc', iv: 'fedcba98765432100123456789abcdef'}) // 加密,cbc 模式
+```
+
+### 解密
+
+```js
+const sm4 = require('sm-crypto').sm4
+const encryptData = '0e395deb10f6e8a17e17823e1fd9bd98a1bff1df508b5b8a1efb79ec633d1bb129432ac1b74972dbe97bab04f024e89c' // 可以为 16 进制串或字节数组
+const key = '0123456789abcdeffedcba9876543210' // 可以为 16 进制串或字节数组,要求为 128 比特
+
+let decryptData = sm4.decrypt(encryptData, key) // 解密,默认输出 utf8 字符串,默认使用 pkcs#7 填充(传 pkcs#5 也会走 pkcs#7 填充)
+let decryptData = sm4.decrypt(encryptData, key, {padding: 'none'}) // 解密,不使用 padding
+let decryptData = sm4.decrypt(encryptData, key, {padding: 'none', output: 'array'}) // 解密,不使用 padding,输出为字节数组
+let decryptData = sm4.decrypt(encryptData, key, {mode: 'cbc', iv: 'fedcba98765432100123456789abcdef'}) // 解密,cbc 模式
+```
+
+## 其他实现
+
+* 小程序移植版:[https://github.com/wechat-miniprogram/sm-crypto](https://github.com/wechat-miniprogram/sm-crypto)
+* java 实现(感谢 @antherd 提供):[https://github.com/antherd/sm-crypto](https://github.com/antherd/sm-crypto)
+* dart 实现(感谢 @luckykellan 提供):[https://github.com/luckykellan/dart_sm](https://github.com/luckykellan/dart_sm)
+## 协议
+
+MIT

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
node_modules/sm-crypto/dist/sm2.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
node_modules/sm-crypto/dist/sm3.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
node_modules/sm-crypto/dist/sm4.js


+ 42 - 0
node_modules/sm-crypto/package.json

@@ -0,0 +1,42 @@
+{
+  "name": "sm-crypto",
+  "version": "0.3.13",
+  "description": "sm-crypto",
+  "main": "src/index.js",
+  "scripts": {
+    "prepublish": "npm run build",
+    "test": "jest ./test/*",
+    "lint": "eslint \"src/**/*.js\" --fix",
+    "build": "npm run lint && webpack"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/JuneAndGreen/sm-crypto.git"
+  },
+  "keywords": [
+    "sm",
+    "js",
+    "crypto"
+  ],
+  "jest": {
+    "testEnvironment": "jsdom",
+    "testURL": "https://jest.test"
+  },
+  "author": "june_01",
+  "license": "MIT",
+  "dependencies": {
+    "jsbn": "^1.1.0"
+  },
+  "devDependencies": {
+    "babel-core": "^6.26.0",
+    "babel-loader": "^7.1.2",
+    "babel-preset-es2015": "^6.24.1",
+    "jest": "^22.1.4",
+    "webpack": "^3.10.0",
+    "eslint": "^5.3.0",
+    "eslint-config-airbnb-base": "13.1.0",
+    "eslint-plugin-import": "^2.14.0",
+    "eslint-plugin-node": "^7.0.1",
+    "eslint-plugin-promise": "^3.8.0"
+  }
+}

+ 5 - 0
node_modules/sm-crypto/src/index.js

@@ -0,0 +1,5 @@
+module.exports = {
+  sm2: require('./sm2/index'),
+  sm3: require('./sm3/index'),
+  sm4: require('./sm4/index'),
+}

+ 161 - 0
node_modules/sm-crypto/src/sm2/asn1.js

@@ -0,0 +1,161 @@
+/* eslint-disable class-methods-use-this */
+const {BigInteger} = require('jsbn')
+
+function bigintToValue(bigint) {
+  let h = bigint.toString(16)
+  if (h[0] !== '-') {
+    // 正数
+    if (h.length % 2 === 1) h = '0' + h // 补齐到整字节
+    else if (!h.match(/^[0-7]/)) h = '00' + h // 非0开头,则补一个全0字节
+  } else {
+    // 负数
+    h = h.substr(1)
+
+    let len = h.length
+    if (len % 2 === 1) len += 1 // 补齐到整字节
+    else if (!h.match(/^[0-7]/)) len += 2 // 非0开头,则补一个全0字节
+
+    let mask = ''
+    for (let i = 0; i < len; i++) mask += 'f'
+    mask = new BigInteger(mask, 16)
+
+    // 对绝对值取反,加1
+    h = mask.xor(bigint).add(BigInteger.ONE)
+    h = h.toString(16).replace(/^-/, '')
+  }
+  return h
+}
+
+class ASN1Object {
+  constructor() {
+    this.tlv = null
+    this.t = '00'
+    this.l = '00'
+    this.v = ''
+  }
+
+  /**
+   * 获取 der 编码比特流16进制串
+   */
+  getEncodedHex() {
+    if (!this.tlv) {
+      this.v = this.getValue()
+      this.l = this.getLength()
+      this.tlv = this.t + this.l + this.v
+    }
+    return this.tlv
+  }
+
+  getLength() {
+    const n = this.v.length / 2 // 字节数
+    let nHex = n.toString(16)
+    if (nHex.length % 2 === 1) nHex = '0' + nHex // 补齐到整字节
+
+    if (n < 128) {
+      // 短格式,以 0 开头
+      return nHex
+    } else {
+      // 长格式,以 1 开头
+      const head = 128 + nHex.length / 2 // 1(1位) + 真正的长度占用字节数(7位) + 真正的长度
+      return head.toString(16) + nHex
+    }
+  }
+
+  getValue() {
+    return ''
+  }
+}
+
+class DERInteger extends ASN1Object {
+  constructor(bigint) {
+    super()
+
+    this.t = '02' // 整型标签说明
+    if (bigint) this.v = bigintToValue(bigint)
+  }
+
+  getValue() {
+    return this.v
+  }
+}
+
+class DERSequence extends ASN1Object {
+  constructor(asn1Array) {
+    super()
+
+    this.t = '30' // 序列标签说明
+    this.asn1Array = asn1Array
+  }
+
+  getValue() {
+    this.v = this.asn1Array.map(asn1Object => asn1Object.getEncodedHex()).join('')
+    return this.v
+  }
+}
+
+/**
+ * 获取 l 占用字节数
+ */
+function getLenOfL(str, start) {
+  if (+str[start + 2] < 8) return 1 // l 以0开头,则表示短格式,只占一个字节
+  return +str.substr(start + 2, 2) & 0x7f + 1 // 长格式,取第一个字节后7位作为长度真正占用字节数,再加上本身
+}
+
+/**
+ * 获取 l
+ */
+function getL(str, start) {
+  // 获取 l
+  const len = getLenOfL(str, start)
+  const l = str.substr(start + 2, len * 2)
+
+  if (!l) return -1
+  const bigint = +l[0] < 8 ? new BigInteger(l, 16) : new BigInteger(l.substr(2), 16)
+
+  return bigint.intValue()
+}
+
+/**
+ * 获取 v 的位置
+ */
+function getStartOfV(str, start) {
+  const len = getLenOfL(str, start)
+  return start + (len + 1) * 2
+}
+
+module.exports = {
+  /**
+   * ASN.1 der 编码,针对 sm2 签名
+   */
+  encodeDer(r, s) {
+    const derR = new DERInteger(r)
+    const derS = new DERInteger(s)
+    const derSeq = new DERSequence([derR, derS])
+
+    return derSeq.getEncodedHex()
+  },
+
+  /**
+   * 解析 ASN.1 der,针对 sm2 验签
+   */
+  decodeDer(input) {
+    // 结构:
+    // input = | tSeq | lSeq | vSeq |
+    // vSeq = | tR | lR | vR | tS | lS | vS |
+    const start = getStartOfV(input, 0)
+
+    const vIndexR = getStartOfV(input, start)
+    const lR = getL(input, start)
+    const vR = input.substr(vIndexR, lR * 2)
+
+    const nextStart = vIndexR + vR.length
+    const vIndexS = getStartOfV(input, nextStart)
+    const lS = getL(input, nextStart)
+    const vS = input.substr(vIndexS, lS * 2)
+
+    const r = new BigInteger(vR, 16)
+    const s = new BigInteger(vS, 16)
+
+    return {r, s}
+  }
+}

+ 332 - 0
node_modules/sm-crypto/src/sm2/ec.js

@@ -0,0 +1,332 @@
+/* eslint-disable no-case-declarations, max-len */
+const {BigInteger} = require('jsbn')
+
+/**
+ * thanks for Tom Wu : http://www-cs-students.stanford.edu/~tjw/jsbn/
+ *
+ * Basic Javascript Elliptic Curve implementation
+ * Ported loosely from BouncyCastle's Java EC code
+ * Only Fp curves implemented for now
+ */
+
+const TWO = new BigInteger('2')
+const THREE = new BigInteger('3')
+
+/**
+ * 椭圆曲线域元素
+ */
+class ECFieldElementFp {
+  constructor(q, x) {
+    this.x = x
+    this.q = q
+    // TODO if (x.compareTo(q) >= 0) error
+  }
+
+  /**
+   * 判断相等
+   */
+  equals(other) {
+    if (other === this) return true
+    return (this.q.equals(other.q) && this.x.equals(other.x))
+  }
+
+  /**
+   * 返回具体数值
+   */
+  toBigInteger() {
+    return this.x
+  }
+
+  /**
+   * 取反
+   */
+  negate() {
+    return new ECFieldElementFp(this.q, this.x.negate().mod(this.q))
+  }
+
+  /**
+   * 相加
+   */
+  add(b) {
+    return new ECFieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q))
+  }
+
+  /**
+   * 相减
+   */
+  subtract(b) {
+    return new ECFieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q))
+  }
+
+  /**
+   * 相乘
+   */
+  multiply(b) {
+    return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q))
+  }
+
+  /**
+   * 相除
+   */
+  divide(b) {
+    return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger().modInverse(this.q)).mod(this.q))
+  }
+
+  /**
+   * 平方
+   */
+  square() {
+    return new ECFieldElementFp(this.q, this.x.square().mod(this.q))
+  }
+}
+
+class ECPointFp {
+  constructor(curve, x, y, z) {
+    this.curve = curve
+    this.x = x
+    this.y = y
+    // 标准射影坐标系:zinv == null 或 z * zinv == 1
+    this.z = z == null ? BigInteger.ONE : z
+    this.zinv = null
+    // TODO: compression flag
+  }
+
+  getX() {
+    if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q)
+
+    return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q))
+  }
+
+  getY() {
+    if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q)
+
+    return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q))
+  }
+
+  /**
+   * 判断相等
+   */
+  equals(other) {
+    if (other === this) return true
+    if (this.isInfinity()) return other.isInfinity()
+    if (other.isInfinity()) return this.isInfinity()
+
+    // u = y2 * z1 - y1 * z2
+    const u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q)
+    if (!u.equals(BigInteger.ZERO)) return false
+
+    // v = x2 * z1 - x1 * z2
+    const v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q)
+    return v.equals(BigInteger.ZERO)
+  }
+
+  /**
+   * 是否是无穷远点
+   */
+  isInfinity() {
+    if ((this.x === null) && (this.y === null)) return true
+    return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO)
+  }
+
+  /**
+   * 取反,x 轴对称点
+   */
+  negate() {
+    return new ECPointFp(this.curve, this.x, this.y.negate(), this.z)
+  }
+
+  /**
+   * 相加
+   *
+   * 标准射影坐标系:
+   *
+   * λ1 = x1 * z2
+   * λ2 = x2 * z1
+   * λ3 = λ1 − λ2
+   * λ4 = y1 * z2
+   * λ5 = y2 * z1
+   * λ6 = λ4 − λ5
+   * λ7 = λ1 + λ2
+   * λ8 = z1 * z2
+   * λ9 = λ3^2
+   * λ10 = λ3 * λ9
+   * λ11 = λ8 * λ6^2 − λ7 * λ9
+   * x3 = λ3 * λ11
+   * y3 = λ6 * (λ9 * λ1 − λ11) − λ4 * λ10
+   * z3 = λ10 * λ8
+   */
+  add(b) {
+    if (this.isInfinity()) return b
+    if (b.isInfinity()) return this
+
+    const x1 = this.x.toBigInteger()
+    const y1 = this.y.toBigInteger()
+    const z1 = this.z
+    const x2 = b.x.toBigInteger()
+    const y2 = b.y.toBigInteger()
+    const z2 = b.z
+    const q = this.curve.q
+
+    const w1 = x1.multiply(z2).mod(q)
+    const w2 = x2.multiply(z1).mod(q)
+    const w3 = w1.subtract(w2)
+    const w4 = y1.multiply(z2).mod(q)
+    const w5 = y2.multiply(z1).mod(q)
+    const w6 = w4.subtract(w5)
+
+    if (BigInteger.ZERO.equals(w3)) {
+      if (BigInteger.ZERO.equals(w6)) {
+        return this.twice() // this == b,计算自加
+      }
+      return this.curve.infinity // this == -b,则返回无穷远点
+    }
+
+    const w7 = w1.add(w2)
+    const w8 = z1.multiply(z2).mod(q)
+    const w9 = w3.square().mod(q)
+    const w10 = w3.multiply(w9).mod(q)
+    const w11 = w8.multiply(w6.square()).subtract(w7.multiply(w9)).mod(q)
+
+    const x3 = w3.multiply(w11).mod(q)
+    const y3 = w6.multiply(w9.multiply(w1).subtract(w11)).subtract(w4.multiply(w10)).mod(q)
+    const z3 = w10.multiply(w8).mod(q)
+
+    return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3)
+  }
+
+  /**
+   * 自加
+   *
+   * 标准射影坐标系:
+   *
+   * λ1 = 3 * x1^2 + a * z1^2
+   * λ2 = 2 * y1 * z1
+   * λ3 = y1^2
+   * λ4 = λ3 * x1 * z1
+   * λ5 = λ2^2
+   * λ6 = λ1^2 − 8 * λ4
+   * x3 = λ2 * λ6
+   * y3 = λ1 * (4 * λ4 − λ6) − 2 * λ5 * λ3
+   * z3 = λ2 * λ5
+   */
+  twice() {
+    if (this.isInfinity()) return this
+    if (!this.y.toBigInteger().signum()) return this.curve.infinity
+
+    const x1 = this.x.toBigInteger()
+    const y1 = this.y.toBigInteger()
+    const z1 = this.z
+    const q = this.curve.q
+    const a = this.curve.a.toBigInteger()
+
+    const w1 = x1.square().multiply(THREE).add(a.multiply(z1.square())).mod(q)
+    const w2 = y1.shiftLeft(1).multiply(z1).mod(q)
+    const w3 = y1.square().mod(q)
+    const w4 = w3.multiply(x1).multiply(z1).mod(q)
+    const w5 = w2.square().mod(q)
+    const w6 = w1.square().subtract(w4.shiftLeft(3)).mod(q)
+
+    const x3 = w2.multiply(w6).mod(q)
+    const y3 = w1.multiply(w4.shiftLeft(2).subtract(w6)).subtract(w5.shiftLeft(1).multiply(w3)).mod(q)
+    const z3 = w2.multiply(w5).mod(q)
+
+    return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3)
+  }
+
+  /**
+   * 倍点计算
+   */
+  multiply(k) {
+    if (this.isInfinity()) return this
+    if (!k.signum()) return this.curve.infinity
+
+    // 使用加减法
+    const k3 = k.multiply(THREE)
+    const neg = this.negate()
+    let Q = this
+
+    for (let i = k3.bitLength() - 2; i > 0; i--) {
+      Q = Q.twice()
+
+      const k3Bit = k3.testBit(i)
+      const kBit = k.testBit(i)
+
+      if (k3Bit !== kBit) {
+        Q = Q.add(k3Bit ? this : neg)
+      }
+    }
+
+    return Q
+  }
+}
+
+/**
+ * 椭圆曲线 y^2 = x^3 + ax + b
+ */
+class ECCurveFp {
+  constructor(q, a, b) {
+    this.q = q
+    this.a = this.fromBigInteger(a)
+    this.b = this.fromBigInteger(b)
+    this.infinity = new ECPointFp(this, null, null) // 无穷远点
+  }
+
+  /**
+   * 判断两个椭圆曲线是否相等
+   */
+  equals(other) {
+    if (other === this) return true
+    return (this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b))
+  }
+
+  /**
+   * 生成椭圆曲线域元素
+   */
+  fromBigInteger(x) {
+    return new ECFieldElementFp(this.q, x)
+  }
+
+  /**
+   * 解析 16 进制串为椭圆曲线点
+   */
+  decodePointHex(s) {
+    switch (parseInt(s.substr(0, 2), 16)) {
+      // 第一个字节
+      case 0:
+        return this.infinity
+      case 2:
+      case 3:
+        // 压缩
+        const x = this.fromBigInteger(new BigInteger(s.substr(2), 16))
+        // 对 p ≡ 3 (mod4),即存在正整数 u,使得 p = 4u + 3
+        // 计算 y = (√ (x^3 + ax + b) % p)^(u + 1) modp
+        let y = this.fromBigInteger(x.multiply(x.square()).add(
+          x.multiply(this.a)
+        ).add(this.b).toBigInteger()
+          .modPow(
+            this.q.divide(new BigInteger('4')).add(BigInteger.ONE), this.q
+          ))
+        // 算出结果 2 进制最后 1 位不等于第 1 个字节减 2 则取反
+        if (!y.toBigInteger().mod(TWO).equals(new BigInteger(s.substr(0, 2), 16).subtract(TWO))) {
+          y = y.negate()
+        }
+        return new ECPointFp(this, x, y)
+      case 4:
+      case 6:
+      case 7:
+        const len = (s.length - 2) / 2
+        const xHex = s.substr(2, len)
+        const yHex = s.substr(len + 2, len)
+
+        return new ECPointFp(this, this.fromBigInteger(new BigInteger(xHex, 16)), this.fromBigInteger(new BigInteger(yHex, 16)))
+      default:
+        // 不支持
+        return null
+    }
+  }
+}
+
+module.exports = {
+  ECPointFp,
+  ECCurveFp,
+}

+ 261 - 0
node_modules/sm-crypto/src/sm2/index.js

@@ -0,0 +1,261 @@
+/* eslint-disable no-use-before-define */
+const {BigInteger} = require('jsbn')
+const {encodeDer, decodeDer} = require('./asn1')
+const _ = require('./utils')
+const sm3 = require('./sm3').sm3
+
+const {G, curve, n} = _.generateEcparam()
+const C1C2C3 = 0
+
+/**
+ * 加密
+ */
+function doEncrypt(msg, publicKey, cipherMode = 1) {
+  msg = typeof msg === 'string' ? _.hexToArray(_.utf8ToHex(msg)) : Array.prototype.slice.call(msg)
+  publicKey = _.getGlobalCurve().decodePointHex(publicKey) // 先将公钥转成点
+
+  const keypair = _.generateKeyPairHex()
+  const k = new BigInteger(keypair.privateKey, 16) // 随机数 k
+
+  // c1 = k * G
+  let c1 = keypair.publicKey
+  if (c1.length > 128) c1 = c1.substr(c1.length - 128)
+
+  // (x2, y2) = k * publicKey
+  const p = publicKey.multiply(k)
+  const x2 = _.hexToArray(_.leftPad(p.getX().toBigInteger().toRadix(16), 64))
+  const y2 = _.hexToArray(_.leftPad(p.getY().toBigInteger().toRadix(16), 64))
+
+  // c3 = hash(x2 || msg || y2)
+  const c3 = _.arrayToHex(sm3([].concat(x2, msg, y2)))
+
+  let ct = 1
+  let offset = 0
+  let t = [] // 256 位
+  const z = [].concat(x2, y2)
+  const nextT = () => {
+    // (1) Hai = hash(z || ct)
+    // (2) ct++
+    t = sm3([...z, ct >> 24 & 0x00ff, ct >> 16 & 0x00ff, ct >> 8 & 0x00ff, ct & 0x00ff])
+    ct++
+    offset = 0
+  }
+  nextT() // 先生成 Ha1
+
+  for (let i = 0, len = msg.length; i < len; i++) {
+    // t = Ha1 || Ha2 || Ha3 || Ha4
+    if (offset === t.length) nextT()
+
+    // c2 = msg ^ t
+    msg[i] ^= t[offset++] & 0xff
+  }
+  const c2 = _.arrayToHex(msg)
+
+  return cipherMode === C1C2C3 ? c1 + c2 + c3 : c1 + c3 + c2
+}
+
+/**
+ * 解密
+ */
+function doDecrypt(encryptData, privateKey, cipherMode = 1, {
+  output = 'string',
+} = {}) {
+  privateKey = new BigInteger(privateKey, 16)
+
+  let c3 = encryptData.substr(128, 64)
+  let c2 = encryptData.substr(128 + 64)
+
+  if (cipherMode === C1C2C3) {
+    c3 = encryptData.substr(encryptData.length - 64)
+    c2 = encryptData.substr(128, encryptData.length - 128 - 64)
+  }
+
+  const msg = _.hexToArray(c2)
+  const c1 = _.getGlobalCurve().decodePointHex('04' + encryptData.substr(0, 128))
+
+  const p = c1.multiply(privateKey)
+  const x2 = _.hexToArray(_.leftPad(p.getX().toBigInteger().toRadix(16), 64))
+  const y2 = _.hexToArray(_.leftPad(p.getY().toBigInteger().toRadix(16), 64))
+
+  let ct = 1
+  let offset = 0
+  let t = [] // 256 位
+  const z = [].concat(x2, y2)
+  const nextT = () => {
+    // (1) Hai = hash(z || ct)
+    // (2) ct++
+    t = sm3([...z, ct >> 24 & 0x00ff, ct >> 16 & 0x00ff, ct >> 8 & 0x00ff, ct & 0x00ff])
+    ct++
+    offset = 0
+  }
+  nextT() // 先生成 Ha1
+
+  for (let i = 0, len = msg.length; i < len; i++) {
+    // t = Ha1 || Ha2 || Ha3 || Ha4
+    if (offset === t.length) nextT()
+
+    // c2 = msg ^ t
+    msg[i] ^= t[offset++] & 0xff
+  }
+
+  // c3 = hash(x2 || msg || y2)
+  const checkC3 = _.arrayToHex(sm3([].concat(x2, msg, y2)))
+
+  if (checkC3 === c3.toLowerCase()) {
+    return output === 'array' ? msg : _.arrayToUtf8(msg)
+  } else {
+    return output === 'array' ? [] : ''
+  }
+}
+
+/**
+ * 签名
+ */
+function doSignature(msg, privateKey, {
+  pointPool, der, hash, publicKey, userId
+} = {}) {
+  let hashHex = typeof msg === 'string' ? _.utf8ToHex(msg) : _.arrayToHex(msg)
+
+  if (hash) {
+    // sm3杂凑
+    publicKey = publicKey || getPublicKeyFromPrivateKey(privateKey)
+    hashHex = getHash(hashHex, publicKey, userId)
+  }
+
+  const dA = new BigInteger(privateKey, 16)
+  const e = new BigInteger(hashHex, 16)
+
+  // k
+  let k = null
+  let r = null
+  let s = null
+
+  do {
+    do {
+      let point
+      if (pointPool && pointPool.length) {
+        point = pointPool.pop()
+      } else {
+        point = getPoint()
+      }
+      k = point.k
+
+      // r = (e + x1) mod n
+      r = e.add(point.x1).mod(n)
+    } while (r.equals(BigInteger.ZERO) || r.add(k).equals(n))
+
+    // s = ((1 + dA)^-1 * (k - r * dA)) mod n
+    s = dA.add(BigInteger.ONE).modInverse(n).multiply(k.subtract(r.multiply(dA))).mod(n)
+  } while (s.equals(BigInteger.ZERO))
+
+  if (der) return encodeDer(r, s) // asn.1 der 编码
+
+  return _.leftPad(r.toString(16), 64) + _.leftPad(s.toString(16), 64)
+}
+
+/**
+ * 验签
+ */
+function doVerifySignature(msg, signHex, publicKey, {der, hash, userId} = {}) {
+  let hashHex = typeof msg === 'string' ? _.utf8ToHex(msg) : _.arrayToHex(msg)
+
+  if (hash) {
+    // sm3杂凑
+    hashHex = getHash(hashHex, publicKey, userId)
+  }
+
+  let r; let
+    s
+  if (der) {
+    const decodeDerObj = decodeDer(signHex) // asn.1 der 解码
+    r = decodeDerObj.r
+    s = decodeDerObj.s
+  } else {
+    r = new BigInteger(signHex.substring(0, 64), 16)
+    s = new BigInteger(signHex.substring(64), 16)
+  }
+
+  const PA = curve.decodePointHex(publicKey)
+  const e = new BigInteger(hashHex, 16)
+
+  // t = (r + s) mod n
+  const t = r.add(s).mod(n)
+
+  if (t.equals(BigInteger.ZERO)) return false
+
+  // x1y1 = s * G + t * PA
+  const x1y1 = G.multiply(s).add(PA.multiply(t))
+
+  // R = (e + x1) mod n
+  const R = e.add(x1y1.getX().toBigInteger()).mod(n)
+
+  return r.equals(R)
+}
+
+/**
+ * sm3杂凑算法
+ */
+function getHash(hashHex, publicKey, userId = '1234567812345678') {
+  // z = hash(entl || userId || a || b || gx || gy || px || py)
+  userId = _.utf8ToHex(userId)
+  const a = _.leftPad(G.curve.a.toBigInteger().toRadix(16), 64)
+  const b = _.leftPad(G.curve.b.toBigInteger().toRadix(16), 64)
+  const gx = _.leftPad(G.getX().toBigInteger().toRadix(16), 64)
+  const gy = _.leftPad(G.getY().toBigInteger().toRadix(16), 64)
+  let px
+  let py
+  if (publicKey.length === 128) {
+    px = publicKey.substr(0, 64)
+    py = publicKey.substr(64, 64)
+  } else {
+    const point = G.curve.decodePointHex(publicKey)
+    px = _.leftPad(point.getX().toBigInteger().toRadix(16), 64)
+    py = _.leftPad(point.getY().toBigInteger().toRadix(16), 64)
+  }
+  const data = _.hexToArray(userId + a + b + gx + gy + px + py)
+
+  const entl = userId.length * 4
+  data.unshift(entl & 0x00ff)
+  data.unshift(entl >> 8 & 0x00ff)
+
+  const z = sm3(data)
+
+  // e = hash(z || msg)
+  return _.arrayToHex(sm3(z.concat(_.hexToArray(hashHex))))
+}
+
+/**
+ * 计算公钥
+ */
+function getPublicKeyFromPrivateKey(privateKey) {
+  const PA = G.multiply(new BigInteger(privateKey, 16))
+  const x = _.leftPad(PA.getX().toBigInteger().toString(16), 64)
+  const y = _.leftPad(PA.getY().toBigInteger().toString(16), 64)
+  return '04' + x + y
+}
+
+/**
+ * 获取椭圆曲线点
+ */
+function getPoint() {
+  const keypair = _.generateKeyPairHex()
+  const PA = curve.decodePointHex(keypair.publicKey)
+
+  keypair.k = new BigInteger(keypair.privateKey, 16)
+  keypair.x1 = PA.getX().toBigInteger()
+
+  return keypair
+}
+
+module.exports = {
+  generateKeyPairHex: _.generateKeyPairHex,
+  compressPublicKeyHex: _.compressPublicKeyHex,
+  comparePublicKeyHex: _.comparePublicKeyHex,
+  doEncrypt,
+  doDecrypt,
+  doSignature,
+  doVerifySignature,
+  getPublicKeyFromPrivateKey,
+  getPoint,
+  verifyPublicKey: _.verifyPublicKey,
+}

+ 170 - 0
node_modules/sm-crypto/src/sm2/sm3.js

@@ -0,0 +1,170 @@
+// 消息扩展
+const W = new Uint32Array(68)
+const M = new Uint32Array(64) // W'
+
+/**
+ * 循环左移
+ */
+function rotl(x, n) {
+  const s = n & 31
+  return (x << s) | (x >>> (32 - s))
+}
+
+/**
+ * 二进制异或运算
+ */
+function xor(x, y) {
+  const result = []
+  for (let i = x.length - 1; i >= 0; i--) result[i] = (x[i] ^ y[i]) & 0xff
+  return result
+}
+
+/**
+ * 压缩函数中的置换函数 P0(X) = X xor (X <<< 9) xor (X <<< 17)
+ */
+function P0(X) {
+  return (X ^ rotl(X, 9)) ^ rotl(X, 17)
+}
+
+/**
+ * 消息扩展中的置换函数 P1(X) = X xor (X <<< 15) xor (X <<< 23)
+ */
+function P1(X) {
+  return (X ^ rotl(X, 15)) ^ rotl(X, 23)
+}
+
+/**
+ * sm3 本体
+ */
+function sm3(array) {
+  let len = array.length * 8
+
+  // k 是满足 len + 1 + k = 448mod512 的最小的非负整数
+  let k = len % 512
+  // 如果 448 <= (512 % len) < 512,需要多补充 (len % 448) 比特'0'以满足总比特长度为512的倍数
+  k = k >= 448 ? 512 - (k % 448) - 1 : 448 - k - 1
+
+  // 填充
+  const kArr = new Array((k - 7) / 8)
+  const lenArr = new Array(8)
+  for (let i = 0, len = kArr.length; i < len; i++) kArr[i] = 0
+  for (let i = 0, len = lenArr.length; i < len; i++) lenArr[i] = 0
+  len = len.toString(2)
+  for (let i = 7; i >= 0; i--) {
+    if (len.length > 8) {
+      const start = len.length - 8
+      lenArr[i] = parseInt(len.substr(start), 2)
+      len = len.substr(0, start)
+    } else if (len.length > 0) {
+      lenArr[i] = parseInt(len, 2)
+      len = ''
+    }
+  }
+  const m = new Uint8Array([...array, 0x80, ...kArr, ...lenArr])
+  const dataView = new DataView(m.buffer, 0)
+
+  // 迭代压缩
+  const n = m.length / 64
+  const V = new Uint32Array([0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e])
+  for (let i = 0; i < n; i++) {
+    W.fill(0)
+    M.fill(0)
+
+    // 将消息分组B划分为 16 个字 W0, W1,……,W15
+    const start = 16 * i
+    for (let j = 0; j < 16; j++) {
+      W[j] = dataView.getUint32((start + j) * 4, false)
+    }
+
+    // W16 ~ W67:W[j] <- P1(W[j−16] xor W[j−9] xor (W[j−3] <<< 15)) xor (W[j−13] <<< 7) xor W[j−6]
+    for (let j = 16; j < 68; j++) {
+      W[j] = (P1((W[j - 16] ^ W[j - 9]) ^ rotl(W[j - 3], 15)) ^ rotl(W[j - 13], 7)) ^ W[j - 6]
+    }
+
+    // W′0 ~ W′63:W′[j] = W[j] xor W[j+4]
+    for (let j = 0; j < 64; j++) {
+      M[j] = W[j] ^ W[j + 4]
+    }
+
+    // 压缩
+    const T1 = 0x79cc4519
+    const T2 = 0x7a879d8a
+    // 字寄存器
+    let A = V[0]
+    let B = V[1]
+    let C = V[2]
+    let D = V[3]
+    let E = V[4]
+    let F = V[5]
+    let G = V[6]
+    let H = V[7]
+    // 中间变量
+    let SS1
+    let SS2
+    let TT1
+    let TT2
+    let T
+    for (let j = 0; j < 64; j++) {
+      T = j >= 0 && j <= 15 ? T1 : T2
+      SS1 = rotl(rotl(A, 12) + E + rotl(T, j), 7)
+      SS2 = SS1 ^ rotl(A, 12)
+
+      TT1 = (j >= 0 && j <= 15 ? ((A ^ B) ^ C) : (((A & B) | (A & C)) | (B & C))) + D + SS2 + M[j]
+      TT2 = (j >= 0 && j <= 15 ? ((E ^ F) ^ G) : ((E & F) | ((~E) & G))) + H + SS1 + W[j]
+
+      D = C
+      C = rotl(B, 9)
+      B = A
+      A = TT1
+      H = G
+      G = rotl(F, 19)
+      F = E
+      E = P0(TT2)
+    }
+
+    V[0] ^= A
+    V[1] ^= B
+    V[2] ^= C
+    V[3] ^= D
+    V[4] ^= E
+    V[5] ^= F
+    V[6] ^= G
+    V[7] ^= H
+  }
+
+  // 转回 uint8
+  const result = []
+  for (let i = 0, len = V.length; i < len; i++) {
+    const word = V[i]
+    result.push((word & 0xff000000) >>> 24, (word & 0xff0000) >>> 16, (word & 0xff00) >>> 8, word & 0xff)
+  }
+
+  return result
+}
+
+/**
+ * hmac 实现
+ */
+const blockLen = 64
+const iPad = new Uint8Array(blockLen)
+const oPad = new Uint8Array(blockLen)
+for (let i = 0; i < blockLen; i++) {
+  iPad[i] = 0x36
+  oPad[i] = 0x5c
+}
+function hmac(input, key) {
+  // 密钥填充
+  if (key.length > blockLen) key = sm3(key)
+  while (key.length < blockLen) key.push(0)
+
+  const iPadKey = xor(key, iPad)
+  const oPadKey = xor(key, oPad)
+
+  const hash = sm3([...iPadKey, ...input])
+  return sm3([...oPadKey, ...hash])
+}
+
+module.exports = {
+  sm3,
+  hmac,
+}

+ 194 - 0
node_modules/sm-crypto/src/sm2/utils.js

@@ -0,0 +1,194 @@
+/* eslint-disable no-bitwise, no-mixed-operators, no-use-before-define, max-len */
+const {BigInteger, SecureRandom} = require('jsbn')
+const {ECCurveFp} = require('./ec')
+
+const rng = new SecureRandom()
+const {curve, G, n} = generateEcparam()
+
+/**
+ * 获取公共椭圆曲线
+ */
+function getGlobalCurve() {
+  return curve
+}
+
+/**
+ * 生成ecparam
+ */
+function generateEcparam() {
+  // 椭圆曲线
+  const p = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16)
+  const a = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16)
+  const b = new BigInteger('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93', 16)
+  const curve = new ECCurveFp(p, a, b)
+
+  // 基点
+  const gxHex = '32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7'
+  const gyHex = 'BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0'
+  const G = curve.decodePointHex('04' + gxHex + gyHex)
+
+  const n = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123', 16)
+
+  return {curve, G, n}
+}
+
+/**
+ * 生成密钥对:publicKey = privateKey * G
+ */
+function generateKeyPairHex(a, b, c) {
+  const random = a ? new BigInteger(a, b, c) : new BigInteger(n.bitLength(), rng)
+  const d = random.mod(n.subtract(BigInteger.ONE)).add(BigInteger.ONE) // 随机数
+  const privateKey = leftPad(d.toString(16), 64)
+
+  const P = G.multiply(d) // P = dG,p 为公钥,d 为私钥
+  const Px = leftPad(P.getX().toBigInteger().toString(16), 64)
+  const Py = leftPad(P.getY().toBigInteger().toString(16), 64)
+  const publicKey = '04' + Px + Py
+
+  return {privateKey, publicKey}
+}
+
+/**
+ * 生成压缩公钥
+ */
+function compressPublicKeyHex(s) {
+  if (s.length !== 130) throw new Error('Invalid public key to compress')
+
+  const len = (s.length - 2) / 2
+  const xHex = s.substr(2, len)
+  const y = new BigInteger(s.substr(len + 2, len), 16)
+
+  let prefix = '03'
+  if (y.mod(new BigInteger('2')).equals(BigInteger.ZERO)) prefix = '02'
+
+  return prefix + xHex
+}
+
+/**
+ * utf8串转16进制串
+ */
+function utf8ToHex(input) {
+  input = unescape(encodeURIComponent(input))
+
+  const length = input.length
+
+  // 转换到字数组
+  const words = []
+  for (let i = 0; i < length; i++) {
+    words[i >>> 2] |= (input.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8)
+  }
+
+  // 转换到16进制
+  const hexChars = []
+  for (let i = 0; i < length; i++) {
+    const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff
+    hexChars.push((bite >>> 4).toString(16))
+    hexChars.push((bite & 0x0f).toString(16))
+  }
+
+  return hexChars.join('')
+}
+
+/**
+ * 补全16进制字符串
+ */
+function leftPad(input, num) {
+  if (input.length >= num) return input
+
+  return (new Array(num - input.length + 1)).join('0') + input
+}
+
+/**
+ * 转成16进制串
+ */
+function arrayToHex(arr) {
+  return arr.map(item => {
+    item = item.toString(16)
+    return item.length === 1 ? '0' + item : item
+  }).join('')
+}
+
+/**
+ * 转成utf8串
+ */
+function arrayToUtf8(arr) {
+  const words = []
+  let j = 0
+  for (let i = 0; i < arr.length * 2; i += 2) {
+    words[i >>> 3] |= parseInt(arr[j], 10) << (24 - (i % 8) * 4)
+    j++
+  }
+
+  try {
+    const latin1Chars = []
+
+    for (let i = 0; i < arr.length; i++) {
+      const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff
+      latin1Chars.push(String.fromCharCode(bite))
+    }
+
+    return decodeURIComponent(escape(latin1Chars.join('')))
+  } catch (e) {
+    throw new Error('Malformed UTF-8 data')
+  }
+}
+
+/**
+ * 转成字节数组
+ */
+function hexToArray(hexStr) {
+  const words = []
+  let hexStrLength = hexStr.length
+
+  if (hexStrLength % 2 !== 0) {
+    hexStr = leftPad(hexStr, hexStrLength + 1)
+  }
+
+  hexStrLength = hexStr.length
+
+  for (let i = 0; i < hexStrLength; i += 2) {
+    words.push(parseInt(hexStr.substr(i, 2), 16))
+  }
+  return words
+}
+
+/**
+ * 验证公钥是否为椭圆曲线上的点
+ */
+function verifyPublicKey(publicKey) {
+  const point = curve.decodePointHex(publicKey)
+  if (!point) return false
+
+  const x = point.getX()
+  const y = point.getY()
+
+  // 验证 y^2 是否等于 x^3 + ax + b
+  return y.square().equals(x.multiply(x.square()).add(x.multiply(curve.a)).add(curve.b))
+}
+
+/**
+ * 验证公钥是否等价,等价返回true
+ */
+function comparePublicKeyHex(publicKey1, publicKey2) {
+  const point1 = curve.decodePointHex(publicKey1)
+  if (!point1) return false
+
+  const point2 = curve.decodePointHex(publicKey2)
+  if (!point2) return false
+
+  return point1.equals(point2)
+}
+
+module.exports = {
+  getGlobalCurve,
+  generateEcparam,
+  generateKeyPairHex,
+  compressPublicKeyHex,
+  utf8ToHex,
+  leftPad,
+  arrayToHex,
+  arrayToUtf8,
+  hexToArray,
+  verifyPublicKey,
+  comparePublicKeyHex,
+}

+ 94 - 0
node_modules/sm-crypto/src/sm3/index.js

@@ -0,0 +1,94 @@
+const {sm3, hmac} = require('../sm2/sm3')
+
+/**
+ * 补全16进制字符串
+ */
+function leftPad(input, num) {
+  if (input.length >= num) return input
+
+  return (new Array(num - input.length + 1)).join('0') + input
+}
+
+/**
+ * 字节数组转 16 进制串
+ */
+function ArrayToHex(arr) {
+  return arr.map(item => {
+    item = item.toString(16)
+    return item.length === 1 ? '0' + item : item
+  }).join('')
+}
+
+/**
+ * 转成字节数组
+ */
+function hexToArray(hexStr) {
+  const words = []
+  let hexStrLength = hexStr.length
+
+  if (hexStrLength % 2 !== 0) {
+    hexStr = leftPad(hexStr, hexStrLength + 1)
+  }
+
+  hexStrLength = hexStr.length
+
+  for (let i = 0; i < hexStrLength; i += 2) {
+    words.push(parseInt(hexStr.substr(i, 2), 16))
+  }
+  return words
+}
+
+/**
+ * utf8 串转字节数组
+ */
+function utf8ToArray(str) {
+  const arr = []
+
+  for (let i = 0, len = str.length; i < len; i++) {
+    const point = str.codePointAt(i)
+
+    if (point <= 0x007f) {
+      // 单字节,标量值:00000000 00000000 0zzzzzzz
+      arr.push(point)
+    } else if (point <= 0x07ff) {
+      // 双字节,标量值:00000000 00000yyy yyzzzzzz
+      arr.push(0xc0 | (point >>> 6)) // 110yyyyy(0xc0-0xdf)
+      arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
+    } else if (point <= 0xD7FF || (point >= 0xE000 && point <= 0xFFFF)) {
+      // 三字节:标量值:00000000 xxxxyyyy yyzzzzzz
+      arr.push(0xe0 | (point >>> 12)) // 1110xxxx(0xe0-0xef)
+      arr.push(0x80 | ((point >>> 6) & 0x3f)) // 10yyyyyy(0x80-0xbf)
+      arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
+    } else if (point >= 0x010000 && point <= 0x10FFFF) {
+      // 四字节:标量值:000wwwxx xxxxyyyy yyzzzzzz
+      i++
+      arr.push((0xf0 | (point >>> 18) & 0x1c)) // 11110www(0xf0-0xf7)
+      arr.push((0x80 | ((point >>> 12) & 0x3f))) // 10xxxxxx(0x80-0xbf)
+      arr.push((0x80 | ((point >>> 6) & 0x3f))) // 10yyyyyy(0x80-0xbf)
+      arr.push((0x80 | (point & 0x3f))) // 10zzzzzz(0x80-0xbf)
+    } else {
+      // 五、六字节,暂时不支持
+      arr.push(point)
+      throw new Error('input is not supported')
+    }
+  }
+
+  return arr
+}
+
+module.exports = function (input, options) {
+  input = typeof input === 'string' ? utf8ToArray(input) : Array.prototype.slice.call(input)
+
+  if (options) {
+    const mode = options.mode || 'hmac'
+    if (mode !== 'hmac') throw new Error('invalid mode')
+
+    let key = options.key
+    if (!key) throw new Error('invalid key')
+
+    key = typeof key === 'string' ? hexToArray(key) : Array.prototype.slice.call(key)
+    return ArrayToHex(hmac(input, key))
+  }
+
+  return ArrayToHex(sm3(input))
+}

+ 359 - 0
node_modules/sm-crypto/src/sm4/index.js

@@ -0,0 +1,359 @@
+/* eslint-disable no-bitwise, no-mixed-operators, complexity */
+const DECRYPT = 0
+const ROUND = 32
+const BLOCK = 16
+
+const Sbox = [
+  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
+]
+
+const 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
+]
+
+/**
+ * 16 进制串转字节数组
+ */
+function hexToArray(str) {
+  const arr = []
+  for (let i = 0, len = str.length; i < len; i += 2) {
+    arr.push(parseInt(str.substr(i, 2), 16))
+  }
+  return arr
+}
+
+/**
+ * 字节数组转 16 进制串
+ */
+function ArrayToHex(arr) {
+  return arr.map(item => {
+    item = item.toString(16)
+    return item.length === 1 ? '0' + item : item
+  }).join('')
+}
+
+/**
+ * utf8 串转字节数组
+ */
+function utf8ToArray(str) {
+  const arr = []
+
+  for (let i = 0, len = str.length; i < len; i++) {
+    const point = str.codePointAt(i)
+
+    if (point <= 0x007f) {
+      // 单字节,标量值:00000000 00000000 0zzzzzzz
+      arr.push(point)
+    } else if (point <= 0x07ff) {
+      // 双字节,标量值:00000000 00000yyy yyzzzzzz
+      arr.push(0xc0 | (point >>> 6)) // 110yyyyy(0xc0-0xdf)
+      arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
+    } else if (point <= 0xD7FF || (point >= 0xE000 && point <= 0xFFFF)) {
+      // 三字节:标量值:00000000 xxxxyyyy yyzzzzzz
+      arr.push(0xe0 | (point >>> 12)) // 1110xxxx(0xe0-0xef)
+      arr.push(0x80 | ((point >>> 6) & 0x3f)) // 10yyyyyy(0x80-0xbf)
+      arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
+    } else if (point >= 0x010000 && point <= 0x10FFFF) {
+      // 四字节:标量值:000wwwxx xxxxyyyy yyzzzzzz
+      i++
+      arr.push((0xf0 | (point >>> 18) & 0x1c)) // 11110www(0xf0-0xf7)
+      arr.push((0x80 | ((point >>> 12) & 0x3f))) // 10xxxxxx(0x80-0xbf)
+      arr.push((0x80 | ((point >>> 6) & 0x3f))) // 10yyyyyy(0x80-0xbf)
+      arr.push((0x80 | (point & 0x3f))) // 10zzzzzz(0x80-0xbf)
+    } else {
+      // 五、六字节,暂时不支持
+      arr.push(point)
+      throw new Error('input is not supported')
+    }
+  }
+
+  return arr
+}
+
+/**
+ * 字节数组转 utf8 串
+ */
+function arrayToUtf8(arr) {
+  const str = []
+  for (let i = 0, len = arr.length; i < len; i++) {
+    if (arr[i] >= 0xf0 && arr[i] <= 0xf7) {
+      // 四字节
+      str.push(String.fromCodePoint(((arr[i] & 0x07) << 18) + ((arr[i + 1] & 0x3f) << 12) + ((arr[i + 2] & 0x3f) << 6) + (arr[i + 3] & 0x3f)))
+      i += 3
+    } else if (arr[i] >= 0xe0 && arr[i] <= 0xef) {
+      // 三字节
+      str.push(String.fromCodePoint(((arr[i] & 0x0f) << 12) + ((arr[i + 1] & 0x3f) << 6) + (arr[i + 2] & 0x3f)))
+      i += 2
+    } else if (arr[i] >= 0xc0 && arr[i] <= 0xdf) {
+      // 双字节
+      str.push(String.fromCodePoint(((arr[i] & 0x1f) << 6) + (arr[i + 1] & 0x3f)))
+      i++
+    } else {
+      // 单字节
+      str.push(String.fromCodePoint(arr[i]))
+    }
+  }
+
+  return str.join('')
+}
+
+/**
+ * 32 比特循环左移
+ */
+function rotl(x, n) {
+  const s = n & 31
+  return (x << s) | (x >>> (32 - s))
+}
+
+/**
+ * 非线性变换
+ */
+function byteSub(a) {
+  return (Sbox[a >>> 24 & 0xFF] & 0xFF) << 24 |
+    (Sbox[a >>> 16 & 0xFF] & 0xFF) << 16 |
+    (Sbox[a >>> 8 & 0xFF] & 0xFF) << 8 |
+    (Sbox[a & 0xFF] & 0xFF)
+}
+
+/**
+ * 线性变换,加密/解密用
+ */
+function l1(b) {
+  return b ^ rotl(b, 2) ^ rotl(b, 10) ^ rotl(b, 18) ^ rotl(b, 24)
+}
+
+/**
+ * 线性变换,生成轮密钥用
+ */
+function l2(b) {
+  return b ^ rotl(b, 13) ^ rotl(b, 23)
+}
+
+/**
+ * 以一组 128 比特进行加密/解密操作
+ */
+function sms4Crypt(input, output, roundKey) {
+  const x = new Array(4)
+
+  // 字节数组转成字数组(此处 1 字 = 32 比特)
+  const tmp = new Array(4)
+  for (let i = 0; i < 4; i++) {
+    tmp[0] = input[4 * i] & 0xff
+    tmp[1] = input[4 * i + 1] & 0xff
+    tmp[2] = input[4 * i + 2] & 0xff
+    tmp[3] = input[4 * i + 3] & 0xff
+    x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3]
+  }
+
+  // x[i + 4] = x[i] ^ l1(byteSub(x[i + 1] ^ x[i + 2] ^ x[i + 3] ^ roundKey[i]))
+  for (let r = 0, mid; r < 32; r += 4) {
+    mid = x[1] ^ x[2] ^ x[3] ^ roundKey[r + 0]
+    x[0] ^= l1(byteSub(mid)) // x[4]
+
+    mid = x[2] ^ x[3] ^ x[0] ^ roundKey[r + 1]
+    x[1] ^= l1(byteSub(mid)) // x[5]
+
+    mid = x[3] ^ x[0] ^ x[1] ^ roundKey[r + 2]
+    x[2] ^= l1(byteSub(mid)) // x[6]
+
+    mid = x[0] ^ x[1] ^ x[2] ^ roundKey[r + 3]
+    x[3] ^= l1(byteSub(mid)) // x[7]
+  }
+
+  // 反序变换
+  for (let j = 0; j < 16; j += 4) {
+    output[j] = x[3 - j / 4] >>> 24 & 0xff
+    output[j + 1] = x[3 - j / 4] >>> 16 & 0xff
+    output[j + 2] = x[3 - j / 4] >>> 8 & 0xff
+    output[j + 3] = x[3 - j / 4] & 0xff
+  }
+}
+
+/**
+ * 密钥扩展算法
+ */
+function sms4KeyExt(key, roundKey, cryptFlag) {
+  const x = new Array(4)
+
+  // 字节数组转成字数组(此处 1 字 = 32 比特)
+  const tmp = new Array(4)
+  for (let i = 0; i < 4; i++) {
+    tmp[0] = key[0 + 4 * i] & 0xff
+    tmp[1] = key[1 + 4 * i] & 0xff
+    tmp[2] = key[2 + 4 * i] & 0xff
+    tmp[3] = key[3 + 4 * i] & 0xff
+    x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3]
+  }
+
+  // 与系统参数做异或
+  x[0] ^= 0xa3b1bac6
+  x[1] ^= 0x56aa3350
+  x[2] ^= 0x677d9197
+  x[3] ^= 0xb27022dc
+
+  // roundKey[i] = x[i + 4] = x[i] ^ l2(byteSub(x[i + 1] ^ x[i + 2] ^ x[i + 3] ^ CK[i]))
+  for (let r = 0, mid; r < 32; r += 4) {
+    mid = x[1] ^ x[2] ^ x[3] ^ CK[r + 0]
+    roundKey[r + 0] = x[0] ^= l2(byteSub(mid)) // x[4]
+
+    mid = x[2] ^ x[3] ^ x[0] ^ CK[r + 1]
+    roundKey[r + 1] = x[1] ^= l2(byteSub(mid)) // x[5]
+
+    mid = x[3] ^ x[0] ^ x[1] ^ CK[r + 2]
+    roundKey[r + 2] = x[2] ^= l2(byteSub(mid)) // x[6]
+
+    mid = x[0] ^ x[1] ^ x[2] ^ CK[r + 3]
+    roundKey[r + 3] = x[3] ^= l2(byteSub(mid)) // x[7]
+  }
+
+  // 解密时使用反序的轮密钥
+  if (cryptFlag === DECRYPT) {
+    for (let r = 0, mid; r < 16; r++) {
+      mid = roundKey[r]
+      roundKey[r] = roundKey[31 - r]
+      roundKey[31 - r] = mid
+    }
+  }
+}
+
+function sm4(inArray, key, cryptFlag, {
+  padding = 'pkcs#7', mode, iv = [], output = 'string'
+} = {}) {
+  if (mode === 'cbc') {
+    // CBC 模式,默认走 ECB 模式
+    if (typeof iv === 'string') iv = hexToArray(iv)
+    if (iv.length !== (128 / 8)) {
+      // iv 不是 128 比特
+      throw new Error('iv is invalid')
+    }
+  }
+
+  // 检查 key
+  if (typeof key === 'string') key = hexToArray(key)
+  if (key.length !== (128 / 8)) {
+    // key 不是 128 比特
+    throw new Error('key is invalid')
+  }
+
+  // 检查输入
+  if (typeof inArray === 'string') {
+    if (cryptFlag !== DECRYPT) {
+      // 加密,输入为 utf8 串
+      inArray = utf8ToArray(inArray)
+    } else {
+      // 解密,输入为 16 进制串
+      inArray = hexToArray(inArray)
+    }
+  } else {
+    inArray = [...inArray]
+  }
+
+  // 新增填充,sm4 是 16 个字节一个分组,所以统一走到 pkcs#7
+  if ((padding === 'pkcs#5' || padding === 'pkcs#7') && cryptFlag !== DECRYPT) {
+    const paddingCount = BLOCK - inArray.length % BLOCK
+    for (let i = 0; i < paddingCount; i++) inArray.push(paddingCount)
+  }
+
+  // 生成轮密钥
+  const roundKey = new Array(ROUND)
+  sms4KeyExt(key, roundKey, cryptFlag)
+
+  const outArray = []
+  let lastVector = iv
+  let restLen = inArray.length
+  let point = 0
+  while (restLen >= BLOCK) {
+    const input = inArray.slice(point, point + 16)
+    const output = new Array(16)
+
+    if (mode === 'cbc') {
+      for (let i = 0; i < BLOCK; i++) {
+        if (cryptFlag !== DECRYPT) {
+          // 加密过程在组加密前进行异或
+          input[i] ^= lastVector[i]
+        }
+      }
+    }
+
+    sms4Crypt(input, output, roundKey)
+
+
+    for (let i = 0; i < BLOCK; i++) {
+      if (mode === 'cbc') {
+        if (cryptFlag === DECRYPT) {
+          // 解密过程在组解密后进行异或
+          output[i] ^= lastVector[i]
+        }
+      }
+
+      outArray[point + i] = output[i]
+    }
+
+    if (mode === 'cbc') {
+      if (cryptFlag !== DECRYPT) {
+        // 使用上一次输出作为加密向量
+        lastVector = output
+      } else {
+        // 使用上一次输入作为解密向量
+        lastVector = input
+      }
+    }
+
+    restLen -= BLOCK
+    point += BLOCK
+  }
+
+  // 去除填充,sm4 是 16 个字节一个分组,所以统一走到 pkcs#7
+  if ((padding === 'pkcs#5' || padding === 'pkcs#7') && cryptFlag === DECRYPT) {
+    const len = outArray.length
+    const paddingCount = outArray[len - 1]
+    for (let i = 1; i <= paddingCount; i++) {
+      if (outArray[len - i] !== paddingCount) throw new Error('padding is invalid')
+    }
+    outArray.splice(len - paddingCount, paddingCount)
+  }
+
+  // 调整输出
+  if (output !== 'array') {
+    if (cryptFlag !== DECRYPT) {
+      // 加密,输出转 16 进制串
+      return ArrayToHex(outArray)
+    } else {
+      // 解密,输出转 utf8 串
+      return arrayToUtf8(outArray)
+    }
+  } else {
+    return outArray
+  }
+}
+
+module.exports = {
+  encrypt(inArray, key, options) {
+    return sm4(inArray, key, 1, options)
+  },
+  decrypt(inArray, key, options) {
+    return sm4(inArray, key, 0, options)
+  }
+}

+ 26 - 0
node_modules/sm-crypto/webpack.config.js

@@ -0,0 +1,26 @@
+const path = require('path');
+const webpack = require('webpack');
+
+module.exports = {
+    entry: {
+        sm2: './src/sm2/index.js',
+        sm3: './src/sm3/index.js',
+        sm4: './src/sm4/index.js',
+    },
+    output: {
+        path: path.resolve(__dirname, 'dist'),
+        filename: '[name].js',
+        library: '[name]',
+        libraryTarget: 'umd',
+    },
+    module: {    
+        loaders: [{    
+            test: /\.js$/,    
+            exclude: /node_modules/,    
+            loader: 'babel-loader'    
+        }]    
+    },
+    plugins: [
+        new webpack.optimize.UglifyJsPlugin(),
+    ]
+};

+ 34 - 0
package-lock.json

@@ -0,0 +1,34 @@
+{
+  "name": "Fuelwx",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "dependencies": {
+        "miniprogram-sm-crypto": "^0.3.13",
+        "sm-crypto": "^0.3.13"
+      }
+    },
+    "node_modules/jsbn": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
+      "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
+    },
+    "node_modules/miniprogram-sm-crypto": {
+      "version": "0.3.13",
+      "resolved": "https://registry.npmjs.org/miniprogram-sm-crypto/-/miniprogram-sm-crypto-0.3.13.tgz",
+      "integrity": "sha512-H7qwbCEmIXZzekCSgEWeHh1mb4cnz0E42YH3U5xqpOaJBB2Sj9ySq0hTGv0f+Jwo5SknABR6fw+EtjnMyJ/O/Q==",
+      "dependencies": {
+        "jsbn": "^1.1.0"
+      }
+    },
+    "node_modules/sm-crypto": {
+      "version": "0.3.13",
+      "resolved": "https://registry.npmjs.org/sm-crypto/-/sm-crypto-0.3.13.tgz",
+      "integrity": "sha512-ztNF+pZq6viCPMA1A6KKu3bgpkmYti5avykRHbcFIdSipFdkVmfUw2CnpM2kBJyppIalqvczLNM3wR8OQ0pT5w==",
+      "dependencies": {
+        "jsbn": "^1.1.0"
+      }
+    }
+  }
+}

+ 6 - 0
package.json

@@ -0,0 +1,6 @@
+{
+  "dependencies": {
+    "miniprogram-sm-crypto": "^0.3.13",
+    "sm-crypto": "^0.3.13"
+  }
+}

+ 71 - 0
pages/login/login.js

@@ -1,3 +1,6 @@
+
+//const app = require('../../js/api');
+import api from '../../js/api'
 // pages/login/login.js
 Page({
 
@@ -62,5 +65,73 @@ Page({
    */
   onShareAppMessage() {
 
+  },
+  handleAuthLogin() {
+    console.log('一键授权登录按钮被点击');
+     api.request_wechatPay(1)
+     .then(res => {
+      wx.requestPayment({
+        timeStamp: res.data.data.unifiedOrderResult.timeStamp,
+        nonceStr: res.data.data.unifiedOrderResult.nonceStr,
+        package: res.data.data.unifiedOrderResult.package,
+        signType: res.data.data.unifiedOrderResult.signType,
+        paySign: res.data.data.unifiedOrderResult.paySign,
+        success: res => {
+          wx.hideLoading()
+          wx.showToast({
+            title: '支付成功!',
+          })
+          setTimeout(function () {
+            wx.switchTab({
+              url: '../index/index',
+            })
+          }, 2000)
+
+        },
+        fail: res => {
+          wx.hideLoading()
+          wx.showModal({
+            title: '支付失败',
+            content: res.errMsg + '请稍后再试',
+            showCancel: false,
+            success(res) {
+              if (res.confirm) {
+                wx.switchTab({
+                  url: '../home/home',
+                })
+              }
+            }
+          })
+        }
+      })
+     });
+    // 调用微信登录接口
+    wx.login({
+      success(res) {
+        if (res.code) {
+          console.log('登录成功,code:', res.code);
+          // 将 code 发送到服务器,获取用户信息
+          // 例如:wx.request({ url: 'https://example.com/login', data: { code: res.code } })
+        } else {
+          console.log('登录失败:', res.errMsg);
+        }
+      },
+      fail(err) {
+        console.error('登录接口调用失败:', err);
+      },
+    });
+
+    // 获取用户信息授权
+    wx.getUserProfile({
+      desc: '用于完善用户资料', // 声明获取用户信息的目的
+      success(res) {
+        console.log('用户信息:', res.userInfo);
+        // 将用户信息发送到服务器
+        // 例如:wx.request({ url: 'https://example.com/userInfo', data: res.userInfo })
+      },
+      fail(err) {
+        console.error('获取用户信息失败:', err);
+      },
+    });
   }
 })

+ 1 - 1
pages/login/login.wxml

@@ -3,7 +3,7 @@
     <image src="/images/v2_sony48.svg" mode="widthFix" class="auto-image"></image>
   </view>
   <view class="action-text">立码加油</view>
-  <button class="auth-button" style="width: 547rpx; height: 94rpx; display: block; box-sizing: border-box; left: 0rpx; top: 0rpx">一键授权登录</button>
+  <button class="auth-button" style="width: 547rpx; height: 94rpx; display: block; box-sizing: border-box; left: 0rpx; top: 0rpx"  bindtap="handleAuthLogin">一键授权登录</button>
   <view class="agreement">
     <checkbox checked="{{true}}" disabled="{{true}}" />
     <text>我已阅读并同意</text>

+ 2 - 1
project.private.config.json

@@ -2,6 +2,7 @@
   "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
   "projectname": "fuelwx",
   "setting": {
-    "compileHotReLoad": true
+    "compileHotReLoad": true,
+    "urlCheck": false
   }
 }

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä