Designing an End-to-End Encrypted HTML Form Using OpenPGP.js
Published on 01 Sep 2021
| Updated on 20 Jun 2022
Written by Pranav Chakkarwar
12 min to read
Advantages of using End-to-End Encryption
Almost all form backend providers support submissions over TLS/HTTPS. That means, if someone submits a message on your website, the message is already encrypted between the sender, form’s backend provider, form’s email provider, your email provider and you, but that also adds more participants to your conversation: form and email service providers. So, if you want to keep your conversation between you and the sender only, you’ll need an end-to-end encrypted contact form that encrypts messages on the client side before transmitting them. This way, email or backend service providers would not understand the contents of a message and as a result, you can use this approach to handle sensitive communications. This solution is also resistant to person-in-the-middle attacks. But, keep in mind that metadata, like, time of submission, IP address, etc, may still be recorded. I have also not considered any security aspects of end users or browsers. Like cross-site-scripting attacks or browser extensions. I will probably work on it when I have some time.
Take a look at my contact form to get an idea of the user experience.
Building a Basic Contact Form
Lastly, we need a button to call the encryptUserMessage() function.
Make the Form Look Pretty
Did you notice that I also added a main.js file? Yes, we will use it to pass our public key to openPGP.js, which will be used to encrypt the sender’s message.
OpenPGP provides a readKey function to read your armoredKey. We will pass a public key to it and store the result in a const.
Once a user enters their contact details, name and a message, we will combine all three inputs as one whole message.
Encrypting a message is fairly simple and can be done by using an encrypt function from the OpenPGP library. You just need to pass a message and a processed public key as arguments to the function. To do that, create an async function, so you can call it using the encrypt button.
The encrypt button will also hide all unnecessary fields (email, name, encrypt message button) and assign the encrypted message as the value to the textarea, because the form will send any text that is included within the textarea. It also serves as a visual cue to the user that their message has been encrypted!
Below is the full function to encrypt a message.
The code to submit the contact form should be self-explanatory.
I hope this will serve as a cool programming project for your weekend. Stay subscribed.
Get an E2EE Contact Form
In the past, I had a section where people could easily get their own contact form. It turns out that the process wasn’t all that simple for many people. I’m now working on a better solution.