Creating File Encryption app using Electron and Tailwind CSS

Creating File Encryption app using Electron and Tailwind CSS

ยท

7 min read


If you want to use the program without reading the blog feel free to download the app from my GitHub repo below and get started.

Quick demo ๐Ÿ“ฝ


What is Electron ๐ŸŒŒ

Electron is a framework that allows us to create Desktop applications using web technologies like HTML, CSS and JavaScript. The main advantage of Electron is cross-platform support, meaning one code base can be used to target different Operating-systems i.e. Windows, macOS and Linux.

Why a File Encryption App ๐Ÿค”

I use VeraCrypt, which is a free and open-source Disk Encryption software. But it can seem a bit daunting and hard to use with its UI and all the various settings it offers. Sometimes you just need a quick way to encrypt your files.

A Use-case which I personally had was that my laptop hinge had to be repaired. So I went to the Service-center and they told me I have to keep my laptop for a few days and need to give them my laptop password so that they can check if everything is working fine after the repair was done. So I had to copy all my personal/family photos and videos, Aadhaar card, Pan card PDFs, etc. which are always needed for some work to my phone coz I don't trust nobody ๐Ÿ˜‚. My app is really helpful in such situations and I don't need to worry about people going through my stuff.

Another reason is that macOS already has a built-in app called FileVault which can be used to encrypt files. On the other hand, Windows has BitLocker but is only available for Pro, Enterprise, or Education versions of Windows 10.

Video Tutorial by Traversy Media ๐Ÿ“บ

In this tutorial he creates a Simple Image resizer app and teaches how Electron works.

Creating an Electron app ๐Ÿ—

The Electron Documentation is a great source to know about how to create an Electron app and how it works. In this blog, I'm gonna tell about how the encryption process works and how I built the app. To know more about how Electron works, check the above video or any other tutorial on YT.

First, create a package.json file with npm init -y and then install Electron and Tailwind CSS using the below command.

npm i --save-dev electron tailwindcss

The package.json will look something like this.

{
  "name": "file-encryptor",
  "version": "1.0.0",
  "description": "An app to encrypt/decrypt files with a password.",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "electron": "^21.2.3",
    "tailwindcss": "^3.2.3"
  }
}

Electron has 2 types of processes, the Main process(only 1) and the Renderer processes(more than 1). The entry point of an Electron app is its Main process which controls the state of the application while the Renderer process controls the UI using HTML, CSS and JavaScript. Now let's create our main.js

The function createMainWindow will create our window app. We are importing app, BrowserWindow and Menu modules from electron. When the Electron app is ready we create a new BrowserWindow with the properties provided and load it in our index.html file which is going to be the main UI of our application, so create and add some content in the index.html.

By default the DevTools cannot be accessed so if we need to debug our app, we can use the below code to open DevTools.

mainWindow.webContents.openDevTools()

I have set a condition for it and the resize property in my code cause when I build the app, I don't want the console to be shown to the user.

Creating a Menu is pretty easy and you can do so by watching the above video.

Running the App ๐Ÿƒโ€โ™‚๏ธ

The basic app is complete and now to run the app add the below command in the scripts section of package.json and run npm run start.

"start": "electron ."

This is good but now if we make any changes in our app we need to run the command again and again, to tackle this we can use electronmon which is like a live server that updates any changes we make in the app instantly. To use type the below command.

npx electronmon .

Setting up Tailwind CSS ๐ŸŽจ

The Best video tutorial on how to setup TailwindCSS by Shruti Balasa

Encryption ๐Ÿ”

Now let's go over the encryption code. Here I used the built-in Crypto module in NodeJS. Both encrypt and decrypt functions takes the data i.e. the file content and password to encrypt/decrypt. Next using pbkdf2Sync ("Sync" meaning Synchronous) which is a KDF, we create a secure key from the password and use it to create the Cipheriv and Decipheriv that uses AES-256 to encrypt/decrypt the data. I also append the random salt and AuthTag at the start of the encrypted data since we will need that to decrypt the data.

What is KDF and AuthTag ๐Ÿ—

KDF (Key Derivation Functions) derives a key from a value. When saving a user's password in a database, SHA-256 or some other hash functions (which are one-way functions meaning it cannot be reversed to its original content), are used to save the password. So in case of a data leak, the hashes are exposed to the hacker and not the actual passwords in plaintext. But SHA-256 as a KDF is not as secure. It is vulnerable to Brute-Force and Dictionary Attacks. PBKDF2 is a better KDF that is designed to withstand such attacks.

AuthTag (Authentication Tag) also known as MAC (Message Authentication Code) is like a hash function, so a minor change in the data or key will result in a totally different AuthTag value from which we can know that the data has been tampered. You can check the below page to learn more about the MAC and the parameters used in PBKDF2.

File Encryption/Decryption ๐Ÿ“„

To read/write files we are going to use the fs and path modules which makes it easier to work with files. With the help of fs.createReadStream and fs.createWriteStream we can read/write a file in small chunks instead of the whole file which can cause memory to be filled if the file size is really big. The default chunk size returned by the Stream is 64KiB which can be increased using the highWaterMark option.

With the help of path module, we get the directory, file name and file extension of a file from which we can create a new file path and add __ENC to the file name.

Next with the help of pipeline, we can link our ReadStream and WriteStream which handles the errors and closes the Stream to make sure there are no memory leaks. The Transform stream in it, is a Stream that reads data from the ReadStream, transforms the data, and then writes the transformed data in the WriteStream. You can read more about it here with simpler examples.

Preload Scripts ๐Ÿ”—

Now that we have all the functions ready, how do we use them in the frontend of our app, meaning in the Renderer process because the Main process is a NodeJS environment that has full OS access and can use the built-in NodeJS modules. The Renderer process on the other hand runs web pages and does not run NodeJS for security reasons and thus cannot access the NodeJS modules we used like - fs, Crypto and path.

With the help of Preload script we can bridge the NodeJS code to the Renderer process and expose any functionality or APIs using contextBridge from electron and to access it we use the window Object.

To learn more about Preload Script check out the docs here or the below video for a quick example.

Conclusion ๐Ÿ‘‹

And that's pretty much the main code of the app. The rest of the app is plain HTML, CSS and JavaScript which you can learn from here. This is not the most detailed blog on Electron and so I added some resources to learn from. I just wanted to give you an overview of how I built the app.

Do download it from the link below and give it a go. Hope you learned something and thanks for reading.

Did you find this article valuable?

Support Abhishek by becoming a sponsor. Any amount is appreciated!

ย