10

The associated code, works well in an independent console application, whereas errors out, while trying to make it work, within an NSB architecture. I have tried to test the same within the worker, and also independently within a test console app. In either case, it errors out in the line - X509Certificate2 certificate = new X509Certificate2(filePath, "***key***UeUHFxS"); The exception message being - System.Security.Cryptography.CryptographicException: 'The system cannot find the file specified. The code consists of the one as shown and also an associated helper file for the Activate device. The exception is however, in the section for initializing the X509Certificate2, from the pfx file path and key.

class Program
{
    static void Main(string[] args)
    {
        try
        {
            string filePath = Path.GetDirectoryName(System.AppDomain.CurrentDomain.BaseDirectory);
            filePath = Directory.GetParent(Directory.GetParent(filePath).FullName).FullName;
            filePath = Path.Combine(filePath, @"Cert\TestCompany-qa.partner.client.siriusxm.com.pfx");

            X509Certificate2 certificate = new X509Certificate2(filePath, "****key****");
            SoapMessageHelper soapHelper = new SoapMessageHelper(certificate, @"https://api-ext-test.siriusxm.com/SAT/UpdateDeviceSatRefresh/v_1");
            var test = soapHelper.ActivateDevice(new ActivateDeviceRequest()
            {
                SourceName = "12493",
                ESN = "W26890HW",
                TimeStamp = DateTime.UtcNow,
                TrasanctionId = System.Guid.NewGuid().ToString()
            });

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(test);

            foreach (XmlNode node in doc.DocumentElement.ChildNodes)
            {
                foreach (XmlNode locNode in node)
                {
                    if (locNode.Name == "ns0:responseRefreshDevice")
                    {
                        string resultCode = locNode["ns0:resultCode"].InnerText;
                        string errorCode = locNode["ns0:errorCode"].InnerText;
                        string errorMessage = locNode["ns0:errorMessage"].InnerText;
                        Console.WriteLine(resultCode + errorCode + errorMessage);
                    }
                }
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine(
                String.Format("Exception occurred{0}Message:{1}{2}Inner Exception: {3}", Environment.NewLine, ex.Message, Environment.NewLine, ex.InnerException));
        }

    }

}
Rakesh Kumar
  • 307
  • 1
  • 2
  • 10
  • Have you tried debugging at your filePath to verify if it has expected path value? – popsiporkkanaa Jul 24 '18 at 05:02
  • @popsiporkkanaa - yes, I have tried debugging and filePath has the certificate PFX file. Also, attaching the sample code for debugging - Console.WriteLine(File.Exists(filePath) ? "File exists." : "File does not exist."); – Rakesh Kumar Jul 24 '18 at 05:19
  • Can you paste here your full CryptographicException message and its stack trace? There may be something useful in the stack trace to find the root cause – popsiporkkanaa Jul 24 '18 at 05:26
  • `"File exists." : "File does not exist."` -- this is your problem. Exception is thrown, because the code cannot find the certificate file. – Crypt32 Jul 24 '18 at 05:28
  • System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr) at System.Security.Cryptography.X509Certificates.X509Utils._QueryCertFileType(String fileName) at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromFile(String fileName, Object password, X509KeyStorageFlags keyStorageFlags) at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(String fileName, String password) at TestApp.Program.Main:line 34 – Rakesh Kumar Jul 24 '18 at 05:30
  • @Crypt32 - that is the sample code, to show that file does exist. Real error is as pasted here. – Rakesh Kumar Jul 24 '18 at 05:33
  • 1
    @RakeshKumar Probably it is related with your current user profile loading. Let's try this solution here: https://stackoverflow.com/a/27242467/4329813 – popsiporkkanaa Jul 24 '18 at 05:36
  • @popsiporkkanaa - I have already tried the same. In the application pools - Advanced settings - process model, the load user profile ise already set to True. – Rakesh Kumar Jul 24 '18 at 05:39
  • Achei uma solução que deva resolver https://stackoverflow.com/a/10048789 – Fernando Ewald Jul 29 '22 at 13:00

4 Answers4

28

Let's try to modify your constructor to:

X509Certificate2 certificate = new X509Certificate2(filePath, key, 
                               X509KeyStorageFlags.MachineKeySet
                             | X509KeyStorageFlags.PersistKeySet
                             | X509KeyStorageFlags.Exportable);

Using MachineKeySet as msdn said that:

"Private keys are stored in the local computer store rather than the current user store. "

popsiporkkanaa
  • 678
  • 1
  • 9
  • 17
  • I have tried the same, however with not much success. The exception remains. – Rakesh Kumar Jul 24 '18 at 05:54
  • If "filepath" does not work there, can you try to use another constructor where it reads the raw data (byte array) of certificate? – popsiporkkanaa Jul 24 '18 at 06:01
  • 1
    Same exception with the byte array as well. The code currently looks as follows - byte[] bytes = System.IO.File.ReadAllBytes(filePath); X509Certificate2 certificate = new X509Certificate2(bytes, "****key****", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); – Rakesh Kumar Jul 24 '18 at 06:17
  • 1
    Adding MachineKeySet resolved this for me: X509Certificate2(filePath, key, X509KeyStorageFlags.MachineKeySet). – w00ngy Mar 13 '19 at 13:36
  • 3
    Thanks @popsiporkkanaa adding X509KeyStorageFlags.MachineKeySet fixed my issue when deployed to azure webapp. it worked fine locally without this value been set – Nishank May 20 '20 at 20:56
  • MachineKey solved my problem as well. The error message was very confusing. – Kishan Vaishnav May 26 '21 at 12:47
  • Thank you so much @popsiporkkanaa adding the X509KeyStorageFlags fixed the problem in a azure website – Eduardo Isaac Ballesteros May 10 '22 at 15:04
  • I have error even after this change :( – Neel May 01 '23 at 14:00
3

Providing an Absolute path, rather than a Relative path did help. The intention of providing a relative path was to include the certificate as part of the artifacts, and when the application gets deployed to the server, the certificate would get written to the output path, and get read from the location. However, while trying to test the working code, and currently, I find that only the absolute path is working, although the certificate property is set to copy always. The working code now looks like this :

filePath = @"C:\Users\<user name>\Documents\TestCompany-qa.partner.client.siriusxm.com.pfx"; 

X509Certificate2 certificate = new X509Certificate2(filePath, "****key****"); 

So, need to know the path in the server where the application is deployed and the certificate location, to proceed now, as the workaround solution.

spaleet
  • 838
  • 2
  • 10
  • 23
Rakesh Kumar
  • 307
  • 1
  • 2
  • 10
2

See more details here: https://github.com/dotnet/runtime/issues/25143

The certificate was, indeed, present and was readable from the user running - so it's not an issue that the certificate can't be found!

The actual error is, I believe, that it can't put the certificate the LocalUser's cert store.

Here is what worked for me:

var issuerCertificate  = new X509Certificate2(caFileName, caPassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
Dror
  • 1,406
  • 12
  • 15
1

!!! For all people with this problem who has toggled IIS and played with all the keyFlags !!!

I was having this issue on my local machine. Couldn't figure it out. So I inserted Directory.GetFiles(certs folder) above the X509 call to 6x check the file path was correct. new X509Certification2() started working.

The certs folder is outside of the project scope, and my project on my local had never accessed it before. The cert store must use a shadow folder structure you have to register by simply reading the files.

Hope this helps somebody before they spend half the day on this.

Mr9mm
  • 19
  • 3