1

I am loading a .pfx cert from embedded resource file in my project. The embedded resource file is loaded properly and I'm getting the raw data correctly - code:

 using (Stream stream = assembly.GetManifestResourceStream(resourceName))
 {
       try
       {
                Byte[] raw = new Byte[stream.Length];

                for (Int32 i = 0; i < stream.Length; i++)
                {
                    raw[i] = (Byte)stream.ReadByte();
                }
                //X509Certificate2 cert = new X509Certificate2(raw, password);
                X509Certificate2 cert = new X509Certificate2(raw, password, X509KeyStorageFlags.MachineKeySet);
                //Both of the above attempts give me invalid network password
                //errors on Azure.
                builder.AddSigningCredential(cert);
                builder.AddValidationKey(cert);
       }
       catch (Exception e)
       {
            //Notify me of exception
       }
} //end using

However, when attempting to initialize a new X509Certificate2 object, I think it's attempting to access more certificates in the store which don't exist or something

(according to this question:

ASP.NET - The specified network password is not correct

)

Full error: Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: The specified network password is not correct at Internal.Cryptography.Pal.CertificatePal.FilterPFXStore(Byte[] rawData, SafePasswordHandle password, PfxCertStoreFlags pfxCertStoreFlags) at Internal.Cryptography.Pal.CertificatePal.FromBlobOrFile(Byte[] rawData, String fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags)

JakeJ
  • 2,361
  • 5
  • 23
  • 35
  • It's the correct password I set on the certificate when exporting it. – JakeJ Jun 22 '18 at 15:42
  • 509Certificate2 cert = new X509Certificate2(raw, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); Doesn't work either... – JakeJ Jun 22 '18 at 16:06
  • Not working: X509Certificate2 cert = new X509Certificate2(raw, password, X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.PersistKeySet); – JakeJ Jun 22 '18 at 16:13
  • I'm seeing comments on forums of related issues that app pools have to be set to load user profiles...not sure if I should do that or try a different cert file format like .cer: https://stackoverflow.com/questions/9951729/x509certificate-constructor-exception – JakeJ Jun 22 '18 at 16:38
  • Tried to create a blank cert, then use the import, got: X509Certificate is immutable on this platform. Use the equivalent constructor instead – JakeJ Jun 22 '18 at 18:14
  • That's it, I'm going to OpenSSL. Already found some .pem loader code, modified to return an X509Certificate2. Now just have to install OpenSSL to generate the self-signed key file. – JakeJ Jun 22 '18 at 18:38
  • I just encountered this too... but in my case I can't use openssl. – Jeremy Holovacs Oct 31 '19 at 15:56

1 Answers1

3

I ended up downloading an x64 OpenSSL binary (you can see a list of available binaries at this link: https://wiki.openssl.org/index.php/Binaries ).

With OpenSSL, you can create .pfx files that can be used to create X509Certificate2 objects with less hassle than using Microsoft's tools.

Basically, you'll get a zip file, unzip that, then use Windows command line to run the openssl.ex in the bin folder. Here is how you can become your own root CA, generate a private key, create your root certificate from that, then finally create a .pfx certificate file with your private key and root certificate (after you generate a .pfx properly this way, you will get around whatever it was Microsoft was thinking and be able to load your certificate from the .pfx file into an X509Certificate2):

These commands are from Window's command line, in the same folder as the openssl.exe:

  1. Use openssl to generate an rsa private key:

openssl genrsa -out myPrivateKey.rsa 2048

  1. Become your own root CA, get your certificate:

openssl req -new -x509 -days 3652 -key myPrivateKey.rsa -out rootCertificate.crt

  1. Create your pfx file (pkcs12 format .pfx file):

openssl pkcs12 -export -out MyCertificate.pfx -inkey myPrivateKey.rsa -in rootCertificate.crt

  1. Right click your project in Visual Studio 2017 Solution Explorer, select Add Existing Item, select your MyCertificate.pfx file, click OK. Right click on the file, select properties, for build actions, select "embedded resource".

  2. Use the code in my question. You can uncomment the line:

    X509Certificate2 cert = new X509Certificate2(raw, password);

and get rid of the other line attempt. It will now work without problems. (the resource name variable in this case would be "Your.Project.Namespace.MyCertificate.pfx")

JakeJ
  • 2,361
  • 5
  • 23
  • 35
  • I had created the not working pfx file with PowerShell's New-SelfSignedCertificate module and exported it with MMC. Obviously, those tools are not user friendly, and you will get more done more quickly with OpenSSL. – JakeJ Jun 22 '18 at 20:36
  • I ended up not having to use the extra pem loader code I had found because using the above method, I'm creating a .pfx file directly with OpenSSL. Once added to the project as an embedded resource, the code in the question works. – JakeJ Jun 22 '18 at 20:40
  • A lot of it came from this blog post: https://blog.didierstevens.com/2008/12/30/howto-make-your-own-cert-with-openssl/ – JakeJ Jun 22 '18 at 20:42