openssl, one subcommand per page
Twenty-eight lessons on openssl, one subcommand or one certificate concept per page: what OpenSSL is; certificate anatomy and the SAN field; genpkey and the key pair; req and the CSR; self-signed, honestly and the lie; inspecting with x509; the PEM armor and DER; converting forms; s_client as the TLS microscope; reading the chain; what verify checks; the trust store; dgst hashes and HMAC; signing with dgst and pkeyutl; enc and its limits; passwd hashing; rand; speed; pkcs12 bundles; the Heartbleed story; the honest limits; and teaching a friend a first end to end.
One command, one page, one real capture. That's the rhythm.
openssl, one subcommand per page
Twenty-eight lessons on openssl, one subcommand or one certificate concept per page: what OpenSSL is; certificate anatomy and the SAN field; genpkey and the key pair; req and the CSR; self-signed, honestly and the lie; inspecting with x509; the PEM armor and DER; converting forms; s_client as the TLS microscope; reading the chain; what verify checks; the trust store; dgst hashes and HMAC; signing with dgst and pkeyutl; enc and its limits; passwd hashing; rand; speed; pkcs12 bundles; the Heartbleed story; the honest limits; and teaching a friend a first end to end.
Set in Space Grotesk, Inter and JetBrains Mono (SIL Open Font License).
Every fact in this book is as the official source states it, fetched and read during this build: the openssl.org manual pages for openssl, genpkey, req, x509, s_client, dgst, enc, rand, verify, passwd, pkeyutl, pkcs12 and speed (the definition of truth for this book), and the Wikipedia articles OpenSSL, Transport Layer Security, X.509, Public key certificate, Certificate signing request, Certificate authority, Heartbleed, Privacy-Enhanced Mail, PKCS 12 and RSA cryptosystem. No facts are sourced from Reddit, Stack Overflow, vendor blogs or commercial sites. Every command and output pair was run on this machine (OpenSSL 3.0.13 30 Jan 2024 at /usr/bin/openssl, Ubuntu) in throwaway scratch space, throwaway lab keys, CSRs and certificates only, never a real personal key or a real site certificate; keys are fresh per build, so serials and fingerprints differ. The s_server and s_client pair was captured locally on localhost:4433. Honest notes: genrsa still runs silently on this 3.0.13 (genpkey is the general command), and a 30-day cert honestly answers Certificate will expire to a 31-day -checkend. An independent guide, not affiliated with or endorsed by the OpenSSL Software Foundation or the Wikimedia Foundation.
Your purchase is for personal use only. You do not have redistribution rights: please do not share, resell, or republish this book or its pages.
© 2026 Steve Hodgkiss. All rights reserved. Personal use only; no redistribution rights.
Edition 1.0 · stevehodgkiss.net
Contents
Per the Wikipedia X.509 article, a certificate's structure includes the Issuer Name, the Validity period, the Subject name and the Subject Public Key Info, and X.509 was initially issued on July 3, 1988, assuming a strict hierarchical system of certificate authorities for issuing the certificates. Per the Wikipedia Public key certificate article, the Subject field must identify the primary hostname of the server as the Common Name. This machine's capture: openssl x509 -noout -subject -issuer -serial -dates printed subject=C = GB, O = Lab, CN = lab.local, an identical issuer, serial 358204C252D82A941AA8F989173CFCA58988A57D, notBefore=Nov 3 11:00:52 2026 GMT and notAfter=Dec 3 11:00:52 2026 GMT.
Certificate anatomy
A certificate is a signed card with four load-bearing fields, per the X.509 article: who issued it, who it names, until when, and the public key it carries.
A self-signed cert shows the trick plainly: issuer and subject are the same string.
Our capture: issuer= and subject= both read C = GB, O = Lab, CN = lab.local; notBefore Nov 3, notAfter Dec 3 2026 GMT.
Print one cert's card: openssl x509 -in cert.pem -noout -subject -issuer -dates.
Per the openssl req manual page, this command can additionally create self-signed certificates for use as root CAs for example, and -x509 outputs a certificate instead of a certificate request. Per the Wikipedia X.509 article, X.509 assumes a strict hierarchical system of certificate authorities for issuing the certificates. This machine's capture: openssl req -x509 -key key.pem -days 30 issued a Version 3 (0x2) certificate with Signature Algorithm sha256WithRSAEncryption in which Issuer and Subject are both C = GB, O = Lab, CN = lab.local.
Self-signed, honestly
Same command, one flag: openssl req -x509 signs its own application. Issuer equals subject, and the manual page names the honest use: root CAs, for example.
Our capture printed Version: 3 (0x2), sha256WithRSAEncryption, thirty days of validity.
Honest scope: a lab door badge. It says who you claim to be, countersigned by yourself.
Issue yourself a lab cert: openssl req -x509 -key key.pem -out cert.pem -days 30 -subj "/CN=lab.local".
Per the Wikipedia Privacy-Enhanced Mail article, PEM is a de facto file format for storing and sending cryptographic keys, certificates and other data; because DER produces binary output that is challenging to transmit through systems that only support ASCII, the PEM format encodes the binary data using base64, with a one-line header of -----BEGIN, a label and -----, and a matching -----END footer; common labels include CERTIFICATE, CERTIFICATE REQUEST and PRIVATE KEY; the original 1993 standards were never broadly adopted but the textual encoding they defined became very popular, and the format was eventually formalized by the IETF in RFC 7468. This machine's captures: the key file opens -----BEGIN PRIVATE KEY-----; file identified cert.pem as PEM certificate at 1216 bytes.
The PEM armor
The armor is base64 between BEGIN and END lines, says the PEM article. The label, not the file suffix, tells you what is inside: CERTIFICATE, CERTIFICATE REQUEST, PRIVATE KEY.
Indigo mechanism: the armor exists because mail systems pass text, not bytes.
Our capture: key.pem opens -----BEGIN PRIVATE KEY-----; file calls cert.pem a PEM certificate, 1216 bytes.
Look inside your own armor: head -1 key.pem, then head -3 csr.pem.
Per the openssl verify manual page, this command verifies certificate chains, and if a certificate chain has multiple problems, this program attempts to display all of them. Per the Wikipedia Certificate authority article, the client uses the CA certificate to authenticate the CA signature on the server certificate. This machine's captures: a mini CA (Demo Lab CA) signed a CSR with openssl x509 -req -CA ca.crt -CAkey ca.key; openssl verify -CAfile ca.crt server.crt answered server.crt: OK; openssl verify cert.pem alone failed error 18 at 0 depth lookup: self-signed certificate; pointing -CAfile at the wrong root failed error 20 at 0 depth lookup: unable to get local issuer certificate.
What verify checks
verify walks signatures and dates from your cert toward a root you hand it, and attempts to display all of them when a chain has several problems.
Error numbers are a map: 18 self-signed, 20 unable to get local issuer.
Our capture: server.crt: OK under its own CA, with two honest failures beside it.
Run openssl verify -CAfile ca.crt server.crt, then drop the -CAfile and compare the two answers.
Per the openssl dgst manual page, this command also generates and verifies digital signatures using message digests, with -sign signing using the private key and -signature naming the signature file. Per the Wikipedia RSA cryptosystem article, there are no published methods to defeat the system if a large enough key is used. This machine's captures: openssl dgst -sha256 -sign key.pem -out note.sig note.txt wrote a signature of exactly 256 bytes for the RSA-2048 key (wc -c answered 256); with the public half, openssl dgst -sha256 -verify pub.pem -signature note.sig note.txt answered Verified OK.
Sign with dgst
Signing is hashing plus your private key: dgst -sign digests the file, then wraps the digest under the key only you hold.
For an RSA-2048 key the signature is exactly the key size: our note.sig is 256 bytes.
Our capture: Verified OK from the -verify run with pub.pem. Anyone can check it; only the key holder could make it.
Sign and verify one file: dgst -sha256 -sign key.pem, then -verify pub.pem -signature note.sig.
Per the openssl rand manual page, openssl-rand generates pseudo-random bytes, with -hex and -base64 output forms. Per this book's plan, randomness is a resource and two runs of the same command must never agree. This machine's captures: openssl rand -hex 16 printed 532edabe881837712b9f70770dbaf681; a second run printed baac6d6f25730cde341a648f36a20681; openssl rand -base64 16 printed +vXu3xu32DilutYI2lrwbg==.
rand, good bytes
Randomness is a resource, and openssl rand is the tap: -hex 16 gives 32 hex characters, 16 real bytes; -base64 16 gives 24 characters.
Run it twice: two different answers. That difference is the whole point, and the check.
Our capture: 532edabe881837712b9f70770dbaf681, then baac6d6f25730cde341a648f36a20681. Fresh each run, by nature.
Draw from the well twice: openssl rand -hex 16; confirm the two answers differ.
Per this book's plan, the closing lesson is teaching one friend one subcommand end to end, with the book's first end-to-end folded in: generate a key, request a certificate, self-sign it for the lab, inspect it, and hash a file. Per the openssl genpkey, req, x509 and dgst manual pages, each step is one documented command. This machine's captures: genpkey -algorithm RSA built friend.key; req -new wrote friend.csr for CN = friend.local; req -x509 issued friend.crt valid Nov 3 to Dec 3 2026 GMT; x509 -noout -subject -dates read it back; dgst -sha256 fingerprinted friend.crt; a dgst -sha256 -sign and -verify pair on note.txt answered Verified OK.
Teaching a friend
The whole book in one sitting with a friend: key, application, lab cert, inspect, fingerprint. Five commands, one story.
Teach the reading as much as the typing: what does each output prove, and what does it not?
Our capture: friend.local certified Nov 3 to Dec 3 2026 GMT; its signature Verified OK. Now it is theirs to run.
Sit with one friend and run all five steps on their machine; let them type every line.