OpenSSL Command Builder
Pick a PKI job and read off the exact openssl line — every flag explained, quoting handled, and nothing executed on this page.
This command overwrites files
It writes key.pem and cert.crt. openssl replaces an existing file at that path without asking — run ls -l key.pem cert.crt first if you are not sure.
LibreSSL 3.3.6executed
openssl req \ -x509 \ -new \ -newkey rsa:2048 \ -keyout key.pem \ -subj /CN=example.com \ -days 365 \ -sha256 \ -out cert.crt
Executed on LibreSSL 3.3.6 — Every command marked executed was run by LibreSSL 3.3.6 (/usr/bin/openssl on the machine that generated this page's examples); rows marked cited come from OpenSSL 3.x documentation and were not executed here.
Code W_OVERWRITES_OUTPUTThis command writes key.pem and cert.crt. openssl replaces an existing file at that path without asking — check first with: ls -l key.pem cert.crt
One entry per flag the command above uses, in the order openssl reads them. Each line is this page's summary and links to the manual entry it was checked against.
openssl reqThe certificate-request subcommand: creates and inspects CSRs, and self-signs with -x509. manual-x509Makes req output a self-signed certificate instead of a request. manual-newCreates a new request (or, with -x509, a new certificate) instead of reading one. manual-newkeyGenerates a fresh key as part of the same command. manual-keyoutWhere the newly generated private key is written. manual-subjThe subject distinguished name, written as /TYPE=value pairs. manual-daysHow long the certificate is valid, counted from now. manual-sha256The hash used for the signature or digest. manual-outWhere the result is written. An existing file at that path is replaced. manual
This page only assembles text. It has no execution path for openssl, does no cryptography, and opens no connection — copying the command is the only output.
Press ? for shortcuts
Do it offline:$ openssl version
How to use it
- Choose a task card: inspect a certificate or CSR, generate a key, create a CSR, self-sign, probe with s_client, hash, encrypt, or bundle to PKCS#12.
- Fill in the fields the task shows — paths, a subject, days of validity. The command updates on every keystroke; a bad value is refused with the reason, and the last good line stays visible.
- Pick where a passphrase should come from: a terminal prompt (the flag is simply omitted), an environment variable (env:NAME), or a file (file:path). There is nowhere to type the passphrase itself.
- Check the dialect label on the command card. LibreSSL rows were executed on the golden host; OpenSSL 3.x rows are cited to the manual, and the notes quote what LibreSSL says when it refuses one.
- Copy the command, or switch to the multi-line layout first if you want one flag per line with backslash continuations.
Pick a PKI job — inspect, generate, sign, bundle — and read off the exact openssl line, with every flag explained beside it. Each executed example was produced by a real binary, LibreSSL 3.3.6, and forms that only exist on OpenSSL 3.x are labelled as cited instead of guessed. File paths and subjects are quoted for a POSIX shell, and your passphrase is never part of the command.
How it works
Each control maps to a fixed run of argv atoms: the task picks the subcommand (x509, req, genpkey, dgst, enc, pkcs12, s_client), toggles add their flag, and text fields ride as arguments. The atoms are grouped into segments, and the layout choice only changes how segments join — spaces for one line, backslash-newline for the multi-line block — never what they contain.
Quoting happens once, at the moment a value becomes part of a segment. A value made of provably inert characters is left bare; anything else is wrapped in single quotes, with an embedded apostrophe spelled as '\'' so the shell re-assembles the original bytes. A path that begins with a dash is emitted as ./name instead, because openssl would otherwise read it as an option.
Every task row satisfies one of two provenance rules (D-017): it was executed on the golden host — whose openssl version output is LibreSSL 3.3.6 — or it carries a citation into the OpenSSL 3.x manual. Where the two implementations actually diverge (-legacy, providers, Ed25519), the page shows the divergence and quotes LibreSSL's own refusal text byte for byte rather than pretending one command fits both.
No openssl runs in your browser. The page ships no cryptography and no execution path — it concatenates validated, quoted strings and hands you the result, which is why a malformed input can never do more than change text on screen.
Examples
Generate an RSA-2048 private keyopenssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out key.pemgenpkey is the modern front door for key generation. Executed at mint time, the resulting key.pem opens with -----BEGIN PRIVATE KEY----- — the PKCS#8 wrapper, not the older RSA-specific header.
Create a CSR from that keyopenssl req -new -key key.pem -subj /CN=example.com -out req.csr-subj skips the interactive questionnaire entirely. This subject is left unquoted because every character in it is shell-inert; add a space or a comma and the whole value gets single quotes.
Self-signed certificate, key and cert in one commandopenssl req -x509 -new -newkey rsa:2048 -keyout ss-key.pem -subj /CN=example.com -days 365 -sha256 -out ss-cert.crtNo pass flag appears, so openssl asks for the key's passphrase on the terminal — at mint time it was fed on stdin, and the key landed as -----BEGIN ENCRYPTED PRIVATE KEY-----. Lab and internal use only: nothing signed by this certificate chains to a trusted root.
Read a certificate's subject and validity windowopenssl x509 -in keypem-cert.crt -noout -subject -datesOn LibreSSL the first line comes back as subject= /CN=example.com — with a space after the equals sign and slash separators. That exact byte shape is a LibreSSL trait; scripts that parse it break quietly on OpenSSL 3.x, which prints the field differently by default.
SHA-256 fingerprint of a certificateopenssl x509 -in keypem-cert.crt -noout -fingerprint -sha256Output starts SHA256 Fingerprint= followed by colon-separated hex — the value pinning tools and certificate managers ask for.
Hash a file with dgstopenssl dgst -sha256 notes.txtdgst takes the file as a positional argument and prints SHA256(notes.txt)= followed by the digest hex. For checking downloads against a published checksum, this is the whole job.
Encrypt a file with AES-256, passphrase from an env variableopenssl enc -aes-256-cbc -pbkdf2 -pass env:GKEY -in notes.txt -out notes.txt.enc-pbkdf2 upgrades the key derivation and LibreSSL 3.3.6 accepts it — the mint run round-tripped this file back to its original bytes with the matching -d command. env:GKEY names a variable; the shell expands nothing here because the value is only read by openssl.
Bundle key and certificate into a .p12openssl pkcs12 -export -out bundle.p12 -inkey key.pem -in keypem-cert.crt -passout env:GKEYPKCS#12 is what Windows, Java keystores and most MDM tools want to import. The minted bundle came out at 2,285 bytes; a .p12 under a couple of kilobytes usually means the key or cert did not make it in.
Edge case: key path with a space, an apostrophe and $HOMEopenssl req \
-x509 \
-new \
-newkey rsa:2048 \
-keyout 'my keys/O'\''Brien $HOME.pem' \
-passout env:GKEY \
-subj '/CN=example.com/O=Acme, Inc.' \
-days 365 \
-sha256 \
-out edge-cert.crtExecuted exactly as printed: the key file appeared at the literal path my keys/O'Brien $HOME.pem. The space did not split the word, the apostrophe did not end the quote, and $HOME stayed five characters of file name instead of becoming a directory.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
-legacy is an OpenSSL 3.x word
Some importers still demand PKCS#12 bundles encrypted with the old algorithms, which OpenSSL 3.x provides behind pkcs12 -export -legacy. LibreSSL 3.3.6 rejects the flag outright — unknown option '-legacy' — so ticking the legacy box here produces two labelled cards: the line the golden host actually ran, and the cited 3.x line with the flag in place.
There is no provider subsystem to list
openssl list -providers is how OpenSSL 3.x shows its loadable algorithm modules. On LibreSSL the list command does not exist at all: the binary answers openssl:Error: 'list' is an invalid command. and then prints its command roster. If a how-to mentions providers, it is written for OpenSSL 3.x.
Ed25519 generation needs OpenSSL 3.x
Asking LibreSSL 3.3.6 for an Ed25519 key fails in both spellings, and not with the same words: genpkey -algorithm ed25519 says Algorithm ed25519 not found, while req -newkey ed25519 says Unknown algorithm ed25519. Pick Ed25519 here and the card flips to the cited OpenSSL 3.x form with both refusals quoted in the notes.
The subject line prints differently per implementation
x509 -subject on the golden host prints subject= /CN=example.com — note the space after the equals sign — while req -subject prints the same certificate request field with no space at all, and OpenSSL 3.x formats names its own way unless you pass -nameopt. Anything that greps these lines needs to know which binary wrote them.
Common errors
No command was built: one value is over the 512-character field limit.- Paths, subjects and names are capped at 512 characters each; the engine names the field and the actual length underneath.
No command was built: the subject is not in /TYPE=value form.- A -subj value starts with a slash and chains TYPE=value pairs, so CN=example.com without the leading slash is refused before it can confuse openssl.
No command was built: the validity period must be 1 to 36500 whole days.- Zero, negative and fractional day counts are refused; 36500 days is the hundred-year ceiling this builder accepts.
No command was built: s_client needs a plain host and a port from 1 to 65535.- A pasted URL is the usual trigger — s_client wants host and port as host:port, so the scheme has to go and the port rides in its own box.
No command was built. The engine reported:- The general banner: whatever refused the build is printed under it in the engine's own words, with its stable code.
FAQ
Does this page ever execute openssl or read my files?
No. There is no openssl in your browser, no WebAssembly build of it, and no upload — the page turns picker state into a quoted string and stops there. The proof is in the network tab: after load, using this builder sends nothing anywhere.
Why is there no box to type a passphrase?
Because a passphrase typed into a command generator tends to end up inside the generated command, and never paste a real passphrase into a command you are going to share. The picker offers the three safe spellings instead: omit the flag and let openssl prompt, point at an environment variable with env:NAME, or point at a file with file:path. The pass:text spelling exists in openssl but this page never writes it.
Why do the examples name LibreSSL when the command says openssl?
The machine that generated and verified this page's examples is a Mac, where /usr/bin/openssl is LibreSSL — version 3.3.6 there. The command name is the same; the implementation behind it is not. Run openssl version on your own box: if it answers OpenSSL 3.x, the cited rows apply to you and the four divergences on this page are exactly the places to check.
Can I do these jobs without a terminal at all?
Four of them, yes — do this without the terminal by opening the in-browser siblings: /certificate-decoder inspects a certificate, /csr-decoder reads a signing request, /rsa-key-generator makes a keypair, and /hash-generator covers the dgst job. Those tools do the work locally in your browser; this page only writes commands.
What changes when I mark the input as DER?
The line gains -inform DER. Without it openssl assumes PEM text, and pointing it at a binary file fails — as unable to load certificate for a certificate, and as unable to load X509 request for a CSR — so the builder adds the flag and a note quoting the right refusal whenever DER is selected.
Why is SHA-1 still offered if it is weak?
Because you sometimes have to match an old system, and refusing to write the command would just send you to a worse reference. Picking SHA-1 emits the line you asked for plus a warning that public collisions exist — honesty over paternalism.
Keyboard shortcuts
- ⌘/Ctrl + C
- Copy the command when nothing is selected and focus is in the tool.
- ⌘/Ctrl + Shift + C
- Copy the command even while text is selected.
- t
- Cycle theme.
- ? or ⌘/Ctrl + /
- Open the shortcut help overlay.
- Esc
- Close the overlay and refocus the form.