HttpWebRequest and PAssowrd Protected Private Keys

B

Brian R.

I am writing a Post client with the HttpWebRequest object and using the
Crypto API to access "MY" store and pull out the certificate that I want. I
attach it and send it, but I still get a forbidden (403).

If I browse the site with Internet Explorer, the certificate exchange is
different. I select the same certificate that I programmatically attached,
but IE (cryptoAPI actually) prompts me for a password to access the private
key. Once I type in the password that came with the key, I can access the
site.

What do I need to do in my .NET client to pass these credentials (password)
as part of the X509Certificate in code?

I think the issue is the password as I can programmatically access the site
with a different client certificate that does not have a password protected
private key.

Thanks!
 
S

Steven Cheng[MSFT]

Hi Brian,

From your description, you're using HttpWebrequest to send http message
and will need to attach client certificate for authentication. However, you
found that the program will always fail with 403 exception at runtime, and
when using webbrowser to select that certain client certificate, you'll get
prompt dialog for input password, correct?

As for this behavior, it is due to your client certificate is requested and
installed in a strong-protection mode, that means whenever any program need
to access the private key associated with that certificate, the system will
prompt for password. When you use this certificate in some desktop
application(such as IE browser or winform application), the windows system
will show dialog for you to input password so as to access the private key.
However, if you use the certificate(private key) in some non-interactive
application(such as ASP.NET web application, windows service), the dialog
is invisible, therefore cause the program end with error.

Based on my test, for such scenario, since strong-protected certificate
force the user to input the password, you can consider either of the
following approachs:

1. Export the certificate(from certificate store) out to a Pfx file on the
disk(contains private key), do remember to uncheck the "enable strong
protection..." option when doing the exporting. After that, in your
program, you can programmatically load the certificate from the pfx file.
e.g.

================
private void btnPwdTest_Click(object sender, EventArgs e)
{

X509Certificate2 certpwd = new X509Certificate2();

certpwd.Import(@"E:\temp\cert_temp\pwdtest\pwdtestcert1.pfx",
"Password01!", X509KeyStorageFlags.DefaultKeySet);
.......................
}
=======================

You will not be asked for the password interactively. Notice that the
"Password01!" above is different from the password you're asked under
"Strong-Protection mode", the "Password01!" password above is the one used
to secure the pfx file.


2. Since you've exported the certificate (with "strong-protection..."
unchecked) into a pfx file, you can import it again into certificate store
(without strong-protection). thus, you can access that unprotected
certificate in code.

How do you think? If you have anything unclear or any other questions on
this, please feel free to let me know.;


Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead



==================================================

Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.



Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.

==================================================



This posting is provided "AS IS" with no warranties, and confers no rights.
 
B

Brian R.

Your description of my scenario is accurate and describes my problem.
Exporting the key and eliminating the strong protection would work, but I was
hoping for a solution that could access the private key perhaps through the
Win32 CryptoAPI (P/Invoke) to programmatically get that password dialog box
to be displayed to gain access to the key.

Do you know if this is possible? My other solution is to host the IE
browser control in my application and make calls to it to perform the work.

thanks,
 
S

Steven Cheng[MSFT]

Hi Brian,

Thanks for your reply.

For the further things you mentioned, do you mean you're looking for a
programmatic way to suppress the prompt password dialog through win32
crypto API?

I haven't explored the win32 crypto API much, but will do some further
research to see whether there is a way to do so. I'll update you as soon as
I get any new information.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
 
S

Steven Cheng[MSFT]

Hi Brian,

I have discussed with some other security engineers on this issue, and so
far what we conclude is that if use STRONG_PROTECTION on your certificate,
the password dialog box will surely display and there is no programmatic
way to suppress it. Also, this STRONG_PROTECTION is available only for
certificate in current user store, for those certificates in machine
certificate store, there is no such STRONG_PROTECT setting(the security is
controlled by the access permssion to machine store). Therefore, they also
suggest that for server-side application, it is recommend that we put those
certificates in machine store (avoid such STRONG_PROTECT setting).

Here is the original comments from our security engineers for your
reference:
If you are referring to the smartcard PIN prompt while accessing the
private key in the smartcard, this can be accomplished using
CryptSetProvParam as Shawn explained below.

If you are referring to the password for the strong protection of private
key, there is no programmatic Crypto API to supply this password.

When strong protection is enabled for the RSA private key, the user is
notified through a dialog box when applications attempt to use the private
key.

One specifies that the RSA private key is enabled for strong protection
either during certificate request or when pfx is imported. Essentially this
is done when the RSA private key is generated/installed/imported etc.

With Medium strong protection, the user is notified. But there is no
password to enter.
With High strong protection, the user has to supply the password, every
time the key is used.

The dialog to choose "Security Level" comes from Protected Storage
component of Windows that allows the user to select either medium or high
protection on the RSA private key while the private key is
generated/installed/imported.

Later, when there is an attempt to access that RSA private key, the dialog
box is presented for security reasons and only the end user has control in
answering this dialog box.

There is no way to control this dialog box behavior from an application
silently when the private key is accessed. Also, there is no programmatic
Crypto API to supply the password. If the private key is not protected, you
will not get the prompt.

Please note that the "strong protection" feature for RSA private key is
available only for certificates installed in current user Certificate store
such as user's certificates where an end user is involved for answering
this dialog box.

However, this feature is not available for certificates generated/installed
in local machine certificate store. You will see that this option is
disabled no matter how the certificate/PFX is generated or installed in any
GUI. Also, the certificate generation requests fail when this mode is
selected programmatically.

If this is purely a server side application like ASP.NET, you cannot use
CurrentUser certificate store anyway as the user's profile (where the
certificates are stored) of the calling user account won't be loaded.

Server side components like IIS/ASP.NET or services running under well
known accounts can typically use only certificates in "Local computer"
certificate store.

So, if this certificate is for the server application component itself to
use, then the solution for server side involves installing and using
certificates in "Local Computer" certificate store as local administrator.
Please note that only local Administrators group (and NT AUTHORITY\SYSTEM)
will have access to the corresponding RSA private key container by default.

If access to the corresponding RSA private key container is required by
non-admins such as Network Service or some other account, local
administrator can configure access through winhttpcertcfg tool as
documented at:

http://msdn2.microsoft.com/en-us/library/aa384088.aspx

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
 
S

Steven Cheng[MSFT]

Hi Brian,

How are you doing on this issue, does the further information in my last
reply helps some? If there is anything else we can help, please feel free
to let me know.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
 

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

Members online

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top