Generation of RSA key pair and storage of only private key PKCS#11

I noticed that the PKCS#11 supports C_GenerateKey function for symmetric keys and for asymmetric there's only C_GenerateKeyPair function. So from the definition, this lets us create only both private-key/public-key pair. From my understanding the private key stores public key info (modulus and public exponent), which are needed for public key creation, so it can be fetched every time to generate the public key.

For my usage I only need the the private key in token storage and don't really need the public key until future use.

Are there any drawbacks if I only store the private key and generate public key every time I need it?

• As you note it's possible that the public part of the key is stored along with the private part anyway, so there truly won't be any drawback to deleting the public key object. But there is no way to tell for sure if that happens or not in the underlying PKCS#11 implementation. Oct 13, 2021 at 12:11
• Let's reverse that question: what kind of advantage are you expecting by just storing the private key? Usually the RSA private key is a much larger object than the public key anyway due to the CRT parameters being stored. Oct 14, 2021 at 23:32
• I have a key management system (KMS) program and I only store and use the private key on the KMS. The public key is not used in my case and is only exported (extracted from the private key) per request which will be mostly one time event or a few rare occasion events. My advantage in this case would be managing with only one key handle and saving up token storage. Oct 18, 2021 at 7:10

The most obvious: performance.

I know SPHINCS+ being an example where generating public key from the private key is especially costly, there may be other schemes where this is true, but I'm not aware of any.

Also, since it's PKCS#11 hardwares we're talking about, and we've mentioned the hash-based stateless signature SPHINCS+ now, we should also mention that NIST had approved hardware implementations of XMSS and LMS stateful hash-based signatures.

Your approach can only be applied to RSA and only if you are using keys generated according to PKCS#11 version >= 2.40. The PKCS#11 standard defines (section 2.1.3 "RSA private key objects" in the 3.0 base specification): "Effective with version 2.40, tokens MUST also store CKA_PUBLIC_EXPONENT."

Therefore, you're able to get the modulus and public exponent attributes (C_GetAttributeValue) and create a public key object from it using C_CreateObject. But as DannyNiu pointed out this certainly costs performance.

Depending on the token you might be able to use the private key object instead of the public key for operations such as C_Encrypt* or C_Verify* since the token will just use the public attributes.

For other asymmetric keys, eg. EC keys, there is no definition similar to the one for RSA in the PKCS#11 standard. Therefore, no public parts will be stored. It will depend on the token if the public key is calculated on the fly (confirming Conrado's comment). This certainly has an even higher performance impact. If the token is not doing it automatically, there is no way to trigger the calculation of a public key from a private key from PKCS#11. And of course you should never do it externally - why would you use a token (HSM) at all then if you use the private key in plain externally?

Finally, if you use standard applications your approach will likely fail since applications often add CKA_CLASS=CKO_PUBLIC_KEY to the search template when they look for the public key they want to use.