How to know if a .pem file contains public or private key

opensslpemprivate-keypublic-key

I have a .pem file (base64-encoded cryptography information). What OpenSSL command-line should I use to detect whether it contains a public key or a private key?

As explained in this StackOverflow question, a .pem can contain both.

Since the contents of the file are juste garbled base64, when sending a .pem certificate to some other machine, I would like to make sure I'm exporting the public key and not giving out my private key.

Best Answer

I have a .pem file (base64-encoded cryptography information). What OpenSSL command-line should I use to detect whether it contains a public key or a private key?

In general, you have to inspect the the first line of the PEM file to determine what is present.

OpenSSL can detect a subset of available encoded things (for lack of a better term). You can see the list of what OpenSSL can decode by examining <openssl src>/crypto/pem/pem.h. From the file:

#define PEM_STRING_X509_OLD "X509 CERTIFICATE"
#define PEM_STRING_X509     "CERTIFICATE"
#define PEM_STRING_X509_PAIR    "CERTIFICATE PAIR"
#define PEM_STRING_X509_TRUSTED "TRUSTED CERTIFICATE"
#define PEM_STRING_X509_REQ_OLD "NEW CERTIFICATE REQUEST"
#define PEM_STRING_X509_REQ "CERTIFICATE REQUEST"
#define PEM_STRING_X509_CRL "X509 CRL"
#define PEM_STRING_EVP_PKEY "ANY PRIVATE KEY"
#define PEM_STRING_PUBLIC   "PUBLIC KEY"
#define PEM_STRING_RSA      "RSA PRIVATE KEY"
#define PEM_STRING_RSA_PUBLIC   "RSA PUBLIC KEY"
#define PEM_STRING_DSA      "DSA PRIVATE KEY"
#define PEM_STRING_DSA_PUBLIC   "DSA PUBLIC KEY"
#define PEM_STRING_PKCS7    "PKCS7"
#define PEM_STRING_PKCS7_SIGNED "PKCS #7 SIGNED DATA"
#define PEM_STRING_PKCS8    "ENCRYPTED PRIVATE KEY"
#define PEM_STRING_PKCS8INF "PRIVATE KEY"
#define PEM_STRING_DHPARAMS "DH PARAMETERS"
#define PEM_STRING_SSL_SESSION  "SSL SESSION PARAMETERS"
#define PEM_STRING_DSAPARAMS    "DSA PARAMETERS"
#define PEM_STRING_ECDSA_PUBLIC "ECDSA PUBLIC KEY"
#define PEM_STRING_ECPARAMETERS "EC PARAMETERS"
#define PEM_STRING_ECPRIVATEKEY "EC PRIVATE KEY"
#define PEM_STRING_PARAMETERS   "PARAMETERS"
#define PEM_STRING_CMS      "CMS"

Some things will be more difficult than others. For example, its obvious what a RSA PUBLIC KEY is, but its not so obvious what a PUBLIC KEY is. In this case, you do one of two things. First, you ASN.1/DER decode the thing and then look ups its OID if available. Second, you try and load into a data structure that you expect the thing to be.

As an example of the second strategy, you would attempt to load a PEM blob into a RSA private key with PEM_read_bio_RSAPrivateKey. If it succeeds, then its a RSA private key. If its fails, then it may be a damaged RSA private key, or it may be an EC private key, or it may not be a PEM blob.


In 2006, a request was made to standardize the names of the things with the PKIX working group. It fell on deaf ears within the IETF. See PEM file format rfc draft request.