From 1d6bf629ece0f08f889d3f06fd5bf40c9769e9e3 Mon Sep 17 00:00:00 2001 From: shirlwang <15254118591@163.com> Date: Fri, 31 Oct 2025 17:48:31 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apiRc/login.js | 177 +++ apiRc/person.js | 84 + apiRc/system/dict.js | 51 + main.js | 7 +- manifest.json | 2 +- node_modules/.package-lock.json | 20 + node_modules/jsbn/.npmignore | 2 + node_modules/jsbn/CHANGELOG.md | 16 + node_modules/jsbn/LICENSE | 40 + node_modules/jsbn/README.md | 173 +++ node_modules/jsbn/example.html | 11 + node_modules/jsbn/example.js | 5 + node_modules/jsbn/index.js | 1361 +++++++++++++++++ node_modules/jsbn/package.json | 21 + node_modules/jsbn/test/es6-import.js | 3 + node_modules/sm-crypto/.babelrc | 3 + node_modules/sm-crypto/.eslintrc.js | 97 ++ node_modules/sm-crypto/CHANGELOG.md | 82 + node_modules/sm-crypto/LICENCE_MIT | 7 + node_modules/sm-crypto/README.md | 171 +++ node_modules/sm-crypto/dist/sm2.js | 1 + node_modules/sm-crypto/dist/sm3.js | 1 + node_modules/sm-crypto/dist/sm4.js | 1 + node_modules/sm-crypto/package.json | 42 + node_modules/sm-crypto/src/index.js | 5 + node_modules/sm-crypto/src/sm2/asn1.js | 161 ++ node_modules/sm-crypto/src/sm2/ec.js | 332 ++++ node_modules/sm-crypto/src/sm2/index.js | 261 ++++ node_modules/sm-crypto/src/sm2/sm3.js | 170 ++ node_modules/sm-crypto/src/sm2/utils.js | 194 +++ node_modules/sm-crypto/src/sm3/index.js | 94 ++ node_modules/sm-crypto/src/sm4/index.js | 359 +++++ node_modules/sm-crypto/webpack.config.js | 26 + package-lock.json | 40 + package.json | 5 + packageRc/api/company/index.js | 512 ++++++- packageRc/components/PopupLists.vue | 374 +++++ packageRc/components/exitPopup.vue | 130 ++ packageRc/pages/daiban/daiban.vue | 12 +- packageRc/pages/personalList/personalList.vue | 1004 ++++++++++++ pages.json | 11 +- .../dist/dev/mp-weixin/project.config.json | 4 +- .../dev/mp-weixin/project.private.config.json | 21 + utilsRc/auth.js | 19 + utilsRc/common.js | 248 +++ utilsRc/config.js | 38 + utilsRc/constant.js | 19 + utilsRc/errorCode.js | 13 + utilsRc/plugins/auth.js | 60 + utilsRc/plugins/index.js | 14 + utilsRc/plugins/loadingPlugin.js | 50 + utilsRc/plugins/modal.js | 74 + utilsRc/plugins/tab.js | 30 + utilsRc/request.js | 107 ++ utilsRc/storage.js | 44 + utilsRc/store/getters.js | 19 + utilsRc/store/index.js | 18 + utilsRc/store/modules/user.js | 233 +++ 58 files changed, 7065 insertions(+), 14 deletions(-) create mode 100644 apiRc/login.js create mode 100644 apiRc/person.js create mode 100644 apiRc/system/dict.js create mode 100644 node_modules/.package-lock.json create mode 100644 node_modules/jsbn/.npmignore create mode 100644 node_modules/jsbn/CHANGELOG.md create mode 100644 node_modules/jsbn/LICENSE create mode 100644 node_modules/jsbn/README.md create mode 100644 node_modules/jsbn/example.html create mode 100644 node_modules/jsbn/example.js create mode 100644 node_modules/jsbn/index.js create mode 100644 node_modules/jsbn/package.json create mode 100644 node_modules/jsbn/test/es6-import.js create mode 100644 node_modules/sm-crypto/.babelrc create mode 100644 node_modules/sm-crypto/.eslintrc.js create mode 100644 node_modules/sm-crypto/CHANGELOG.md create mode 100644 node_modules/sm-crypto/LICENCE_MIT create mode 100644 node_modules/sm-crypto/README.md create mode 100644 node_modules/sm-crypto/dist/sm2.js create mode 100644 node_modules/sm-crypto/dist/sm3.js create mode 100644 node_modules/sm-crypto/dist/sm4.js create mode 100644 node_modules/sm-crypto/package.json create mode 100644 node_modules/sm-crypto/src/index.js create mode 100755 node_modules/sm-crypto/src/sm2/asn1.js create mode 100755 node_modules/sm-crypto/src/sm2/ec.js create mode 100644 node_modules/sm-crypto/src/sm2/index.js create mode 100755 node_modules/sm-crypto/src/sm2/sm3.js create mode 100644 node_modules/sm-crypto/src/sm2/utils.js create mode 100644 node_modules/sm-crypto/src/sm3/index.js create mode 100755 node_modules/sm-crypto/src/sm4/index.js create mode 100644 node_modules/sm-crypto/webpack.config.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 packageRc/components/PopupLists.vue create mode 100644 packageRc/components/exitPopup.vue create mode 100644 packageRc/pages/personalList/personalList.vue create mode 100644 utilsRc/auth.js create mode 100644 utilsRc/common.js create mode 100644 utilsRc/config.js create mode 100644 utilsRc/constant.js create mode 100644 utilsRc/errorCode.js create mode 100644 utilsRc/plugins/auth.js create mode 100644 utilsRc/plugins/index.js create mode 100644 utilsRc/plugins/loadingPlugin.js create mode 100644 utilsRc/plugins/modal.js create mode 100644 utilsRc/plugins/tab.js create mode 100644 utilsRc/request.js create mode 100644 utilsRc/storage.js create mode 100644 utilsRc/store/getters.js create mode 100644 utilsRc/store/index.js create mode 100644 utilsRc/store/modules/user.js diff --git a/apiRc/login.js b/apiRc/login.js new file mode 100644 index 0000000..2c517e0 --- /dev/null +++ b/apiRc/login.js @@ -0,0 +1,177 @@ +/* + * @Descripttion: + * @Author: lip + * @Date: 2023-07-27 16:01:59 + * @LastEditors: shirlwang + */ +import request from '@/utilsRc/request' + +// 登录方法 +// export function login(data) { +// return request({ +// 'url': '/login', +// headers: { +// isToken: false +// }, +// 'method': 'post', +// data +// }) +// } +const userApi = { + Login: '/login', + Logout: '/logout', + Register: '/register', + // get my info + UserInfo: '/getInfo' +} +// 登录接口 +export function login(data) { + return request({ + 'url': '/personnel/personBaseInfo/loginGrAndQy', + headers: { + isToken: false + }, + 'method': 'post', + data + }) +} +export function loginphone(data) { + return request({ + 'url': '/not/login/person/xcxLogin', + 'method': 'get', + headers: { + isToken: false + }, + data + }) +} + + +// 注册方法 +export function register (data) { + return request({ + 'url': '/register', + headers: { + isToken: false + }, + method: 'post', + data: data + }) +} + +// 短信登录 +export function smsLogin(data) { + return request({ + 'url': '/smsLogin', + 'method': 'post', + 'data': data + }) +} +export function wechatLogin(data) { + return request({ + url: '/xcxLogin', + method: 'post', + params: data + }) +} + +// 获取用户详细信息 +export function getInfo() { + return request({ + 'url': '/getInfo', + 'method': 'get' + }) +} + +// 退出方法 +export function logout() { + return request({ + 'url': '/logout', + 'method': 'post' + }) +} + +// 获取验证码 +export function getCodeImg() { + return request({ + 'url': '/captchaImage', + headers: { + isToken: false + }, + method: 'get', + timeout: 20000 + }) +} + +export function registerReq(data) { + // const data = { + // username, + // password, + // code, + // uuid, + // userType + // } + return request({ + 'url': '/registerBody', + headers: { + isToken: false + }, + 'method': 'post', + 'data': data + }) +} + +// 发送邮箱验证码 +export function sendMailCode(query) { + return request({ + url: '/manage/mail/sendMailCode', + method: 'get', + params: query + }) +} + +// 发送短信(人才集团) +export function sendSmsForRcjt(data) { + return request({ + 'url': '/sendSmsForRcjt', + 'method': 'post', + 'data': data + }) +} +// 发送登录短信 +export function sendSmsCode(data) { + return request({ + 'url': '/onlySendSms', + 'method': 'post', + 'data': data + }) +} +// 修改密码 +export function updateUserPwd({oldPassword, newPassword}) { + return request({ + url: '/system/center/user/profile/updatePwd', + method: 'put', + params: { + oldPassword, + newPassword + } + }) +} + +// 找回密码 发送验证码 +export function sendSms(data) { + return request({ + 'url': '/sendSms', + 'method': 'post', + data + }) +} + +// 找回密码 +export function retrieve(data) { + return request({ + 'url': '/retrieve', + 'method': 'post', + data + }) +} diff --git a/apiRc/person.js b/apiRc/person.js new file mode 100644 index 0000000..ed193ff --- /dev/null +++ b/apiRc/person.js @@ -0,0 +1,84 @@ +/* + * @Date: 2025-10-31 13:50:15 + * @LastEditors: shirlwang + * @LastEditTime: 2025-10-31 14:30:31 + */ +import request from '@/utilsRc/request' + +// 人员信息保存 +export function savePersonBase(data) { + return request({ + 'url': '/personnel/personBaseInfo', + 'method': 'put', + 'data': data + }) +} + +// 人员信息查询 +export function getPersonBase(userId) { + return request({ + 'url': `/personnel/personBaseInfo/user/${userId}`, + 'method': 'get', + }) +} +// 获取行政区划列表 +export function getQUList() { + return request({ + url: `/manage/xzqh//xzqhTree`, + method: 'get' + }) + } +// 查询部门下拉树结构 +export function deptTreeSelect() { + return request({ + url: '/system/center/user/deptTree', + method: 'get' + }) +} + + +// 社群端 根据所在社区 获取姓名 +export function generateUserName(deptId) { + return request({ + url: `/generateUserName/${deptId}`, + method: 'get' + }) +} + +// 获取部门列表 +export function getDeptList(name,personId) { + return request({ + url: `/system/center/user/getDeptList?name=${name}&parentId=${personId}`, + method: 'get' + }) + } +// 求职工种列表 +export function touristWork() { + return request({ + url: `/basicdata/workType/workTypeTree`, + method: 'get' + }) +} +// 获取招聘工种列表 +export function jobTypeList(params) { + return request({ + url: '/basicdata/workType/list', + method: 'get', + params + }) +} +// 未读消息数量 + +export function unreadNum() { + return request({ + url: '/manage/tjgw/notReadNum', + method: 'get', + }) +} +// 地图类型列表 +export function jyshdt(cyfhjd) { + return request({ + url: `/jyshdt/jyshdt/queryList?lx=${cyfhjd}`, + method: 'get', + }) +} diff --git a/apiRc/system/dict.js b/apiRc/system/dict.js new file mode 100644 index 0000000..f031632 --- /dev/null +++ b/apiRc/system/dict.js @@ -0,0 +1,51 @@ +import request from '@/utilsRc/request' +// 查询字典数据列表 +export function listData (query) { + return request({ + url: '/system/dict/data/list', + method: 'get', + params: query + }) +} + +// 查询字典数据详细 +export function getData (dictCode) { + return request({ + url: '/system/dict/data/' + dictCode, + method: 'get' + }) +} + +// 根据字典类型查询字典数据信息 +export function getDicts (dictType) { + return request({ + url: '/system/dict/data/type/' + dictType, + method: 'get' + }) +} + +// 新增字典数据 +export function addData (data) { + return request({ + url: '/system/dict/data/add', + method: 'post', + data: data + }) +} + +// 修改字典数据 +export function updateData (data) { + return request({ + url: '/system/dict/data', + method: 'post', + data: data + }) +} + +// 删除字典数据 +export function delData (dictCode) { + return request({ + url: '/system/dict/data/remove' + dictCode, + method: 'get' + }) +} diff --git a/main.js b/main.js index 849ab2d..a6b8327 100644 --- a/main.js +++ b/main.js @@ -1,7 +1,7 @@ /* * @Date: 2025-10-23 14:48:48 * @LastEditors: shirlwang - * @LastEditTime: 2025-10-23 15:02:07 + * @LastEditTime: 2025-10-31 16:51:55 */ import App from './App' import * as Pinia from 'pinia' @@ -36,6 +36,8 @@ import { createSSRApp } from 'vue' import uniIcons from './uni_modules/uni-icons/components/uni-icons/uni-icons.vue' import uniPopup from './uni_modules/uni-popup/components/uni-popup/uni-popup.vue' + +import storeRc from './utilsRc/store/index.js' // const foldFeature = window.visualViewport && 'segments' in window.visualViewport // console.log('是否支持多段屏幕:', foldFeature) @@ -106,12 +108,15 @@ export function createApp() { // 先注册Pinia app.use(Pinia.createPinia()); + // 注册vuex + app.use(storeRc); // 注册其他插件 app.use(SelectPopupPlugin); // Vue 3 中挂载全局属性 - 字典获取方法 app.config.globalProperties.$getDict = getDict; + app.config.globalProperties.$store = storeRc; app.config.globalProperties.$getDictSelectOption = async (dictType, isDigital = false, forceRefresh = false) => { const dictData = await getDict(dictType, forceRefresh); return dictData.map(item => ({ diff --git a/manifest.json b/manifest.json index c5ab907..a2a7df3 100644 --- a/manifest.json +++ b/manifest.json @@ -50,7 +50,7 @@ "quickapp" : {}, /* 小程序特有相关 */ "mp-weixin" : { - "appid" : "wxc63baa791b81a51a", + "appid" : "wxc0f37e549415bb4e", "setting" : { "urlCheck" : false, "es6" : true, diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 0000000..f6c78cf --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,20 @@ +{ + "name": "ks-app-employment-service", + "lockfileVersion": 2, + "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/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" + } + } + } +} diff --git a/node_modules/jsbn/.npmignore b/node_modules/jsbn/.npmignore new file mode 100644 index 0000000..28f1ba7 --- /dev/null +++ b/node_modules/jsbn/.npmignore @@ -0,0 +1,2 @@ +node_modules +.DS_Store \ No newline at end of file diff --git a/node_modules/jsbn/CHANGELOG.md b/node_modules/jsbn/CHANGELOG.md new file mode 100644 index 0000000..23f17f4 --- /dev/null +++ b/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`. + diff --git a/node_modules/jsbn/LICENSE b/node_modules/jsbn/LICENSE new file mode 100644 index 0000000..24502a9 --- /dev/null +++ b/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 diff --git a/node_modules/jsbn/README.md b/node_modules/jsbn/README.md new file mode 100644 index 0000000..62e8273 --- /dev/null +++ b/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 diff --git a/node_modules/jsbn/example.html b/node_modules/jsbn/example.html new file mode 100644 index 0000000..1c0489b --- /dev/null +++ b/node_modules/jsbn/example.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/node_modules/jsbn/example.js b/node_modules/jsbn/example.js new file mode 100644 index 0000000..8597990 --- /dev/null +++ b/node_modules/jsbn/example.js @@ -0,0 +1,5 @@ +(function () { + var BigInteger = jsbn.BigInteger; + var a = new BigInteger('91823918239182398123'); + console.log(a.bitLength()); +}()); diff --git a/node_modules/jsbn/index.js b/node_modules/jsbn/index.js new file mode 100644 index 0000000..e9eb697 --- /dev/null +++ b/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<= 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))<>(this.DB-sh)); + } + else + this[this.t-1] |= x<= 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)< 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< 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+=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<= 0; --i) { + r[i+ds+1] = (this[i]>>cbs)|c; + c = (this[i]&bm)<= 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; + for(var i = ds+1; i < this.t; ++i) { + r[i-ds-1] |= (this[i]&bm)<>bs; + } + if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<>= 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<1)?y[ys-2]>>this.F2:0); + var d1 = this.FV/yt, d2 = (1<= 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< 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))<>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< 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+=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<>= 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< 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< 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 + // + // 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); diff --git a/node_modules/jsbn/package.json b/node_modules/jsbn/package.json new file mode 100644 index 0000000..97b137c --- /dev/null +++ b/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" +} diff --git a/node_modules/jsbn/test/es6-import.js b/node_modules/jsbn/test/es6-import.js new file mode 100644 index 0000000..668cbdf --- /dev/null +++ b/node_modules/jsbn/test/es6-import.js @@ -0,0 +1,3 @@ +import {BigInteger} from '../'; + +console.log(typeof BigInteger) diff --git a/node_modules/sm-crypto/.babelrc b/node_modules/sm-crypto/.babelrc new file mode 100644 index 0000000..dc1bc4f --- /dev/null +++ b/node_modules/sm-crypto/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["es2015"] +} \ No newline at end of file diff --git a/node_modules/sm-crypto/.eslintrc.js b/node_modules/sm-crypto/.eslintrc.js new file mode 100644 index 0000000..a23efe2 --- /dev/null +++ b/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 + } +} diff --git a/node_modules/sm-crypto/CHANGELOG.md b/node_modules/sm-crypto/CHANGELOG.md new file mode 100644 index 0000000..a9f8f8a --- /dev/null +++ b/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 支持输入输出为字符串 diff --git a/node_modules/sm-crypto/LICENCE_MIT b/node_modules/sm-crypto/LICENCE_MIT new file mode 100644 index 0000000..09149e1 --- /dev/null +++ b/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. \ No newline at end of file diff --git a/node_modules/sm-crypto/README.md b/node_modules/sm-crypto/README.md new file mode 100644 index 0000000..2a0b0d1 --- /dev/null +++ b/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 diff --git a/node_modules/sm-crypto/dist/sm2.js b/node_modules/sm-crypto/dist/sm2.js new file mode 100644 index 0000000..93e7a4a --- /dev/null +++ b/node_modules/sm-crypto/dist/sm2.js @@ -0,0 +1 @@ +!function(t,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define([],r):"object"==typeof exports?exports.sm2=r():t.sm2=r()}("undefined"!=typeof self?self:this,function(){return function(t){function r(e){if(i[e])return i[e].exports;var n=i[e]={i:e,l:!1,exports:{}};return t[e].call(n.exports,n,n.exports,r),n.l=!0,n.exports}var i={};return r.m=t,r.c=i,r.d=function(t,i,e){r.o(t,i)||Object.defineProperty(t,i,{configurable:!1,enumerable:!0,get:e})},r.n=function(t){var i=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(i,"a",i),i},r.o=function(t,r){return Object.prototype.hasOwnProperty.call(t,r)},r.p="",r(r.s=2)}([function(t,r,i){(function(){function i(t,r,i){null!=t&&("number"==typeof t?this.fromNumber(t,r,i):null==r&&"string"!=typeof t?this.fromString(t,256):this.fromString(t,r))}function e(){return new i(null)}function n(t,r,i,e,n,o){for(;--o>=0;){var s=r*this[t++]+i[e]+n;n=Math.floor(s/67108864),i[e++]=67108863&s}return n}function o(t,r,i,e,n,o){for(var s=32767&r,u=r>>15;--o>=0;){var h=32767&this[t],a=this[t++]>>15,f=u*h+a*s;h=s*h+((32767&f)<<15)+i[e]+(1073741823&n),n=(h>>>30)+(f>>>15)+u*a+(n>>>30),i[e++]=1073741823&h}return n}function s(t,r,i,e,n,o){for(var s=16383&r,u=r>>14;--o>=0;){var h=16383&this[t],a=this[t++]>>14,f=u*h+a*s;h=s*h+((16383&f)<<14)+i[e]+n,n=(h>>28)+(f>>14)+u*a,i[e++]=268435455&h}return n}function u(t){return pr.charAt(t)}function h(t,r){var i=vr[t.charCodeAt(r)];return null==i?-1:i}function a(t){for(var r=this.t-1;r>=0;--r)t[r]=this[r];t.t=this.t,t.s=this.s}function f(t){this.t=1,this.s=t<0?-1:0,t>0?this[0]=t:t<-1?this[0]=t+this.DV:this.t=0}function l(t){var r=e();return r.fromInt(t),r}function c(t,r){var e;if(16==r)e=4;else if(8==r)e=3;else if(256==r)e=8;else if(2==r)e=1;else if(32==r)e=5;else{if(4!=r)return void this.fromRadix(t,r);e=2}this.t=0,this.s=0;for(var n=t.length,o=!1,s=0;--n>=0;){var u=8==e?255&t[n]:h(t,n);u<0?"-"==t.charAt(n)&&(o=!0):(o=!1,0==s?this[this.t++]=u:s+e>this.DB?(this[this.t-1]|=(u&(1<>this.DB-s):this[this.t-1]|=u<=this.DB&&(s-=this.DB))}8==e&&0!=(128&t[0])&&(this.s=-1,s>0&&(this[this.t-1]|=(1<0&&this[this.t-1]==t;)--this.t}function v(t){if(this.s<0)return"-"+this.negate().toString(t);var r;if(16==t)r=4;else if(8==t)r=3;else if(2==t)r=1;else if(32==t)r=5;else{if(4!=t)return this.toRadix(t);r=2}var i,e=(1<0)for(h>h)>0&&(n=!0,o=u(i));s>=0;)h>(h+=this.DB-r)):(i=this[s]>>(h-=r)&e,h<=0&&(h+=this.DB,--s)),i>0&&(n=!0),n&&(o+=u(i));return n?o:"0"}function y(){var t=e();return i.ZERO.subTo(this,t),t}function m(){return this.s<0?this.negate():this}function d(t){var r=this.s-t.s;if(0!=r)return r;var i=this.t;if(0!=(r=i-t.t))return this.s<0?-r:r;for(;--i>=0;)if(0!=(r=this[i]-t[i]))return r;return 0}function g(t){var r,i=1;return 0!=(r=t>>>16)&&(t=r,i+=16),0!=(r=t>>8)&&(t=r,i+=8),0!=(r=t>>4)&&(t=r,i+=4),0!=(r=t>>2)&&(t=r,i+=2),0!=(r=t>>1)&&(t=r,i+=1),i}function T(){return this.t<=0?0:this.DB*(this.t-1)+g(this[this.t-1]^this.s&this.DM)}function F(t,r){var i;for(i=this.t-1;i>=0;--i)r[i+t]=this[i];for(i=t-1;i>=0;--i)r[i]=0;r.t=this.t+t,r.s=this.s}function b(t,r){for(var i=t;i=0;--i)r[i+s+1]=this[i]>>n|u,u=(this[i]&o)<=0;--i)r[i]=0;r[s]=u,r.t=this.t+s+1,r.s=this.s,r.clamp()}function B(t,r){r.s=this.s;var i=Math.floor(t/this.DB);if(i>=this.t)return void(r.t=0);var e=t%this.DB,n=this.DB-e,o=(1<>e;for(var s=i+1;s>e;e>0&&(r[this.t-i-1]|=(this.s&o)<>=this.DB;if(t.t>=this.DB;e+=this.s}else{for(e+=this.s;i>=this.DB;e-=t.s}r.s=e<0?-1:0,e<-1?r[i++]=this.DV+e:e>0&&(r[i++]=e),r.t=i,r.clamp()}function D(t,r){var e=this.abs(),n=t.abs(),o=e.t;for(r.t=o+n.t;--o>=0;)r[o]=0;for(o=0;o=0;)t[i]=0;for(i=0;i=r.DV&&(t[i+r.t]-=r.DV,t[i+r.t+1]=1)}t.t>0&&(t[t.t-1]+=r.am(i,r[i],t,2*i,0,1)),t.s=0,t.clamp()}function q(t,r,n){var o=t.abs();if(!(o.t<=0)){var s=this.abs();if(s.t0?(o.lShiftTo(f,u),s.lShiftTo(f,n)):(o.copyTo(u),s.copyTo(n));var l=u.t,c=u[l-1];if(0!=c){var p=c*(1<1?u[l-2]>>this.F2:0),v=this.FV/p,y=(1<=0&&(n[n.t++]=1,n.subTo(F,n)),i.ONE.dlShiftTo(l,F),F.subTo(u,u);u.t=0;){var b=n[--d]==c?this.DM:Math.floor(n[d]*v+(n[d-1]+m)*y);if((n[d]+=u.am(0,b,n,T,0,l))0&&n.rShiftTo(f,n),h<0&&i.ZERO.subTo(n,n)}}}function S(t){var r=e();return this.abs().divRemTo(t,null,r),this.s<0&&r.compareTo(i.ZERO)>0&&t.subTo(r,r),r}function E(t){this.m=t}function A(t){return t.s<0||t.compareTo(this.m)>=0?t.mod(this.m):t}function P(t){return t}function O(t){t.divRemTo(this.m,null,t)}function R(t,r,i){t.multiplyTo(r,i),this.reduce(i)}function M(t,r){t.squareTo(r),this.reduce(r)}function C(){if(this.t<1)return 0;var t=this[0];if(0==(1&t))return 0;var r=3&t;return r=r*(2-(15&t)*r)&15,r=r*(2-(255&t)*r)&255,r=r*(2-((65535&t)*r&65535))&65535,r=r*(2-t*r%this.DV)%this.DV,r>0?this.DV-r:-r}function H(t){this.m=t,this.mp=t.invDigit(),this.mpl=32767&this.mp,this.mph=this.mp>>15,this.um=(1<0&&this.m.subTo(r,r),r}function V(t){var r=e();return t.copyTo(r),this.reduce(r),r}function N(t){for(;t.t<=this.mt2;)t[t.t++]=0;for(var r=0;r>15)*this.mpl&this.um)<<15)&t.DM;for(i=r+this.m.t,t[i]+=this.m.am(0,e,t,r,0,this.m.t);t[i]>=t.DV;)t[i]-=t.DV,t[++i]++}t.clamp(),t.drShiftTo(this.m.t,t),t.compareTo(this.m)>=0&&t.subTo(this.m,t)}function j(t,r){t.squareTo(r),this.reduce(r)}function L(t,r,i){t.multiplyTo(r,i),this.reduce(i)}function z(){return 0==(this.t>0?1&this[0]:this.s)}function K(t,r){if(t>4294967295||t<1)return i.ONE;var n=e(),o=e(),s=r.convert(this),u=g(t)-1;for(s.copyTo(n);--u>=0;)if(r.sqrTo(n,o),(t&1<0)r.mulTo(o,s,n);else{var h=n;n=o,o=h}return r.revert(n)}function Z(t,r){var i;return i=t<256||r.isEven()?new E(r):new H(r),this.exp(t,i)}function U(){var t=e();return this.copyTo(t),t}function _(){if(this.s<0){if(1==this.t)return this[0]-this.DV;if(0==this.t)return-1}else{if(1==this.t)return this[0];if(0==this.t)return 0}return(this[1]&(1<<32-this.DB)-1)<>24}function Y(){return 0==this.t?this.s:this[0]<<16>>16}function G(t){return Math.floor(Math.LN2*this.DB/Math.log(t))}function J(){return this.s<0?-1:this.t<=0||1==this.t&&this[0]<=0?0:1}function Q(t){if(null==t&&(t=10),0==this.signum()||t<2||t>36)return"0";var r=this.chunkSize(t),i=Math.pow(t,r),n=l(i),o=e(),s=e(),u="";for(this.divRemTo(n,o,s);o.signum()>0;)u=(i+s.intValue()).toString(t).substr(1)+u,o.divRemTo(n,o,s);return s.intValue().toString(t)+u}function W(t,r){this.fromInt(0),null==r&&(r=10);for(var e=this.chunkSize(r),n=Math.pow(r,e),o=!1,s=0,u=0,a=0;a=e&&(this.dMultiply(n),this.dAddOffset(u,0),s=0,u=0))}s>0&&(this.dMultiply(Math.pow(r,s)),this.dAddOffset(u,0)),o&&i.ZERO.subTo(this,this)}function $(t,r,e){if("number"==typeof r)if(t<2)this.fromInt(1);else for(this.fromNumber(t,e),this.testBit(t-1)||this.bitwiseTo(i.ONE.shiftLeft(t-1),ut,this),this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(r);)this.dAddOffset(2,0),this.bitLength()>t&&this.subTo(i.ONE.shiftLeft(t-1),this);else{var n=new Array,o=7&t;n.length=1+(t>>3),r.nextBytes(n),o>0?n[0]&=(1<0)for(e>e)!=(this.s&this.DM)>>e&&(r[n++]=i|this.s<=0;)e<8?(i=(this[t]&(1<>(e+=this.DB-8)):(i=this[t]>>(e-=8)&255,e<=0&&(e+=this.DB,--t)),0!=(128&i)&&(i|=-256),0==n&&(128&this.s)!=(128&i)&&++n,(n>0||i!=this.s)&&(r[n++]=i);return r}function rt(t){return 0==this.compareTo(t)}function it(t){return this.compareTo(t)<0?this:t}function et(t){return this.compareTo(t)>0?this:t}function nt(t,r,i){var e,n,o=Math.min(t.t,this.t);for(e=0;e>=16,r+=16),0==(255&t)&&(t>>=8,r+=8),0==(15&t)&&(t>>=4,r+=4),0==(3&t)&&(t>>=2,r+=2),0==(1&t)&&++r,r}function dt(){for(var t=0;t=this.t?0!=this.s:0!=(this[r]&1<>=this.DB;if(t.t>=this.DB;e+=this.s}else{for(e+=this.s;i>=this.DB;e+=t.s}r.s=e<0?-1:0,e>0?r[i++]=e:e<-1&&(r[i++]=this.DV+e),r.t=i,r.clamp()}function It(t){var r=e();return this.addTo(t,r),r}function qt(t){var r=e();return this.subTo(t,r),r}function St(t){var r=e();return this.multiplyTo(t,r),r}function Et(){var t=e();return this.squareTo(t),t}function At(t){var r=e();return this.divRemTo(t,r,null),r}function Pt(t){var r=e();return this.divRemTo(t,null,r),r}function Ot(t){var r=e(),i=e();return this.divRemTo(t,r,i),new Array(r,i)}function Rt(t){this[this.t]=this.am(0,t-1,this,0,0,this.t),++this.t,this.clamp()}function Mt(t,r){if(0!=t){for(;this.t<=r;)this[this.t++]=0;for(this[r]+=t;this[r]>=this.DV;)this[r]-=this.DV,++r>=this.t&&(this[this.t++]=0),++this[r]}}function Ct(){}function Ht(t){return t}function kt(t,r,i){t.multiplyTo(r,i)}function Vt(t,r){t.squareTo(r)}function Nt(t){return this.exp(t,new Ct)}function jt(t,r,i){var e=Math.min(this.t+t.t,r);for(i.s=0,i.t=e;e>0;)i[--e]=0;var n;for(n=i.t-this.t;e=0;)i[e]=0;for(e=Math.max(r-this.t,0);e2*this.m.t)return t.mod(this.m);if(t.compareTo(this.m)<0)return t;var r=e();return t.copyTo(r),this.reduce(r),r}function Zt(t){return t}function Ut(t){for(t.drShiftTo(this.m.t-1,this.r2),t.t>this.m.t+1&&(t.t=this.m.t+1,t.clamp()),this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3),this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);t.compareTo(this.r2)<0;)t.dAddOffset(1,this.m.t+1);for(t.subTo(this.r2,t);t.compareTo(this.m)>=0;)t.subTo(this.m,t)}function _t(t,r){t.squareTo(r),this.reduce(r)}function Xt(t,r,i){t.multiplyTo(r,i),this.reduce(i)}function Yt(t,r){var i,n,o=t.bitLength(),s=l(1);if(o<=0)return s;i=o<18?1:o<48?3:o<144?4:o<768?5:6,n=o<8?new E(r):r.isEven()?new zt(r):new H(r);var u=new Array,h=3,a=i-1,f=(1<1){var c=e();for(n.sqrTo(u[1],c);h<=f;)u[h]=e(),n.mulTo(c,u[h-2],u[h]),h+=2}var p,v,y=t.t-1,m=!0,d=e();for(o=g(t[y])-1;y>=0;){for(o>=a?p=t[y]>>o-a&f:(p=(t[y]&(1<0&&(p|=t[y-1]>>this.DB+o-a)),h=i;0==(1&p);)p>>=1,--h;if((o-=h)<0&&(o+=this.DB,--y),m)u[p].copyTo(s),m=!1;else{for(;h>1;)n.sqrTo(s,d),n.sqrTo(d,s),h-=2;h>0?n.sqrTo(s,d):(v=s,s=d,d=v),n.mulTo(d,u[p],s)}for(;y>=0&&0==(t[y]&1<0&&(r.rShiftTo(o,r),i.rShiftTo(o,i));r.signum()>0;)(n=r.getLowestSetBit())>0&&r.rShiftTo(n,r),(n=i.getLowestSetBit())>0&&i.rShiftTo(n,i),r.compareTo(i)>=0?(r.subTo(i,r),r.rShiftTo(1,r)):(i.subTo(r,i),i.rShiftTo(1,i));return o>0&&i.lShiftTo(o,i),i}function Jt(t){if(t<=0)return 0;var r=this.DV%t,i=this.s<0?t-1:0;if(this.t>0)if(0==r)i=this[0]%t;else for(var e=this.t-1;e>=0;--e)i=(r*i+this[e])%t;return i}function Qt(t){var r=t.isEven();if(this.isEven()&&r||0==t.signum())return i.ZERO;for(var e=t.clone(),n=this.clone(),o=l(1),s=l(0),u=l(0),h=l(1);0!=e.signum();){for(;e.isEven();)e.rShiftTo(1,e),r?(o.isEven()&&s.isEven()||(o.addTo(this,o),s.subTo(t,s)),o.rShiftTo(1,o)):s.isEven()||s.subTo(t,s),s.rShiftTo(1,s);for(;n.isEven();)n.rShiftTo(1,n),r?(u.isEven()&&h.isEven()||(u.addTo(this,u),h.subTo(t,h)),u.rShiftTo(1,u)):h.isEven()||h.subTo(t,h),h.rShiftTo(1,h);e.compareTo(n)>=0?(e.subTo(n,e),r&&o.subTo(u,o),s.subTo(h,s)):(n.subTo(e,n),r&&u.subTo(o,u),h.subTo(s,h))}return 0!=n.compareTo(i.ONE)?i.ZERO:h.compareTo(t)>=0?h.subtract(t):h.signum()<0?(h.addTo(t,h),h.signum()<0?h.add(t):h):h}function Wt(t){var r,i=this.abs();if(1==i.t&&i[0]<=yr[yr.length-1]){for(r=0;r>1)>yr.length&&(t=yr.length);for(var s=e(),u=0;u>8&255,gr[Tr++]^=t>>16&255,gr[Tr++]^=t>>24&255,Tr>=Br&&(Tr-=Br)}function rr(){tr((new Date).getTime())}function ir(){if(null==dr){for(rr(),dr=hr(),dr.init(gr),Tr=0;Tr>>8,gr[Tr++]=255&Fr;Tr=0,rr()}nr.prototype.nextBytes=er,or.prototype.init=sr,or.prototype.next=ur;var Br=256;r=t.exports={default:i,BigInteger:i,SecureRandom:nr}}).call(this)},function(t,r,i){"use strict";function e(t){if(Array.isArray(t)){for(var r=0,i=Array(t.length);r>>32-i}function o(t,r){for(var i=[],e=t.length-1;e>=0;e--)i[e]=255&(t[e]^r[e]);return i}function s(t){return t^n(t,9)^n(t,17)}function u(t){return t^n(t,15)^n(t,23)}function h(t){var r=8*t.length,i=r%512;i=i>=448?512-i%448-1:448-i-1;for(var o=new Array((i-7)/8),h=new Array(8),a=0,c=o.length;a=0;y--)if(r.length>8){var m=r.length-8;h[y]=parseInt(r.substr(m),2),r=r.substr(0,m)}else r.length>0&&(h[y]=parseInt(r,2),r="");for(var d=new Uint8Array([].concat(e(t),[128],o,h)),g=new DataView(d.buffer,0),T=d.length/64,F=new Uint32Array([1937774191,1226093241,388252375,3666478592,2842636476,372324522,3817729613,2969243214]),b=0;b=0&&N<=15?2043430169:2055708042,M=n(n(I,12)+A+n(V,N),7),C=M^n(I,12),H=(N>=0&&N<=15?I^q^S:I&q|I&S|q&S)+E+C+l[N],k=(N>=0&&N<=15?A^P^O:A&P|~A&O)+R+M+f[N],E=S,S=n(q,9),q=I,I=H,R=O,O=n(P,19),P=A,A=s(k);F[0]^=I,F[1]^=q,F[2]^=S,F[3]^=E,F[4]^=A,F[5]^=P,F[6]^=O,F[7]^=R}for(var j=[],L=0,z=F.length;L>>24,(16711680&K)>>>16,(65280&K)>>>8,255&K)}return j}function a(t,r){for(r.length>c&&(r=h(r));r.length2&&void 0!==arguments[2]?arguments[2]:1;t="string"==typeof t?m.hexToArray(m.utf8ToHex(t)):Array.prototype.slice.call(t),r=m.getGlobalCurve().decodePointHex(r);var n=m.generateKeyPairHex(),o=new c(n.privateKey,16),s=n.publicKey;s.length>128&&(s=s.substr(s.length-128));var u=r.multiply(o),h=m.hexToArray(m.leftPad(u.getX().toBigInteger().toRadix(16),64)),a=m.hexToArray(m.leftPad(u.getY().toBigInteger().toRadix(16),64)),f=m.arrayToHex(d([].concat(h,t,a))),l=1,p=0,v=[],y=[].concat(h,a),g=function(){v=d([].concat(e(y),[l>>24&255,l>>16&255,l>>8&255,255&l])),l++,p=0};g();for(var T=0,F=t.length;T2&&void 0!==arguments[2]?arguments[2]:1,n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},o=n.output,s=void 0===o?"string":o;r=new c(r,16);var u=t.substr(128,64),h=t.substr(192);i===w&&(u=t.substr(t.length-64),h=t.substr(128,t.length-128-64));var a=m.hexToArray(h),f=m.getGlobalCurve().decodePointHex("04"+t.substr(0,128)),l=f.multiply(r),p=m.hexToArray(m.leftPad(l.getX().toBigInteger().toRadix(16),64)),v=m.hexToArray(m.leftPad(l.getY().toBigInteger().toRadix(16),64)),y=1,g=0,T=[],F=[].concat(p,v),b=function(){T=d([].concat(e(F),[y>>24&255,y>>16&255,y>>8&255,255&y])),y++,g=0};b();for(var B=0,x=a.length;B2&&void 0!==arguments[2]?arguments[2]:{},e=i.pointPool,n=i.der,o=i.hash,s=i.publicKey,u=i.userId,l="string"==typeof t?m.utf8ToHex(t):m.arrayToHex(t);o&&(s=s||a(r),l=h(l,s,u));var p=new c(r,16),y=new c(l,16),d=null,g=null,T=null;do{do{var F=void 0;F=e&&e.length?e.pop():f(),d=F.k,g=y.add(F.x1).mod(b)}while(g.equals(c.ZERO)||g.add(d).equals(b));T=p.add(c.ONE).modInverse(b).multiply(d.subtract(g.multiply(p))).mod(b)}while(T.equals(c.ZERO));return n?v(g,T):m.leftPad(g.toString(16),64)+m.leftPad(T.toString(16),64)}function u(t,r,i){var e=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},n=e.der,o=e.hash,s=e.userId,u="string"==typeof t?m.utf8ToHex(t):m.arrayToHex(t);o&&(u=h(u,i,s));var a=void 0,f=void 0;if(n){var l=y(r);a=l.r,f=l.s}else a=new c(r.substring(0,64),16),f=new c(r.substring(64),16);var p=F.decodePointHex(i),v=new c(u,16),d=a.add(f).mod(b);if(d.equals(c.ZERO))return!1;var g=T.multiply(f).add(p.multiply(d)),w=v.add(g.getX().toBigInteger()).mod(b);return a.equals(w)}function h(t,r){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"1234567812345678";i=m.utf8ToHex(i);var e=m.leftPad(T.curve.a.toBigInteger().toRadix(16),64),n=m.leftPad(T.curve.b.toBigInteger().toRadix(16),64),o=m.leftPad(T.getX().toBigInteger().toRadix(16),64),s=m.leftPad(T.getY().toBigInteger().toRadix(16),64),u=void 0,h=void 0;if(128===r.length)u=r.substr(0,64),h=r.substr(64,64);else{var a=T.curve.decodePointHex(r);u=m.leftPad(a.getX().toBigInteger().toRadix(16),64),h=m.leftPad(a.getY().toBigInteger().toRadix(16),64)}var f=m.hexToArray(i+e+n+o+s+u+h),l=4*i.length;f.unshift(255&l),f.unshift(l>>8&255);var c=d(f);return m.arrayToHex(d(c.concat(m.hexToArray(t))))}function a(t){var r=T.multiply(new c(t,16));return"04"+m.leftPad(r.getX().toBigInteger().toString(16),64)+m.leftPad(r.getY().toBigInteger().toString(16),64)}function f(){var t=m.generateKeyPairHex(),r=F.decodePointHex(t.publicKey);return t.k=new c(t.privateKey,16),t.x1=r.getX().toBigInteger(),t}var l=i(0),c=l.BigInteger,p=i(3),v=p.encodeDer,y=p.decodeDer,m=i(4),d=i(1).sm3,g=m.generateEcparam(),T=g.G,F=g.curve,b=g.n,w=0;t.exports={generateKeyPairHex:m.generateKeyPairHex,compressPublicKeyHex:m.compressPublicKeyHex,comparePublicKeyHex:m.comparePublicKeyHex,doEncrypt:n,doDecrypt:o,doSignature:s,doVerifySignature:u,getPublicKeyFromPrivateKey:a,getPoint:f,verifyPublicKey:m.verifyPublicKey}},function(t,r,i){"use strict";function e(t,r){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!r||"object"!=typeof r&&"function"!=typeof r?t:r}function n(t,r){if("function"!=typeof r&&null!==r)throw new TypeError("Super expression must either be null or a function, not "+typeof r);t.prototype=Object.create(r&&r.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),r&&(Object.setPrototypeOf?Object.setPrototypeOf(t,r):t.__proto__=r)}function o(t,r){if(!(t instanceof r))throw new TypeError("Cannot call a class as a function")}function s(t){var r=t.toString(16);if("-"!==r[0])r.length%2==1?r="0"+r:r.match(/^[0-7]/)||(r="00"+r);else{r=r.substr(1);var i=r.length;i%2==1?i+=1:r.match(/^[0-7]/)||(i+=2);for(var e="",n=0;n>>2]|=(255&t.charCodeAt(e))<<24-e%4*8;for(var n=[],o=0;o>>2]>>>24-o%4*8&255;n.push((s>>>4).toString(16)),n.push((15&s).toString(16))}return n.join("")}function h(t,r){return t.length>=r?t:new Array(r-t.length+1).join("0")+t}function a(t){return t.map(function(t){return t=t.toString(16),1===t.length?"0"+t:t}).join("")}function f(t){for(var r=[],i=0,e=0;e<2*t.length;e+=2)r[e>>>3]|=parseInt(t[i],10)<<24-e%8*4,i++;try{for(var n=[],o=0;o>>2]>>>24-o%4*8&255;n.push(String.fromCharCode(s))}return decodeURIComponent(escape(n.join("")))}catch(t){throw new Error("Malformed UTF-8 data")}}function l(t){var r=[],i=t.length;i%2!=0&&(t=h(t,i+1)),i=t.length;for(var e=0;e0;n--){e=e.twice();var o=r.testBit(n);o!==t.testBit(n)&&(e=e.add(o?this:i))}return e}}]),t}(),l=function(){function t(r,i,n){e(this,t),this.q=r,this.a=this.fromBigInteger(i),this.b=this.fromBigInteger(n),this.infinity=new f(this,null,null)}return n(t,[{key:"equals",value:function(t){return t===this||this.q.equals(t.q)&&this.a.equals(t.a)&&this.b.equals(t.b)}},{key:"fromBigInteger",value:function(t){return new a(this.q,t)}},{key:"decodePointHex",value:function(t){switch(parseInt(t.substr(0,2),16)){case 0:return this.infinity;case 2:case 3:var r=this.fromBigInteger(new s(t.substr(2),16)),i=this.fromBigInteger(r.multiply(r.square()).add(r.multiply(this.a)).add(this.b).toBigInteger().modPow(this.q.divide(new s("4")).add(s.ONE),this.q));return i.toBigInteger().mod(u).equals(new s(t.substr(0,2),16).subtract(u))||(i=i.negate()),new f(this,r,i);case 4:case 6:case 7:var e=(t.length-2)/2,n=t.substr(2,e),o=t.substr(e+2,e);return new f(this,this.fromBigInteger(new s(n,16)),this.fromBigInteger(new s(o,16)));default:return null}}}]),t}();t.exports={ECPointFp:f,ECCurveFp:l}}])}); \ No newline at end of file diff --git a/node_modules/sm-crypto/dist/sm3.js b/node_modules/sm-crypto/dist/sm3.js new file mode 100644 index 0000000..67a7028 --- /dev/null +++ b/node_modules/sm-crypto/dist/sm3.js @@ -0,0 +1 @@ +!function(r,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.sm3=n():r.sm3=n()}("undefined"!=typeof self?self:this,function(){return function(r){function n(e){if(t[e])return t[e].exports;var o=t[e]={i:e,l:!1,exports:{}};return r[e].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var t={};return n.m=r,n.c=t,n.d=function(r,t,e){n.o(r,t)||Object.defineProperty(r,t,{configurable:!1,enumerable:!0,get:e})},n.n=function(r){var t=r&&r.__esModule?function(){return r.default}:function(){return r};return n.d(t,"a",t),t},n.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},n.p="",n(n.s=6)}({1:function(r,n,t){"use strict";function e(r){if(Array.isArray(r)){for(var n=0,t=Array(r.length);n>>32-t}function u(r,n){for(var t=[],e=r.length-1;e>=0;e--)t[e]=255&(r[e]^n[e]);return t}function i(r){return r^o(r,9)^o(r,17)}function f(r){return r^o(r,15)^o(r,23)}function a(r){var n=8*r.length,t=n%512;t=t>=448?512-t%448-1:448-t-1;for(var u=new Array((t-7)/8),a=new Array(8),s=0,p=u.length;s=0;y--)if(n.length>8){var g=n.length-8;a[y]=parseInt(n.substr(g),2),n=n.substr(0,g)}else n.length>0&&(a[y]=parseInt(n,2),n="");for(var d=new Uint8Array([].concat(e(r),[128],u,a)),w=new DataView(d.buffer,0),m=d.length/64,A=new Uint32Array([1937774191,1226093241,388252375,3666478592,2842636476,372324522,3817729613,2969243214]),b=0;b=0&&F<=15?2043430169:2055708042,V=o(o(I,12)+S+o(C,F),7),q=V^o(I,12),z=(F>=0&&F<=15?I^O^P:I&O|I&P|O&P)+k+q+l[F],B=(F>=0&&F<=15?S^_^D:S&_|~S&D)+M+V+c[F],k=P,P=o(O,9),O=I,I=z,M=D,D=o(_,19),_=S,S=i(B);A[0]^=I,A[1]^=O,A[2]^=P,A[3]^=k,A[4]^=S,A[5]^=_,A[6]^=D,A[7]^=M}for(var G=[],H=0,J=A.length;H>>24,(16711680&K)>>>16,(65280&K)>>>8,255&K)}return G}function s(r,n){for(n.length>p&&(n=a(n));n.length=n?r:new Array(n-r.length+1).join("0")+r}function o(r){return r.map(function(r){return r=r.toString(16),1===r.length?"0"+r:r}).join("")}function u(r){var n=[],t=r.length;t%2!=0&&(r=e(r,t+1)),t=r.length;for(var o=0;o>>6),n.push(128|63&o);else if(o<=55295||o>=57344&&o<=65535)n.push(224|o>>>12),n.push(128|o>>>6&63),n.push(128|63&o);else{if(!(o>=65536&&o<=1114111))throw n.push(o),new Error("input is not supported");t++,n.push(240|o>>>18&28),n.push(128|o>>>12&63),n.push(128|o>>>6&63),n.push(128|63&o)}}return n}var f=t(1),a=f.sm3,s=f.hmac;r.exports=function(r,n){if(r="string"==typeof r?i(r):Array.prototype.slice.call(r),n){if("hmac"!==(n.mode||"hmac"))throw new Error("invalid mode");var t=n.key;if(!t)throw new Error("invalid key");return t="string"==typeof t?u(t):Array.prototype.slice.call(t),o(s(r,t))}return o(a(r))}}})}); \ No newline at end of file diff --git a/node_modules/sm-crypto/dist/sm4.js b/node_modules/sm-crypto/dist/sm4.js new file mode 100644 index 0000000..16b7c9f --- /dev/null +++ b/node_modules/sm-crypto/dist/sm4.js @@ -0,0 +1 @@ +!function(r,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.sm4=n():r.sm4=n()}("undefined"!=typeof self?self:this,function(){return function(r){function n(e){if(t[e])return t[e].exports;var o=t[e]={i:e,l:!1,exports:{}};return r[e].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var t={};return n.m=r,n.c=t,n.d=function(r,t,e){n.o(r,t)||Object.defineProperty(r,t,{configurable:!1,enumerable:!0,get:e})},n.n=function(r){var t=r&&r.__esModule?function(){return r.default}:function(){return r};return n.d(t,"a",t),t},n.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},n.p="",n(n.s=7)}({7:function(r,n,t){"use strict";function e(r){if(Array.isArray(r)){for(var n=0,t=Array(r.length);n>>6),n.push(128|63&o);else if(o<=55295||o>=57344&&o<=65535)n.push(224|o>>>12),n.push(128|o>>>6&63),n.push(128|63&o);else{if(!(o>=65536&&o<=1114111))throw n.push(o),new Error("input is not supported");t++,n.push(240|o>>>18&28),n.push(128|o>>>12&63),n.push(128|o>>>6&63),n.push(128|63&o)}}return n}function f(r){for(var n=[],t=0,e=r.length;t=240&&r[t]<=247?(n.push(String.fromCodePoint(((7&r[t])<<18)+((63&r[t+1])<<12)+((63&r[t+2])<<6)+(63&r[t+3]))),t+=3):r[t]>=224&&r[t]<=239?(n.push(String.fromCodePoint(((15&r[t])<<12)+((63&r[t+1])<<6)+(63&r[t+2]))),t+=2):r[t]>=192&&r[t]<=223?(n.push(String.fromCodePoint(((31&r[t])<<6)+(63&r[t+1]))),t++):n.push(String.fromCodePoint(r[t]));return n.join("")}function s(r,n){var t=31&n;return r<>>32-t}function c(r){return(255&w[r>>>24&255])<<24|(255&w[r>>>16&255])<<16|(255&w[r>>>8&255])<<8|255&w[255&r]}function p(r){return r^s(r,2)^s(r,10)^s(r,18)^s(r,24)}function a(r){return r^s(r,13)^s(r,23)}function h(r,n,t){for(var e=new Array(4),o=new Array(4),i=0;i<4;i++)o[0]=255&r[4*i],o[1]=255&r[4*i+1],o[2]=255&r[4*i+2],o[3]=255&r[4*i+3],e[i]=o[0]<<24|o[1]<<16|o[2]<<8|o[3];for(var u,f=0;f<32;f+=4)u=e[1]^e[2]^e[3]^t[f+0],e[0]^=p(c(u)),u=e[2]^e[3]^e[0]^t[f+1],e[1]^=p(c(u)),u=e[3]^e[0]^e[1]^t[f+2],e[2]^=p(c(u)),u=e[0]^e[1]^e[2]^t[f+3],e[3]^=p(c(u));for(var s=0;s<16;s+=4)n[s]=e[3-s/4]>>>24&255,n[s+1]=e[3-s/4]>>>16&255,n[s+2]=e[3-s/4]>>>8&255,n[s+3]=255&e[3-s/4]}function l(r,n,t){for(var e=new Array(4),o=new Array(4),i=0;i<4;i++)o[0]=255&r[0+4*i],o[1]=255&r[1+4*i],o[2]=255&r[2+4*i],o[3]=255&r[3+4*i],e[i]=o[0]<<24|o[1]<<16|o[2]<<8|o[3];e[0]^=2746333894,e[1]^=1453994832,e[2]^=1736282519,e[3]^=2993693404;for(var u,f=0;f<32;f+=4)u=e[1]^e[2]^e[3]^m[f+0],n[f+0]=e[0]^=a(c(u)),u=e[2]^e[3]^e[0]^m[f+1],n[f+1]=e[1]^=a(c(u)),u=e[3]^e[0]^e[1]^m[f+2],n[f+2]=e[2]^=a(c(u)),u=e[0]^e[1]^e[2]^m[f+3],n[f+3]=e[3]^=a(c(u));if(t===d)for(var s,p=0;p<16;p++)s=n[p],n[p]=n[31-p],n[31-p]=s}function v(r,n,t){var s=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},c=s.padding,p=void 0===c?"pkcs#7":c,a=s.mode,v=s.iv,w=void 0===v?[]:v,m=s.output,b=void 0===m?"string":m;if("cbc"===a&&("string"==typeof w&&(w=o(w)),16!==w.length))throw new Error("iv is invalid");if("string"==typeof n&&(n=o(n)),16!==n.length)throw new Error("key is invalid");if(r="string"==typeof r?t!==d?u(r):o(r):[].concat(e(r)),("pkcs#5"===p||"pkcs#7"===p)&&t!==d)for(var A=y-r.length%y,x=0;x=y;){var E=r.slice(C,C+16),O=new Array(16);if("cbc"===a)for(var _=0;_ 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} + } +} diff --git a/node_modules/sm-crypto/src/sm2/ec.js b/node_modules/sm-crypto/src/sm2/ec.js new file mode 100755 index 0000000..4ca92c9 --- /dev/null +++ b/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, +} diff --git a/node_modules/sm-crypto/src/sm2/index.js b/node_modules/sm-crypto/src/sm2/index.js new file mode 100644 index 0000000..c08e759 --- /dev/null +++ b/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, +} diff --git a/node_modules/sm-crypto/src/sm2/sm3.js b/node_modules/sm-crypto/src/sm2/sm3.js new file mode 100755 index 0000000..7cdcdb0 --- /dev/null +++ b/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, +} diff --git a/node_modules/sm-crypto/src/sm2/utils.js b/node_modules/sm-crypto/src/sm2/utils.js new file mode 100644 index 0000000..196659b --- /dev/null +++ b/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, +} diff --git a/node_modules/sm-crypto/src/sm3/index.js b/node_modules/sm-crypto/src/sm3/index.js new file mode 100644 index 0000000..48cbe1a --- /dev/null +++ b/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)) +} diff --git a/node_modules/sm-crypto/src/sm4/index.js b/node_modules/sm-crypto/src/sm4/index.js new file mode 100755 index 0000000..42b39b7 --- /dev/null +++ b/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) + } +} diff --git a/node_modules/sm-crypto/webpack.config.js b/node_modules/sm-crypto/webpack.config.js new file mode 100644 index 0000000..0d7c0de --- /dev/null +++ b/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(), + ] +}; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b72f450 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,40 @@ +{ + "name": "ks-app-employment-service", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "dependencies": { + "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/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" + } + } + }, + "dependencies": { + "jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + }, + "sm-crypto": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/sm-crypto/-/sm-crypto-0.3.13.tgz", + "integrity": "sha512-ztNF+pZq6viCPMA1A6KKu3bgpkmYti5avykRHbcFIdSipFdkVmfUw2CnpM2kBJyppIalqvczLNM3wR8OQ0pT5w==", + "requires": { + "jsbn": "^1.1.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..89c3c5c --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "sm-crypto": "^0.3.13" + } +} diff --git a/packageRc/api/company/index.js b/packageRc/api/company/index.js index 43a87c1..ba181c1 100644 --- a/packageRc/api/company/index.js +++ b/packageRc/api/company/index.js @@ -2,11 +2,513 @@ -import { post, get } from '../../utils/request.js' +// import { post, get } from '../../utils/request.js' -export function getPersonInfo(id) { - return get({ - url: `personnel/personBaseInfo/${id}`, +// export function getPersonInfo(id) { +// return get({ +// url: `personnel/personBaseInfo/${id}`, +// method: 'get' +// }) +// } + +import request from '@/utilsRc/request' + +// 根据 userId 获取企业详情 +export function companyDetails(userId) { + return request({ + method: 'get', + url: `/company/unitBaseInfo/user/${userId}`, + }) +} + +// 企业-推荐人员信息 +export function recommendedPerson(params) { + return request({ + url: '/company/unitBaseInfo/recommend/person', + method: 'get', + params + }) +} + +// 人员邀请 +export function invitePerson(params) { + return request({ + url: '/company/unitBaseInfo/invite', + method: 'get', + params + }) +} + +// 获取企业招聘岗位列表 +export function jobList(params) { + return request({ + url: '/company/unitPostInfo/list', + method: 'get', + params + }) +} + +// 查找已投递、已推荐、已邀请的人员信息 +export function listMatch(query) { + return request({ + url: '/company/unitBaseInfo/relevance', + method: 'get', + params: query + }) +} + +// 添加企业基本信息 +export function addJobBase(data) { + return request({ + url: '/company/unitBaseInfo', + method: 'post', + data: data + }) +} + +// 查询部门下拉树结构 +export function deptTreeSelect() { + return request({ + url: '/system/center/user/deptTree', method: 'get' }) -} \ No newline at end of file +} + +// 企业发布招聘岗位 +export function addJob(data) { + return request({ + url: '/company/unitPostInfo', + method: 'post', + data: data + }) +} + +// 获取招聘工种列表 +export function jobTypeList(params) { + return request({ + url: '/basicdata/workType/list', + method: 'get', + params + }) +} + +// 企业基本信息列表 +export function jobBaseList(query) { + return request({ + url: '/company/unitBaseInfo/list', + method: 'get', + params: query + }) +} + +// 获取企业招聘岗位信息详细信息 +export function getJob(id) { + return request({ + url: `/company/unitPostInfo/${id}`, + method: 'get' + }) +} +// 修改企业招聘岗位信息 +export function updateJob(data) { + return request({ + url: '/company/unitPostInfo', + method: 'put', + data: data + }) +} + +// 修改企业基本信息 +export function updateJobBase(data) { + return request({ + url: '/company/unitBaseInfo', + method: 'put', + data: data + }) +} +// 查询角色详细 +export function getJobService(id) { + return request({ + url: '/personnel/personBaseInfo/' + id, + method: 'get' + }) +} + +// 查询推荐人员、已推荐、已邀请 详情 +export function getUnitBaseInfo(id) { + return request({ + url: '/manage/personDemand/' + id, + method: 'get' + }) +} + + +// 查询工种列表 +export function listJobType(query) { + return request({ + url: '/basicdata/workType/list', + method: 'get', + params: query + }) +} + +// 人员基本信息 - 列表 +export function personInfoList(query) { + return request({ + url: '/personnel/personBaseInfo/list', + method: 'get', + params: query + }) +} + +// 获取人员基本信息详情 +export function getPersonInfo(id) { + return request({ + url: `/personnel/personBaseInfo/${id}`, + method: 'get' + }) +} + + +// 删除人员基本信息 +export function delPersonInfo(ids) { + return request({ + url: '/personnel/personBaseInfo/' + ids, + method: 'delete' + }) +} + +// 删除录入人员 公用 type = 1 失业中 2 就业困难 3 离校生 4 其他人员 +export function delPersonUser(ids) { + return request({ + url: `/personnel/personInputInfo/${ids}`, + method: 'delete', + }) +} + +// 新增人员基本信息 +export function addPersonInfo(data) { + return request({ + url: '/personnel/personBaseInfo', + method: 'post', + data: data + }) +} + +// 修改人员基本信息 +export function updatePersonInfo(data) { + return request({ + url: '/personnel/personBaseInfo', + method: 'put', + data + }) +} + +//社区人员审核 +export function personInfoAudit(data) { + return request({ + url: '/personnel/personBaseInfo/audit', + method: 'post', + data: data + }) +} + + +//记录查看身份证 +export function recordLookIdCard(params) { + return request({ + url: '/personnel/personBaseInfo/recordLookIdCard', + method: 'get', + params + }) +} + + + + +/* 失业人员 --------------------------------------------- start */ + +// 新增失业人员 +export function addPersonUnemployed(data) { + return request({ + url: '/person/unemployment', + method: 'post', + data + }) +} + +// 失业人员修改 +export function updatePersonUnemployed(data) { + return request({ + url: '/person/unemployment', + method: 'put', + data, + }) +} + +// 失业人员列表 +export function unemployment(params) { + return request({ + url: '/person/unemployment/list', + method: 'get', + params + }) +} + +// 失业人员详情 +export function unemploymentDetails(id) { + return request({ + url: `/person/unemployment/${id}`, + method: 'get', + }) +} + +// 失业人员删除 +export function unemploymentDelete(id) { + return request({ + url: `/person/unemployment/${id}`, + method: 'delete', + }) +} + +/* 失业人员 --------------------------------------------- end */ + + +/* 就业困难人员 --------------------------------------------- start */ + +// 新增就业困难 +export function addPersonDifficult(data) { + return request({ + url: '/person/findingEmployment', + method: 'post', + data + }) +} + +// 修改就业困难 +export function updatePersonDifficult(data) { + return request({ + url: '/person/findingEmployment', + method: 'put', + data + }) +} + +// 就业困难列表 +export function findingEmployment(params) { + return request({ + url: '/person/findingEmployment/list', + method: 'get', + params + }) +} + +// 就业困难详情 +export function findingEmploymentDetails(id) { + return request({ + url: `/person/findingEmployment/${id}`, + method: 'get', + }) +} + +// 就业困难删除 +export function findingEmploymentDelete(id) { + return request({ + url: `/person/findingEmployment/${id}`, + method: 'delete', + }) +} +/* 就业困难人员 --------------------------------------------- end */ + + +/* 离校未就业高校生 --------------------------------------------- start */ + +// 新增离校未就业高校生 +export function addLeaveSchool(data) { + return request({ + url: '/person/leavingSchoolInfo', + method: 'post', + data + }) +} + +// 修改离校未就业高校生 +export function updateLeaveSchool(data) { + return request({ + url: '/person/leavingSchoolInfo', + method: 'put', + data, + }) +} + +// 高校未就业列表 +export function leavingSchoolInfo(params) { + return request({ + url: '/person/leavingSchoolInfo/list', + method: 'get', + params + }) +} + +// 高校未就业详情 +export function leavingSchoolInfoDetails(id) { + return request({ + url: `/person/leavingSchoolInfo/${id}`, + method: 'get', + }) +} + + +// 高校未就业删除 +export function leavingSchoolInfoDelete(id) { + return request({ + url: `/person/leavingSchoolInfo/${id}`, + method: 'delete', + }) +} + + +/* 离校未就业高校生 --------------------------------------------- end */ + +/* 其他人员 --------------------------------------------- start */ + +// 新增其他人员 +export function addOther(data) { + return request({ + url: '/person/other', + method: 'post', + data + }) +} + +// 其他人员修改 +export function updateOther(data) { + return request({ + url: '/person/other', + method: 'post', + data, + }) +} + + +// 其他人员列表 +export function other(params) { + return request({ + url: '/person/other/list', + method: 'get', + params + }) +} + +// 其他人员详情 +export function otherDetails(id) { + return request({ + url: `/person/other/${id}`, + method: 'get', + }) +} + +// 其他人员删除 +export function otherDelete(id) { + return request({ + url: `/person/other/${id}`, + method: 'delete', + }) +} +/* 其他人员 --------------------------------------------- end */ + +// 需求预警列表 +export function personAlertList(params) { + return request({ + url: '/manage/personDemand/warningList', + method: 'get', + params + }) +} +export function personDealList(params) { + return request({ + url: '/manage/personDemand/dealingList', + method: 'get', + params + }) +} +// 服务追踪 服务类型/服务id +export function serviceTraceability({ + demandType, + id +}) { + return request({ + // url: `/system/personRequirementsRecords/serviceTraceability/${demandType}/${id}`, + url: `/timelime/timelime/fwzs/${id}`, + method: 'get', + }) +} + +// 需求办结 +export function requirementCompletion(url, data) { + return request({ + url, + method: 'post', + data + }) +} + +//岗位审核 +export function jobAudit(data) { + return request({ + url: '/company/unitPostInfo/audit', + method: 'post', + data: data + }) +} + +//社群 首页未完成数 +// export function getPeopleCount() { +// return request({ +// url: '/pc/index/getPeopleCount', +// method: 'get', +// }) +// } + +//社群 首页未完成数 +export function getDemandUnfinished() { + return request({ + url: '/pc/index/todo', + method: 'get', + }) +} + + + +// 删除企业招聘岗位信息 +export function delJob(ids) { + return request({ + url: '/company/unitPostInfo/' + ids, + method: 'delete' + }) +} + +// 所在社区列表 +export function deptList(params) { + return request({ + 'url': `/system/center/user/deptList`, + 'method': 'get', + params + }) +} + +// 所在社区列表 +export function returnPerson(params) { + return request({ + 'url': `/personnel/personBaseInfo/returnPerson`, + 'method': 'get', + params + }) +} +// 根据人的身份证查询人的详细信息 +export function getIdNumberInfo(params) { + return request({ + 'url': `/personnel/personBaseInfo/getIdNumberInfo`, + 'method': 'get', + params + }) +} diff --git a/packageRc/components/PopupLists.vue b/packageRc/components/PopupLists.vue new file mode 100644 index 0000000..589cf89 --- /dev/null +++ b/packageRc/components/PopupLists.vue @@ -0,0 +1,374 @@ + + + + + diff --git a/packageRc/components/exitPopup.vue b/packageRc/components/exitPopup.vue new file mode 100644 index 0000000..72e3f98 --- /dev/null +++ b/packageRc/components/exitPopup.vue @@ -0,0 +1,130 @@ + + + + + diff --git a/packageRc/pages/daiban/daiban.vue b/packageRc/pages/daiban/daiban.vue index dd7b396..943d1ef 100644 --- a/packageRc/pages/daiban/daiban.vue +++ b/packageRc/pages/daiban/daiban.vue @@ -1,9 +1,10 @@ + + diff --git a/pages.json b/pages.json index add44b6..f94ee61 100644 --- a/pages.json +++ b/pages.json @@ -402,12 +402,17 @@ { "navigationBarTitleText" : "高校毕业生智慧就业" } + } , { + "path": "pages/personalList/personalList", + "style": { + "navigationBarTitleText": "添加帮扶" + } },{ "path": "pages/daiban/daiban", "style": { - "navigationBarTitleText": "待办任务", - "navigationBarBackgroundColor": "#4778EC", - "navigationBarTextStyle": "white" + "navigationBarTitleText": "待办任务" + // "navigationBarBackgroundColor": "#4778EC", + // "navigationBarTextStyle": "white" } }, { diff --git a/unpackage/dist/dev/mp-weixin/project.config.json b/unpackage/dist/dev/mp-weixin/project.config.json index f6f97cf..b78e9f1 100644 --- a/unpackage/dist/dev/mp-weixin/project.config.json +++ b/unpackage/dist/dev/mp-weixin/project.config.json @@ -12,8 +12,8 @@ "bigPackageSizeSupport": true }, "compileType": "miniprogram", - "libVersion": "", - "appid": "wx42c70417d01ab767", + "libVersion": "3.5.7", + "appid": "wxc0f37e549415bb4e", "projectname": "qingdao-employment-service", "condition": { "search": { diff --git a/unpackage/dist/dev/mp-weixin/project.private.config.json b/unpackage/dist/dev/mp-weixin/project.private.config.json index 25e4cb8..75ae66b 100644 --- a/unpackage/dist/dev/mp-weixin/project.private.config.json +++ b/unpackage/dist/dev/mp-weixin/project.private.config.json @@ -8,6 +8,27 @@ "condition": { "miniprogram": { "list": [ + { + "name": "packageRc/pages/personalList/personalList", + "pathName": "packageRc/pages/personalList/personalList", + "query": "", + "launchMode": "default", + "scene": null + }, + { + "name": "packageRc/pages/daiban/daiban", + "pathName": "packageRc/pages/daiban/daiban", + "query": "", + "launchMode": "default", + "scene": null + }, + { + "name": "packageRc/pages/index/index", + "pathName": "packageRc/pages/index/index", + "query": "", + "launchMode": "default", + "scene": null + }, { "name": "packageB/pages/userCenter/personDocument", "pathName": "packageB/pages/userCenter/personDocument", diff --git a/utilsRc/auth.js b/utilsRc/auth.js new file mode 100644 index 0000000..1f5bb72 --- /dev/null +++ b/utilsRc/auth.js @@ -0,0 +1,19 @@ +/* + * @Descripttion: + * @Author: lip + * @Date: 2023-07-27 15:55:08 + * @LastEditors: lip + */ +const TokenKey = 'App-Token' + +export function getToken() { + return uni.getStorageSync(TokenKey) +} + +export function setToken(token) { + return uni.setStorageSync(TokenKey, token) +} + +export function removeToken() { + return uni.removeStorageSync(TokenKey) +} diff --git a/utilsRc/common.js b/utilsRc/common.js new file mode 100644 index 0000000..9d635c5 --- /dev/null +++ b/utilsRc/common.js @@ -0,0 +1,248 @@ +/* + * @Descripttion: + * @Author: lip + * @Date: 2023-07-27 15:56:06 + * @LastEditors: shirlwang + */ +import { + getPersonBase +} from '@/apiRc/person'; +import store from '@/utilsRc/store'; +import tab from '@/utilsRc/plugins/tab.js' +/** + * 显示消息提示框 + * @param content 提示的标题 + */ +export function toast(content) { + uni.showToast({ + icon: 'none', + title: content + }) +} + +/** + * 显示模态弹窗 + * @param content 提示的标题 + */ +export function showConfirm(content, cancelText, confirmText, showCancel) { + return new Promise((resolve, reject) => { + uni.showModal({ + title: '提示', + content: content, + cancelText: cancelText || '取消', + confirmText: confirmText || '确定', + showCancel: showCancel === false ? false : true, + success: function(res) { + resolve(res) + } + }) + }) +} +// 修改后的 checkPersonBase 方法 +export function checkPersonBase() { + return new Promise((resolve) => { + const roles = store.getters.roles; + const userId = store.getters.userId; + const isRole = (role) => roles.includes(role); + + if (isRole('qunzhong')) { + getPersonBase(userId).then(resp => { + const shouldGoToPersonInfo = resp.data.auditStatus === '0'; + if (shouldGoToPersonInfo) { + uni.showModal({ + title: '提示', + content: '您的个人信息尚未维护,请前往维护个人信息。', + confirmText: '去维护', + cancelText: '取消', + success: function(res) { + if (res.confirm) { + tab.navigateTo('/pages/personInfo/index'); + } + resolve(false); // 需要维护,返回 false + } + }); + } else { + resolve(true); // 不需要维护,返回 true + } + }); + } else { + resolve(true); // 非群众角色直接放行 + } + }); +} +/** + * 参数处理 + * @param params 参数 + */ +export function tansParams(params) { + let result = '' + for (const propName of Object.keys(params)) { + const value = params[propName] + var part = encodeURIComponent(propName) + "=" + if (value !== null && value !== "" && typeof(value) !== "undefined") { + if (typeof value === 'object') { + for (const key of Object.keys(value)) { + if (value[key] !== null && value[key] !== "" && typeof(value[key]) !== 'undefined') { + let params = propName + '[' + key + ']' + var subPart = encodeURIComponent(params) + "=" + result += subPart + encodeURIComponent(value[key]) + "&" + } + } + } else { + result += part + encodeURIComponent(value) + "&" + } + } + } + return result +} +/** + * 姓名、手机、邮箱、身份证脱敏 + * @param str 姓名或手机或邮箱或身份证 + * @param type 数据类型 + */ +export function publicEncrypt(str, type) { + if (!str) { + return '' + } else if (type == 'name') { + return str.substr(0, 1) + '*' + } else if (type == 'idCard') { + return str.replace(/^(.{6})(?:\d+)(.{4})$/, '$1********$2') + } else if (type == 'phone') { + return str.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') + } else if (type == 'email') { + let count, emailArr, emailFront, emailBack; + emailArr = str.split('@'); + emailFront = emailArr[0]; + count = emailFront.length / 2; + emailFront = emailFront.substring(0, emailFront.length - count); + emailBack = emailArr[1]; + return emailFront + '***@' + emailBack; + } +} + + +/** + * 根据value值筛选对应的label + * @param {Array} options - 原数组 + * @param {string | Number} value - 表示 + * @returns {string} - 返回后的汉字 + */ +export function getLabelByValue(options = [], value, valueKey = 'value', labelKey = 'label') { + for (let i = 0; i < options.length; i++) { + // 动态使用传入的 valueKey 和 labelKey + if (options[i][valueKey] === value) { + return options[i][labelKey]; + } + } + return null; +} +/** + * 将数组转换为字符串 + * @param {Array} arr - 要转换的数组 + * @param {string} delimiter - 用于连接数组元素的分隔符,默认为逗号 + * @returns {string} - 转换后的字符串 + */ +export function arrayToString(arr, delimiter = ',') { + return arr.join(delimiter); +} + +/* 延时函数 */ +export function delay(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +/* 获取当前年月日 时分秒 */ +export function getCurrentDate() { + const date = new Date(); + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,需要加1 + const day = String(date.getDate()).padStart(2, '0'); // 使用padStart补零 + const hours = String(date.getHours()).padStart(2, '0'); // 补零 + const minutes = String(date.getMinutes()).padStart(2, '0'); // 补零 + const seconds = String(date.getSeconds()).padStart(2, '0'); // 补零 + + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; +} + + +export function processFileUrl(fileUrl) { + let fileList = []; + if (typeof fileUrl === 'string' && fileUrl) { + // 如果 fileUrl 是一个字符串,则按照逗号分割成数组 + const urls = fileUrl.split(',').map(url => url.trim()); // 去除每个 URL 前后的空白字符 + fileList = urls.map(url => ({ + url, + success: 'success', + name: 'fileUrl' + })); + } + return fileList; +} + +// 密码强校验 +export function isPasswordComplex(password) { + // 长度在8位以上,并且包含大小写字母、数字和特殊符号 + return /^(?=.*[A-Za-z])(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@#$%^&*!])[A-Za-z\d@#$%^&*!]{8,}$/.test(password); +} + +// 手机号码校验 +export function isPhoneNumberValid(phoneNumber) { + // 匹配国内常见的手机号格式 + return /^1[3-9]\d{9}$/.test(phoneNumber); +} + + +// 身份证校验函数 +export function isValidIdCard (idCard) { + if (typeof idCard !== 'string') { + return false; + } + + // 定义省份代码 + const provinceCodes = { + 11: "北京", 12: "天津", 13: "河北", 14: "山西", 15: "内蒙古", + 21: "辽宁", 22: "吉林", 23: "黑龙江", + 31: "上海", 32: "江苏", 33: "浙江", 34: "安徽", 35: "福建", 36: "江西", 37: "山东", + 41: "河南", 42: "湖北", 43: "湖南", 44: "广东", 45: "广西", 46: "海南", + 50: "重庆", 51: "四川", 52: "贵州", 53: "云南", 54: "西藏", + 61: "陕西", 62: "甘肃", 63: "青海", 64: "宁夏", 65: "新疆", + 71: "台湾", 81: "香港", 82: "澳门", 91: "国外" + }; + + // 检查长度 + if (!/^\d{17}(\d|X|x)$/.test(idCard)) { + return false; + } + + // 验证省份代码 + const provinceCode = idCard.substring(0, 2); + if (!provinceCodes[provinceCode]) { + return false; + } + // 验证出生日期 + const birthDate = idCard.substring(6, 14); + const birthYear = parseInt(birthDate.substring(0, 4), 10); + const birthMonth = parseInt(birthDate.substring(4, 6), 10); + const birthDay = parseInt(birthDate.substring(6, 8), 10); + const birthDateObject = new Date(birthYear, birthMonth - 1, birthDay); + + if ( + birthDateObject.getFullYear() !== birthYear || + birthDateObject.getMonth() + 1 !== birthMonth || + birthDateObject.getDate() !== birthDay + ) { + return false; + } + // 验证校验码 + const weightFactors = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; + const checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']; + + const sum = idCard + .substring(0, 17) + .split('') + .reduce((acc, num, index) => acc + parseInt(num, 10) * weightFactors[index], 0); + + const checkCode = checkCodes[sum % 11]; + return checkCode === idCard[17].toUpperCase(); +}; + diff --git a/utilsRc/config.js b/utilsRc/config.js new file mode 100644 index 0000000..e011f73 --- /dev/null +++ b/utilsRc/config.js @@ -0,0 +1,38 @@ +/* + * @Descripttion: + * @Author: lip + * @Date: 2022-12-28 13:59:09 + * @LastEditors: shirlwang + */ +// 应用全局配置 +let exports = { + + + // baseUrl: 'http://127.0.0.1:8903', // 本地开发 + + // baseUrl: 'http://172.20.0.104:8903', // xubaiqi 地址 + + // baseUrl: 'http://172.20.1.76:8903', // 演示环境内网 + + // baseUrl: 'http://36.140.162.216:8904/prod-api', // 演示环境外网 + + // baseUrl: 'http://10.160.0.5:8903', // 演示环境外网 + + // baseUrl: 'http://111.34.80.140:8081/prod-api', // 正式环境(不要轻易连接) + + baseUrl: 'http://10.160.0.5:8907', // 正式环境在济南人才上部署(不要轻易连接) + + + + // 应用信息 + appInfo: { + // 应用名称 + name: "泉就业H5", + // 应用版本 + version: "1.1.0", + // 应用logo + logo: "/static/logo.png", + } + } + +export default exports \ No newline at end of file diff --git a/utilsRc/constant.js b/utilsRc/constant.js new file mode 100644 index 0000000..5fadd14 --- /dev/null +++ b/utilsRc/constant.js @@ -0,0 +1,19 @@ +/* + * @Descripttion: + * @Author: lip + * @Date: 2023-07-27 15:53:48 + * @LastEditors: lip + */ +const constant = { + avatar: 'vuex_avatar', + name: 'vuex_name', + roles: 'vuex_roles', + permissions: 'vuex_permissions', + type: 'vuex_type', + phonenumber: 'vuex_phonenumber', + nick: 'vuex_nick', + userId: 'vuex_userId', + handlerData: 'vuex_handlerData', + } + + export default constant diff --git a/utilsRc/errorCode.js b/utilsRc/errorCode.js new file mode 100644 index 0000000..8849d23 --- /dev/null +++ b/utilsRc/errorCode.js @@ -0,0 +1,13 @@ +/* + * @Descripttion: + * @Author: lip + * @Date: 2023-07-27 15:56:30 + * @LastEditors: lip + */ +export default { + '401': '您的登录状态已过期,请重新登录', + '403': '当前操作没有权限', + '404': '访问资源不存在', + 'default': '系统未知错误,请反馈给管理员' + } + \ No newline at end of file diff --git a/utilsRc/plugins/auth.js b/utilsRc/plugins/auth.js new file mode 100644 index 0000000..57ac0a8 --- /dev/null +++ b/utilsRc/plugins/auth.js @@ -0,0 +1,60 @@ +import store from '@/store' + +function authPermission(permission) { + const all_permission = "*:*:*" + const permissions = store.getters && store.getters.permissions + if (permission && permission.length > 0) { + return permissions.some(v => { + return all_permission === v || v === permission + }) + } else { + return false + } +} + +function authRole(role) { + const super_admin = "shequn" + const roles = store.getters && store.getters.roles + if (role && role.length > 0) { + return roles.some(v => { + return super_admin === v || v === role + }) + } else { + return false + } +} + +export default { + // 验证用户是否具备某权限 + hasPermi(permission) { + return authPermission(permission) + }, + // 验证用户是否含有指定权限,只需包含其中一个 + hasPermiOr(permissions) { + return permissions.some(item => { + return authPermission(item) + }) + }, + // 验证用户是否含有指定权限,必须全部拥有 + hasPermiAnd(permissions) { + return permissions.every(item => { + return authPermission(item) + }) + }, + // 验证用户是否具备某角色 + hasRole(role) { + return authRole(role) + }, + // 验证用户是否含有指定角色,只需包含其中一个 + hasRoleOr(roles) { + return roles.some(item => { + return authRole(item) + }) + }, + // 验证用户是否含有指定角色,必须全部拥有 + hasRoleAnd(roles) { + return roles.every(item => { + return authRole(item) + }) + } +} diff --git a/utilsRc/plugins/index.js b/utilsRc/plugins/index.js new file mode 100644 index 0000000..efbae15 --- /dev/null +++ b/utilsRc/plugins/index.js @@ -0,0 +1,14 @@ +import tab from './tab' +import auth from './auth' +import modal from './modal' + +export default { + install(Vue) { + // 页签操作 + Vue.prototype.$tab = tab + // 认证对象 + Vue.prototype.$auth = auth + // 模态框对象 + Vue.prototype.$modal = modal + } +} diff --git a/utilsRc/plugins/loadingPlugin.js b/utilsRc/plugins/loadingPlugin.js new file mode 100644 index 0000000..c20d9b6 --- /dev/null +++ b/utilsRc/plugins/loadingPlugin.js @@ -0,0 +1,50 @@ +import ULoadingPage from 'uview-ui/components/u-loading-page/u-loading-page'; // 确保正确引入组件 + +export default { + install(Vue) { + // 注册 u-loading-page 组件为全局组件 + Vue.component('u-loading-page', ULoadingPage); + + // 用于存储全局的 loading 组件实例 + let loadingInstance = null; + + // 创建一个全局的显示 loading 的方法 + Vue.prototype.$showLoading = function () { + // 如果没有创建过实例,则创建一个 + if (!loadingInstance) { + const LoadingConstructor = Vue.extend({ + data() { + return { + loading: true, // 控制 loading 显示的状态 + }; + }, + render(h) { + return h('u-loading-page', { + props: { + loading: this.loading, + loadingText: '', + loadingColor: "#000", + iconSize: '58rpx', + }, + style: { + zIndex: '200', + opacity: 0.7 + } + }); + } + }); + loadingInstance = new LoadingConstructor(); + loadingInstance.$mount(); // 手动挂载实例 + document.body.appendChild(loadingInstance.$el); // 将组件挂载到 body + } + loadingInstance.loading = true; // 显示 loading + }; + + // 创建一个全局的隐藏 loading 的方法 + Vue.prototype.$hideLoading = function () { + if (loadingInstance) { + loadingInstance.loading = false; // 隐藏 loading + } + }; + }, +}; diff --git a/utilsRc/plugins/modal.js b/utilsRc/plugins/modal.js new file mode 100644 index 0000000..87960fd --- /dev/null +++ b/utilsRc/plugins/modal.js @@ -0,0 +1,74 @@ +export default { + // 消息提示 + msg(content) { + uni.showToast({ + title: content, + icon: 'none' + }) + }, + // 错误消息 + msgError(content) { + uni.showToast({ + title: content, + icon: 'error' + }) + }, + // 成功消息 + msgSuccess(content) { + uni.showToast({ + title: content, + icon: 'success' + }) + }, + // 隐藏消息 + hideMsg(content) { + uni.hideToast() + }, + // 弹出提示 + alert(content) { + uni.showModal({ + title: '提示', + content: content, + showCancel: false + }) + }, + // 确认窗体 + confirm(content) { + return new Promise((resolve, reject) => { + uni.showModal({ + title: '系统提示', + content: content, + cancelText: '取消', + confirmText: '确定', + success: function(res) { + if (res.confirm) { + resolve(res.confirm) + } + } + }) + }) + }, + // 提示信息 + showToast(option) { + if (typeof option === "object") { + uni.showToast(option) + } else { + uni.showToast({ + title: option, + icon: "none", + duration: 2500 + }) + } + }, + // 打开遮罩层 + loading(content) { + uni.showLoading({ + title: content, + icon: 'none' + }) + }, + // 关闭遮罩层 + closeLoading() { + uni.hideLoading() + } +} diff --git a/utilsRc/plugins/tab.js b/utilsRc/plugins/tab.js new file mode 100644 index 0000000..5d1b305 --- /dev/null +++ b/utilsRc/plugins/tab.js @@ -0,0 +1,30 @@ +export default { + // 关闭所有页面,打开到应用内的某个页面 + reLaunch(url) { + return uni.reLaunch({ + url: url + }) + }, + // 跳转到tabBar页面,并关闭其他所有非tabBar页面 + switchTab(url) { + return uni.switchTab({ + url: url + }) + }, + // 关闭当前页面,跳转到应用内的某个页面 + redirectTo(url) { + return uni.redirectTo({ + url: url + }) + }, + // 保留当前页面,跳转到应用内的某个页面 + navigateTo(url) { + return uni.navigateTo({ + url: url + }) + }, + // 关闭当前页面,返回上一页面或多级页面 + navigateBack() { + return uni.navigateBack() + } +} diff --git a/utilsRc/request.js b/utilsRc/request.js new file mode 100644 index 0000000..533390c --- /dev/null +++ b/utilsRc/request.js @@ -0,0 +1,107 @@ +/* + * @Descripttion: + * @Author: lip + * @Date: 2023-05-12 08:44:49 + * @LastEditors: shirlwang + */ +import store from './store/index.js' +import configRc from './config.js' +import { getToken } from '@/utilsRc/auth' +import errorCode from '@/utilsRc/errorCode' +import { toast, showConfirm, tansParams } from '@/utilsRc/common' + +let timeout = 10000 +const baseUrl = configRc.baseUrl + +const request = config => { + // 是否需要设置 token + const isToken = (config.headers || {}).isToken === false + config.header = config.header || {} + if (getToken() && !isToken) { + config.header['Authorization'] = 'Bearer ' + getToken() + } + console.log('(sjdoifjsidof') + config.header['Authorization'] = 'Bearer ' + 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJCVFJHeXdHcjB1M1dFN1lpOXVUSmxMQXltMjZjWldyQiIsInVzZXJJZCI6MX0.ItipztABmyMHsNESI_a34HT_FuTtmeIlzz6cldH7tB0' + // get请求映射params参数 + if (config.params) { + let url = config.url + '?' + tansParams(config.params) + url = url.slice(0, -1) + config.url = url + } + return new Promise((resolve, reject) => { + uni.request({ + method: config.method || 'get', + timeout: config.timeout || timeout, + url: baseUrl + config.url, + // url: 'https://gccrcdh.sd-talent.cn:80/zhq' + config.url, + data: config.data, + header: config.header, + dataType: 'json' + }).then(response => { + let res = response.data + let error = response.errMsg!='request:ok' + if (error) { + toast('网络出小差,请稍后再试') + reject('网络出小差,请稍后再试') + return + } + const code = res.code || 200 + console.log(code, 'const code = res.code || 200') + const msg = errorCode[code] || res.msg || errorCode['default'] + const isShowModel = getApp().globalData.isShowModel + if (code === 200) { + resolve(res) + }else if (code === 401) { + if(isShowModel === false) { + getApp().globalData.isShowModel = true + showConfirm('您好!登录后,您才可以继续操作。', '取消', '去登录').then(res => { + if (res.confirm) { + getApp().globalData.isShowModel = false + store.dispatch('LogOut').then(res => { + uni.reLaunch({ url: '/pages/login/login-one' }) + }) + } else if(res.cancel) { + getApp().globalData.isShowModel = false + uni.navigateBack() + } + + }) + } + // reject(code) + } + // if (code === 401) { + // showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then(res => { + // if (res.confirm) { + // store.dispatch('LogOut').then(res => { + // uni.reLaunch({ url: '/page_other/login/index' }) + // }) + // } + // }) + // reject('无效的会话,或者会话已过期,请重新登录。') + // } else + else if (code === 500) { + toast(msg) + reject('500') + } else if (code !== 200 && code !== 9999) { + // 9999是正常的业务状态码,不应该被当作错误处理 + toast(msg) + reject(code) + } + resolve(res.data) + }) + .catch(error => { + let { message } = error + if (message === 'Network Error') { + message = '网络出小差,请稍后再试' + } else if (message.includes('timeout')) { + message = '系统接口请求超时' + } else if (message.includes('Request failed with status code')) { + message = '系统接口' + message.substr(message.length - 3) + '异常' + } + toast(message) + reject(error) + }) + }) +} + +export default request diff --git a/utilsRc/storage.js b/utilsRc/storage.js new file mode 100644 index 0000000..c3bf5db --- /dev/null +++ b/utilsRc/storage.js @@ -0,0 +1,44 @@ +/* + * @Descripttion: + * @Author: lip + * @Date: 2023-07-27 15:56:55 + * @LastEditors: lip + */ +import constant from './constant' + +// 存储变量名 +let storageKey = 'storage_data' + +// 存储节点变量名 +let storageNodeKeys = [constant.avatar, constant.name, constant.roles, constant.permissions, constant.type, constant + .phonenumber, + constant.userId, + constant.handlerData, + constant.nick +] + +// 存储的数据 +let storageData = uni.getStorageSync(storageKey) || {} + +const storage = { + set: function(key, value) { + if (storageNodeKeys.indexOf(key) != -1) { + let tmp = uni.getStorageSync(storageKey) + tmp = tmp ? tmp : {} + tmp[key] = value + uni.setStorageSync(storageKey, tmp) + } + }, + get: function(key) { + return storageData[key] || "" + }, + remove: function(key) { + delete storageData[key] + uni.setStorageSync(storageKey, storageData) + }, + clean: function() { + uni.removeStorageSync(storageKey) + } +} + +export default storage diff --git a/utilsRc/store/getters.js b/utilsRc/store/getters.js new file mode 100644 index 0000000..14ab276 --- /dev/null +++ b/utilsRc/store/getters.js @@ -0,0 +1,19 @@ +/* + * @Descripttion: + * @Author: lip + * @Date: 2023-07-27 15:59:34 + * @LastEditors: lip + */ +const getters = { + token: state => state.user.token, + avatar: state => state.user.avatar, + name: state => state.user.name, + roles: state => state.user.roles, + permissions: state => state.user.permissions, + userId: state => state.user.userId, + handlerData: state => state.user.handlerData, + nick: state => state.user.nick, + showExitPopup: state => state.user.showExitPopup, + publicKey: state => state.user.publicKey + } + export default getters diff --git a/utilsRc/store/index.js b/utilsRc/store/index.js new file mode 100644 index 0000000..f3475ea --- /dev/null +++ b/utilsRc/store/index.js @@ -0,0 +1,18 @@ +/* + * @Descripttion: + * @Author: lip + * @Date: 2023-07-27 09:04:34 + * @LastEditors: shirlwang + */ +import user from '@/utilsRc/store/modules/user' +import getters from './getters' + +// src/store/index.js +import { createStore } from 'vuex'; +let store = createStore({ + modules: { + user + }, + getters +}); +export default store; diff --git a/utilsRc/store/modules/user.js b/utilsRc/store/modules/user.js new file mode 100644 index 0000000..0113c11 --- /dev/null +++ b/utilsRc/store/modules/user.js @@ -0,0 +1,233 @@ +import config from '@/config' +import storage from '@/utilsRc/storage' +import constant from '@/utilsRc/constant' +import { + login, + logout, + getInfo, + register, + smsLogin, + wechatLogin +} from '@/apiRc/login' +import { + getToken, + setToken, + removeToken +} from '@/utilsRc/auth' + +import {sm2} from 'sm-crypto' +// const sm2 = require('sm-crypto').sm2 +const baseUrl = config.baseUrl + +const user = { + state: { + token: getToken(), + name: storage.get(constant.name), + avatar: storage.get(constant.avatar), + roles: storage.get(constant.roles), + permissions: storage.get(constant.permissions), + type: storage.get(constant.type), + phonenumber: storage.get(constant.phonenumber), + nick: storage.get(constant.nick), + userId: storage.get(constant.userId), + handlerData: storage.get(constant.handlerData), + showExitPopup: false, + publicKey: '04970A174A090FCCD2B2503DD978152ACB906919245E4C8F237BE290E6E72334DDD89B857177A11C609FAA62CC62AD75D4BB1395E2A22F2663357A5D3EF9B1C1B8', + + }, + + + mutations: { + SET_TOKEN: (state, token) => { + state.token = token + // 同时更新存储中的token + setToken(token) + }, + SET_NAME: (state, name) => { + state.name = name + storage.set(constant.name, name) + }, + SET_AVATAR: (state, avatar) => { + state.avatar = avatar + storage.set(constant.avatar, avatar) + }, + SET_ROLES: (state, roles) => { + state.roles = roles + storage.set(constant.roles, roles) + }, + SET_PERMISSIONS: (state, permissions) => { + state.permissions = permissions + storage.set(constant.permissions, permissions) + }, + SET_TYPE: (state, type) => { + state.type = type + storage.set(constant.type, type) + }, + SET_PHONENUMBER: (state, phonenumber) => { + state.phonenumber = phonenumber + storage.set(constant.phonenumber, phonenumber) + }, + SET_NICK: (state, nick) => { + state.nick = nick + storage.set(constant.nick, nick) + }, + SET_USER_ID: (state, userId) => { + state.userId = userId + storage.set(constant.userId, userId) + }, + + // 存储经办人信息 + SET_HAND_LER(state, data) { + state.handlerData = data + storage.set(constant.handlerData, data) + }, + + SET_SHOWEXITPOPUP(state, type) { + state.showExitPopup = type + } + }, + + actions: { + // 登录 + Login({ + commit, + state + }, userInfo) { + + return new Promise((resolve, reject) => { + const info = JSON.parse(JSON.stringify(userInfo)) + info.password = '04' + sm2.doEncrypt(info.password, state.publicKey, 0) + info.username = '04' + sm2.doEncrypt(info.username, state.publicKey, 0) + login(info).then(res => { + console.log('登录接口返回:', res); + setToken(res.data.token) + commit('SET_TOKEN', res.data.token) + resolve(res) + }).catch(error => { + reject(error) + }) + }) + }, + // 登录 + SMSLogin({ + commit + }, userInfo) { + return new Promise((resolve, reject) => { + smsLogin(userInfo).then(res => { + setToken(res.data.token) + commit('SET_TOKEN', res.data.token) + resolve(res) + }).catch(error => { + reject(error) + }) + }) + }, + // 登录 + WXLogin({ + commit + }, userInfo) { + return new Promise((resolve, reject) => { + wechatLogin(userInfo).then(res => { + setToken(res.data.token) + commit('SET_TOKEN', res.data.token) + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + // 注册 + Register({ + commit + }, userInfo) { + const username = userInfo.username + const password = userInfo.password + const code = userInfo.code + const uuid = userInfo.uuid + const userType = userInfo.userType + const userNumber = userInfo.userNumber + return new Promise((resolve, reject) => { + register(username, password, code, uuid, userType, userNumber).then(res => { + uni.showToast({ + title: `账号${username}注册成功`, + icon: 'none' + }) + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // 获取用户信息 + GetInfo({ + commit, + state + }) { + return new Promise((resolve, reject) => { + getInfo().then(res => { + const user = res.data.user + const avatar = (user == null || user.avatar == "" || user.avatar == null) ? + "https://rc.jinan.gov.cn/qcwjyH5/static/icon/my.png" : user.avatar + const username = (user == null || user.userName == "" || user.userName == + null) ? "" : user.userName + const usertype = (user == null || user.userType == "" || user.userType == + null) ? "" : user.userType + const usernumber = (user == null || user.phonenumber == "" || user + .phonenumber == null) ? "" : user.phonenumber + const nick = (user == null || user.nickName == "" || user.nickName == null) ? + "" : user.nickName + const userId = (user == null || user.userId == "" || user.userId == null) ? "" : + user.userId + if (res.data.roles && res.data.roles.length > 0) { + commit('SET_ROLES', res.data.roles) + commit('SET_PERMISSIONS', res.data.permissions) + } else { + commit('SET_ROLES', ['ROLE_DEFAULT']) + } + commit('SET_NAME', username) + commit('SET_AVATAR', avatar) + commit('SET_TYPE', usertype) + commit('SET_PHONENUMBER', usernumber) + commit('SET_NICK', nick) + commit('SET_USER_ID', userId) + + // commit('SET_HAND_LER', { + // deptName: user.dept.deptName, + // nickName: user.nickName + // }) + + resolve(res) + }).catch(error => { + reject(error) + }) + }) + }, + + // 退出系统 + LogOut({ + commit, + state + }) { + return new Promise((resolve, reject) => { + logout(state.token).then(() => { + commit('SET_TOKEN', '') + commit('SET_ROLES', []) + commit('SET_PERMISSIONS', []) + commit('SET_TYPE', '') + commit('SET_NICK', '') + commit('SET_PHONENUMBER', '') + commit('SET_USER_ID', '') + commit('SET_SHOWEXITPOPUP', false) + removeToken() + storage.clean() + resolve() + }).catch(error => { + reject(error) + }) + }) + } + } +} + +export default user