A digital artwork of a large tree with twisting roots intertwined with metallic, key-shaped structures. The tree branches transform into glowing circuit-like patterns against a serene, slightly futuristic background blending organic and technological elements.

Common Public Key Standards and Their Use with OpenSSL

This post outlines several commonly adopted standards for working with public keys in cryptographic systems. It highlights their primary purposes, relevant use cases and gives examples of how to generate or work with these standards using OpenSSL commands.

This post does not cover specific file formats (e.g., PEM, DER, or JWK), for more information on file formats, please refer to:

Common Cryptographic File Formats

An overview of PEM, DER, JWK, and JWKS, covering usage details, file extensions, and import/export examples with OpenSSL and Web Crypto API.

PKCS #8

  • Purpose: Defines a generic, algorithm-agnostic format for private keys.
  • Context: Used wherever private keys need to be stored or exchanged in a standardized manner, supporting RSA, EC, DSA, and others in a single format.
  • Typical Extensions: .pem (PEM-encoded)
  • Formal Definition: historically RFC 5208, but obsoleted by RFC 5958.

Example (PEM format):

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9...
-----END PRIVATE KEY-----

Generate an RSA private key in PKCS #8 format:

openssl genpkey -algorithm RSA -out private_key.pem

SPKI (SubjectPublicKeyInfo)

  • Purpose: Defines a standard, algorithm-agnostic format for public keys, as part of the X.509 certificate structure.
  • Context: Commonly extracted from certificates or derived from a PKCS #8 private key. By taking a PKCS #8 private key (which includes both algorithm parameters and the private key material), one can produce the corresponding public key in SPKI format, ensuring consistent algorithm identification and key data representation.
  • Typical Extensions: .pem (PEM-encoded)
  • Formal Definition: Defined within X.509 RFC 5280 (see SubjectPublicKeyInfo section)

Example (PEM public key):

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkq...
-----END PUBLIC KEY-----

Generate a public key from a private key in PKCS #8 format with OpenSSL:

openssl rsa -pubout -in private_key.pem -out public_key.pem

It is not trivial to extract the public key from a private key in PKCS #8 format using the Web Crypto API. If you are interested in this process, you can refer to the article below for a guide:

PKCS #10 (Certificate Signing Request - CSR)

  • Purpose: A request for a certificate, including a public key (SPKI) and identifying information like the requested subject’s name.
  • Context: Submitted to a certificate authority to obtain an X.509 certificate.
  • Typical Extensions: .csr, sometimes .pem (Note: .csr files are typically PEM-encoded.)
  • Formal Definition:: RFC 2986
    • PKCS #10 was defined in the context of the original PKCS standards by RSA Labs
    • It was not formally standardized by the IETF, but the format is widely used in practice
    • RFC 2986 is basically a re-publication of the original PKCS #10 specification

Example (PEM-encoded CSR):

-----BEGIN CERTIFICATE REQUEST-----
MIICzDCCAbQCAQAwCzEJMAcGA1UEAwwAM...
... (This request includes the public key and the subject details such as CN, O, L, ST, C)
-----END CERTIFICATE REQUEST-----

Generate a CSR with OpenSSL and an existing private key (the private key is used to create the public key in the CSR and to sign the CSR):

The signature algorithm is defined by PKCS #1, when using RSA, which is the default for OpenSSL.

openssl req -new -key private_key.pem -out request.csr

You can view the contents (mainly Subject, SPKI and Signature) of a CSR with:

openssl req -in request.csr -noout -text

X.509

What It Is:
X.509 is a standard defining the format of public key certificates. These certificates bind a public key to an identity (e.g., a server name or a person). The X.509 structure also uses ASN.1. Many PKCS standards build on or interact with X.509 certificates.

Formal Definition: RFC 5280

Example (PEM):

-----BEGIN CERTIFICATE-----
MIIDazCCAlOgA...
-----END CERTIFICATE-----

Generate a self-signed certificate using a CSR (Certificate Signing Request) and a private key:

openssl req -new -key private_key.pem -out request.csr
openssl x509 -req -in request.csr -signkey private_key.pem -out cert.pem

Generate a self-signed certificate with OpenSSL and an RSA private key (PKCS #8 format):

openssl req -new -x509 -key private_key.pem -out cert.pem -days 365

You can also create a self signed certificate without a private key, openssl will generate a new key for you:

openssl req -new -x509 -keyout private_key.pem -out cert.pem -days 365
# this will ask for a password, because the private key will be encrypted with AES256 per default
# you can create a private key without password with the -nodes (No DES) option
openssl req -new -x509 -keyout private_key.pem -out cert.pem -days 365 -nodes # no DES encryption, option name is a bit misleading, because nowadays AES is used

You can view the contents of a certificate with:

openssl x509 -in cert.pem -noout -text

PKCS #12 (PFX)

  • Purpose: Binary container for private keys, certificates, and optionally a chain of certificates, often encrypted with a password.
  • Context: Used to transport and back up key+certificate pairs securely, commonly in Windows environments or when importing keys into browsers or servers.
  • Typical Extensions: .p12, .pfx
  • (Binary format, no direct PEM example.)
  • Formal Definition: RFC 7292

Generate a PKCS #12 file from a private key and certificate:

openssl pkcs12 -export -inkey private_key.pem -in cert.pem -out keystore.p12

You can view the contents of a PKCS #12 file with:

openssl pkcs12 -info -nodes -in keystore.p12 # no DES (-nodes) option to avoid password prompt, remove it if the private key is encrypted

You can extract the private key and certificate from a PKCS #12 file with:

# Extract the private key (unencrypted)
openssl pkcs12 -in keystore.p12 -out private_key.pem -nodes -nocerts # remove no DES (-nodes) option if the private key is encrypted
# Extract the certificate
openssl pkcs12 -in keystore.p12 -out cert.pem -nokeys -clcerts

CMS (Cryptographic Message Syntax)

  • Purpose: CMS is the IETF’s standard syntax for cryptographically protected messages. It supports digital signatures, message digests, and encryption. CMS is effectively the evolution of PKCS #7 in an IETF standards track.
  • Context: CMS is widely used in secure email (S/MIME), secure file transfer, and other scenarios requiring signed or encrypted data interchange.
  • Typical Extensions: While CMS can be encapsulated in various file extensions (.p7s, .p7m, or sometimes .cms), it often appears in contexts where PKCS #7 formats were traditionally used.
  • Structure: A CMS object (like PKCS #7) can contain certificates, signer info, and encrypted data. However, private keys are not typically included. The data can be encoded in binary (DER) or ASCII-armored (PEM).
  • Formal Definition: RFC 5652
  • CMS was derived from PKCS #7 but became an IETF standard.

Example (PEM) Although PEM labels vary in practice, you might see:

-----BEGIN CMS-----
MIIGCSqGSIb3DQEHAaCCA...
-----END CMS-----

Create a Signed CMS Message:

openssl cms -sign \
    -in data.txt \
    -signer cert.pem \
    -inkey private_key.pem \
    -out signed.cms \
    -nodetach \
    -outform PEM

Verify a CMS Message:

Since we are using a self signed certificate the signer and the CA are the same, normally you would use a root CA certificate to verify the signature.

openssl cms -verify \
    -in signed.cms \
    -CAfile cert.pem \
    -out verified_data.txt

Encrypt Data Using CMS:

openssl cms -encrypt \
    -in data.txt \
    -out encrypted.cms \
    -outform PEM \
    cert.pem

Decrypt Data Using CMS:

openssl cms -decrypt \
    -in encrypted.cms \
    -recip cert.pem \
    -inkey private_key.pem \
    -out decrypted_data.txt

S/MIME (Secure/Multipurpose Internet Mail Extensions)

  • Purpose: S/MIME provides a standard for public key encryption and signing of MIME data, typically used in email. It leverages CMS (formerly PKCS #7) as its core cryptographic structure.
  • Context: S/MIME is the de-facto standard for secure email. It adds cryptographic enhancements to MIME messages, allowing for end-to-end encryption and digital signatures in email clients.
  • Typical Extensions / Usage: S/MIME messages often appear as .p7s attachments for detached signatures, or .p7m for enveloped (encrypted) data within email clients.
  • Structure (No Private Key): The actual S/MIME messages will contain CMS/PKCS #7 structures but do not embed private keys. Certificates for the sender or the encryption recipient may be included to facilitate trust. (typically not PEM encoded)
  • Formal Definition: RFC 5751

Example

MIME-Version: 1.0
Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----abc1"

This is an S/MIME signed message

------abc1
Content-Type: text/plain

(SOME DATA)
------abc1
Content-Type: application/x-pkcs7-signature; name="smime.p7s"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"

MIIGGgYJK...

------abc1--

Create a Signed S/MIME Message

openssl smime -sign \
    -in data.txt \
    -text \
    -signer cert.pem \
    -inkey private_key.pem \
    -out signed.p7m

Verify a Signed S/MIME Message

  • Since the generated p7m file includes the signer's public key certificate, it is self contained and can be verified without explicitly providing the CA certificate.
  • In a real-world scenario, you would need the CA certificate to make sure the signer's certificate is trusted, since we are using a self signed certificate here, we skip the validation of the signer's certificate chain with -noverify.
openssl smime -verify \
    -noverify \
    -in signed.p7m \
    -out verified_message.txt

Encrypt a Message for S/MIME

openssl smime -encrypt \
    -in data.txt \
    -out encrypted.p7m \
    cert.pem

Decrypt an Encrypted S/MIME Message

openssl smime -decrypt \
    -in encrypted.p7m \
    -recip cert.pem \
    -inkey private_key.pem \
    -out decrypted_data.txt

Other Notable Standards

PKCS #1

  • Purpose: Defines the RSA cryptography standard, including the mathematical properties of RSA keys, as well as the encoding, encryption, and signature schemes (e.g., RSAES-OAEP, RSASSA-PSS).
  • Key Handling: Primarily defines how to work with RSA keys and their operations, not how to store them. While PKCS #1 private key structures can still appear in legacy deployments, modern environments often use PKCS #8 for key storage.
  • Relevance: PKCS #1 is actively maintained and forms the basis for RSA usage in various protocols. While the PKCS #1 format is considered legacy (modern systems use PKCS #8 for private key storage), the standard itself is still fundamental for specifying RSA algorithm behavior, padding, and signature schemes.
  • Typical Usage: Referenced whenever RSA signatures or encryption must be performed, ensuring interoperability and consistent algorithm definitions.
  • Formal Definition: RFC 8017

Legacy Example (RSA Private Key, PEM):

this format is considered legacy and not recommended for new deployments, newer systems use PKCS #8 for storing private keys

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA...
-----END RSA PRIVATE KEY-----

PKCS #3 (Diffie-Hellman Parameters)

  • Purpose: Specifies parameters for Diffie-Hellman key exchange.
  • Context: Used to share and standardize DH parameters, less common today but still used in some legacy systems.
  • Typical Extensions: .pem
  • Formal Definition: RFC 2631

Example (PEM):

-----BEGIN DH PARAMETERS-----
MIGHAoGBALWo...
-----END DH PARAMETERS-----

PKCS #7 (Cryptographic Message Syntax)

  • Purpose: Defines a format for signed or encrypted data, and can bundle certificates.
  • Context: Used to distribute certificates or signed messages without revealing private keys.
  • Typical Extensions: .p7b, .p7c
  • (No private key included, typically a binary or PEM-encoded structure with certificates and signatures.)
  • Formal Definition: RFC 2315
    • RFC 2315 is not an internet standard,
    • But CMS (Cryptographic Message Syntax - RFC 5652) was directly derived from PKCS #7
    • And in the end CMS is the basis for S/MIME (Secure/Multipurpose Internet Mail Extensions - RFC 5751)

Example (PEM):

-----BEGIN PKCS7-----
MIIBIjANBgkq...
-----END PKCS7-----

Generate a PKCS #7 file with OpenSSL (-nocrl for no Certificate Revocation List, which is ):

openssl crl2pkcs7 -nocrl -certfile cert.pem -out certs.p7b

Inspect the contents of a PKCS #7 file:

openssl pkcs7 -in certs.p7b -print_certs -text