Donald Jansen Donald Jansen - 8 months ago 130
C# Question

X509Certificate2 crash IIS

Here is the code that breaks IIS, after doing research I found the following post
X509Certificate2 makes IIS crash and it fixed my problem

var cert = new X509Certificate2();
cert.Import(Resources.wildcard, "xxx", X509KeyStorageFlags.Exportable);


The fixed code

var cert = new X509Certificate2();
cert.Import(Resources.wildcard, "xxx", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);


But now this causes my signing to throw the following exception

n exception of type 'System.Security.Cryptography.CryptographicException' occurred in mscorlib.dll but was not handled in user code
Additional information: Invalid provider type specified.


My code

public class RsaSha1
{
private readonly X509Certificate2 _certificate;

public RsaSha1(X509Certificate2 certificate)
{
_certificate = certificate;
}

public string Sign(string signatureBaseString)
{
return SignCore(signatureBaseString);
}

string SignCore(string baseString)
{
using (var hash = Hash(baseString))
{
return Base64Encode(Sign(hash));
}
}

private static string Base64Encode(byte[] signature)
{
return Convert.ToBase64String(signature);
}


private byte[] Sign(SHA1CryptoServiceProvider hash)
{
var formatter = new RSAPKCS1SignatureFormatter(_certificate.PrivateKey).
Tap(it => it.SetHashAlgorithm("MD5"));
//The line above throws the Exception if X509KeyStorageFlags.MachineKeySet is added,
//but without X509KeyStorageFlags.MachineKeySet my application works in a console application (stress testing) but not in IIS (in a web application)
return formatter.CreateSignature(hash);
}

SHA1CryptoServiceProvider Hash(string signatureBaseString)
{
var sha1 = new SHA1CryptoServiceProvider();

var bytes = Encoding.ASCII.GetBytes(signatureBaseString);

using (var crypto = new CryptoStream(Stream.Null, sha1, CryptoStreamMode.Write))
{
crypto.Write(bytes, 0, bytes.Length);
}

return sha1;
}
}


EDIT 1:
New information, it seems that when I add X509KeyStorageFlags.MachineKeySet then _certificate.PrivateKey would throw the Exception but when I remove X509KeyStorageFlags.MachineKeySet then IIS would crash. PS I am using a certificate generated from StartSSL

Answer Source

I imported the Certificate into the LocalMachine Store (not via code) then in my Software I changed

   var cert = new X509Certificate2();
   cert.Import(Resources.wildcard, "xxx", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);

to

        X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
        store.Open(OpenFlags.ReadOnly);
        foreach (X509Certificate2 certificate in store.Certificates)
        {
            if (certificate.SubjectName.Name != null && certs.SubjectName.Name.Contains("*.domain.xxx"))
            {
                cert = certificate;
            }
        }

This seemed to work better than loading the certificate from a file and also it doesn't break IIS when loaded

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download