0

I'm trying to understanding why in .NET, calling the constructor System.Security.Cryptography.X509Certificates.X509Certificate2() fails with an "internal error" when a file name and matching password are passed. This happens on a Windows 2008 R2 server. On a different machine, running Windows 7, the call works properly using the same file name and password (actually, I tried with two different pairs of files and passwords and got the same results). I'm hoping that there's just some setting that must be enabled (or disabled) on the Windows 2008 R2 server for this command to work. (The server has much more stringent security, so maybe it's blocking something?) But to better understand the problem, I guess I need to get a better sense of what .X509Certificate2() is actually doing.

For starters, the following two commands work fine on both machines:

    var x = new X509Certificate2();
    var y = new X509Certificate2(fullFilePath);

However, any of the overloads that take a password will fail on the Windows 2008 R2 server if the password is correct, but not on the Windows 7 machine. (Both are 64-bit.) For example:

    var z = new X509Certificate2(fullFilePath, password);

If I pass an incorrect or blank password (on either machine), then I get "The specified network password is not correct." However, if the password is correct, then the Windows 2008 R2 server says "An internal error occurred."

This leads me to believe that somewhere in the X509Certificate2 code, if the password is found to match, then another action is taken, and that's the one that's failing.

I did find some information on the source code through a Google search that brought me here:

http://www.dotnetframework.org/default.aspx/4@0/4@0/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/fx/src/security/system/security/cryptography/x509/X509Certificate2@cs/1305376/X509Certificate2@cs

... but I'm still having some difficulty understanding what's going on. Apparently, no matter what parameters are passed, they're dealt with somehow in this line:

m_safeCertContext = CAPI.CertDuplicateCertificateContext(this.Handle);

...but I haven't been able to find the source code for that yet.

What I'm hoping, actually, is to find that maybe someone knows that "oh yes, on Windows 2008 servers, you have to make sure that xyz is enabled for X509Certificate2() to work, and all you have to do is..." or that there must be something else on the machine besides that file being there in the specified place for the constructor to work.

My end goal is to have program working on the server, in the same way as it works on the other machine. However, just having some information on the logic of exactly what happens when I make this call (and what gets executed after it finds that the password matches) would help immensely.

Any insights are appreciated!

Nickadoo
  • 104
  • 2
  • 7
  • http://stackoverflow.com/questions/1345262/an-internal-error-occurred-when-loading-pfx-file-with-x509certificate2 Maybe? – Loathing Apr 18 '15 at 22:47
  • Here's the difference between the two constructors you're using: ["Calling this constructor with the correct password decrypts the private key and saves it to a key container."](https://msdn.microsoft.com/en-us/library/ms148419%28v=vs.110%29.aspx). Maybe the user your code is running on can access the cert, but not the private key. Check out this blog: http://paulstovell.com/blog/x509certificate2, section 3 specifically. – Nathan Cooper Apr 18 '15 at 22:53
  • I think these answers are correct. It's probably having a permissions error trying to save to the container. If I don't want to edit that line in the core code, where on that machine can I give IIS 7.5 / ASP.NET 4.0 the permission it needs to the key container? – Nickadoo Apr 19 '15 at 22:18

1 Answers1

0

Try

var certificate = new X509Certificate2(fileName, password, X509KeyStorageFlags.MachineKeySet);
DreTaX
  • 760
  • 2
  • 9
  • 22