Private key in PFX File does not exist

0 votes
asked Apr 12 by rafael.lasertech (140 points)

Hi,

I did what you said, but still not working. This is a PFX file I have created using Bouncy Castle library in Compact Framework. As I said, the idea is to store this PFX in Key Storage if Rebex Certificate can export private key properly. Following is a "debug" in my code. See that my functions works just fine exporting private key from PFX file, but GetRSAParameters throws an Exception saying that there is no PK.

Link to PFX file: https://www.dropbox.com/s/4muecbuv7qrlq2a/oi1.pfx?dl=0

enter image description here

enter image description here

enter image description here

enter image description here

related to an answer for: Private Key from PFX File

1 Answer

0 votes
answered Apr 12 by Lukas Pokorny (82,430 points)

I'm afraid the scenario you are attempting is not really supported.

The key storage only stores the private key - the certificate to which it belongs is supposed to be stored in certificate storage. Calling LoadPfx with PersistKeySet results in a persisted private key, but non-persisted certificate, which is somewhat contradictory.

The Certificate class features Associate(..., bool permanentBind) method that could be used to associate a private key with a certificate, but the relevant overload is not available for .NET Compact Framework.

However, what are you actually trying to achieve? If you only need to "store a private key in the key storage" and "retrieve it when needed", consider using RSACryptoServiceProvider to achieve that together with your PFXUtil.GetPrivateKeyFromPFXFile method. The following helper methods might be useful:

    public static void SavePrivateKey(RSAParameters privateKey, string keyContainerName)
    {
        var parameters = GetCspParameters(keyContainerName);
        parameters.Flags = CspProviderFlags.NoFlags;

        var rsa = new RSACryptoServiceProvider(parameters);
        rsa.PersistKeyInCsp = true;
        rsa.ImportParameters(privateKey);
        rsa.Clear();
    }

    public static RSAParameters GetPrivateKey(string keyContainerName)
    {
        var parameters = GetCspParameters(keyContainerName);
        parameters.Flags = CspProviderFlags.UseExistingKey;

        var rsa = new RSACryptoServiceProvider(parameters);
        var privateKey = rsa.ExportParameters(true);
        rsa.Clear();
        return privateKey;
    }

    private static CspParameters GetCspParameters(string keyContainerName)
    {
        var rsa = new RSACryptoServiceProvider();
        string providerName = rsa.CspKeyContainerInfo.ProviderName;
        int providerType = rsa.CspKeyContainerInfo.ProviderType;
        rsa.Clear();

        var parameters = new CspParameters(providerType, providerName, keyContainerName);
        parameters.KeyNumber = (int)KeyNumber.Exchange;
        return parameters;
    }
commented Apr 12 by rafael.lasertech (140 points)
Hi.

Here's what I'm trying to achieve:

- Generate Pair of Keys - RSA 512bit - OK
- Generate Certificate (.cer file) with Public Key - OK
- Generate PFX File (.pfx file) with Private Key - OK (I also generated in PEM format)
- Store Certificate into Certificate Storage: Keeping into StoreName.My / StoreLocation.CurrentUser - OK
- Store PFX file or Private Key into Key Storage (I know that Certificates and Private Keys are not stored in same location, but I was trying to save PFX file using X509 Store.

What would you recommend to store private key? I do not want to keep this as a file in SD Card (for instance).
commented Apr 13 by Lukas Pokorny (82,430 points)
Windows key storage is actually a suitable place for storing private keys and offers several security features (such as exportable/non-exportable keys, displaying a dialog when using a key). If the RSACryptoServiceProvider-based code above works, I would give that a try.
commented Apr 14 by rafael.lasertech (140 points)
Hi. Thanks for your support. I managed to implement everything we need with your information.
...