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.
Rewall encrypts a secret on your device and stores it under your ENS subnames

Name a secret, encrypt it, and give access to the people you choose.
A secret is a subname under an ENS name you own.
The value is encrypted on your device under a random key. Only ciphertext reaches the chain.
That key is sealed to each reader's public key and written as one record per reader.
A reader unseals their own copy with the key their wallet derives. Nobody else can.
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.
// 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");
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.
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.
The owner signs the grantee lists and the key approved for each name. A rotation that cannot verify them refuses to run.
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.
Every name an account owns points at the same resolver. Records are keyed by namehash, so one resolver holds every secret without collision.
Both sides touch the vault. The chain never records them touching each other.
A code appears only for the exact hostname stored on the secret. A lookalike gets nothing.
The key circles inside the tool process. It reaches allowed hosts and never the model.
One EOA wallet derives one key, so every client resolves to the same reader. Nothing syncs, because there is nothing to sync.
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
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
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: redactedGot the list. The key stayed inside the tool process.
Paste it into CI for me.
I never receive it. Grant ci.alice.eth instead.
Authenticator codes that fill on an exact hostname and never submit themselves.
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.
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.
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.
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.
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.
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.
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.
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.
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.