SSH Keys
EncodingEverything runs locally in your browser — nothing is uploaded
Two uses, switched in the options. Parse: paste the line from `~/.ssh/id_ed25519.pub` and get the type, size, SHA-256 and MD5 fingerprints, the comment, and any `authorized_keys` options at the start of the line (`command=`, `from=` and friends). The fingerprint is the main reason this tool exists — comparing what `ssh-keygen -lf` prints on the server against your local copy is the standard way to answer “has this key changed?”. ⚠️ A fingerprint is computed over the whole binary blob that the base64 decodes to — not the base64 text, and not some field inside it. Get that wrong and nothing errors; you just get a value that never matches, and matching is the entire purpose. That is why both fingerprints here are tested against real `ssh-keygen` output. ⚠️ MD5 is the old format (OpenSSH 6.8 switched its default to SHA-256). It is shown because plenty of older servers, documents and admin panels still print it — when two values disagree, first check whether they are the same format. Generate: pick a type and a comment and get a key pair made in your browser. ⚠️ The private key is standard PKCS#8 PEM, not OpenSSH’s own format (that one uses bcrypt_pbkdf, which is not available in a browser) — so the result includes the conversion command and a reminder to copy it now, because closing the page loses it. Everything runs locally; nothing is uploaded.
Features
- Parse a public key: type, size, comment, and any `authorized_keys` options at the start of the line
- ⚠️ Both SHA-256 and MD5 fingerprints, matching `ssh-keygen -lf` character for character
- ⚠️ Says plainly that MD5 is the old format — check that first when two values disagree
- ⚠️ RSA size is read from the modulus inside the blob, not estimated from the base64 length
- Lines with options (`command="echo a b",no-pty ssh-ed25519 …`) are not split apart on spaces
- Generate Ed25519 or RSA 2048 / 3072 / 4096
- ⚠️ The generated private key is PKCS#8 PEM, with the command to convert it to OpenSSH format (bcrypt_pbkdf is not available in a browser)
- ⚠️ A reminder that the key lives only in browser memory and is gone on refresh — copy it now
- After generating, the public key is parsed back as a self-check, so “generated” and “read” agree
- Runs entirely in your browser; keys are never uploaded or stored
How to use
- To parse: paste the public key line (copy it whole from `~/.ssh/id_ed25519.pub`)
- To generate: switch “what to do” to generate, pick a type and a comment
- For parsing, compare the fingerprint line against `ssh-keygen -lf` on the server
FAQ
- Why are there two fingerprints, and which should I use?
- Because they are two renderings of the same thing: both hash the binary the base64 decodes to, one with SHA-256 and one with MD5. Use SHA-256 — `ssh-keygen` has defaulted to it since OpenSSH 6.8 in 2014, and MD5 should not be used for any security decision. MD5 is here because plenty of older servers, documents and admin panels still print it, and a format mismatch looks like “the key is wrong”. When they disagree, check the prefix (`SHA256:` versus `MD5:`).
- Why can’t the generated private key be used by ssh directly?
- Because the modern private key `ssh-keygen` writes (`-----BEGIN OPENSSH PRIVATE KEY-----`) uses bcrypt_pbkdf to derive an encryption key from a passphrase, and that KDF is not in the browser crypto API — a web page cannot produce it. So this gives you a standard PKCS#8 PEM, with the `ssh-keygen -p -m pem` conversion command in the result. Pretending to produce a `.ssh/id_ed25519`-shaped file would suggest it just works when copied, and ssh would only report a format error.
- What is that string of options before the key in authorized_keys?
- They are restrictions on the key and must not be dropped when copying. The common ones: `command="..."` allows the key to run only that one command (the usual approach for deploy keys), `from="10.0.0.*"` limits the source address, `no-pty` forbids allocating a terminal, and `no-port-forwarding` forbids forwarding. Dropping them widens the key’s authority to unrestricted — which is exactly what they were added to prevent.
- Ed25519 or RSA?
- Ed25519, unless something forces otherwise. It is much shorter (a 68-character public key against 500-plus for RSA 2048), faster to sign with, and has none of RSA’s parameter-choice pitfalls. RSA is still useful when an older server or device does not accept Ed25519 — in that case use 3072 bits or more; 2048 is on the short side by current standards.
- Are the generated keys secure?
- The key comes from the browser’s `crypto.subtle.generateKey`, which uses the operating system’s cryptographically secure random source, and is strong enough. The risk is not in generating it but in where you put it: never commit it (one commit keeps it in history forever, deletion and all), never paste it into a chat app, never sync it through cloud storage. On a development machine you can delete it and make another — it takes seconds. The public key carries none of that risk; it is meant to be public.
Related tools
Self-signed Cert
EncodingGenerate an RSA key pair and a self-signed X.509 certificate in the browser. 1024–4096-bit keys, SHA-256/384/512, optional SAN. For local HTTPS.
Certificate Reader
EncodingRead an X.509 certificate: subject, issuer, validity, public key, SAN, key usage, signature algorithm and fingerprints. Reads only, no chain validation.
Hash
EncodingCompute MD5, SHA-1, SHA-256, SHA-512 or MD4 digests of any text, hashed as UTF-8 bytes so they match openssl exactly. Runs in your browser.
Base64
EncodingConvert text to Base64 and back, with correct UTF-8 handling for accents, CJK and emoji. Runs entirely in your browser — nothing is uploaded.
URL Encode
EncodingEscape text into %XX form and back again, treating a whole URL and a single parameter value as different jobs. Runs entirely in your browser.
HTML Entities
EncodingTurn < > & and quotes into HTML entities and decode them back in a single pass, so &lt; becomes <, not an angle bracket. Runs in your browser.