On-chain secrets
made simple

Rewall encrypts a secret on your device and stores it under your ENS subnames

Dashboard
Read Docs

Nothing here asks you to trust us.

A secret is one subname, a handful of text records, and a ciphertext nobody but its readers can open. The mechanism is specified in full and small enough to read end to end.

secrets.ts
// one key, derived from a signature, never written down
await rewall.identity();

await rewall.create("openai.rewall.alice.eth", key, {
    type: "apikey",
    grantees: ["ci.alice.eth"],
    recovery: ["vault.alice.eth"],
    allow: ["api.openai.com"],
});

// a wrap for bob, then a rotation that strips it
await rewall.grant("openai.rewall.alice.eth", "bob.eth");
await rewall.revoke("openai.rewall.alice.eth", "bob.eth");

The SDK is the protocol

Encryption uses platform WebCrypto for AES-256-GCM and libsodium for the sealed-box wraps. No hand-rolled primitives, and no algorithm the spec does not name.

Padded blobs

Four bytes of length, the plaintext, then zeros, out to a multiple of 256. Every credential under 252 bytes produces a blob of identical length.

Signed lists

The owner signs the grantee lists and the key approved for each name. A rotation that cannot verify them refuses to run.

Wrap records

One record per key, holding the data key sealed to a reader’s X25519 public key. A rotation writes the new set and clears whoever left.

One resolver

Every name an account owns points at the same resolver. Records are keyed by namehash, so one resolver holds every secret without collision.

Semi‑Confidential Transfers

Both sides touch the vault. The chain never records them touching each other.

alice.eth
charlie.eth
bob.eth
org.bob.eth

Two‑Factor Codes

A code appears only for the exact hostname stored on the secret. A lookalike gets nothing.

alice.eth
g1thub.com
github.com

Agents That Cannot Leak

The key circles inside the tool process. It reaches allowed hosts and never the model.

alice.eth
Model
Allowed model

The same identity, wherever you work.

One EOA wallet derives one key, so every client resolves to the same reader. Nothing syncs, because there is nothing to sync.

TypeScript SDK

Read and write secrets from your own code. Everything else here is a surface over it.

const name = "db.rewall.rewall-test-1.eth";

await rewall.create(name, value, {
  type: "dburl",
  recovery: ["rewall-test-3.eth"],
});

const secret = await rewall.get(name);

// Uint8Array, decrypted in memory

Grant and revoke

Hand a secret to another ENS name, then take it back. The value itself never moves.

await rewall.grant(name, "rewall-test-2.eth");

// Their key gets a wrap of its own

await rewall.revoke(name, "rewall-test-2.eth");

// Rotates, so the old wrap opens nothing

Agent server

An agent spends a secret it is never given, and the reply comes back with it removed.

List the models my key can reach.

http_with_secret("openai-key", "/v1/models")200 OK · authorization: redacted

Got the list. The key stayed inside the tool process.

Paste it into CI for me.

I never receive it. Grant ci.alice.eth instead.

Browser extension

Authenticator codes that fill on an exact hostname and never submit themselves.

github.comgithub.rewall.alice.eth
••• •••

Questions worth asking first.

Where is a secret actually stored?

In ENS text records on the secret’s own subname, on ENSv2 Sepolia. The ciphertext sits inline in a record on that name. There is no offchain storage, no content addressing, and nothing for us to host.

What happens if I lose my wallet?

The SDK refuses to create a secret wrapped only to you, so a recovery grantee always exists. That is either a second name backed by a cold wallet, or k of n guardians who each hold a Shamir share of a recovery key nobody holds whole.

Can Rewall read my secrets?

There is nothing to read them with. No Rewall service holds a key that opens a secret, and every decryption runs in your own browser or on your own machine. A secret opens only for a name it was sealed to.

Is revoking someone retroactive?

No, and a public chain makes that plainer than usual. The transaction that granted a name is permanently in history and carries its wrap, so whoever held that key can still decrypt the old value from an archive node. Treat a grant as handing over a copy, and rotate the credential itself when someone leaves.

How is my identity key derived?

Your wallet signs one fixed EIP-712 payload. The signature is reduced to canonical form, hashed into a 32-byte seed, and used directly as an X25519 scalar. Sign it only in Rewall: whoever collects that signature reads every secret shared with you, permanently.

What does an agent receive?

A result, never a value. The MCP server decrypts inside its own process, attaches the secret to the request it was allowed to make, and hands back the response with the value scrubbed out.

Do I need an ENS name?

To own secrets, yes, because a secret is a subname under your namespace. To be granted one, a name that publishes your key. To decrypt it afterwards, nothing but the key itself.

What does it cost to run?

Gas, and the ENS registration. Rewall charges nothing and has no account to open. On Sepolia the registrar is paid in a mock token whose mint is open, so a name costs only the gas to register it.

Teach your AI about Rewall.

One command installs a skill that tells Claude Code, Cursor and other agents what Rewall is, how a secret is stored and shared, and how to build on it.