A service asks for a PEM file, a PKCS#8 key, and an X.509 certificate. Those names describe different things, and mixing them up makes TLS setup harder than it needs to be.
Let’s generate a disposable pair and inspect what each file proves.
Separate content from encoding
A private key is secret signing material. A certificate contains a public key and identity information signed by an issuer. X.509 describes the certificate structure. PKCS#8 describes a private-key structure. PEM is a text encoding that can wrap either kind of object.
So “PEM or PKCS#8?” is not a choice between mutually exclusive alternatives. A PKCS#8 private key can be PEM encoded.
Use the diagram to keep the two kinds of file separate.
Generate a one-day test identity
Create a fresh working directory, then run:
umask 077
openssl req -x509 -newkey rsa:2048 -noenc -days 1 \
-keyout server.key.pem -out server.cert.pem \
-subj '/CN=app.example.test' \
-addext 'subjectAltName=DNS:app.example.test'
The hostname is fictional. -noenc creates an unencrypted private key for this local exercise. File permissions matter because anyone who obtains the key can use it. In a real service, choose key protection compatible with its startup and credential-management design.
The subject alternative name, or SAN, carries the DNS identity. The OpenSSL request reference documents these options.
Make an explicit PKCS#8 copy:
openssl pkcs8 -topk8 -nocrypt \
-in server.key.pem -out server.pkcs8.pem
A modern generator may already have produced PKCS#8. This conversion makes the requested output format explicit; it doesn’t make a new identity or add trust. -nocrypt leaves this copy unencrypted too. See the PKCS#8 reference.
Inspect before installing
Read the certificate’s identity and validity:
openssl x509 -in server.cert.pem -noout \
-subject -issuer -dates -ext subjectAltName
Now compare public-key fingerprints:
openssl pkey -in server.pkcs8.pem -pubout -outform DER | openssl sha256
openssl x509 -in server.cert.pem -pubkey -noout | \
openssl pkey -pubin -outform DER | openssl sha256
The two hashes should match. We extract the public key from each file, encode both in the same binary format, and hash that representation. Hashing the original files would compare different objects and tell us nothing useful about pairing.
Pause and predict
The key and certificate have different filenames. Does that mean they cannot be a pair?
Need a hint?
Filenames are labels chosen by the operator.
Show the reasoning
Test identity separately from trust
Use the disposable certificate as an explicit trust input for this command only:
openssl verify -CAfile server.cert.pem \
-verify_hostname app.example.test server.cert.pem
Expect server.cert.pem: OK. Repeat with -verify_hostname wrong.example.test; expect failure. This checks one property of the certificate. It doesn’t prove that a running server loaded this file or presents it correctly.
A self-signed certificate isn’t automatically trusted by other clients. Distributing trust and verifying a name are separate responsibilities. Avoid turning off verification to hide a missing trust setup.
Try it yourself
Generate a second key/certificate pair under different filenames. Compare the first key with the second certificate. Predict whether their fingerprints should match before running the commands.
Apply the idea
A service accepts the PKCS#8 file, but clients reject its certificate for the wrong name. Will converting the key again fix that?
Need a hint?
Which file contains the hostname?
Show the reasoning
Remove the disposable directory, including both unencrypted keys, after the exercise. Continue with the local curl HTTPS lab (lesson in preparation) to inspect identity over a real connection.