diff --git a/.gitignore b/.gitignore index e4a3998..1d34e75 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,4 @@ /out/* /node_modules /config.json -/mails.txt \ No newline at end of file +/mails.txt diff --git a/bin/opentoken-linux b/bin/opentoken-linux new file mode 100755 index 0000000..c465d7b Binary files /dev/null and b/bin/opentoken-linux differ diff --git a/bin/opentoken-macos b/bin/opentoken-macos new file mode 100755 index 0000000..38cd6e2 Binary files /dev/null and b/bin/opentoken-macos differ diff --git a/bin/opentoken-win.exe b/bin/opentoken-win.exe new file mode 100644 index 0000000..6b481d8 Binary files /dev/null and b/bin/opentoken-win.exe differ diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..36d0daf --- /dev/null +++ b/dist/index.js @@ -0,0 +1,131 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var fs = __importStar(require("fs")); +var generate_1 = require("./src/generate"); +var vault_1 = require("./src/vault"); +var configPath = "", action = -1, pubKey = "", privKey = "", safeFile = "", mails = "", html = ""; +for (var i = 1; i < process.argv.length; i++) { + if (process.argv[i] === "--config") { + if (i + 1 < process.argv.length && !process.argv[i + 1].startsWith("--")) { + configPath = process.argv[i + 1]; + } + else { + throw new Error("Invalid params"); + } + } + if (process.argv[i] === "--pubkey") { + if (i + 1 < process.argv.length && !process.argv[i + 1].startsWith("--")) { + pubKey = process.argv[i + 1]; + } + else { + throw new Error("Invalid params"); + } + } + if (process.argv[i] === "--privkey") { + if (i + 1 < process.argv.length && !process.argv[i + 1].startsWith("--")) { + privKey = process.argv[i + 1]; + } + else { + throw new Error("Invalid params"); + } + } + if (process.argv[i] === "--safe") { + if (i + 1 < process.argv.length && !process.argv[i + 1].startsWith("--")) { + safeFile = process.argv[i + 1]; + } + else { + throw new Error("Invalid params"); + } + } + if (process.argv[i] === "--mails") { + if (i + 1 < process.argv.length && !process.argv[i + 1].startsWith("--")) { + mails = process.argv[i + 1]; + } + else { + throw new Error("Invalid params"); + } + } + if (process.argv[i] === "--html") { + if (i + 1 < process.argv.length && !process.argv[i + 1].startsWith("--")) { + html = process.argv[i + 1]; + } + else { + throw new Error("Invalid params"); + } + } + if (process.argv[i] === "--send") { + action = 1; + } + if (process.argv[i] === "--decrypt") { + action = 2; + } + if (process.argv[i] === "--genkey") { + action = 3; + } +} +if (action == -1) { + throw new Error("No Action specified"); +} +if (!configPath && action == 1) { + throw new Error("Config-Path not specified"); +} +if (!pubKey && action != 2) { + throw new Error("Public-Key not specified"); +} +if (!safeFile && action != 3) { + throw new Error("Safe-file not specified"); +} +if (!privKey && action >= 2) { + throw new Error("Private-Key not specified"); +} +if (!mails && action == 1) { + throw new Error("Mail-Input not specified"); +} +if (!html && action == 1) { + throw new Error("Mail-Template not specified"); +} +if (action == 1) { + var dataSafe_1 = new vault_1.SecureVault(pubKey, privKey); + var confRaw = fs.readFileSync(configPath, 'utf8'); + var config = {}; + try { + config = JSON.parse(confRaw); + config.inFileMail = mails; + config.htmlPath = html; + } + catch (error) { + console.error("Cannote read config file!"); + process.exit(100); + } + generate_1.generateToken(config, dataSafe_1).then(function (el) { + console.log(el); + dataSafe_1.saveData(safeFile); + }).catch(function (err) { return console.error("error", err); }); +} +else if (action == 2) { + var dataSafe = new vault_1.SecureVault(pubKey, privKey); + dataSafe.loadData(safeFile); + dataSafe.decryptData(); +} +else if (action == 3) { + vault_1.SecureVault.genKey(pubKey, privKey); +} diff --git a/dist/src/generate.js b/dist/src/generate.js new file mode 100644 index 0000000..7da9f6b --- /dev/null +++ b/dist/src/generate.js @@ -0,0 +1,184 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.generateToken = void 0; +var fs = __importStar(require("fs")); +var nodemailer = __importStar(require("nodemailer")); +var shuffle_1 = require("./util/shuffle"); +var token_1 = require("./util/token"); +var Handlebars = __importStar(require("handlebars")); +function generateToken(config, dataSafe) { + var pr = new Promise(function (resolve, error) { + var mailArray = []; + var readline = require('readline'), instream = fs.createReadStream(config.inFileMail), outstream = new (require('stream'))(), rl = readline.createInterface(instream, outstream); + rl.on('line', function (line) { + console.log(line); + mailArray.push({ + mail: line.substr(0, line.indexOf(";")), + name: line.substr(line.indexOf(";") + 1) + }); + }); + rl.on('close', function (line) { + generateCodes(resolve, error, mailArray, config, dataSafe); + }); + }); + return pr; +} +exports.generateToken = generateToken; +function generateCodes(resolve, error, mailArray, config, dataSafe) { + return __awaiter(this, void 0, void 0, function () { + var codeArray, checkString, listString, i, code; + return __generator(this, function (_a) { + codeArray = []; + checkString = ''; + listString = ''; + for (i = 0; i < mailArray.length; i++) { + code = token_1.mkstring(4); + while (codeArray.includes(code)) { + code = token_1.mkstring(4); + } + codeArray.push(code); + checkString = checkString + "|" + code; + listString = listString + "\n" + code; + } + checkString = checkString.substr(1); + listString = listString.substr(1); + try { + fs.writeFileSync(config.outFileMatch, checkString); + fs.writeFileSync(config.outFileCodes, listString); + } + catch (error) { + error(error); + } + sendMails(resolve, error, mailArray, codeArray, config, dataSafe); + return [2]; + }); + }); +} +function sendMails(resolve, error, mailArray, codeArray, config, dataSafe) { + return __awaiter(this, void 0, void 0, function () { + var mailserver, template, htmlSrc, i; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + mailserver = nodemailer.createTransport(config.mail); + try { + htmlSrc = fs.readFileSync(config.htmlPath, "utf8"); + template = Handlebars.compile(htmlSrc); + } + catch (error) { + console.error("Cannote read template file!"); + error(error); + } + shuffle_1.shuffleArray(mailArray); + shuffle_1.shuffleArray(codeArray); + i = 0; + _a.label = 1; + case 1: + if (!(i < mailArray.length)) return [3, 4]; + dataSafe.pushData({ + name: mailArray[i].name, + mail: mailArray[i].mail, + code: codeArray[i] + }); + return [4, send(mailArray[i].name, mailArray[i].mail, codeArray[i], template, mailserver, config)]; + case 2: + _a.sent(); + _a.label = 3; + case 3: + i++; + return [3, 1]; + case 4: + resolve(codeArray); + return [2]; + } + }); + }); +} +function send(name, mail, code, template, mailserver, config) { + return __awaiter(this, void 0, void 0, function () { + var html, mailOptions, error_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + html = template({ + "name": name, + "mail": mail, + "code": code + }); + mailOptions = { + from: config.mailFrom + " <" + config.mail.auth.user + ">", + to: mail, + subject: "Dein Zugangscode zur BJR Wahl", + html: html + }; + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4, mailserver.sendMail(mailOptions)]; + case 2: + _a.sent(); + return [3, 4]; + case 3: + error_1 = _a.sent(); + console.log("Error sendign mail to " + mail + " : " + error_1); + return [3, 4]; + case 4: return [2]; + } + }); + }); +} diff --git a/dist/src/util/shuffle.js b/dist/src/util/shuffle.js new file mode 100644 index 0000000..270fd75 --- /dev/null +++ b/dist/src/util/shuffle.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.shuffleArray = void 0; +function shuffleArray(array) { + for (var i = array.length - 1; i > 0; i--) { + var j = Math.floor(Math.random() * (i + 1)); + var temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } +} +exports.shuffleArray = shuffleArray; diff --git a/dist/src/util/token.js b/dist/src/util/token.js new file mode 100644 index 0000000..ce08c03 --- /dev/null +++ b/dist/src/util/token.js @@ -0,0 +1,13 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.mkstring = void 0; +function mkstring(length) { + var result = ''; + var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + var charactersLength = characters.length; + for (var i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + return result; +} +exports.mkstring = mkstring; diff --git a/dist/src/vault.js b/dist/src/vault.js new file mode 100644 index 0000000..4e7fa7a --- /dev/null +++ b/dist/src/vault.js @@ -0,0 +1,156 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SecureVault = void 0; +var crypto = __importStar(require("crypto")); +var path_1 = __importDefault(require("path")); +var fs = __importStar(require("fs")); +var crypto_1 = require("crypto"); +var SecureVault = (function () { + function SecureVault(publicKey, privateKey) { + this.safe = { + items: [], + publicKey: publicKey ? fs.readFileSync(path_1.default.resolve(publicKey)) : undefined, + privateKey: privateKey ? fs.readFileSync(path_1.default.resolve(privateKey)) : undefined + }; + this.privPath = publicKey ? path_1.default.resolve(publicKey) : undefined, + this.pubPath = privateKey ? path_1.default.resolve(privateKey) : undefined; + } + SecureVault.prototype.pushData = function (data) { + return __awaiter(this, void 0, void 0, function () { + var txtData, key, iv, cipher, encrypted, buffer, asym_encrypted; + return __generator(this, function (_a) { + txtData = JSON.stringify(data); + key = crypto.randomBytes(32); + iv = crypto.randomBytes(16); + cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key), iv); + encrypted = cipher.update(txtData); + encrypted = Buffer.concat([encrypted, cipher.final()]); + buffer = new Buffer(key); + if (!this.safe.publicKey) { + throw new Error("Public Key not found"); + } + asym_encrypted = crypto.publicEncrypt(this.safe.publicKey, buffer); + this.safe.items.push({ + d: encrypted.toString('hex'), + k: asym_encrypted.toString("base64"), + iv: iv.toString('hex') + }); + return [2]; + }); + }); + }; + SecureVault.prototype.saveData = function (path) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + fs.writeFileSync(path, JSON.stringify(this.safe.items)); + return [2]; + }); + }); + }; + SecureVault.prototype.loadData = function (path) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + this.safe.items = JSON.parse(fs.readFileSync(path, 'utf8')); + return [2]; + }); + }); + }; + SecureVault.prototype.decryptData = function () { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + this.safe.items.forEach(function (el) { + var buffer = new Buffer(el.k, "base64"); + if (!_this.safe.privateKey) { + throw new Error("Private Key not found"); + } + var key = crypto.privateDecrypt(_this.safe.privateKey, buffer); + var iv = Buffer.from(el.iv, 'hex'); + var encryptedText = Buffer.from(el.d, 'hex'); + var decipher = crypto.createDecipheriv('aes-256-cbc', key, iv); + var decrypted = decipher.update(encryptedText); + decrypted = Buffer.concat([decrypted, decipher.final()]); + var obj = JSON.parse(decrypted.toString()); + console.log(obj); + }); + return [2]; + }); + }); + }; + SecureVault.genKey = function (publicKeyDir, privateKeyDir) { + crypto_1.generateKeyPair('rsa', { + modulusLength: 4096, + publicKeyEncoding: { + type: 'pkcs1', + format: 'pem' + }, + privateKeyEncoding: { + type: 'pkcs1', + format: 'pem', + } + }, function (err, publicKey, privateKey) { + fs.writeFileSync(privateKeyDir, privateKey); + fs.writeFileSync(publicKeyDir, publicKey); + }); + }; + return SecureVault; +}()); +exports.SecureVault = SecureVault; diff --git a/package.json b/package.json index 606fb4a..730c088 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,11 @@ { - "name": "random", + "name": "opentoken", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "build": "rm bin/* -f && rm dist/* -Rf && tsc && pkg . --out-path bin --targets linux,macos,win" }, "author": "", "license": "ISC", @@ -15,5 +16,13 @@ "crypto": "^1.0.1", "handlebars": "^4.7.6", "nodemailer": "^6.4.11" - } + }, + "pkg": { + "scripts": "dist/**/*.js", + "targets": [ + "node12" + ], + "outputPath":"bin/" + }, + "bin": "dist/index.js" } diff --git a/src/generate.js b/src/generate.js new file mode 100644 index 0000000..aed69e0 --- /dev/null +++ b/src/generate.js @@ -0,0 +1,190 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.generateToken = void 0; +var fs = __importStar(require("fs")); +var nodemailer = __importStar(require("nodemailer")); +var shuffle_1 = require("./util/shuffle"); +var token_1 = require("./util/token"); +var Handlebars = __importStar(require("handlebars")); +function generateToken(config, dataSafe) { + var pr = new Promise(function (resolve, error) { + var mailArray = []; + // read and process mail list + var readline = require('readline'), instream = fs.createReadStream(config.inFileMail), outstream = new (require('stream'))(), rl = readline.createInterface(instream, outstream); + rl.on('line', function (line) { + console.log(line); + mailArray.push({ + mail: line.substr(0, line.indexOf(";")), + name: line.substr(line.indexOf(";") + 1) + }); + }); + rl.on('close', function (line) { + // next step + generateCodes(resolve, error, mailArray, config, dataSafe); + }); + }); + return pr; +} +exports.generateToken = generateToken; +// generate codes +function generateCodes(resolve, error, mailArray, config, dataSafe) { + return __awaiter(this, void 0, void 0, function () { + var codeArray, checkString, listString, i, code; + return __generator(this, function (_a) { + codeArray = []; + checkString = ''; + listString = ''; + for (i = 0; i < mailArray.length; i++) { // as many codes as adresses + code = token_1.mkstring(4); + while (codeArray.includes(code)) { + code = token_1.mkstring(4); + } + codeArray.push(code); + checkString = checkString + "|" + code; + listString = listString + "\n" + code; + } + checkString = checkString.substr(1); + listString = listString.substr(1); + //write code lists + try { + fs.writeFileSync(config.outFileMatch, checkString); + fs.writeFileSync(config.outFileCodes, listString); + } + catch (error) { + error(error); + } + sendMails(resolve, error, mailArray, codeArray, config, dataSafe); + return [2 /*return*/]; + }); + }); +} +// randomize mails and tokens +function sendMails(resolve, error, mailArray, codeArray, config, dataSafe) { + return __awaiter(this, void 0, void 0, function () { + var mailserver, template, htmlSrc, i; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + mailserver = nodemailer.createTransport(config.mail); + try { + htmlSrc = fs.readFileSync(config.htmlPath, "utf8"); + template = Handlebars.compile(htmlSrc); + } + catch (error) { + console.error("Cannote read template file!"); + error(error); + } + shuffle_1.shuffleArray(mailArray); + shuffle_1.shuffleArray(codeArray); + i = 0; + _a.label = 1; + case 1: + if (!(i < mailArray.length)) return [3 /*break*/, 4]; + // send mail + dataSafe.pushData({ + name: mailArray[i].name, + mail: mailArray[i].mail, + code: codeArray[i] + }); + return [4 /*yield*/, send(mailArray[i].name, mailArray[i].mail, codeArray[i], template, mailserver, config)]; + case 2: + _a.sent(); + _a.label = 3; + case 3: + i++; + return [3 /*break*/, 1]; + case 4: + resolve(codeArray); + return [2 /*return*/]; + } + }); + }); +} +function send(name, mail, code, template, mailserver, config) { + return __awaiter(this, void 0, void 0, function () { + var html, mailOptions, error_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + html = template({ + "name": name, + "mail": mail, + "code": code + }); + mailOptions = { + from: config.mailFrom + " <" + config.mail.auth.user + ">", + to: mail, + subject: "Dein Zugangscode zur BJR Wahl", + html: html + }; + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, mailserver.sendMail(mailOptions)]; + case 2: + _a.sent(); + return [3 /*break*/, 4]; + case 3: + error_1 = _a.sent(); + console.log("Error sendign mail to " + mail + " : " + error_1); + return [3 /*break*/, 4]; + case 4: return [2 /*return*/]; + } + }); + }); +} diff --git a/src/util/shuffle.js b/src/util/shuffle.js new file mode 100644 index 0000000..270fd75 --- /dev/null +++ b/src/util/shuffle.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.shuffleArray = void 0; +function shuffleArray(array) { + for (var i = array.length - 1; i > 0; i--) { + var j = Math.floor(Math.random() * (i + 1)); + var temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } +} +exports.shuffleArray = shuffleArray; diff --git a/src/util/token.js b/src/util/token.js new file mode 100644 index 0000000..ce08c03 --- /dev/null +++ b/src/util/token.js @@ -0,0 +1,13 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.mkstring = void 0; +function mkstring(length) { + var result = ''; + var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + var charactersLength = characters.length; + for (var i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + return result; +} +exports.mkstring = mkstring; diff --git a/src/vault.js b/src/vault.js new file mode 100644 index 0000000..2877b4c --- /dev/null +++ b/src/vault.js @@ -0,0 +1,158 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SecureVault = void 0; +var crypto = __importStar(require("crypto")); +var path_1 = __importDefault(require("path")); +var fs = __importStar(require("fs")); +var crypto_1 = require("crypto"); +var SecureVault = /** @class */ (function () { + function SecureVault(publicKey, privateKey) { + this.safe = { + items: [], + publicKey: publicKey ? fs.readFileSync(path_1.default.resolve(publicKey)) : undefined, + privateKey: privateKey ? fs.readFileSync(path_1.default.resolve(privateKey)) : undefined + }; + this.privPath = publicKey ? path_1.default.resolve(publicKey) : undefined, + this.pubPath = privateKey ? path_1.default.resolve(privateKey) : undefined; + } + SecureVault.prototype.pushData = function (data) { + return __awaiter(this, void 0, void 0, function () { + var txtData, key, iv, cipher, encrypted, buffer, asym_encrypted; + return __generator(this, function (_a) { + txtData = JSON.stringify(data); + key = crypto.randomBytes(32); + iv = crypto.randomBytes(16); + cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key), iv); + encrypted = cipher.update(txtData); + encrypted = Buffer.concat([encrypted, cipher.final()]); + buffer = new Buffer(key); + if (!this.safe.publicKey) { + throw new Error("Public Key not found"); + } + asym_encrypted = crypto.publicEncrypt(this.safe.publicKey, buffer); + this.safe.items.push({ + d: encrypted.toString('hex'), + k: asym_encrypted.toString("base64"), + iv: iv.toString('hex') + }); + return [2 /*return*/]; + }); + }); + }; + SecureVault.prototype.saveData = function (path) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + fs.writeFileSync(path, JSON.stringify(this.safe.items)); + return [2 /*return*/]; + }); + }); + }; + SecureVault.prototype.loadData = function (path) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + this.safe.items = JSON.parse(fs.readFileSync(path, 'utf8')); + return [2 /*return*/]; + }); + }); + }; + SecureVault.prototype.decryptData = function () { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + this.safe.items.forEach(function (el) { + // decrpyt key + var buffer = new Buffer(el.k, "base64"); + if (!_this.safe.privateKey) { + throw new Error("Private Key not found"); + } + var key = crypto.privateDecrypt(_this.safe.privateKey, buffer); + // decrpyt payload + var iv = Buffer.from(el.iv, 'hex'); + var encryptedText = Buffer.from(el.d, 'hex'); + var decipher = crypto.createDecipheriv('aes-256-cbc', key, iv); + var decrypted = decipher.update(encryptedText); + decrypted = Buffer.concat([decrypted, decipher.final()]); + var obj = JSON.parse(decrypted.toString()); + console.log(obj); + }); + return [2 /*return*/]; + }); + }); + }; + SecureVault.genKey = function (publicKeyDir, privateKeyDir) { + crypto_1.generateKeyPair('rsa', { + modulusLength: 4096, + publicKeyEncoding: { + type: 'pkcs1', + format: 'pem' + }, + privateKeyEncoding: { + type: 'pkcs1', + format: 'pem', + } + }, function (err, publicKey, privateKey) { + fs.writeFileSync(privateKeyDir, privateKey); + fs.writeFileSync(publicKeyDir, publicKey); + }); + }; + return SecureVault; +}()); +exports.SecureVault = SecureVault; diff --git a/tsconfig.json b/tsconfig.json index c9f603c..9bd59c5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,11 +14,11 @@ // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ // "sourceMap": true, /* Generates corresponding '.map' file. */ // "outFile": "./", /* Concatenate and emit output to single file. */ - // "outDir": "./", /* Redirect output structure to the directory. */ + "outDir": "./dist/", /* Redirect output structure to the directory. */ // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ // "composite": true, /* Enable project compilation */ // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ - // "removeComments": true, /* Do not emit comments to output. */ + "removeComments": true, /* Do not emit comments to output. */ // "noEmit": true, /* Do not emit outputs. */ // "importHelpers": true, /* Import emit helpers from 'tslib'. */ // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */