Initial commit
This commit is contained in:
160
src/main.ts
Normal file
160
src/main.ts
Normal file
@ -0,0 +1,160 @@
|
||||
import {app, BrowserWindow, dialog, ipcMain, powerSaveBlocker, screen} from "electron";
|
||||
import * as path from "path";
|
||||
import AppUpdater from "./updater";
|
||||
const crypto = require('crypto');
|
||||
|
||||
const setupPug = require('electron-pug');
|
||||
const packageJson = require("../package.json");
|
||||
const Store = require('electron-store');
|
||||
|
||||
|
||||
const store = new Store();
|
||||
|
||||
|
||||
process.on("uncaughtException", (err) => {
|
||||
console.log("Uncaught Exception")
|
||||
console.error(err);
|
||||
const messageBoxOptions = {
|
||||
type: "error",
|
||||
title: "Shit - There was an error!",
|
||||
message: err.message
|
||||
};
|
||||
dialog.showMessageBoxSync(messageBoxOptions);
|
||||
});
|
||||
|
||||
const updater = new AppUpdater();
|
||||
let pug;
|
||||
|
||||
|
||||
const operatingSystem = process.platform;
|
||||
console.log("Starting TryCrypt v" + packageJson.version);
|
||||
console.log("Detected operating system is " + operatingSystem);
|
||||
|
||||
let mainWindow: BrowserWindow;
|
||||
|
||||
|
||||
function sleep(ms: number) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => resolve(null), ms);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Main window
|
||||
*/
|
||||
function createWindow() {
|
||||
return new Promise((resolve) => {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, "preload.js"),
|
||||
contextIsolation: true,
|
||||
nodeIntegration: true,
|
||||
},
|
||||
width: 1000,
|
||||
height: 600,
|
||||
alwaysOnTop: false,
|
||||
autoHideMenuBar: false,
|
||||
title: "TryCrypt",
|
||||
show: true,
|
||||
});
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile(path.join(__dirname, "../static/index.pug"));
|
||||
|
||||
mainWindow.on("ready-to-show", (e: Event) => {
|
||||
resolve(true);
|
||||
});
|
||||
|
||||
mainWindow.on("closed", () => {
|
||||
console.log("Closing app...");
|
||||
app.exit(0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* App is ready (Electron has booted up!)
|
||||
*/
|
||||
app.on("ready", async () => {
|
||||
try {
|
||||
pug = await setupPug({pretty: true});
|
||||
pug.on('error', (err: string) => console.error('render error', err));
|
||||
|
||||
let updateAvailable = await updater.checkForUpdates();
|
||||
if (updateAvailable) {
|
||||
await updater.downloadAndInstallUpdate();
|
||||
const messageBoxOptions = {
|
||||
type: "info",
|
||||
title: "Update!",
|
||||
message: "An update of this application will be installed now..."
|
||||
};
|
||||
dialog.showMessageBoxSync(messageBoxOptions);
|
||||
return;
|
||||
}
|
||||
|
||||
await createWindow();
|
||||
|
||||
} catch (e) {
|
||||
app.relaunch();
|
||||
app.exit();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
////// IPC HANDLES \\\\\\\
|
||||
|
||||
function generateRandom(length: number) {
|
||||
let result = '';
|
||||
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
const charactersLength = characters.length;
|
||||
let counter = 0;
|
||||
while (counter < length) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
counter += 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Relaunch handler
|
||||
ipcMain.on("relaunch", () => {
|
||||
app.relaunch();
|
||||
app.exit();
|
||||
return;
|
||||
});
|
||||
|
||||
|
||||
ipcMain.handle("getKey", (e) => {
|
||||
console.log("Key requested!");
|
||||
return [store.get('key'), store.get('iv')];
|
||||
});
|
||||
|
||||
ipcMain.handle("generateKey", (e) => {
|
||||
console.log("Key generating...");
|
||||
const key = generateRandom(32);
|
||||
const iv = generateRandom(16);
|
||||
return [key, iv];
|
||||
});
|
||||
|
||||
ipcMain.on("setKey", (e, key: string, iv: string) => {
|
||||
console.log("Got new key!");
|
||||
store.set('key', key);
|
||||
store.set('iv', iv);
|
||||
});
|
||||
|
||||
ipcMain.handle("encrypt", (e, text) => {
|
||||
console.log("Encrypting...");
|
||||
const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(store.get('key')), Buffer.from(store.get('iv')));
|
||||
const encryptedData = cipher.update(text, 'utf8', 'base64') + cipher.final('base64');
|
||||
return encryptedData;
|
||||
});
|
||||
|
||||
ipcMain.handle("decrypt", (e, text) => {
|
||||
console.log("Decrypting...");
|
||||
const decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(store.get('key')), Buffer.from(store.get('iv')));
|
||||
let decrypted = decipher.update(text, 'base64', 'utf8');
|
||||
decrypted += decipher.final('utf8');
|
||||
return decrypted.toString();
|
||||
});
|
30
src/preload.ts
Normal file
30
src/preload.ts
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) Tobias Hopp, 2022.
|
||||
* This program is copyright protected.
|
||||
* Copying, distributing or using source code is prohibited.
|
||||
* Any distribution or illegal copying will be prosecuted.
|
||||
*
|
||||
* You may not use this sourcecode.
|
||||
*
|
||||
*/
|
||||
|
||||
import {contextBridge, ipcRenderer} from "electron";
|
||||
|
||||
|
||||
contextBridge.exposeInMainWorld('trycrypt', {
|
||||
getKey: () : Promise<string[]> => {
|
||||
return ipcRenderer.invoke("getKey");
|
||||
},
|
||||
setKey: (key: string, iv: string) => {
|
||||
ipcRenderer.send("setKey", key, iv);
|
||||
},
|
||||
generateKey: () : Promise<string[]> => {
|
||||
return ipcRenderer.invoke("generateKey");
|
||||
},
|
||||
encrypt: (text: string) : Promise<string> => {
|
||||
return ipcRenderer.invoke("encrypt", text);
|
||||
},
|
||||
decrypt: (text: string) : Promise<string> => {
|
||||
return ipcRenderer.invoke("decrypt", text);
|
||||
}
|
||||
})
|
14
src/tsconfig.json
Normal file
14
src/tsconfig.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"*": [
|
||||
"/src/*"
|
||||
]
|
||||
},
|
||||
"module": "Node16",
|
||||
"target": "ES6"
|
||||
},
|
||||
"include": [
|
||||
]
|
||||
}
|
59
src/updater.ts
Normal file
59
src/updater.ts
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) Tobias Hopp, 2022.
|
||||
* This program is copyright protected.
|
||||
* Copying, distributing or using source code is prohibited.
|
||||
* Any distribution or illegal copying will be prosecuted.
|
||||
*
|
||||
* You may not use this sourcecode.
|
||||
*
|
||||
*/
|
||||
|
||||
import {autoUpdater} from "electron-updater";
|
||||
|
||||
export default class AppUpdater {
|
||||
constructor() {
|
||||
|
||||
//log.transports.file.level = "debug"
|
||||
autoUpdater.autoDownload = false;
|
||||
autoUpdater.allowDowngrade = false;
|
||||
autoUpdater.setFeedURL("https://infoscreen.iif.li/releases/");
|
||||
}
|
||||
|
||||
public checkForUpdates(): Promise<boolean> {
|
||||
return new Promise((resolve, reject) => {
|
||||
autoUpdater.on('update-available', (ev) => {
|
||||
resolve(true);
|
||||
})
|
||||
autoUpdater.on('update-not-available', (ev) => {
|
||||
resolve(false);
|
||||
})
|
||||
|
||||
autoUpdater.on("update-cancelled", () => {
|
||||
resolve(false);
|
||||
})
|
||||
|
||||
autoUpdater.checkForUpdates().then(result => {
|
||||
if (result == null)
|
||||
resolve(false);
|
||||
}).catch(() => reject());
|
||||
setTimeout( () => reject(false), 1000 * 30 );
|
||||
});
|
||||
}
|
||||
|
||||
public downloadAndInstallUpdate() {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
autoUpdater.on('update-downloaded', (ev) => {
|
||||
// Wait 5 seconds, then quit and install
|
||||
// In your application, you don't need to wait 5 seconds.
|
||||
// You could call autoUpdater.quitAndInstall(); immediately
|
||||
resolve(true);
|
||||
setTimeout(() => autoUpdater.quitAndInstall(true, true), 5000);
|
||||
});
|
||||
autoUpdater.downloadUpdate().catch(() => reject());
|
||||
} catch (e) {
|
||||
reject();
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
97
src/web/page.ts
Normal file
97
src/web/page.ts
Normal file
@ -0,0 +1,97 @@
|
||||
let key: string, iv: string;
|
||||
let keyField: HTMLInputElement;
|
||||
let ivField: HTMLInputElement;
|
||||
let keySave: HTMLButtonElement;
|
||||
let keyShow: HTMLButtonElement;
|
||||
let keyGenerate: HTMLButtonElement;
|
||||
let decryptBtn: HTMLButtonElement;
|
||||
let encryptBtn: HTMLButtonElement;
|
||||
let userTB: HTMLTextAreaElement;
|
||||
let systemTB: HTMLTextAreaElement;
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
// Loaded
|
||||
keyField = document.getElementById("keyField") as HTMLInputElement;
|
||||
ivField = document.getElementById("ivField") as HTMLInputElement;
|
||||
keySave = document.getElementById("keySave") as HTMLButtonElement;
|
||||
keyShow = document.getElementById("keyRefresh") as HTMLButtonElement;
|
||||
keyGenerate = document.getElementById("generateRandom") as HTMLButtonElement;
|
||||
userTB = document.getElementById("userTB") as HTMLTextAreaElement;
|
||||
systemTB = document.getElementById("systemTB") as HTMLTextAreaElement;
|
||||
encryptBtn = document.getElementById("btnEncrypt") as HTMLButtonElement;
|
||||
decryptBtn = document.getElementById("btnDecrypt") as HTMLButtonElement;
|
||||
|
||||
systemTB.onclick = () => {
|
||||
const range = document.createRange();
|
||||
range.selectNodeContents(systemTB);
|
||||
const selection = window.getSelection();
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
navigator.clipboard.writeText(systemTB.value);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// @ts-ignore
|
||||
[key, iv] = await window.trycrypt.getKey();
|
||||
|
||||
if (key)
|
||||
keyField.value = key;
|
||||
if (iv)
|
||||
ivField.value = iv;
|
||||
|
||||
keySave.onclick = () => onKeySave();
|
||||
keyShow.onmousedown = () => {
|
||||
keyField.type = "text";
|
||||
ivField.type = "text";
|
||||
}
|
||||
keyShow.onmouseup = () => {
|
||||
keyField.type = "password";
|
||||
ivField.type = "password";
|
||||
}
|
||||
|
||||
encryptBtn.onclick = () => encrypt();
|
||||
decryptBtn.onclick = () => decrypt();
|
||||
keyGenerate.onclick = () => generateRandom();
|
||||
});
|
||||
|
||||
function onKeySave() {
|
||||
key = keyField.value;
|
||||
iv = ivField.value;
|
||||
// @ts-ignore
|
||||
window.trycrypt.setKey(key, iv);
|
||||
keySave.style.backgroundColor = "green";
|
||||
setTimeout(() => keySave.style.backgroundColor = "", 1000);
|
||||
}
|
||||
|
||||
async function generateRandom() {
|
||||
//@ts-ignore
|
||||
let [gen_key, gen_iv] = await window.trycrypt.generateKey();
|
||||
key = gen_key;
|
||||
iv = gen_iv;
|
||||
|
||||
keyField.value = key;
|
||||
ivField.value = iv;
|
||||
|
||||
keyField.type = "text";
|
||||
ivField.type = "text";
|
||||
setTimeout( () => {
|
||||
keyField.type = "password";
|
||||
ivField.type = "password";
|
||||
}, 3000 );
|
||||
}
|
||||
|
||||
async function encrypt() {
|
||||
let text = userTB.value;
|
||||
|
||||
// @ts-ignore
|
||||
systemTB.value = await window.trycrypt.encrypt(text);
|
||||
}
|
||||
|
||||
async function decrypt() {
|
||||
let text = userTB.value;
|
||||
|
||||
// @ts-ignore
|
||||
systemTB.value = await window.trycrypt.decrypt(text);
|
||||
}
|
||||
|
23
src/web/tsconfig.json
Normal file
23
src/web/tsconfig.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"target": "ES6",
|
||||
"module": "CommonJS",
|
||||
"lib": [
|
||||
"es5",
|
||||
"es6",
|
||||
"dom",
|
||||
"dom.iterable"
|
||||
],
|
||||
"allowJs": true,
|
||||
"sourceMap": true,
|
||||
"downlevelIteration": true,
|
||||
"baseUrl": "src/web/",
|
||||
"paths": {
|
||||
"*": [
|
||||
"src/web/*",
|
||||
"src/preload.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user