I need to create a self signed certificate in code. I have a working example using Security.Cryptography.dll from http://clrsecurity.codeplex.com but it uses SHA1 and I need to use SHA256.
I've updated the provided example to use SHA256 algorithm but I don't know how to force it to use "Microsoft Enhanced RSA and AES Cryptographic Provider" as CSP.
When accessing the privateKey of the generated certificate I get a System.Security.Cryptography.CryptographicException "Invalid provider type specified."
at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)
at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()
at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize)
at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()
I've read a lot of posts on this subject without finding a way to do this. I've also tried calling the Native API Crypt32.dll, CertCreateSelfSignCertificate but it only gives me SHA1 and when I try to pass in the following parameters:
_In_opt_ PCRYPT_KEY_PROV_INFO pKeyProvInfo,
_In_opt_ PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm
It fails with an exception - probably because the structure I created isn't correct but I'm finding the documentation a bit limited.
So that is why my current approach is with Security.Cryptography.dll as it seems easier but I can't figure out how to force it to use the provider it needs for SHA256.
Below is the code:
private void CreateCertificate(string fileName, string password) { X509Certificate2 cert = null; var name = new X500DistinguishedName("cn=" + WindowsIdentity.GetCurrent().Name); // Generate Key CngKeyCreationParameters keyParams = new CngKeyCreationParameters(); keyParams.KeyUsage = CngKeyUsages.Signing; keyParams.Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider; //keyParams.Provider = new CngProvider("Microsoft Enhanced RSA and AES Cryptographic Provider"); keyParams.ExportPolicy = CngExportPolicies.AllowExport; keyParams.Parameters.Add(new CngProperty("Length", BitConverter.GetBytes(2048), CngPropertyOptions.None)); CngKey newKey = CngKey.Create(CngAlgorithm2.Rsa, Guid.NewGuid().ToString(), keyParams); // Init certificate X509CertificateCreationParameters certParams = new X509CertificateCreationParameters(name); certParams.StartTime = DateTime.Today.AddDays(-1); certParams.EndTime = DateTime.Today.AddYears(30); certParams.SignatureAlgorithm = X509CertificateSignatureAlgorithm.RsaSha256; // Create cert cert = newKey.CreateSelfSignedCertificate(certParams); using (Stream outputStream = File.Create(fileName)) { byte[] pfx = cert.Export(X509ContentType.Pfx, password); outputStream.Write(pfx, 0, pfx.Length); outputStream.Close(); } }
Please note that I can't use makecert, openssl or powershell since I need to do it in c# only.
Karin, Stockholm