# Age Key Generator

Generate an age X25519 identity and its shareable age1 public recipient in your browser, or derive the recipient from an identity you already have.

## Run it

- **CLI:** `gizza tool age-keygen 'format=text'`
- **Web:** https://gizza.ai/tools/age-keygen/
- **Agents:** machine-readable descriptor (parameters JSON Schema) at https://gizza.ai/tools/age-keygen/tool.json

## Inputs

- `format` — Output _(field)_
- `comment` — Comment (optional label) _(field)_
- `include_created` — Include # created: timestamp _(field)_
- `seed_or_identity` — Existing identity (optional) _(field)_

## Output

- Age identity (text)

## Query parameters

Open the tool pre-filled and auto-run via URL:

- `format` — Output
- `comment` — Comment (optional label)
- `include_created` — Include # created: timestamp
- `seed_or_identity` — Existing identity (optional)

Example: `https://gizza.ai/tools/age-keygen/?format=text&comment=laptop%20backup%20key&include_created=true&seed_or_identity=AGE-SECRET-KEY-1%E2%80%A6%20%E2%80%94%20leave%20blank%20to%20generate%20a%20fresh%20random%20key`

---

## About this tool

This generator creates an **age X25519 identity** — the key pair used by the
`age` file-encryption format. Every run produces two matching strings:

- a **secret identity**, `AGE-SECRET-KEY-1…`, which decrypts files and must stay private;
- a **public recipient**, `age1…`, which you hand out so other people can encrypt to you.

The default output is the same key-file layout the age command-line tools write: an
optional `# created:` timestamp, an optional comment line, a `# public key:` line, and
finally the secret key. Anything produced here can be pasted straight into an age
client, and any identity produced by an age client can be pasted back in here.

Keys are generated locally in WebAssembly using your browser's cryptographically
secure random generator. Nothing is uploaded, and no key is stored anywhere.

## Worked example

Paste an existing identity into **Existing identity** and choose **Public recipient
only** to look up its public half — the age key-file format does not store the
recipient anywhere except that comment line, so this is how you recover it:

```
Existing identity: AGE-SECRET-KEY-1GQ9778VQXMMJVE8SK7J6VT8UJ4HDQAJUVSFCWCM02D8GEWQ72PVQ2Y5J33
Output:            age1t7rxyev2z3rw82stdlrrepyc39nvn86l5078zqkf5uasdy86jp6svpy7pa
```

Leaving that field blank instead draws a brand-new random key, and the default
**Age key file** output looks like this:

```
# created: 2026-08-13T09:41:07Z
# laptop backup key
# public key: age1t7rxyev2z3rw82stdlrrepyc39nvn86l5078zqkf5uasdy86jp6svpy7pa
AGE-SECRET-KEY-1GQ9778VQXMMJVE8SK7J6VT8UJ4HDQAJUVSFCWCM02D8GEWQ72PVQ2Y5J33
```

## Options

- **Output** — *Age key file* writes the full commented identity file; *JSON* returns
  `recipient` and `identity` fields for scripts; *Public recipient only* prints just the
  `age1…` string, which is the safe one to paste into chats, tickets, or a repository;
  *Secret key only* prints just the `AGE-SECRET-KEY-1…` line with no comments.
- **Comment** — an optional one-line label (up to 200 characters) so you can tell keys
  apart later. It becomes a `#` comment in the key file and a `comment` field in JSON.
  Line breaks are folded to spaces.
- **Include `# created:` timestamp** — on by default, matching the age tools. Turn it
  off when you want a byte-stable file or the shortest possible key.
- **Existing identity** — leave blank for a fresh random key, or paste an
  `AGE-SECRET-KEY-1…` identity to re-derive its recipient. Raw hex or base64 seeds are
  not accepted (see the FAQ).

## Limits

- Only X25519 identities are produced. Post-quantum hybrid identities (ML-KEM-768 +
  X25519) and age plugin identities are not supported.
- No vanity-prefix search: recipients cannot be brute-forced toward a chosen prefix.
- The key is not passphrase-encrypted here, and there is no file writing — copy or
  download the output and store it yourself, with restrictive permissions.
- SSH keys are a different format entirely and are not generated by this tool.

## FAQ

<details>
<summary>Which of the two keys do I share?</summary>

Share the `age1…` **recipient** — that is the public half, and it only lets people
encrypt to you. The `AGE-SECRET-KEY-1…` **identity** is the private half: it decrypts
everything sent to that recipient, so it should never be pasted into a chat, a ticket,
or a repository. Choosing *Public recipient only* keeps the secret key out of the
output entirely.

</details>

<details>
<summary>Are the keys really generated on my device?</summary>

Yes. The generator is a WebAssembly module that runs inside this page and draws its
randomness from the browser's `crypto.getRandomValues` CSPRNG. There is no network
request in the key path and nothing is stored — reloading the page loses the key, so
copy or download it before you navigate away. For keys guarding something valuable, the
usual advice still applies: generate on a machine you trust and keep the only copy
offline.

</details>

<details>
<summary>I lost the public key but still have the secret one. Can I get it back?</summary>

Yes — paste the identity into **Existing identity** and pick *Public recipient only*.
The recipient is derived mathematically from the secret key, so it can always be
recomputed; the `# public key:` comment in a key file is a convenience, not the source
of truth. This is the same operation age's own key tool performs when asked to print
the recipients of an identity file.

</details>

<details>
<summary>Can I generate the same key again from a seed?</summary>

No. Apart from pasting a full `AGE-SECRET-KEY-1…` identity, there is no way to make the
output reproducible: raw hex or passphrase-derived seeds are deliberately rejected
because getting X25519 clamping and the bech32 encoding subtly wrong produces a key that
looks valid but interoperates badly — and a key derived from a memorable seed is only as
strong as that seed. If you need the same key on several machines, generate it once and
copy the identity itself.

</details>

<details>
<summary>How do I use the key once I have it?</summary>

Give the `age1…` recipient to whoever is encrypting; they select it as the recipient and
the resulting file can only be opened with your identity. To decrypt, save the identity
as a key file (the *Age key file* output is already in the right shape) and point your
age client at it. If you also want to encrypt something right now, the age encryption
tool on this site accepts `age1…` recipients directly.

</details>

## Related tools

- [Age encrypt](https://gizza.ai/tools/age-encrypt/): Encrypt small text into an ASCII-armored age ciphertext with a passphrase or native X25519 recipients.
- [SM2 public key from private key](https://gizza.ai/tools/sm2-public-from-private/): Derive an SM2 public key from a private key (GM/T 0003, curve sm2p256v1) — hex scalar or PKCS#8 PEM in, SEC1 hex and SPKI PEM out. In-browser, no upload.
- [X25519 ECDH key agreement](https://gizza.ai/tools/x25519-ecdh/): Derive an X25519 (Curve25519) ECDH shared secret from your private key and a peer public key, then expand it with HKDF-SHA256/512. Runs in your browser.
- [AES cipher](https://gizza.ai/tools/aes-cipher/): Encrypt or decrypt text with AES in CBC, CTR, GCM or ECB mode and 128/192/256-bit keys, with hex/base64 I/O — in your browser. Nothing is uploaded.
- [AES Key Wrap](https://gizza.ai/tools/aes-key-wrap/): Wrap and unwrap cryptographic keys with AES Key Wrap (KW / RFC 3394, KWP / RFC 5649) using a 128/192/256-bit KEK — hex or base64, free and in-browser.
