End to end encryption for WordPress
Skip to: Installation
The leaking of information by Edward Snowden has helped increased awareness of privacy, but unfortunately most people do not know how to securely store their own data. I have seen people storing extremely sensitive data within WordPress installations and assuming everything is fine since they used a “private page” or placed a password on it. But even though WordPress provides private and password protected pages, these still leave your data open to spying at both the server level and whilst in transit. Even if your server is locked down and secure, and you route the data over https, a man in the middle attack could still be used to gain access to your data.
The only true solution to securing your data within WordPress, is through the use of end to end encryption. The End to end encryption plugin for WordPress is my attempt to help alleviate this problem within the WordPress sphere and perhaps increase the prevalence of secure data storage across the interwebz.
How?
The trick to ensuring true end to end encryption within WordPress, is to encrypt your posts before they are sent back to the server and only decrypt them once they arrive back at browser level. This means that there is no point of failure outside of the computers being used to access the web pages.
Even if the server is hacked, the only thing which could be obtained is a blob of encrypted data. To access the content, either your computer would need to be hacked or you would need to be forced to hand over the encryption key. With the End to end plugin, not even your WordPress installation will be able to decrypt your content, due to it’s use of true end to end encryption.
There is one theoretical attack vector left at this point, due to the server being able to provide malicious JavaScript which could be used to acquire your encryption key. This could be fixed through the use of a browser plugin (see below for more information on this possibility), but in the mean time what I have here will hopefully be sufficient for most people’s purposes.
Downsides
The big downside to end to end encryption, is that you need to provide the encryption keys every time you want to access the content. I may be able to implement encryption key storage via browser offline storage in future, but I haven’t implemented it yet.
You will not be able to perform server side searching with encrypted posts. Since the content is encrypted, WordPress has no way to search through it. Front-end searching is technically possible, but not practically feasible due to the need to download every page on your site before searching.
The normal filters on WordPress content can not be applied (since WordPress can’t read the content anyway). So things like paragraph tags and line breaks need to be manually added. The content you put into the WordPress editor will be read as raw HTML. Any extra content added by plugins will also not work on encrypted posts, including many plugins which add things like social sharing icons (since most of them work by filtering the post content).
Encryption type
The encryption used within the end to end WordPress plugin, is the simple but highly effective AES style encryption provided by Chris Veness. AES is a powerful encryption algorithm based on the Rijndael cipher. This is the exact same cipher used and recommended by many government agencies for top secret data storage and is considered the industry standard for storing extremely sensitive data.
To learn more about AES symmetric ciphers, check out Symmetric Ciphers from Leo Laporte and Steve Gibson. To ensure maximal security, it is recommended that use a complex encryption key. Head on over to Steve Gibson’s password haystacks page to help find a suitable password/encryption key.
Innovation?
There is nothing particularly innovative about this WordPress plugin, but it is intended as a way to drop the barrier of entry for those wanting to properly encrypt their own content online. I’ve seen plenty of other tools which claim to protect your data through encryption, but these almost always have failures in some ways. The recent case of the USA authorities compelling Ladar Levison to hand over the SSL keys for the Lavabit email service is a prime example of the problems associated with attempting to secure content with true end to end encryption in place.
Guaranteed?
I’m not guaranteeing anything with this plugin! To the best of my knowledge, the cipher is secure and in principle I believe there is no way to access your data without you sending data in the clear. There are some bugs in the current implementation which can cause you to send unencrypted data if you aren’t careful. This plugin is here as a proof of concept at this stage and is definitely not intended to be trusted for securing highly sensitive data.
Installation
Note 1: This is a beta and contains some known issues (see below)
Note 2: This was created before the Gutenberg block system was added to WordPress. To use this plugin, first install the Classic Editor plugin for WordPress to disable the block system
Download the End to end plugin beta, install it in your WordPress site and activate it.
There will be an encryption key input field above “Publish” when editing a post. If a key is set, then encryption will be applied and you will be prompted to re-enter it to view the content again.
It is critical to ensure that you do not forget the keys. If you forget them, you will never be able to recover the content (which is the point of this plugin – it should be uncrackable).
Note: Since this is true end-to-end encryption, you will be required to enter this EVERY time you access this content.
Known issues
- Using the WordPress visual editor can produce unintended results and break the encryption
- Saving as a draft can result in unencrypted versions being saved
- Auto-save can accidentally save unencrypted versions
- Click “Preview” can result in unexpected behaviours. Future versions will fix this problem.
- If someone can see your screen, then they could work out what keys you are pressing by reversing the encryption for each keystroke.
- https via regular certificate providers is known to be cracked by various governments, including the Five Eyes. To avoid this issue, it is best to use a self-signed certificate with the certificate manually added to your web browser.
Browser plugin
To provide a truly secure system (assuming the users own browser is secure), a browser plugin would be required. This is due to the risk of the server deploying malicious JavaScript which could be used to acquire the encryption key. The browser plugin could block the page itself from loading any JavaScript, then deploy it’s own JavaScript to handle the encryption/decryption process.
Personally, I’m not paranoid enough to require that much protection just yet, but it may be a suitable project for the future perhaps. If anyone would like to tackle it, I’m super keen to work together on it.
Demo
I’ve put up a demo at geek.hellyer.kiwi/encryption-demo. The encryption key for this demo is “test” (but you should never use a key which is this short, I just did it this time since it is here for demo purposes).
Inspiration
I have been storing my own sensitive data in a pseudo-secure way for a long time now and after listening to many episodes of the Security Now podcast by Steve Gibson and Leo Laporte over the past few years, I decided it was time I found a solution to my problems. The End to end encryption plugin now allows me to store anything I like within my WordPress installation without fear that evil doers may be snooping in.
Ryan Hellyer says:
Kaspars Dambis kindly pointed out that I haven’t handle nonce’s correctly, which is a security problem in itself
It also seems there is some confusion over the use of JavaScript, so I’m going to update the page at some point to explain this issue more clearly. As it stands, there is an attack vector (which I alluded to above) caused by the user of in-page JavaScript. If the server is compromised, then so could the JavaScript it self and so you could inadvertently hand over your encryption key if the JavaScript were attacked. To get around this issue, it will be necessary to write a browser plugin, but hopefully the plugin is useful to many people in it’s current form. It’s certainly better than no protection at all.
I also need to fire an error if you attempt to submit the post without having JavaScript turned on (I hadn’t thought of this issue until now).
December 2, 2013 at 10:28 am # //
Alex McMillan says:
Brilliant, Ryan – this is just the kinda thing we need to begin with. I hope you keep developing it and don’t get bored with it π
Cheers,
Alex
December 6, 2013 at 10:56 pm # //
Ryan Hellyer says:
I’m working on it right now π It had WAYYY too many bugs, so needed quite a bit of work. I found another bug about two minutes ago too. If you try to use the visual editor in WordPress, it breaks it, which would be okay since you would see it’s broken, but if you decrypt an old message, then flick to the visual editor and hit “Update”, it actually sends your decrypted message back to the server … poop.
Is there any chance you know much about browser plugins Alex? I tried looking through the Chrome documentation but it looked a little confusing to me and I’m hoping I can find someone interested in this stuff who can assist me in building that side of it. It’s okay in it’s current form (once I iron out the bugs), but it’s not truly secure due to the risk of someone tampering with your JavaScript.
December 6, 2013 at 11:01 pm # //
Alex McMillan says:
Sorry Ryan, I’d love to help but I’m committed to too many projects right now as it is and I don’t want to start giving false promises. Good luck tho man – great cause!
December 6, 2013 at 11:50 pm # //
Paul says:
Hey Ryan,
isn’t HTTPS supposed to protect against man in the middle attacks if it’s correctly configured?
http://stackoverflow.com/a/14907718/285564
December 8, 2013 at 1:06 pm # //
Ryan Hellyer says:
https offers protection from client to server. This plugin is attempting to provide protection from client to server, then back to client.
Of course, it is not perfect, since there is the potential for the server to launch a JavaScript attack on you, but that’s why I’m suggesting the construction of a browser plugin to avoid that risk.
December 8, 2013 at 1:09 pm # //
Ryan Hellyer says:
I forgot to mention one other problem with https … if someone has access to the root certificate, then they can decrypt ALL of your traffic, making https kinda useless. It has already been revealed that the NSA has been obtaining expired certificates, which can be used to retrospectively decrypt content even after the certificate has long since expired and is no longer in use.
December 8, 2013 at 1:19 pm # //
David says:
Hi,
I’m very interested in this plugin and wanted to know how it was progressing?
Does this plugin have the potential to be customized to encrypt specific user details (username, profile information, messages) in the wordpress database, rather than posts?
Ideally would the following be a possible way to deal with the decrypting?
Define a single complex password [CP] that will be used for encrypting all content (or which will be used for accessing a database)
For each user of your site, encrypt the CP and save it in a small file. Use that userβs own web site access password as the password to decrypt their own version of the encrypted CP.
June 17, 2014 at 8:59 pm # //
Ryan says:
You couldn’t use their regular password, as that would be sent back to the server to log you in each time. This plugin could be adapted to encrypt just about anything so long as it isn’t something WordPress needs to analyse internally (usernames for example are used by WordPress itself).
Defining a single password would be nice, but you would either need to constantly enter that password, or find some way via cookies, offline storage or best of all, via a browser plugin to handle it.
I have one more addition I want to add to the plugin and that is preventing it from decrypting the content live whilst you watch it, and instead waiting until you hit a “decrypt” button. This is to prevent anyone watching you, from being able to work out what keys you pressed based on the iterative decryption which occurs now.
June 17, 2014 at 9:06 pm # //
Ryan says:
My attempts to figure out how to do this as a browser plugin failed and I haven’t had any offers to help, so at the moment, that side of it is on hold.
June 17, 2014 at 9:07 pm # //
Frank says:
Isn’t it possible to hash the critical Javascript files and compare the hash with an online fetched hash lying on one or two different servers? This would be much more practical than developing and maintaining(!) browser plugins.
Cheers,
Frank
June 22, 2014 at 9:16 pm # //
Ryan says:
You can verify the JavaScript files via a hash, but how can you verify the hash? Since the hash would be stored alongside the JavaScript files, then an attacker simply need to create a new hash to bypass the check.
You could manually copy and paste the hash from your desktop into a textarea, then store that in a cookie perhaps. But you would still be reliant on JavaScript to do the hash check, JavaScript which could be controlled by an attacker.
The only way I can think of to work around this issue, is through the use of a browser plugin.
June 23, 2014 at 1:15 pm # //
Frank says:
>you would still be reliant on JavaScript to do the hash
>check, JavaScript which could be controlled by an
>attacker.
Good point, yes, you\\\’re right.
At the end: if paranoia is on its way there is no way out. Even a browser extension could be hacked. If you place the processing JS there then the attackers interest also moves there.
Maybe it\\\’s better to think about an independently working security suite that checks file checksums by a servers cron job, like rkhunter.
Cheers,
Frank
June 23, 2014 at 3:23 pm # //
Ryan says:
You can manually go through and check the code in a browser plugin though, you can’t do that with a website (unless you audit the code every time you load a page).
An independent server can be hacked just as easily as the original one, so that won’t help.
June 23, 2014 at 3:34 pm # //
Ryan says:
It is also much harder to attach via a browser plugin, since the update mechanism for the browser plugin would presumably send an email when a change was made (like WordPress does with plugins).
As soon as bad code was deployed, you would be notified about it.
June 23, 2014 at 3:36 pm # //
Frank says:
However, thanks for this plugin so far!
June 23, 2014 at 5:23 pm # //
Ken Griffith says:
I am much more interested in a way to encrypt member data in the WordPress database.
The risk of MIM attacks is pretty small. The valuable data is in the mysql database, which is far easier to attack than performing a MIMA.
January 6, 2015 at 10:51 am # //
Ryan says:
This plugin isn’t only for man in the middle attacks, it also stops attacks on the server. Even if you have encrypted the data in the DB, if you have left the keys for it on the server, then as soon as the server is compromised so is your DB no matter whether it is encrypted or not. And even if you enter the keys in the browser to decrypt each time, those could be stolen once they reach the server (if it is compromised).
What you described would be a completely different plugin since it wouldn’t featured encryption from end to end. I remember seeing a lot of plugins out there when I was researching this one that did exactly that. They possibly have some uses, but you certainly wouldn’t want to go storing extremely sensitive data in there since it wouldn’t be totally secure.
January 6, 2015 at 3:49 pm # //
Ryan says:
I would like to see a plugin which can encrypt images on the server, then decrypt them on the fly each time they’re viewed. I often store images on my website that I’d rather didn’t go public (usually important documents and so forth). Securing them via JavaScript in the browser is probably too cumbersome, but on the server it wouldn’t be too difficult. I’m not sure if there’s anything out there to do that just now though :/
January 6, 2015 at 3:51 pm # //
Shannon W says:
Hi, I found your article searching for encryption and it was insightful and helped me understand there are some solutions available BUT.. . it appears to encrypt posts and post data. can this be used to encrypt files? i.e. if I give access to a customer and they can view files, can I encrypt the files, per user, and they can only view these files with a personal encryption key (not a global, one for all key)
Am I dreaming?
September 1, 2015 at 12:58 am # //
Ryan says:
That is technically possible, and I would love to do it, but there are a lot of problems involved.
For it to be true end-to-end encryption, the file would need to be encrypted in the browser, then sent back to the site as an anonymous data blob, then decrypted as an anonymous blob in the browser when viewing it, and turned back into an image.
My JavaScript skills are not good enough for that. I do know how to do it server side though, which is probably the route I would take if I were to implement this. It would result in more load on the server, as every time an image was downloaded, it would need to be decrypted in PHP and sent out, rather than just dumped out directly by the web server. But I don’t think that performance problem would be a huge concern as I doubt may people would have huge numbers of people viewing encrypted files regularly.
September 1, 2015 at 8:33 am # //
Peter says:
Very interesting plugin Ryan. I am going to experiment with it directly .
I will follow you on Twitter!
Regards
Peter – The Netherlands
February 11, 2017 at 2:22 pm # //
Peter says:
Hi Ryan,
We need your solution combined with Gravity Forms developed forms. Will there be a integration/solution for this?
Thanks for your answer in advance.
Peter
February 11, 2017 at 2:42 pm # //
Ryan says:
Hi Peter. That would need to be custom built and require quite a bit of work.
I am available for paid jobs if you need assistance with this.
https://ryan.hellyer.kiwi/contact/
February 16, 2017 at 8:26 pm # //
Paul says:
As of August 2019, do you have updates to this plugin, or any recommendations as to what others use to achieve the same goals?
August 13, 2019 at 12:24 am # //
Ryan Hellyer says:
I don’t have any updates for the plugin. It seems to be working as well as it did when I created it.
I don’t have any particular advice, although extending it to use a browser extension would be a nifty way of doing it. You may also consider handling the editing via the frontend rather than the backend, as this would allow you to avoid potential security issues caused by changes in the WordPress backend.
January 28, 2020 at 9:34 am # //
mark says:
Is there an update? The new WordPress isn’t compatible…
August 25, 2019 at 9:49 am # //
Ryan Hellyer says:
The new WordPress is compatible. I’m using it right now with it π
January 28, 2020 at 9:30 am # //
Vicente Guzman says:
Hi. I am working in a project and I have been required to use encrypted data in WordPress. Can you help me with the following?, If I use your plugin:
1-Is Data At Rest Encrypt?
2-Is Data Classified?
3-Dynamic Data Masking on Sensitive Data?
Also How can I download it?, I want to use it. Thanks
May 2, 2020 at 6:39 pm # //
Ryan Hellyer says:
The data is encrypted when it as rest. Iβm not sure what you mean by classified or dynamic data masking.
It is available to download on the page you posted the comment on here.
July 6, 2020 at 9:50 am # //
neo says:
Hey there!
First of all thanks for the great concept and work!
I am using the new version of wordpress and while I activate the plugin, the encrypt form doesn’t seem to appear on the admin panel of the post. Hmmm…
May 7, 2020 at 10:24 pm # //
Ryan Hellyer says:
Sorry, I didn’t see your comment until now.
Is it possible that you are trying to edit a Gutenberg post? I haven’t tested it with that, so perhaps it doesn’t work with that interface. It definitely works with the Classic Editor plugin installed though. I’ll leave a note about this here on the page, in case others experience this problem.
July 6, 2020 at 9:51 am # //
Parham Khosro says:
Hi Ryan,
Thanks for the great work and sharing. is it still fine to use this plugin with the latest version of wp?! Also will this plugin conflict with another security plugin like All in one security to worddefence.
Best,
Parham
June 4, 2021 at 10:37 am # //
Ryan Hellyer says:
I’m currently using it with the latest version of WordPress. I’d be surprised if it clashed with other plugins. I’m certainly not aware of any problems with it. Security plugins like WordFence don’t generally do anything like what this one does, so those two specific ones should not clash.
June 4, 2021 at 1:52 pm # //
Parham says:
Hi Ryan,
Thanks for the reply. Got your point.
Best
Parham
June 10, 2021 at 6:25 am # //
Marc says:
Hi Ryan,
I would like to thank you for the effort and the idea you have launched.. wordpress needs this. However, I see that the comments have not moved forward in recent years. Did you continue the project? Do you believe that it is possible to add “your functionality” only to the instant chat? I currently use better-messages. Thanks again for any advice you can provide me on this.
October 2, 2023 at 1:41 pm # //
Ryan Hellyer says:
I’ve decided WordPress doesn’t need it actually. I’m now working on a non-WordPress tool for private storing data with End2End encryption. Unless I could side-tracked, it should be ready within a month I hope.
Using WordPress has unfortunately attracted a lot of interest from people who don’t understand what the tool does. I’d guess maybe 95% of questions I’ve had about it, were by people who had no idea what it actually did.
Once the new tool is out, I’ll send people from here to it instead.
The new tool is much simpler and uses more solid code. It’s still PHP based, but doesn’t require WordPress to be in place in order to use it. Abstracting it from WordPress probably helps with security too.
October 20, 2023 at 6:52 pm # //