IX509PrivateKey::Export Method from C#

3

Just wondering if someone who has worked with the Microsoft Certificate Enrollment API can offer some assistance with this. I am trying to use the IX509PrivateKey::Export method which is documented here: https://msdn.microsoft.com/en-us/library/windows/desktop/aa379006%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396.

My C# code for calling this method looks like this:

privateKey.Export("BCRYPT_PRIVATE_KEY_BLOB", EncodingType.XCN_CRYPT_STRING_ANY);

Unfortunately this returns an error: “The parameter is incorrect. 0x80090027”

The error isn't very helpful as I'm unsure which parameter is causing the problem since they both are using values that are specified in the API documentation. Note that prior to this code being called the private key has been initialized, created and can be successfully used to generate a CSR through this API.

I was thinking this maybe has to do with an issue translating a C# string to a BSTR type that can be used with unmanaged code so I've tried a few methods to test this theory but haven't had much luck. I have a feeling that the error itself may be getting generated by the CNG NCryptExportKey function which is documented here: https://msdn.microsoft.com/en-us/library/windows/desktop/aa376263%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396. I would like to try and avoid messy/unsafe solutions like P/Invoke if possible.

Would be happy to hear any ideas from anyone. Let me know if I can provide further info.

c#
security
ssl-certificate
asked on Stack Overflow May 25, 2018 by Kannwar

1 Answer

3

I was having the exact same issue. For me, the issue was part order of using the private key, and part using the right parameter in the export call. My solution looks like this:

  CX509PrivateKey privateKey = new CX509PrivateKey();
  //these flags have to be set before the key is created-- they're read only afterward
  privateKey.KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_ALL_USAGES;
  privateKey.ExportPolicy = X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;
  privateKey.Create();
  //initialize a request using the private key
  pkcs10.InitializeFromPrivateKey(X509CertificateEnrollmentContext.ContextUser, privateKey, templateName);
  //export the key, using the correct export type and encoding (I used the default)
  string exportedKey = privateKey.Export("PRIVATEBLOB"); 

Note that the parameter passed to the export function is "PRIVATEBLOB" which is noted... nowhere, as far as I can tell. I found it here.

answered on Stack Overflow Sep 14, 2018 by senschen

User contributions licensed under CC BY-SA 3.0