Initial commit

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

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
node_modules/
yarn-error.log
package.json.lock
dist/

5
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,5 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/

6
.idea/jsLibraryMappings.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<includedPredefinedLibrary name="Node.js Core" />
</component>
</project>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/ourcrypt.iml" filepath="$PROJECT_DIR$/.idea/ourcrypt.iml" />
</modules>
</component>
</project>

12
.idea/ourcrypt.iml generated Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

2
electron-builder.env Normal file
View File

@ -0,0 +1,2 @@
ELECTRON_ENABLE_LOGGING=1
NODE_ENV=production

77
package.json Normal file
View File

@ -0,0 +1,77 @@
{
"name": "ourcrypt",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"compile": "tsc && webpack",
"watchTs": "tsc -w",
"watchWp": "webpack --watch",
"start": "yarn run compile && electron ./dist/main.js --trace-warnings",
"dist": "electron-builder",
"distMult": "electron-builder --linux --win",
"build": "yarn run compile && yarn run dist",
"fullBuild": "yarn run compile && yarn run distMult",
"pack": "electron-builder --dir"
},
"keywords": [],
"author": {
"email": "tobi@gaminggeneration.de",
"name": "Tobias Hopp",
"url": "https://git.gaminggeneration.de/tobiash/"
},
"license": "ISC",
"devDependencies": {
"@electron-forge/cli": "^6.0.5",
"@types/electron": "^1.6.10",
"@types/typescript": "^2.0.0",
"electron": "^23.1.1",
"electron-builder": "^23.6.0",
"ts-loader": "^9.4.2",
"typescript": "^4.9.5",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1"
},
"dependencies": {
"axios": "^1.3.4",
"crypto": "^1.0.1",
"electron-pug": "^2.0.0",
"electron-store": "^8.1.0",
"electron-updater": "^5.3.0",
"openpgp": "^5.7.0"
},
"build": {
"appId": "net.hopp.tobias.ourcrypt",
"productName": "TryCrypt",
"forceCodeSigning": false,
"artifactName": "TryCrypt_${version}_${os}_${arch}.${ext}",
"files": [
"dist/**/*",
"static/**/*",
"node_modules/**/*",
"package.json"
],
"win": {
"target": "nsis"
},
"nsis": {
"oneClick": true,
"perMachine": false,
"allowToChangeInstallationDirectory": false
},
"linux": {
"target": "AppImage",
"icon": "staticWeb/Infoscreen-Logo_256x256.png",
"category": "System",
"description": "The official infoscreen app compiled for debian"
},
"deb": {},
"directories": {
"output": "releases"
},
"publish": {
"provider": "generic",
"url": "https://infoscreen.iif.li/releases/"
}
}
}

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"
]
}
}
}

19
static/index.pug Normal file
View File

@ -0,0 +1,19 @@
extends layout.pug
block body
h1 TryCrypt
br
div#general
p Please enter your KEY and IV
input#keyField(type="password" placeholder="Passkey" style="width:30%;")
input#ivField(type="password" placeholder="IV" style="width:16%;")
button#keyRefresh 👁
button#keySave Save
button#generateRandom Generate
br
br
div#boxes
textarea#userTB(placeholder="Your encrypted or plain text" style="width: 48.5%; margin-left: 1%; height: 50%; float:left;")
textarea#systemTB(placeholder="The decrypted/encrypted text" readonly="readonly" style="width: 48.5%; margin-left: 1%; height: 50%; float:left")
button#btnEncrypt Encrypt
button#btnDecrypt Decrypt

23
static/layout.pug Normal file
View File

@ -0,0 +1,23 @@
doctype "html"
html(lang="en")
head
meta(charset="UTF-16")
title TryCrypt
link(rel="stylesheet" href="reset.css")
link(rel="stylesheet" href="style.css")
meta(name="viewport" content="width=device-width, initial-scale=1")
script const exports = { "__esModule": true };
body
block body
script(src="../dist/trycrypt.bundle.js")

60
static/reset.css Normal file
View File

@ -0,0 +1,60 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
border: 0;
font: inherit;
font-size: 100%;
margin: 0;
padding: 0;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: "";
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}

60
static/style.css Normal file
View File

@ -0,0 +1,60 @@
body {
font-size: 14pt;
font-family: SansSerif, serif;
font-weight: 100;
}
h1 {
font-size: 4.5em;
}
h2 {
font-size: 3.7em;
}
h3 {
font-size: 3em;
}
h4 {
font-size: 2em;
}
h5 {
font-size: 1.5em;
}
#general {
margin-left: 3%;
margin-top: 2%;
}
button {
border: 0;
background-color: darkslategrey;
color: white;
height: 1.5em;
border-radius: 3px;
font-size: 0.8em;
}
button:hover {
background-color: #65A4A4;
}
button:active {
background-color: #146B4D;
}
#btnEncrypt, #btnDecrypt
{
float:left;
margin-top: 1%;
height: 6%;
width: 48.5%;
margin-left: 1%;
}
#systemTB:active {
background-color: #91DE93;
transition: background-color 0.1s;
}

20
tsconfig.json Normal file
View File

@ -0,0 +1,20 @@
{
"compilerOptions": {
"noImplicitAny": true,
"sourceMap": true,
"outDir": "dist",
"target": "ES5",
"module": "commonjs",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": true,
"suppressImplicitAnyIndexErrors": true
},
"include": [
"./src/"
],
"exclude": [
"node_modules"
]
}

26
webpack.config.js Normal file
View File

@ -0,0 +1,26 @@
const path = require( "path" );
module.exports = {
mode: "development",
devtool: "inline-source-map",
entry: {
trycrypt: "./src/web/page.ts",
},
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
},
],
},
resolve: {
extensions: [".tsx", ".ts", ".js"],
},
output: {
filename: "[name].bundle.js",
path: path.resolve( __dirname, "dist" ),
},
};

4396
yarn.lock Normal file

File diff suppressed because it is too large Load Diff