Securing Data in Electron Apps, Part 1

Trevor Foskett
Virtru Technology Blog
4 min readFeb 27, 2020

Adding Encryption to Electron with the Virtru Node SDK

Photo by Raphaël Biscaldi on Unsplash

As someone who considers himself a bit of a novice coder, I’ve always found the combined simplicity & power of the Electron framework to be really attractive. Writing desktop apps in nothing but JavaScript, HTML, and CSS means I can start moving my projects out of the browser, off the command line, and into standalone, user-friendly (and demo-friendly!) applications. And since the Virtru SDK is available in NodeJS, I figured it would be relatively easy to integrate into an Electron app (spoiler: it was). Finally, with a large open-source community, there’s no shortage of sample projects to work off or potential integrations to try.

Quick Links

While this project can be expanded in many different directions, I decided to start simple: a desktop application that encrypts and decrypts files based on user input and interaction. Unlike my Node command line encryption project, this project will let users select files from the native file dialog and save to the location of their choice.

Building It

Given this was looking to be my most complex project to date, I broke it down into a few steps:

  1. Get a simple Electron UI running.
  2. Get the native file menu to display after clicking a “Select File” button.
  3. Pull in data from selected file.
  4. Encrypt selected file with the Virtru SDK.
  5. Add additional user controls for sharing, expiration, watermarking, and disabling of re-sharing.
  6. Add advanced settings page to allow users to update credentials and specify save location.

Getting the initial base app running is easy — just follow along with Electron’s “First App” guide and you’ve already got an application with its own window running. I just needed to add my own basic HTML to the index.html file to render Virtru’s logo and a “Select File(s) button. Step 1 done!

main.js — Quickstart Electron code to generate the app & a window.

Next, the button hast to actually perform an action. To do this, we need communication between Electron’s main thread, main.js — responsible for creating browser windows and interacting with your OS and the renderer process, renderer.js — running code within those browser windows generated by the main process. A full breakdown of how these interact is found here. For the purpose of my application, it’s a simple communication: upon button click in the renderer process, send a message to the main process to open a native file dialog to select a file. Electron comes equipped with functionality for both of these already. The ipcRenderer module can exchange messages with the main thread, and the dialog module opens system-native dialogs and menus. Part 2 in the bag.

The dialog module also helps us pass in the full path of any selected files, meaning we’re not restricted to pulling from one predefined “input folder” as was the case in my previous projects. We can then pass that path information to any function in our app to act on that file. Easy win on step 3.

renderer.js — Button click sends event to main thread.
main.js — Main thread registers the button click event and opens the file dialog to select filepaths.

At this point, I added the Virtru SDK to encrypt the selected file(s).

main.js — Pass selected files to Virtru encrypt function.

Now for the bells and whistles. As with my Google Doc encryption project, I added toggles for the user to add security controls to each file; these settings are then used to construct the policy object that will dictate how other users interact with this protected content. Since the policy is created in the main thread, the user selections need to be communicated from the renderer process:

renderer.js — Send user inputs to main thread.

The main process then updates the policy with those settings:

main.js — Construct policy object based on inputs received from renderer.

That takes care of most of the functionality we need, but in order to make this easier to use for others, I wanted to add a few more things:

  • Decryption functionality
  • Settings page

The decrypt functionality was really easy to add after completing all of the above work; I used the same mechanism for opening a file dialog and operating on the selected file, this time simply with a decrypt function rather than encrypt. On a decrypt operation, there’s no need to input any policy settings, so there’s no additional work.

I wanted to add a settings page so that users wouldn’t have to open up some obscure file in order to add or update their Virtru AppID. I added another button that triggers a new BrowserWindow object in the main thread that will open with its own settings.html file to render my settings page.

main.js — Create a new window to show the settings page.

On this page I included three user input fields: email address, appId, and a save location for encrypted or decrypted files. I used Cameron Nokes’ example to create a simple data store object where those values are stored and read.

The finished product.
Settings page.

Conclusion

Being my most complex project to date, I learned a lot about Electron and JS programming concepts in general while building this. I’m excited to keep iterating on this project to see what other functionality I can add. Off the top of my head, I’m thinking about options to upload encrypted data to cloud storage (easy integration with one of my previous projects) or to send as an email attachment. And as mentioned above, there are ton of open source Electron apps out there that would be ripe for an integration. Let me know in the comments if you have any ideas for a future project that we can cover in subsequent posts!

--

--