First steps to post-quantum

We've deployed our first post-quantum crypto change on cast.ente.com. This vets all the moving parts in Ente's transition to quantum-secure cryptography, so now what remains is over time moving the rest of the PQ-affected flows to quantum security.

In the rest of the post, I'll give a brief background of the what and why, explain what we've done, and then outline how it'll tie to the rest of our PQ journey.

Ente uses cryptography to guarantee that no one, not even Ente, can see your photos and read your documents.

Quantum computers, when they become a reality in the future, will have ways of breaking the security of many of the standard cryptography algorithms.

The bulk of the encryption algorithms we use are already safe even in the presence of quantum computers. The main workhorses: the algorithms (the so-called symmetric-key methods) that Ente uses to encrypt your photos and files and auth codes, all of them have no known weaknesses.

However, a small but important subset of the algorithms (the so-called asymmetric-key methods) that allow Ente users to share photos with other Ente users are not quantum safe.

So the task for us is to migrate these asymmetric-key algorithms to new replacements that are ready for a post-quantum universe. These are affectionately known as PQ algorithms.

As I mentioned, the bulk of the encryption we use doesn't need changing. The places where sharing happens are the places that need changing.

But Ente allows things to be shared in a lot of ways! Some of them might not be obvious to a user, but behind the scenes a share-like mechanism is happening.

Case in point is our support for playing your albums on your TV, other cast-enabled devices, and even pairing to a web browser using a PIN. This is done by our "cast" web app, cast.ente.com.

Behind the scenes, this relies on an ephemeral share between the cast web or Apple TV app and your Ente Photos app to ensure that your photos remain end-to-end encrypted. And since a share is involved, we need to use an asymmetric-key algorithm. And these, as we discussed, are not quantum safe.

Since the share is ephemeral, this is both a realistic and a relatively easy flow for us to migrate (since there are no long term shares that need to be re-encrypted). Because of these properties, we chose to use cast as our first step in the post-quantum universe.

The cast app now uses an X25519 + ML-KEM/Kyber exchange, the same recipe that Signal and TLS use for their post-quantum asymmetric key exchanges.

In brief, the new PQ algorithm negotiates two keys: one with the classical method (X25519) and one with the quantum-safe method (ML-KEM-768). Think of it as putting two locks on your box. In the case that there is a quantum computer which can break the classical method, the quantum-safe lock still holds. However, the classical method is battle tested over decades, so in case the relatively new quantum-safe method has a (classical) weakness, the old lock still holds strong.

This change was done fully in Rust! All of the cryptography and the logic for handling the dual key dispatch is taken care of by the same Rust code, and all the Ente Photos apps (mobile, web, desktop) use the same piece of code instead of implementing it again and again.

In fact, while there is a bit of wiring to get this all to work, the core functionality is small enough that I can show it to you here:

fn open_payload(&self, encrypted_payload: &str) -> Result {
    let ciphertext = b64::decode(encrypted_payload)?;
    let plaintext = hpke::open(&ciphertext, &self.pq_secret_key, HPKE_INFO).or_else(|_| {
        crypto::sealed::open(&ciphertext, &self.secret_key.public_key(), &self.secret_key)
    })?;
    Ok(serde_json::from_slice(&plaintext)?)
}

fn seal_payload(
    public_key: &str,
    pq_public_key: Option<&str>,
    payload: &CastPayload,
) -> Result {
    let plaintext = serde_json::to_vec(payload)?;
    let ciphertext = if let Some(pq_public_key) = pq_public_key {
        let public_key = hpke::PublicKey::try_from_slice(&b64::decode(pq_public_key)?)?;
        hpke::seal(&plaintext, &public_key, HPKE_INFO)?
    } else {
        let public_key = PublicKey::try_from_slice(&b64::decode(public_key)?)?;
        crypto::sealed::seal(&plaintext, &public_key)?
    };
    Ok(b64::encode(&ciphertext))
}

(The full code, as usual, is available on our GitHub. Open source ftw!)

The main trickiness comes from handling graceful migration. Reminder that Ente is eminently self-hostable, and we try hard to make sure that self-hosters have a hands-free first-class experience too.

So while we could do a more involved dance to roll this out on our production infrastructure in some orchestrated way, that would've still required self-hosters to also tap along.

Instead, we've arranged things such that all of the flows remain backward compatible. There are three separate moving parts: the cast app (that runs on the TV), the server (that coordinates the pairing), and the Ente Photos app (the mobile/desktop/web app that the user is using to cast their photos). And they can be updated in any order!

For example, if a self-hoster has the latest cast app and the latest server, but still the old client, things will continue to work. Eventually, all three of them will just get naturally updated, and they will be able to recognize each other and agree to the use of the new PQ flow.

The cast app is the first but important checkpoint for us. It vets out the algorithms and the pipeline. Now we will proceed with the longer and more involved task of going through all of the remaining share flows and bringing them along to the post-quantum universe. The symmetric core (the actual photo encryption) is already quantum resistant, so once we're done with the share flows your favorite photo sharing app will be ready for whatever quantum computing brings. See you on the other side :)

添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论