Perry Perry - 2 months ago 26
C# Question

Force HttpWebRequest to send client certificate

I have a p12 certificate, that I load it in this way:

X509Certificate2 certificate = new X509Certificate2(certName, password,
X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet |
X509KeyStorageFlags.Exportable);


It is loaded correcty, in fact If i do
certificate.PrivateKey.ToXmlString(true);
it returns a complete xml without errors.
But If I do:

try
{
X509Chain chain = new X509Chain();
var chainBuilt = chain.Build(certificate);
Console.WriteLine("Chain building status: "+ chainBuilt);

if (chainBuilt == false)
foreach (X509ChainStatus chainStatus in chain.ChainStatus)
Console.WriteLine("Chain error: "+ chainStatus.Status);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}


it writes:

Chain building status: False
Chain error: RevocationStatusUnknown
Chain error: OfflineRevocation


so when I do:

ServicePointManager.CheckCertificateRevocationList = false;
ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;
ServicePointManager.Expect100Continue = true;
Console.WriteLine("connessione a:" + host);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(host);
req.PreAuthenticate = true;
req.AllowAutoRedirect = true;
req.ClientCertificates.Add(certificate);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
string postData = "login-form-type=cert";
byte[] postBytes = Encoding.UTF8.GetBytes(postData);
req.ContentLength = postBytes.Length;
Stream postStream = req.GetRequestStream();
postStream.Write(postBytes, 0, postBytes.Length);
postStream.Flush();
postStream.Close();

WebResponse resp = req.GetResponse();


the server says that the certificate is not sent/valid.

My question is:


  • how can I sent the certificate even with chain build false?

  • there is another class to post a certificate that does not check the certificate validation before send it?



many thanks.
Antonino

Answer

I resolved the problem, The point is that a P12 file (as a PFX) contains more then 1 certificate, so it must be loaded in this way:

X509Certificate2Collection certificates = new X509Certificate2Collection();
certificates.Import(certName, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);

and added to a HttpWebRequest in this way: request.ClientCertificates = certificates;

Thanks everybody for support.