How our encryption works, with the code

Every key Shuriken makes, the relay handshake, what is sealed to whom and the known limits, on one page with the encryption code read at each build.

SEALED beside a real screenshot of Settings › Account's Security card: source sign-ins ready on this device, Change password
Contents

We put the whole encryption system on one page, How the encryption works, with the source code that does it at the bottom. The page shows every key Shuriken makes, the handshake between your apps and your computers, what is sealed to whom, what our cloud sees, how removing a device rotates your keys, and the limits we know about. The code is read from our repository each time the site is built, starting with packages/relay/src/crypto.ts.

Why put the code on the page#

A security engineer told us he would not use Shuriken because the code is closed and he could not tell how his data crosses the network. We wrote that story up in what our cloud can and can't see. The security page answered him in sentences. Sentences can drift from the code, though, and a reader has no way to notice when they do.

So the new page carries the code itself. When the site is built, a build step reads each listed file from the repository, highlights it, and prints the commit the site was built from, plus the last commit and day that changed each file. A deploy after a change to the vault code shows the changed vault code. If a file on the list is renamed or deleted, the build stops. A test also fails when a file in the relay package, or in the app's account folder, starts using cryptography without being on the list or on a short list of files we leave out on purpose, each with its reason.

The short tour#

Your passkey, your password and the vault key#

The vault key is 32 random bytes that one of your devices made. Since 5.1.1 it opens with an unlock key, and the unlock key opens with any one of a passkey, your password or your recovery key. Our cloud stores each of those only wrapped. For the password, your device turns it into a password key with PBKDF2-SHA256, 600,000 rounds. HKDF-SHA-512 of that key is the sign-in key your app sends instead of the password, and an account that hasn't moved to passkeys yet keeps its vault key wrapped under the password key directly. Your AI sign-ins, API keys and MCP sign-ins are sealed under the vault key with AES-256-GCM, and each sealed item names its own id, kind and revision, so the cloud cannot swap two items, and a device that has opened an item refuses an older copy of it.

On your device, your password makes a password key with PBKDF2 at 600,000 rounds. That key locks your vault key, a random AES-256 key made on your device, and the vault key seals your sign-ins, API keys and MCP sign-ins. Our cloud holds only a hash of the sign-in key, the vault key locked by your password key, and the ciphertext of each item. The password itself is never sent. On your device In our cloud Your password Password key PBKDF2-SHA256, 600,000 rounds Vault key Random, made on your device, AES-256 Sign-ins, API keys, MCP sign-ins derives locks seals Never sent A hash of your sign-in key Vault key, locked Ciphertext of each item A copy of our database holds only the right-hand column. To open it, someone has to guess your password.
Your password locks the vault key; our cloud keeps only the locked copy and the sealed items.

Four keys from one#

HKDF-SHA-512 of the vault key gives the account key (Ed25519), the inbox key (X25519), the documents key and the pictures key. Every device that holds the vault key makes the same four. The account key is the one that matters most: it signs each device's key, so an app refuses a computer key our cloud swapped in.

The handshake#

An app reaching a computer sends a one-time X25519 key and a proof signed by your account key. The computer answers with a one-time key of its own. Both sides run HKDF-SHA-512 over two X25519 results and get one key per direction. Frames are sealed with XSalsa20-Poly1305 and numbered, so the relay forwards bytes it cannot open, and a frame it replays or reorders closes the connection. When both sides offer it, frames are also padded to a step. Once the one-time keys are gone, a stolen computer key opens none of the recorded session frames. The page names the one early message that is the exception.

Three cards with arrows. Your app sends a one-time X25519 key and a proof signed by your account key. Our relay forwards frames it can't open, and a replayed frame closes the link. Your computer answers with a one-time key of its own. Below: both sides derive one key per direction with HKDF-SHA-512.
The relay carries every connection and forwards frames it cannot open.

Removing a device#

With your password or a passkey, the device you are on makes a new vault key, seals every item again and seals the new key to each device you keep. The old account key signs the new one, and your computers follow that chain and refuse the old key from then on.

What the page says plainly#

The limits section is as long as the tour, on purpose.

  • In a browser, the web app's code comes from our cloud, so a changed cloud could target one browser.
  • A server added by typing its code, if it never joined before, takes the first account key a client proves to it.
  • A device you removed keeps working with sign-ins it already opened until you sign out at each provider.
  • If you keep a password, your vault is as strong as it, because anyone with a copy of our database can try guesses offline at 600,000 rounds each.
  • The relay still sees who talks to whom, when, and roughly how much. Since the padding offer travels in the open handshake, it can turn padding off for an app's connection to a computer until the app has seen that computer's sealed confirmation of what it offers. After that, the app refuses a handshake with it that leaves padding out.
  • A rotation trusts the device list our cloud hands it. A cloud working with someone who kept a removed device's old key could add a device of its own making and receive the new vault key.

The licence#

The code is shown so it can be checked. We have not chosen a licence for it, so the page grants none. Two files, the relay's primitives (crypto.ts) and its channel (encrypted-channel.ts), began in an open-source project under the Apache License 2.0 and keep that licence; the page marks them.

If you read the code and find it doing something the page says it doesn't, that is a vulnerability. Write to office@shuriken.sh.

Frequently asked questions

Is Shuriken open source now?

No. The files that do the encryption are shown on /security/encryption so you can check them. We have not chosen a licence for them, so the page grants none. Two files began in an open-source project under the Apache License 2.0 and keep that licence.

How do I know the code on the page is the code that runs?

The page is built from our repository: each build reads the files, prints the commit it was built from and the last commit that changed each file. It shows what this site was built from; your installed app is the release it came with.

Can Shuriken's cloud read my chats?

Not chats between your apps and your computers: they are sealed with keys made fresh for each connection, which our relay cannot make. The exceptions, such as a dev server preview or a reply from an app older than 5.1, are listed under Known limits on the page.

Free tools