← Back to context

Comment by masfuerte

5 days ago

I feel like I'm being very stupid. If the key never leaves my machine, how do I share a secret?

When you run:

npx enstash "my secret"

Stasher performs everything locally:

Generates a random 256-bit encryption key

Encrypts your secret using AES-256-GCM

Sends only:

the ciphertext

the IV (initialization vector)

the auth tag

a randomly generated UUID

The encryption key is never sent to the server. It never leaves your machine.

You are then shown a single string:

uuid:base64key

The uuid points to the encrypted stash on the server

The base64key is the encryption key you just generated

Only the person who has both parts can decrypt the secret

How You Share the Secret

You send the full uuid:base64key token to your recipient — over any channel you like slack or whatever.

When they run:

npx destash "uuid:base64key" on the token

Stasher:

Fetches the encrypted stash using the uuid

Deletes it immediately (burn-after-read)

Decrypts it locally using the base64key

Shows the secret

The server never sees the key. Not during upload or during retrieval.

  • >no accounts, no logins, no servers to trust.

    >The uuid points to the encrypted stash on the server

    No servers… “on the server.” hmmm, I must be missing something.

  • So the ten minute thing is a trust issue. How are salts handled?

    • So the ten minute thing is a trust issue?

      Stasher enforces expiry in two layers:

      Reactive expiry — When someone tries to retrieve a stash (destash), the Durable Object checks the creation timestamp before serving. If it's older than 10 minutes, it refuses the request.

      Proactive cleanup — Every stash’s Durable Object sets a scheduled alarm to self-destruct after 10 minutes. This removes the coordinating DO and ensures the encrypted blob in KV expires (via TTL).

      So even if someone tries to cheat the system, or access after the 10-minute window, they’ll get an error — the stash is gone.

      This is part of what makes it “burn-after-read, or expire-after-time”. No guessing, no timers in memory or cron job workers.

      How are salts handled?

      Stasher uses AES-256-GCM, which does not require a traditional salt like in password hashing (e.g. PBKDF2, bcrypt). Instead, it uses an IV (initialization vector).

      With a fresh 96-bit IV is generated for every encryption

      AES-GCM uses that IV as part of the encryption process, ensuring non-deterministic ciphertext. The IV is not secret, and is uploaded alongside the ciphertext and GCM tag

      On decryption, the IV is used to reconstruct the exact same cipher context

      So in short: No static salts and no reused IVs

      Everything you need to decrypt is bundled with the encrypted stash, except the key, which stays with the user (as part of the uuid:base64key token)