Consider the fields highlighted in red in the following keys.

  1. Will the "version" fields (i.e. INTEGER 0) always be zero for the specified structure?
  2. Will the NULL fields fields always be NULL for the specified structure?
  3. If "No", what would cause the values to change?

PKCS#1 Private Key: enter image description here

PKCS#8 Private Key: enter image description here

X.509/SPKI Public Key: enter image description here


2 Answers 2


The NULL fields you ask about are the parameters element of the AlgorithmIdentifier defined in X.509/PKIX e.g. rfc5280 -- although it is defined in relation to the signature on the cert or CRL, it is also used for publickeys and privatekeys as you have seen, and quite a lot of other places as well, such as the DigestInfo used in PKCS1v1 signatures, now retronymed RSASSA-PKCS1-v1_5.

For original-style RSA public keys identifed by rsaEncryption in SPKI, rfc3279 2.3.1 (to which you have been referred several times) specifies parameters to be (explicit, see below) NULL. Although TTBOMK there is no comparable rfc for the embedding of RSA private keys in PKCS8, in practice everyone uses the same AlgId -- that is, the same OID and the same parameters.

For RSASSA-PSS signature (added to PKCS1 at v2.1 aka rfc3447), the AlgId must have parameters as shown in rfc4055 3.1. Depending on other specifications, the keys used to generate (private) and verify (public) such signatures can be either original-style RSA keys, or RSA keys restricted to PSS with the OID and optionally params shown in 3279; as it says "parameters may be either absent or present [in SPKI for publickey]". Historically there has been ambiguity and sometimes confusion over whether AlgId's for algorithms with no parameters should use explicit NULL or simply omit the field since it is OPTIONAL in the ASN.1. OpenSSL (at least) takes 'absent' literally and does the latter here for both SPKI and PKCS8, see Create RSA Public/Private Keys with OID rsassaPss ; also see Are RSA-PSS parameters standardized? for some additional discussion on using the parameters and https://stackoverflow.com/questions/42898747/create-private-key-and-certificate-using-rsassa-pss-with-openssl for creating a key with them.

Algorithms other than RSA can also have parameters. Parameters for DSA, DH(X9.42), and ECDSA/ECDH(X9.62/63/SECG) are defined in 3279; ECDSA/ECDH is updated in rfc5480 which (greatly) simplifies ECParameters by keeping only the 'namedCurve OID` variant. OTOH for Bernstein et al's EdDSA and XDH, rfc8410 specifies different OIDs for each curve and absent parameters (explicit in the ASN.1 in section 9).

  • $\begingroup$ Haha, I sense the "RTM" in there, and I've gone to the links. There are hundreds of those RFC pages. Just the one you linked to has 149 pages of dense material that seems purposefully confusing. The thing that makes it hard to understand is that the whole structure isn't laid out in one place. It is a bunch of little pieces of possible structures scatters across dozens of sections. For a guy like me who is just dipping his toe in the water, seems like a lot to expect that I 1.) can find the right section and 2.) connect that NULL == parameters ANY DEFINED BY algorithm OPTIONAL $\endgroup$ Commented Jan 7, 2023 at 7:52

Will the "version" fields (i.e. INTEGER 0) always be zero for the specified structure?

As long as one is dealing with standard "biprime" RSA, that is the kind with the public modulus having two distinct primes $p$ and $q$, it's a safe bet one won't meet version other than 0 in a PKCS#1 RSAPrivateKey, including in such structure embedded in a PKCS#8 structure. version 1 is specifically for multiprime RSA, where the modulus can have three or more (distinct) prime factors. There's nothing to prevent using version 1 for biprime RSA, but that's definitely not customary.

From PKCS#1 v2.2; see especially CONSTRAINED BY

RSAPublicKey ::= SEQUENCE {
    modulus            INTEGER,  -- n
    publicExponent     INTEGER   -- e

-- Representation of RSA private key with information for the CRT algorithm.
RSAPrivateKey ::= SEQUENCE {
    version            Version,
    modulus            INTEGER,  -- n
    publicExponent     INTEGER,  -- e
    privateExponent    INTEGER,  -- d
    prime1             INTEGER,  -- p
    prime2             INTEGER,  -- q
    exponent1          INTEGER,  -- d mod (p-1)
    exponent2          INTEGER,  -- d mod (q-1)
    coefficient        INTEGER,  -- (inverse of q) mod p
    otherPrimeInfos    OtherPrimeInfos OPTIONAL

Version ::= INTEGER { two-prime(0), multi(1) }
    (CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --})

OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo

OtherPrimeInfo ::= SEQUENCE {
    prime              INTEGER,  -- ri
    exponent           INTEGER,  -- di
    coefficient        INTEGER   -- ti

The version field of an extended PKCS#8 structure has been assigned the value 1 in a new RFC, see dave_thompson_085's comment, though we have no report of seeing other than 0 in the wild (still, I lost my bet that a whole new structure would be created instead should an extension become desirable).

I'll refrain from commenting the NULL that are following the OIDs, for I fail to track their nature.

Note: when parsing or generating ASN.1 in crypto, there are two choices:

  1. Building a small ad-hoc parser/generator for an ASN.1 DER structure at hand; in this case it's essential to stop parsing as soon as something unexpected is met, or we start to parse outside the input.
  2. Using a full-fledged library. This tends to be a huge and complex piece of software, perhaps with bugs, and even more probably with bugs in how a beginner uses it. However, past a certain degree of complexity, including parsing X.509 certificates of unspecified origin or anything BER, PER or more complex, that's perhaps a necessity.
  • $\begingroup$ Well knowing about the two-prime vs multi-prime nature of version is helpful! All I know about the NULL fields is that they are always there in keys generated by OpenSSL, and there are actual ASN.1 bytes that must be present to accurately duplicate them if I, for instance, wanted to read a key in and then write it back out. $\endgroup$ Commented Jan 6, 2023 at 19:00
  • 1
    $\begingroup$ rfc5958 officially obsoletes rfc5208 PKCS8 and is upward compatible but no longer called PKCS8; it makes version a named integer with 0=v1,1=v2 and v2 adds a context-1-tagged optional publickey. I haven't seen this used 'in the wild'. FWIW OpenSSL 1.1.1 up (since 2018) supports the imprecisely-named multiprime RSA. $\endgroup$ Commented Jan 7, 2023 at 6:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.