PKCS#1 vs PKCS#8 vs PKCS#12 for RSA keys
Asked Answered
S

1

5

What is the recommended RSA key format to use if you only started using it nowadays?

  1. I know that PKCS#1 is a format dedicated to RSA keys but do I need to avoid using it because it's old?

  2. recommended RSA key format to use will be PKCS#1, PKCS#8 or PKCS#12 ?

Syllable answered 5/2, 2023 at 9:42 Comment(0)
E
9

TL;DR: Use PKCS#1 only within your own identified scheme, use "inner" PKCS#8 / SPKI if you want to identify a key in a scheme. Use encrypted PKCS#8 when storing private keys and no better method is available; use PKCS#12 if you want to accomplish the same thing and you are using PKIX / X.509. PKCS#12 can also be used as a trust store, usually using a separate file.


I'll cover this because it is more about choosing an encoding than the inner working of RSA and other algorithms. If that wasn't the case then it should be posted on Cryptography, after searching for an answer on that Q/A site, of course.

First, here are the standards that we are talked about. They have been initially been created by RSA Laboratories, but currently they are being maintained as RFC's:

  • PKCS #1: RSA Cryptography Specifications Version 2.2: these specify the RSA cryptosystem, as well as specifying how the public- and private keys can be encoded.
  • PKCS #8: Public-Key Cryptography Standards (PKCS) #8: Private-Key Information Syntax Specification Version 1.2 : This documen specifies "inner" PKCS#8 which describes the private key type and contains the encoded private key and the "outer" PKCS#8 which creates a cryptographic wrapper that can be used to encrypt the private key using a symmetric algorithm such as 3DES or AES.
  • PKCS#12: PKCS #12: Personal Information Exchange Syntax v1.1 : Despite the broad wording of the title, this is "a transfer syntax for personal identity information, including private keys, certificates, miscellaneous secrets, and extensions", i.e. it is about "personal information" in the form of cryptographic objects.

Another important document (or really set) was initially created by ITU-T, formerly known as CCITT, an international treaty organization:

  • X.509 is the basic standard for (digital) certificates, which are a mechanism to infer trust for public keys and related (identity) information contained within certificates, and to allow revocation of those certificates.
  • There are number of other standards in the X.5nn and X.6nn series that support X.509, but people generally just say "X.509" to mean all of them together.

However, the X.509 standards are quite large and complex, and back when they were new cost money to obtain, so IETF (the Internet Engineering Task Force) created a series of RFCs that form a "profile" (effectively, a subset) of X.509 for Internet use, called PKIX (Public Key Infrastructure using X.509). The main one here is:

  • RFC5280 Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile: this is the main standard that describes certificates and revocation lists, which are used by e.g. TLS for server and sometimes client authentication, by CMS and S/MIME for signing and/or encrypting data and email, for RFC3161 timestamping, in "JOSE" (JSON-based cryptography), and more.
  • just as X.509 is supported by other X-series standards, RFC5280 is supported by a number of other, related RFCs. In particular the representation of public keys IN PKIX certs is defined in RFCs 3279, 4055, 4491, 5480, 5756, 8410, 8692, 9295 (at least, there may be more I've missed).

First note that these standards are not independent of each other. PKCS#12 depends on PKCS#8 to encode the private key and X.509/PKIX to encode the certificates within this "container format". PKCS#8 depends on PKCS#1 to encode the private key when it is an RSA key (pair), and X.509/PKIX similarly uses PKCS#1 for the public key. PKCS#8 originally used PKCS#5 (not listed above) for password-based encryption, but PKCS#12 defined additional password-based encryption schemes, and now both PKCS#8 within PKCS#12 and "standalone" PKCS#8 frequently use either the PBEs from PKCS#12 or the "PBES2" scheme from PKCS#5v2 (that v2 is critical; the PKCS#5v1 schemes are now broken and obsolete).

These structures can and often are stored in text rather than binary, in which case the specifications of PEM in RFC 1421 and the extensions for PKIX related structures in RFC 7468 should be consulted.

Which one to use?

Now comes the question which one to use. However, before we talk about storing private keys: private keys have been designed to remain private. That means that you should choose the most secure method of storing and using them (that still would help fulfill your use case). Quite often it is better to generate and store private keys within a secure container such as a hardware device (HSM, TPM) or a system provided certificate- or key store.

After that it depends on what you are trying to achieve.

PKCS#1

PKCS#1 describes a simple, near-minimal format for an RSA public or private key. So if you're handling raw private keys and need to store them on a medium, you need some way to encode the key. This is why the leading RSA specification contains a method of encoding them. So you'd use this standard when you'd work with RSA on a relatively low level, basically when you'd have to specify your own protocol (which you should do if you'd use RSA at such a low level, cryptographic protocols should deserve their own specific section in the documentation).

Notes:

  • The PKCS#1 format for the private key also contains the public exponent. That means that it is easy to extract the public key from the private key.
  • PKCS#1 is often also stored in textual format called PEM, where it has "RSA PUBLIC KEY" or "RSA PRIVATE KEY" in the header. As you can see, the PEM header contains the key type to be able to distinguish between key types and their respective encoding formats.
  • There is no official encryption method for a PKCS#1 private key, although OpenSSL (formerly SSLeay) -- and a huge number of libraries that have been developed to be compatible with OpenSSL -- use an ad-hoc, PEM-based, and quite poor method (specifically for PBKDF it uses OpenSSL's EVP_BytesToKey function with ONE iteration of MD5; see numerous Qs on the crypto and security Stacks about how bad this is).

PKCS#8

The inner format within PKCS#8 would be used if you need a way to identify the private key while using the binary construction. Basically it is a sequence of the key type followed by the key value. The key type consists of an algorithm identifier, which is encoded as an OID plus optional parameters. The original, and for a long time only, OID for an RSA key is defined in the PKCS#1 specifications:

The object identifier rsaEncryption identifies RSA public and private keys as defined in Appendices A.1.1 and A.1.2. The parameters field has associated with this OID in a value of type AlgorithmIdentifier SHALL have a value of type NULL.

rsaEncryption    OBJECT IDENTIFIER ::= { pkcs-1 1 }

Which means that the key is specified using 1.2.840.113549.1.1.1. Note that this doesn't indicate the algorithm to be used for that key. OTOH PKCS#1 (now) defines different OIDs for OAEP and PSS and their related parameters in that same appendix, and RFC4055 directs the use of those OIDs and parameters in public keys in PKIX certificates -- and 4055 is standards track while 8017 is not. [DaveT note: I suspect the statement about always using rsaEncryption is a leftover from v1 when it meant that the key didn't specify a signature hash like sha1withRSA.]

Another reason to choose PKCS#8 is a requirement to use a standard, documented, and (potentially) strong encryption for your private key. (PKCS#8 specifies the encryption with a very general AlgorithmIdentifier syntax, so it is possible to use a weak encryption algorithm, or a low and inadequate iteration count; however most software won't do so by default.)

As indicated, PKCS#8 encoded information can be put within PEM headers. For the "inner" PKCS#8 structure the header "PRIVATE KEY" is used. For the encrypted "outer" structure the header "ENCRYPTED PRIVATE KEY" is used. (Both of these are in RFC7468, cited above.)

SPKI

SPKI is an acronym for SubjectPublicKeyInfo. It is the main method within the X.509/PKIX specification to describe a public key. It is almost identical to the "inner" PKCS#8 structure in the sense that it simply consist of a sequence of an algorithm identifier with the value of the public key. Usually the same algorithm identifier is even used for both the public and the private key. As with PKCS#8, the sole purpose is to be able to identify the key type.

These keys can be encoded within PEM, and they then would use "PUBLIC KEY" in the header analogous to "inner" PCKS#8.

X.509/PKIX

X.509 (or its Internet form, PKIX) specifies the certificate format used for instance for TLS, but also for CMS (the cryptographic message syntax originally specified in and still sometimes called PKCS#7) as well as S/MIME (the standard for secure email based on CMS) and many other protocols such as XMLenc and XMLdigsig but also code signing etc. etc. X.509 certificates can be used to create a PKI, a public key infrastructure. Certificates are the main method of distributing and trusting public keys. When creating a key pair, the public key is quite often simply stored within a certificate that also contains information about the holder of the certificate which can be a human, a "role" or system such as server.

For RSA to work it is usually required to not just have the public key but to establish trust in the public key. Otherwise you'd not know who's public key you would be using to verify a signature, or who you are encrypting data for. For that reason most protocols that have multiple entities must have some way of establishing the identity of those entities. Although there are other ways of establishing trust, X.509 is the most common hierarchical method of establishing trust, relying on trust of Certification Authorities to indicate trust of underlying parties and their certificates.

X.509 certificates are often encoded to text as well, which is unfortunately not directly indicated by the file extension (so a .cer, .crt, .cert or whatever can contain a binary encoding or textual encoding. Multiple (trusted) certificates are sometimes present in a single file as well. Certificates are indicated using the X.509

PKCS#12

PKCS#12 is what cryptographers usually call a container format. It contains a description of storing various cryptographic elements and, of course, a way of establishing what is stored and how to retrieve the information. PKCS#12 is is commonly used in two ways:

  1. to store private keys with their certificate chain, starting with the certificate that contains the public key, followed by the certificate used to sign the certificate.
  2. to store a set of trusted (CA) certificates so that certificate chains can be verified & validated.

Usually PKCS#12 files are used if a more secure method of storing these items such as the aforementioned hardware devices or key stores are not present. They offer protection by allowing the information including private keys and certificates to be encrypted using symmetric cryptography.

Excusatory answered 5/2, 2023 at 13:28 Comment(4)
You got a few points wrong, more than I felt comfortable putting in comments, so I editted, and while doing that also made some minor changes I consider improvements. As standard for Stack, feel free to revert or override as you wish.Zach
@Zach You're always welcome to edit my answers, Dave. I'd only consider your own provided answers more worthwhile, but in this case I suppose an edit makes more sense.Excusatory
Can I suggest to clarify in the PKCS#1 section that the "de-facto" openssl encryption for PKCS#1 is "bad", I mean you explain it in the PKCS#8 section but I think it should be mentioned directly when talking about PKCS#1Kamila
@Kamila Thanks. I have moved the part about PKCS#1 encryption to PKCS#1. It is probably required to go over this answer once more as the info isn't bad but the answer is both overly wordy as well as a bit hand-wavey about things (such as the configuration choics for PKSC#8 encryption).Excusatory

© 2022 - 2024 — McMap. All rights reserved.