Sending SSL certificate with a HTTP request from .NET framework

V

Veerle

Hi,

We have to make calls to a webservice of the Belgian government. We
bought ourselves a p12 certificate that we send along with our http
requests, so that the code at the government side knows that the
request is really coming from us and not from someone pretending to be
us.

We wrote our code in the .NET framework 2.0. First we look up all the
installed personal certificates with the code:

IntPtr storeHandle;
storeHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
CERT_SYSTEM_STORE_CURRENT_USER, "MY");
IntPtr currentCertContext;
currentCertContext = CertEnumCertificatesInStore(storeHandle,
(IntPtr)0);
int i = 0;
while (currentCertContext != (IntPtr)0)
{
listOfPrivateCertificates.Insert(i++, new
X509Certificate(currentCertContext));
currentCertContext = CertEnumCertificatesInStore(storeHandle,
currentCertContext);
}
CertCloseStore(storeHandle, 0);

with

[DllImport("CRYPT32", EntryPoint = "CertOpenStore", CharSet =
CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CertOpenStore(
int storeProvider, int encodingType,
int hcryptProv, int flags, string pvPara);

[DllImport("CRYPT32", EntryPoint = "CertEnumCertificatesInStore",
CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CertEnumCertificatesInStore(
IntPtr storeProvider,
IntPtr prevCertContext);

[DllImport("CRYPT32", EntryPoint = "CertCloseStore", CharSet =
CharSet.Unicode, SetLastError = true)]
public static extern bool CertCloseStore(
IntPtr storeProvider,
int flags);

Next, when we pick out the certificate that we bought for doing the
government communication and we add it to our http request when making
the webservice call:

req.ClientCertificates.Add(myCertificate);

This works fine on all Windows XP machines that we have tested this
on. When we test however on a Windows 7 machine, this code doesn't
work. Retrieving the personal certificates still works but when we
make the http request we retrieve an HTTP 403 Forbidden error,
indicating that the server side code did not receive our certificate,
or did not recognize it in the same way as when sending in Windows
XP.

When we install however an old version of FireFox in Windows 7 and
make it the default browser and then retry everything, then it works!
So we are guessing that the .NET framework is underneath relying on
the default browser of Windows in order to send the web request.And
appearently IE8 in Windows 7 is doing something different than IE8 in
Windows XP. And the server code of our government is not compatible
with the first one.

Can anyone confirm this suspision, maybe even shed a light on with the
difference in sending the certificate actually is? I did some Google
research but could not find much of information.

Thanks!
Veerle
 
C

cubaman

Hi,

We have to make calls to a webservice of the Belgian government. We
bought ourselves a p12 certificate that we send along with our http
requests, so that the code at the government side knows that the
request is really coming from us and not from someone pretending to be
us.

We wrote our code in the .NET framework 2.0. First we look up all the
installed personal certificates with the code:

IntPtr storeHandle;
storeHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
CERT_SYSTEM_STORE_CURRENT_USER, "MY");
IntPtr currentCertContext;
currentCertContext = CertEnumCertificatesInStore(storeHandle,
(IntPtr)0);
int i = 0;
while (currentCertContext != (IntPtr)0)
{
  listOfPrivateCertificates.Insert(i++, new
X509Certificate(currentCertContext));
  currentCertContext = CertEnumCertificatesInStore(storeHandle,
currentCertContext);}

CertCloseStore(storeHandle, 0);

with

[DllImport("CRYPT32", EntryPoint = "CertOpenStore", CharSet =
CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CertOpenStore(
  int storeProvider, int encodingType,
  int hcryptProv, int flags, string pvPara);

[DllImport("CRYPT32", EntryPoint = "CertEnumCertificatesInStore",
CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CertEnumCertificatesInStore(
  IntPtr storeProvider,
  IntPtr prevCertContext);

[DllImport("CRYPT32", EntryPoint = "CertCloseStore", CharSet =
CharSet.Unicode, SetLastError = true)]
public static extern bool CertCloseStore(
  IntPtr storeProvider,
  int flags);

Next, when we pick out the certificate that we bought for doing the
government communication and we add it to our http request when making
the webservice call:

req.ClientCertificates.Add(myCertificate);

This works fine on all Windows XP machines that we have tested this
on. When we test however on a Windows 7 machine, this code doesn't
work. Retrieving the personal certificates still works but when we
make the http request we retrieve an HTTP 403 Forbidden error,
indicating that the server side code did not receive our certificate,
or did not recognize it in the same way as when sending in Windows
XP.

When we install however an old version of FireFox in Windows 7 and
make it the default browser and then retry everything, then it works!
So we are guessing that the .NET framework is underneath relying on
the default browser of Windows in order to send the web request.And
appearently IE8 in Windows 7 is doing something different than IE8 in
Windows XP. And the server code of our government is not compatible
with the first one.

Can anyone confirm this suspision, maybe even shed a light on with the
difference in sending the certificate actually is? I did some Google
research but could not find much of information.

Thanks!
Veerle

I'll suggest looking at the permissions of you app. In win7 Maybe UAC
is stooping you for calling unmanaged code. Have you tried running it
as admin or under a high privilege account?
Best regards.
 
V

Veerle

Found the solution:
If I retrieve the installed certificates in native .NET code instead
of using the cryptoapi, everything works fine, also in Windows 7:

X509Store store = new X509Store("MY",
StoreLocation.CurrentUser);
store.Open(OpenFlags.OpenExistingOnly |
OpenFlags.ReadOnly);
foreach (X509Certificate2 certificate in
store.Certificates)
{
listOfPrivateCertificates.Add(certificate);
}

So it seems that it is the cryptoapi that is different in Windows 7.


We have to make calls to a webservice of the Belgian government. We
bought ourselves a p12 certificate that we send along with our http
requests, so that the code at the government side knows that the
request is really coming from us and not from someone pretending to be
us.
We wrote our code in the .NET framework 2.0. First we look up all the
installed personal certificates with the code:
IntPtr storeHandle;
storeHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
CERT_SYSTEM_STORE_CURRENT_USER, "MY");
IntPtr currentCertContext;
currentCertContext = CertEnumCertificatesInStore(storeHandle,
(IntPtr)0);
int i = 0;
while (currentCertContext != (IntPtr)0)
{
  listOfPrivateCertificates.Insert(i++, new
X509Certificate(currentCertContext));
  currentCertContext = CertEnumCertificatesInStore(storeHandle,
currentCertContext);}
CertCloseStore(storeHandle, 0);

[DllImport("CRYPT32", EntryPoint = "CertOpenStore", CharSet =
CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CertOpenStore(
  int storeProvider, int encodingType,
  int hcryptProv, int flags, string pvPara);
[DllImport("CRYPT32", EntryPoint = "CertEnumCertificatesInStore",
CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CertEnumCertificatesInStore(
  IntPtr storeProvider,
  IntPtr prevCertContext);
[DllImport("CRYPT32", EntryPoint = "CertCloseStore", CharSet =
CharSet.Unicode, SetLastError = true)]
public static extern bool CertCloseStore(
  IntPtr storeProvider,
  int flags);
Next, when we pick out the certificate that we bought for doing the
government communication and we add it to our http request when making
the webservice call:

This works fine on all Windows XP machines that we have tested this
on. When we test however on a Windows 7 machine, this code doesn't
work. Retrieving the personal certificates still works but when we
make the http request we retrieve an HTTP 403 Forbidden error,
indicating that the server side code did not receive our certificate,
or did not recognize it in the same way as when sending in Windows
XP.
When we install however an old version of FireFox in Windows 7 and
make it the default browser and then retry everything, then it works!
So we are guessing that the .NET framework is underneath relying on
the default browser of Windows in order to send the web request.And
appearently IE8 in Windows 7 is doing something different than IE8 in
Windows XP. And the server code of our government is not compatible
with the first one.
Can anyone confirm this suspision, maybe even shed a light on with the
difference in sending the certificate actually is? I did some Google
research but could not find much of information.
Thanks!
Veerle

I'll suggest looking at the permissions of you app. In win7 Maybe UAC
is stooping you for calling unmanaged code. Have you tried running it
as admin or under a high privilege account?
Best regards.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top