1

I create a certificate request using this:

CertificateRequest req = new CertificateRequest(
                          "cn=test",
                          Key,
                          HashAlgorithmName.SHA256,
                          RSASignaturePadding.Pkcs1);

key is set from CSP:

ProviderName: "Utimaco CryptoServer CSP"

KeyContainerName: "Default Container"

But while debugging I found that req.PublicKey.Key.CspKeyContainerInfo refers to a different provider:

ProviderName: "Microsoft Enhanced RSA and AES Cryptographic Provider"

KeyContainerName: null

And when I try to get Exportable value:

var isExportable = ((RSACryptoServiceProvider)req.PublicKey.Key).CspKeyContainerInfo.Exportable;

it throws a CryptographicException: Key doesn't exist

I don't understand why is the private key and pubic key stored separately in different providers?! or does this mean something else?

mshwf
  • 7,009
  • 12
  • 59
  • 133

1 Answers1

2

TL;DR The provider is set to a generic RSA provider but note that the KeyContainerName is null. This is just because it is just generated in memory, and not stored anywhere.

A Certificate Signing Request (CSR) is a public file created from within an application. The "only" relation at that point with the private key is that it:

  1. needs to contain the public key;
  2. needs to be signed by the private key (to show that you've got access to it when creating the CSR, and to protect it against alteration);

For this it loads the public key from the key pair, creates the unsigned CSR from it and then signs it with the private key. Other than that, the CSR is only used for requesting the actual certificate. There is no simply need to store the CSR / private key within the HSM. This is reflected by the fact that (e.g.) PKCS#11 doesn't have any notion of a CSR at all.

Note that there is very little risk of loosing the CSR, you can recreate one at any time. Also, if somebody gets to the CSR before you send it to the CA, then it would be caught by the signature validation (or you'd get an invalid certificate with the wrong public key, always make sure that this is verified and send in the CSR as soon as possible).

When you receive the actual certificate then it makes sense to store it in the HSM. Usually the entire chain of certificates to the root is stored because the intermediate certificates are often required in protocols (including e.g. TLS and CMS). They are used for each and every signature creation after all - hopefully you are not using the private pair for anything else than the PKI for which you've created it.


Many HSM's do provide a provision to store generic data. Although you can put a CSR in there, it would just be a generic storage; the key store itself would not link the CSR with the private key, so you might as well just keep it in storage, hopefully at some protected location where only your key managers have write access.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • Good point, but how does this affect the design of the API, i.e., the `Exportable` property of the public key throws "Key doesn't exist" exception? – mshwf Oct 25 '20 at 14:47
  • I mean if this is a natural behavior (storing the public key in-memory) why not just return `false`, as throwing exception prevent from, for example, serializing it. – mshwf Oct 25 '20 at 14:55
  • That I don't know, but "exportable" or not is definitely also a security property, i.e. if it is exportable then the HSM may not actually be protecting the key. So presumably it is set to "true" just to indicate that they is not protected. However, as it isn't in any key store, you'd still get an exception. But that's reasoning towards the situation, I must admit. – Maarten Bodewes Oct 25 '20 at 15:32