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