Half Light's Encryption

An overview of identity, encryption, and the social graph in Half Light.

background halftone image

Our goal is to have everything about Half Light's encryption approachable and understandable. The code itself is simple enough that it should be easy to understand what is happening under the hood.

identity

We use non-extractable keypairs as the foundation for identity. When you visit the website, we lookup a keypair that has been saved to indexedDB, or we create a new one if need be.

The good thing is that browsers give us a webcrypto API that lets us save a non-extractable keypair to indexedDB. Non-extractable means you are never able to read the private key, even from within the same process. But, it is persistent, and can be reused indefinitely. See an example of persisting keys.

This gets us persistent identity. Any time you visit the webpage, we lookup your keypair in your local browser, and use this keypair to sign any records.

encryption

Also there is a second keypair that we use only for encrypting & decrypting. In general, we use a key encapsulation mechanism where we create a symmetrical (AES) key and encrypt it to a given RSA keypair, and we use the AES key to encrypt the actual content.

Decrypting is a two step process. First, decrypt the AES key with your private key, then use the AES key to decrypt the post content.

the social graph

With what we've talked about thus far, we get multi-device identity, and private messages. Part of the service we provide is that we keep a record of who is able to read what content. This is a record that maps a given set of users to a copy of a post's AES key, that has been encrypted to the user's RSA keypair.

So in that way we get E2E encryption, since only the key in a given user's browser is able to decrypt the AES key, which decrypts the post content.