Initial commit

This commit is contained in:
2023-02-24 01:41:06 +01:00
commit 49cbb85e7b
21 changed files with 5107 additions and 0 deletions

160
src/main.ts Normal file
View 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
View 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
View File

@ -0,0 +1,14 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"paths": {
"*": [
"/src/*"
]
},
"module": "Node16",
"target": "ES6"
},
"include": [
]
}

59
src/updater.ts Normal file
View 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
View 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
View 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"
]
}
}
}