Hi there. We’re the team behind Twilio’s end-to-end encrypted HIPAA-compliant messaging and many health and IoT products that use the awesome innovation of end-to-end encryption to build a whole new world of privacy-first products.
How do we meet HIPAA’s requirements?
We used Virgil Security’s end-to-end encryption SDK (Virgil E3Kit) in a way that’s compliant with HIPAA’s three relevant provisions regarding electronic Protected Health Information, known as “ePHI:” the HIPAA Privacy Rule, the HIPAA Security Rule and the HIPAA Breach Notification Rule.
And we’ve done this in a way that doesn’t require you, Virgil Security or Firebase to sign a HIPAA BAA. Check out our Firebase-specific whitepaper that explains the legal side of things: https://VirgilSecurity.com/firebase-whitepaper. Anyway, we're always ready to sign a BAA with you if it's necessarily.
The inevitable disclaimer: implementing your app’s data security according to this tutorial does not necessarily mean that your whole project is HIPAA-compliant. HIPAA is more than just data security: it has organization requirements such as training for your team, recovery plan in case systems are down, etc. Make sure that you understand all these requirements found on the Health and Human Services website. We’ll cover the data security front, but there’s still some work for your HR & operations folks!
What is End-to-End Encryption?
First, let’s start with a quick refresher of what end-to-end encryption (“E2EE”) is and how it works.
This is what your Firebase app looks like today:
Data is only encrypted as it goes over WiFi and the Internet, but unencrypted elsewhere. Technically, every server and database service along the way can access your users’ plaintext chat messages. When cloud service providers add an extra layer of security by using “at rest” encryption, it only means that the database file is encrypted on disk with a key (or keys) that they can access. Why is this a problem? A two year study in the UK found that 88% of data breaches were caused by developer error, not cyberattacks. While Google is doing a great job protecting their cloud infrastructure, end-to-end encryption is a layer on top that protects developers from mistakes and hacks.
And this is what your app will look like after you implement client-side end-to-end encryption:
The messages are encrypted on the user device and remain encrypted as they travel over the mobile network/Wi-Fi/Internet, through the cloud/web server, into Firestore, and on the way back to your chat partner (such as a patient or doctor in a healthcare scenario). In other words, none of the networks or servers will have a clue what the two of you are chatting about. It’s the WhatsApp ans Signal way.
What can I end-to-end encrypt?
Anything. Really. Chat messages, file or data transfers (health records between hospital and insurance provider). In this example, we keep our focus on In-app Chat in healthcare.
Can I just do it myself from scratch?
What’s difficult in end-to-end encryption is managing the encryption keys in a way that only the users involved in the chat can access them and nobody else. And when we say “nobody else,” we really mean it; even your cloud provider or you, the developer, are out; no accidental mistakes or government-ordered peeking are possible.
Writing crypto, especially to work across multiple client platforms (iOS, Android, JS), is hard. Generating truly random numbers, picking the right algorithms for the operating system/browser, and choosing the right encryption modes are just a few examples of why most developers wave the white flag and end up NOT doing it. It famously took WhatsApp 3 years and 15 smart developers to make their chat app end-to-end encrypted, on par with project timelines at Facebook Messenger, Apple and other tech companies.
Our SDK makes it possible for you to implement an end-to-end encrypted chat proof of concept in 5 minutes and the production feature in a matter of days, getting you to HIPAA compliance as quickly and safely as possible.
How do I end-to-end encrypt my Firebase chat app?
1) For every NEW user, the app generates a private & public key in your app (on the client device) using the EThree.register() function.
- The public key is published to our Cards Service, so that other users of your app can retrieve it to encrypt data for you.
- The private key remains on your device and lives in your browser (or mobile operating system’s native key store in case of Android or iOS). Before you’d ask – no, we don’t send up the private key to the server:
.then(() => console.log('success'))
.catch(e => console.error('error: ', e));
2) Before sending a chat message, the app encrypts it with the recipient’s public key, which is searched by their identity, and signs with the sender's private key (authEncrypt method):
// alice and bob - recipient identities
// steve - sender identity
const identities = ['alice', 'bob'];
// Find users cards with public keys
const findUsersResult = await eThree.findUsers(identities);
// Encrypt text string
const encryptedText = await eThree.authEncrypt('message', findUsersResult);
3) After receiving a message, the app decrypts it with your user’s private key, which never leaves the device, and verifies with the sender's public key (authDecrypt method):
// steve - sender identity
const sender = 'steve';
// Get sender card with public key
const senderCard = await eThree.findUsers(sender);
// Decrypt text and ensure it was written by sender
const decryptedText = await eThree.authDecrypt(encryptedText, senderCard);
The technique above ensures that only end-users are able to see messages; the data won’t be visible to Firebase, Google or developers/IT staff at your company. It’s now an end-to-end encrypted chat, like your WhatsApp conversations.
To find our more about our encryption SDK and its features follow our developers documention for end-to-end encryption
What if I’m building a group chat?
If you’re implementing group chat follow our Group Encryption guide. Our group encryption provides true end-to-end encryption and data signature for one or multiple users. It also provides you with the functions to create and manage dynamic groups for encrypted communication.
A group key is shared between participants, which enables new members to have access to the previously encrypted data history in the group. These functions can be used for chat, file sharing, and more.
Is that all I need to make my Firebase chat app HIPAA compliant?
In addition to all the non-technical HIPAA requirements that are not covered here, there’s a couple more things you need to do.
- First of all, you need to authenticate your users, which isn’t surprising.
- Then to maintain your users’ privacy, you should not use your users’ email addresses or any other personal data as usernames and you shouldn’t store any of their personal data in your Firebase backend. This is how we implemented our sample apps.
- And there’s one more thing that you need to implement to cross your t’s and dot your i’s: Message Redaction. Since patient chat contents are client-side encrypted with keys that never make it to your backend, it’s practically impossible to tell whether the Firestore-stored messages on the backend are sensitive health data or something totally benign. But this isn’t enough for HIPAA. So in order to meet HIPAA’s requirements, we implemented a data redaction feature in the sample apps. This feature deletes messages immediately following a successful message delivery to all users. This way, HIPAA considers your chat to be a “conduit,” i.e. only a message delivery tool that doesn’t store the data beyond delivery, which exempts the messaging function completely from HIPAA.
For the important details, check out our whitepaper at https://VirgilSecurity.com/firebase-whitepaper.
What happens if my user loses her device with the private key on it?
As in the sample, your messages are local-only (Firebase is only an intermediate delivery system), so the messages will be lost with the phone. However, if there’s (non-patient) data that you want to permanently store encrypted in Firebase, there’s a solution for lost devices/keys.
Drumroll, please… Imagine a private key that can be lost, and you don't have to worry about losing your encrypted data. Or, imagine a private key that you can use between devices without needing to transfer the key around (WOW!). This special key is called “BrainKey”: a strong cryptographic key that’s based on your user’s PASSWORD. Every time you capture your user’s password, you can re-generate the same private key, so it won’t be lost with the device.
Here’s how to implement your user private key recovery:
- At signup, generate a BrainKey right after you generate your user’s private key using
eThree.backupPrivateKey(pwd)function. It encrypts the user’s private key with her BrainKey’s public key and the encrypted private key is sent to Virgil Cloud (yes, only key owner can decrypt this key).
- At login-time, if user lost their key, re-generate the BrainKey from thier password using
EThree.restorePrivateKey(pwd)function. It downloads the encrypted user private key from Virgil Cloud and decrypts it with the BrainKey, and Voila! You have a way to recover the key if a device is lost.
This guide shows how to create a backup for user's private key in order to implement multiple-device support and prevent loss of all user's data in case of losing the private key.
How do you deal with a forgotten password and lost device at the same time? Use a concatenated string of 3 secret answers as a password to generate a secondary BrainKey for your users. Use this secondary BrainKey in the same way as you do the password BrainKey: encrypt, then later “unlock” the user private key. Now you have a user lockout solution with 3 secret questions+answers!
Get started on your HIPAA-compliant secure Firebase Chat app
Also, follow our developer's encryption guides to start working with neccessary use-case.
If you have any questions, join our Slack channel and chat with us!
Virgil Security, Inc. enables developers to eliminate passwords & encrypt everything, in hours, without having to become security experts. Learn more at VirgilSecurity.com.