# zoro.io > Small single-page app by Florent Clairambault, no external resources. Two pages, acypher and acypher/keys, which let a human hand a secret (a password, an API key) to an AI agent without typing it in the chat. ## acypher - [acypher](https://zoro.io/acypher/): a page that encrypts a secret in the browser to a public key given in the URL fragment. Nothing is sent over the network: the fragment is never sent to the server and the page's Content-Security-Policy blocks every request after load. ### How an AI agent uses it Prefer an age key: the recipient is 62 characters, so the link is about 90 characters and easy to paste anywhere. The link is built directly from the public key, with no encoding and no call to any server: `https://zoro.io/acypher/#` followed by the `age1...` recipient. 1. Generate an age key on your side, keep the private key in a local secret store (gopass is a good one) and build the link from the public key: ``` age-keygen 2>/dev/null | gopass insert -m agents/acypher/ recipient=$(gopass show agents/acypher/ | age-keygen -y) echo "https://zoro.io/acypher/#$recipient" ``` Without gopass, `age-keygen -o key.txt` and `age-keygen -y key.txt` do the same, but then store `key.txt` in a protected location (mode 600, outside any repository). Use one key per request and delete it once the secret is read. 2. Give the human the link, and tell them the recipient (`age1...`) so they can compare it with the one the page shows. 3. The human types the secret and gets an armored block (`-----BEGIN AGE ENCRYPTED FILE-----`). They paste it back to you. 4. Decrypt it locally, without writing the key to disk: `age -d -i <(gopass show agents/acypher/) message.age` (or `age -d -i key.txt message.age`). Never write the plaintext in a tracked file or a log. PGP also works when age is not available: any key with an encryption subkey (ed25519 + cv25519 v4, or OpenPGP v6 with native X25519). Put the binary public key as base64url in the fragment (`gpg --export --export-options export-minimal | base64 | tr '+/' '-_' | tr -d '=\n'`) or the armored key, URL-encoded, and compare the fingerprint. Decrypt with `gpg --decrypt`. The links are much longer (about 800 characters for OpenPGP v6). If the link has no fragment, the page asks the human to paste a public key (age or PGP). ## acypher keys - [acypher keys](https://zoro.io/acypher/keys/): the receiving side, for a human who wants their own keys instead of an AI's. It creates age or PGP (OpenPGP v6, X25519) keys in the browser, stores them in localStorage (unencrypted, this site only), builds `https://zoro.io/acypher/#` links from them, and decrypts the blocks people send back. Nothing leaves the browser. age keys give much shorter links (about 90 characters, against about 800 for PGP). ## Source - [github.com/fclairamb/zoro.io](https://github.com/fclairamb/zoro.io): private repository. Libraries are vendored in `site/vendor/` (OpenPGP.js 6.3.2, age-encryption 0.3.1), no CDN.