Keys & identity
Your Radicle identity is a cryptographic key pair. Radish generates it for you, signs your contributions with it, and gives you full control over where it's stored and how to take it with you.
What a Radicle key is
Every Radicle user is identified by an Ed25519 key pair. The public half is encoded as a DID (decentralized identifier) like did:key:z6Mk… and shows up next to your name on issues, patches, and comments. The private half signs every operation you perform.
Radish doesn't use a separate "Radish identity" — the keys it generates are real Radicle keys. Anything you do here is indistinguishable on the network from the same action performed by the rad CLI.
Two storage options
At onboarding (and any time afterwards from your profile) you choose where the private key lives.
Radish creates a private repository called .radish on your GitHub account and commits the key inside it. Whenever you perform a write operation, the key is fetched on demand, used to sign once, and dropped from server memory.
- Portable. Sign in to any Radish instance and your identity follows automatically.
- Self-custody. The repo is owned by you; Radish can only read it through your OAuth token.
- Trade-off: GitHub OAuth doesn't allow scoping to a single repo, so you grant Radish broad repo access even though it only touches
.radish.
The key is generated on the server and saved in this instance's database. Radish only needs your GitHub username to log you in.
- Minimal permissions. No GitHub repository access at all.
- Trade-off: The identity only exists on this Radish instance. Signing in to a different instance creates a separate identity there.
How signing actually works
When you submit something — a new issue, a comment, a patch — Radish does the following inside a single HTTP request:
- Reads your GitHub token out of the encrypted session cookie.
- Loads your private key. If it's stored on GitHub, Radish makes an authenticated API call to your
.radishrepository to fetch it. If it's stored on the instance, it's read from the local database. - Uses the key to sign the operation in memory and writes the result to the local Radicle storage that the co-located
radicle-nodereads from. - Drops the private key from memory before the response is sent. Nothing about the key is logged, persisted, or cached.
The first time you do this, Radish creates the .radish repo (if you chose GitHub storage) and generates a brand-new key pair before any signing happens.
Switching storage later
Open Profile → Identity & keys from the user menu. From there you can:
- Migrate to this instance — copy the existing key out of GitHub and into the server database. Useful if you want to revoke the GitHub repo permission.
- Migrate to GitHub — push the server-stored key into a private
.radishrepo so it becomes portable. - Export key — download
radicle.key, the standard SSH-formatted Radicle private key, ready to import into a local node.
Migrations preserve your DID. Issues and patches authored before the migration still resolve to the same identity afterwards.
SSH keys (for Git push)
Your Radicle signing key is separate from any SSH keys you add to your account. SSH keys are only used to authenticate the SSH connection when you push commits via the Radish Git bridge — they are not used to sign Radicle objects.
- Automatic import from GitHub. When you sign in for the first time, Radish fetches the SSH public keys on your GitHub account and imports them automatically. This means you can start pushing over SSH immediately without manually adding any keys.
- Manual re-sync. If you add or remove keys on GitHub after your first login, visit Profile → Identity & keys → SSH Keys for Git push and click Sync from GitHub. New keys are imported, and keys you deleted from GitHub are removed from Radish. Manually added keys are never affected by a sync.
- Keys imported from GitHub are marked with a GitHub badge on the profile page so you can tell them apart from manually added keys.
- You can also paste a key manually under Profile → Identity & keys → SSH Keys for Git push. Paste the same line you would put in
~/.ssh/authorized_keys(e.g.ssh-ed25519 AAAA…). Radish stores only the public key and a SHA-256 fingerprint. - Each key's fingerprint is globally unique on this instance — registering the same key twice (even by a different account) is rejected.
- Delete a key from the same screen. Deletion takes effect immediately and revokes any future SSH access using that key.
- When you push, Radish authenticates the connection by fingerprint, verifies you are a delegate of the target repo, runs
git-receive-packin your namespace, and signs the resulting refs with your Radicle key.
If your Radicle key is on GitHub, Radish needs to fetch it to sign the push. To make that possible without a live session cookie, an encrypted copy of your GitHub token is stored on the server when you sign in. Sign out (or revoke the OAuth grant on GitHub) to invalidate it.
Key security at a glance
- Private keys are never written to disk on the Radish server when GitHub storage is used. They live in memory for the duration of one request and are zeroed afterwards.
- The session cookie is encrypted with a server secret and marked
HttpOnly+Secure. JavaScript cannot read it. - The
.radishrepo is private, owned by your GitHub account, and accessed through your OAuth token. Radish has no way to read another user's.radishrepo. - If a key is compromised, you can rotate by deleting the
.radishrepo (or the server-stored key) and going through onboarding again — but note that this creates a new Radicle identity.