Skip to content

Commit

Permalink
chore: Reorganize code Part 1 (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kunal Nagar committed Jan 2, 2021
1 parent 7272d5d commit d447e7f
Show file tree
Hide file tree
Showing 12 changed files with 218 additions and 122 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
"build:tsc:watch": "tsc --watch",
"deploy": "sh ./scripts/deploy.sh",
"dev": "npm run prebuild && npm run build:tsc && npm run build:copy && npm run build-grunt && electron dist/main.js & npm run build:tsc:watch & grunt watch",
"lint": "eslint src/ --ext .js --max-warnings 0",
"lint:fix": "eslint --fix src/ --ext .js --max-warnings 0",
"lint": "eslint src/ --ext .ts --max-warnings 0",
"lint:fix": "eslint --fix src/ --ext .ts --max-warnings 0",
"release": "npm run prebuild && npm run build:tsc && npm run build:copy && npm run build-grunt && npm run build-mac-x64 && npm run zip-mac-x64 && npm run build-win-x86 && npm run zip-win-x86 && npm run build-win-x64 && npm run zip-win-x64 && npm run build-linux-x64 && npm run zip-linux-x64 && npm run build-linux-deb && npm run zip-linux-deb",
"release:standard-version": "standard-version",
"zip-linux-deb": "zip -r release-builds/encrypt0r-linux-deb.zip release-builds/*.deb",
Expand All @@ -52,8 +52,8 @@
"package.json": [
"sort-package-json"
],
"src/**/*.js": [
"prettier --write src/**/*.js",
"src/**/*.ts": [
"prettier --write src/**/*.ts",
"npm run lint:fix"
]
},
Expand Down
86 changes: 86 additions & 0 deletions src/Crypto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { EventEmitter } from 'events';
import { ReadStream, WriteStream } from 'fs';

import { getCipher, getDecipher } from './utils/cipher';
import { compress, decompress } from './utils/compress';
import { getFileSize } from './utils/file-size';
import {
getInitializationVector,
getInitializationVectorStream,
} from './utils/initialization-vector';
import { calculateProgress } from './utils/progress';
import { getDestinationStream, getSourceStream } from './utils/stream';

export interface ICrypto extends EventEmitter {
encrypt(): void;
decrypt(): void;
}

export default class Crypto extends EventEmitter implements ICrypto {
private _sourceFilePath: string;
private _destinationFilePath: string;
private _passphrase: string;

constructor(
sourceFilePath: string,
destinationFilePath: string,
passphrase: string,
) {
super();
this._sourceFilePath = sourceFilePath;
this._destinationFilePath = destinationFilePath;
this._passphrase = passphrase;
}

encrypt(): void {
const initializationVector = getInitializationVector();
const initializationVectorStream = getInitializationVectorStream(
initializationVector,
);
const cipher = getCipher(this._passphrase, initializationVector);
const sourceStream = getSourceStream(this._sourceFilePath);
const destinationStream = getDestinationStream(this._destinationFilePath);
sourceStream
.pipe(compress())
.pipe(cipher)
.pipe(initializationVectorStream)
.pipe(destinationStream);
this._handleSourceStream(sourceStream);
this._handleDestinationStream(destinationStream);
}

decrypt(): void {
const initializationVectorStream = getSourceStream(
this._sourceFilePath,
0,
15,
);
const sourceStream = getSourceStream(this._sourceFilePath, 16);
const destinationStream = getDestinationStream(this._destinationFilePath);
initializationVectorStream.on('data', (chunk) => {
const initializationVector = chunk as Buffer;
const decipher = getDecipher(this._passphrase, initializationVector);
sourceStream.pipe(decipher).pipe(decompress()).pipe(destinationStream);
});
this._handleSourceStream(sourceStream);
this._handleDestinationStream(destinationStream);
}

private _handleSourceStream(sourceStream: ReadStream) {
let currentSize = 0;
const totalSize = getFileSize(this._sourceFilePath).size;
sourceStream.on('data', (chunk) => {
currentSize += chunk.length;
this.emit(
'crypto:source_stream:progress',
calculateProgress(currentSize, totalSize),
);
});
}

private _handleDestinationStream(destinationStream: WriteStream) {
destinationStream.on('finish', () => {
this.emit('crypto:destination_stream:finish');
});
}
}
24 changes: 14 additions & 10 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { app, BrowserWindow, dialog, ipcMain } from 'electron';
import log from 'electron-log';
import path from 'path';

import Utils from './utils';
import Crypto, { ICrypto } from './Crypto';

let mainWindow: BrowserWindow | null;

Expand Down Expand Up @@ -49,20 +49,24 @@ ipcMain.on('action:encrypt_decrypt', async (e, arg) => {
} else if (arg.action === 'decrypt') {
popupFileName = arg.filePath.replace('.enc', '');
}
let utils: Utils;
let crypto: ICrypto;
try {
const file = await dialog.showSaveDialog({
defaultPath: popupFileName,
});
if (typeof file !== 'undefined') {
utils = new Utils(arg.filePath, file.filePath, arg.passphrase);
crypto = new Crypto(
arg.filePath,
file.filePath as string,
arg.passphrase,
);
if (arg.action === 'encrypt') {
log.info(`Encrypting ${file.filePath} with password <redacted>`);
utils.encrypt();
utils.on('progress', (progress) => {
crypto.encrypt();
crypto.on('crypto:source_stream:progress', (progress) => {
e.sender.send('notice-status', `Encrypting...${progress}%`);
});
utils.on('finished', () => {
crypto.on('crypto:destination_stream:finish', () => {
log.info('File successfully encrypted!');
e.sender.send(
'notice-status',
Expand All @@ -71,18 +75,18 @@ ipcMain.on('action:encrypt_decrypt', async (e, arg) => {
});
} else if (arg.action === 'decrypt') {
log.info(`Decrypting ${file.filePath} with password <redacted>`);
utils.decrypt();
utils.on('progress', (progress) => {
crypto.decrypt();
crypto.on('crypto:source_stream:progress', (progress) => {
e.sender.send('notice-status', `Decrypting...${progress}%`);
});
utils.on('finished', () => {
crypto.on('crypto:destination_stream:finish', () => {
log.info('File successfully decrypted!');
e.sender.send(
'notice-status',
`Done! File has been saved to: ${file.filePath}`,
);
});
utils.on('error', (reason) => {
crypto.on('error', (reason) => {
if (reason === 'BAD_DECRYPT') {
e.sender.send(
'notice-status',
Expand Down
87 changes: 0 additions & 87 deletions src/utils.ts

This file was deleted.

33 changes: 33 additions & 0 deletions src/utils/cipher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {
Cipher,
createCipheriv,
createDecipheriv,
createHash,
Decipher,
} from 'crypto';

const getCipherKey = (password: string): Buffer => {
return createHash('sha256').update(password).digest();
};

export const getCipher = (
password: string,
initializationVector: Buffer,
): Cipher => {
return createCipheriv(
'aes-256-cbc',
getCipherKey(password),
initializationVector,
);
};

export const getDecipher = (
password: string,
initializationVector: Buffer,
): Decipher => {
return createDecipheriv(
'aes-256-cbc',
getCipherKey(password),
initializationVector,
);
};
9 changes: 9 additions & 0 deletions src/utils/compress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createGunzip, createGzip, Gunzip, Gzip } from 'zlib';

export const compress = (): Gzip => {
return createGzip();
};

export const decompress = (): Gunzip => {
return createGunzip();
};
5 changes: 5 additions & 0 deletions src/utils/file-size.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Stats, statSync } from 'fs';

export const getFileSize = (path: string): Stats => {
return statSync(path);
};
13 changes: 13 additions & 0 deletions src/utils/initialization-vector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { randomBytes } from 'crypto';

import Vector from './vector';

export const getInitializationVector = (): Buffer => {
return randomBytes(16);
};

export const getInitializationVectorStream = (
initializationVector: Buffer,
): Vector => {
return new Vector(initializationVector);
};
6 changes: 6 additions & 0 deletions src/utils/progress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const calculateProgress = (
chunkSize: number,
totalSize: number,
): number => {
return Math.floor((chunkSize / totalSize) * 100);
};
21 changes: 21 additions & 0 deletions src/utils/stream.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {
createReadStream,
createWriteStream,
ReadStream,
WriteStream,
} from 'fs';

export const getSourceStream = (
path: string,
start?: number,
end?: number,
): ReadStream => {
return createReadStream(path, {
start,
end,
});
};

export const getDestinationStream = (path: string): WriteStream => {
return createWriteStream(path);
};
27 changes: 27 additions & 0 deletions src/utils/vector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Transform, TransformCallback } from 'stream';

export default class Vector extends Transform {
private initVector: Buffer;
private isAppended: boolean;

constructor(initVector: Buffer) {
super();
this.initVector = initVector;
this.isAppended = false;
}

_transform(
chunk: any,
encoding: BufferEncoding,
cb: TransformCallback,
): void {
if (!this.isAppended) {
this.push(this.initVector);
this.isAppended = true;
}
this.push(chunk);
cb();
}
}

0 comments on commit d447e7f

Please sign in to comment.