Programmatically import cert into IIS? - c#

I have a .pem certificate for SSL, I want to distribute it with my web application in an MSI (has to run on clients' computers). I then need to import it (into some credentials store?) and tell my site bindings to use it. But how can I do this in code? I've discovered Microsoft.Web.Administration, but not sure where to go from there …
This is in IIS7 btw.
EDIT: The goal here is to have a web application that customers can run on their intranets. It mainly acts as an API for an iPhone app. (Maybe this isn't the best design but we're locked in now.) So the customer installs the MSI, and voila, they have a web service. Now there needs to be password authentication between the iPhone and the web service; the simplest way seemed to be to do it in https. So I made a self-signed cert.
I'm aware that redistributing a single cert is generally a bad idea, but we're just trying to defeat casual hackers here … this is going to be intranet only and for businesses only, it seems unlikely that anyone is going to be doing anything too crazy, and the API severely restricts the amount of Bad Things you are able to do to the database anyways.
So there we go, the goal is to have password authentication on an intranet web app, with one-click(ish) installation. :-D

The answer, dear readers, is this:
// Assume 'site' is already set to your site via something like
// Site site = mgr.Sites.Add(siteName, directory, 443);
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);
// Here, directory is my install dir, and (directory)\bin\certificate.pfx is where the cert file is.
// 1234 is the password to the certfile (exported from IIS)
X509Certificate2 certificate = new X509Certificate2(directory + #"\bin\certificate.pfx", "1234");
store.Add(certificate);
var binding = site.Bindings.Add("*:443:", certificate.GetCertHash(), store.Name);
binding.Protocol = "https";
store.Close();
Thanks to this random thread: http://forums.iis.net/t/1163325.aspx

You need to narrow down your question. What is the certificate used for (exactly)?
If your certificate is used for client-side authentication (to authenticate the client on the server), then distributing it with your application makes such authentication plain useless, as you would be disclosing the secret key.
If you need to validate the server's certificate (and you've been given server's certificate or certificate chain in your PEM file), then this could work, but why would you need to install the certificate to the certificate store?
You should note, that PEM format is not natively supported by Windows or .NET libraries so you need to convert it to PFX before deployment, and then import a PFX or just create a store in memory based on PFX (you will find plenty of information by looking for PFX or PKCS#12 on StackOVerflow).
Upd: it would be a better approach to generate the certificate each time you install the application and let the user have their own certificate (eg. it's possible that they already have a valid certificate for their web site).

Related

Two SSL certificates for one domain, one for encryption, and other for authentication?

I am building an web app, that will use ssl certificates for authentication. I will be using IIS web server.
The problem is that CA is self-signed and users will get red bar in browser.
So, i was wandering if it is possible to get a proper certificate from global provider, and use that certificate for encryprion in order to get green bar (or at least no red bar).
And then, on top of that, get server certificate from the local CA, for the same domain, but use it only for authentication pusposes, since local CA will provide users a certificate on PKI device.
Is this setup even possible? I am no expert in this area, so I would appreciate any pointers, or maybe I am on a wrong track, and this is not possible to achieve?
Best regards,
A certificate in TLS is not used for payload encryption in the first place. A certificate is used for authentication and in case of the obsolete RSA key exchange also for sending the premaster secret from the client to the server by encrypting it with the public key of the server. Apart from being obsolete it is not possible to use a different certificate for the RSA key exchange than for the authentication.

How to sign an xml document with a certificate and what type of solutions are required?

We have developed a web application that generates an xml file. To deploy the application to production, we have purchased an SSL certificate through DigiCert, so that it runs under HTTPS protocol, however, one of the requirements are to send the xml file with a signature to be verified by the receiver (client), that it is in fact a genuine xml document sent from our service.
Do we need to get a document/code signing certificate too to achieve this, or is the SSL certificate we have purchased sufficient and to just follow this Microsoft tutorial:
https://learn.microsoft.com/en-us/dotnet/standard/security/how-to-encrypt-xml-elements-with-x-509-certificates
The X509 XML signing code can work with any X509 certificate. From the coding perspective you can use the one you already have unless your client demands you to use a cert generated from a specific CA.
The code you linked does encrypt an XML, but you stated you did need to sign it. They are different things.
Encrypting does make it unreadable to anyone that does not have the private key.
Signing does a signature of the content and adds it at the end of it, so anyone can check the content was not altered.

Keyset does not exist (attempting to sign executable from web service)

See this: X509Certificate - Keyset does not exist
I am attempting to sign a certificate using a web service on IIS 8. I thought it would be as simple as installing a PFX on a server, and then the web service could simply use that certificate (from the store) and sign an executable (these executables are created on demand, and signed by our service, at least that's the idea behind it).
I've exhaused all of the options linked to the above question, I've navigated to C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys, and added EVERYONE to the files to see if I can narrow down that it is (in fact) a permissions issue. I've attempted running MMC and added the snap-in for service\computer accounts, I've ensure that upon installing the certificate it was marked as exportable, I've even attempted to add, in the web service itself, code which would basically add the certificate to the store itself: i.e.
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
store.Add(cert);
store.Close();
Any ideas? Is there another way that I could determine (for sure) if it is actually a permissions issue? Is there no way to sign a certificate without having the certificate in the machine's store (i.e. signtool.exe allows it).
Also, for reference, I used the class found here: Has anyone got any code to call SignerSignEx from C#? for signing the certificate. I've scoured the internet and most of the solutions are very much the same: permissions on the GUID cert files themselves. Any help on this would be greatly appreciated.

How to create my own certificate authority for IIS?

I am tired of buying SSL Certificates for my clients. We spend thousand dollars per month on average. Can someone please show me how to start my own certificate authority (Not the the self-sign certificate)? This SSL is for IIS.
It seemed like IIS can issue self-sign and OpenSSL can do the same thing and I do not want it unless it can provide a full SSL like Verisign and other big companies.
If you want to roll your own certificate authority (suppose for closed in-company infrastructure), you start by (surprise, surprise) creating a self-signed certificate, which will act as a root CA certificate. Then you generate the first child certificate - intermediate CA certificate. Now put the private key of the root certificate to the safe place - most likely you will not need it for years. Intermediate CA certificate is used to issue end-user (or other sub-CA) certificates.
If you want your certificates to be recognized by standard browsers and other client software, you need to find a way to get your public root certificate to the list of trusted roots in the OS itself and in those browsers and clients, if they have their own certificate storages. This is a complicated procedure, different for each OS and each browser. It involves repeating audits, compliance to tough procedures etc.
Again, if you create certificates for internal company use only, you can make software installer (or just write a custom script or application) that will add your certificate to the trusted root list on each user's computer. This can be done in code almost without problems, but the user will have to (a) run that script or program, and (b) confirm addition of the certificate. For some browsers or other client applications the procedure can be more complicated.
The procedure of creating a CA is quite a complex topic. I suggest that you read some books on PKI before you proceed. Here are the great books I'd recommend:
Rsa Security's Official Guide to Cryptography
PKI: Implementing & Managing E-Security
Creating your own certificate authority is not an issue. Your issue is creating a certificate authority that other people will trust!
There is absolutely no point you creating your own unless all your users are prepared to accept certificates signed by you, and this is a pretty unlikely scenario unless you have a small number of users that are prepared to trust your root CA.
Getting them to trust you involves them all installing your root CA as a trusted CA on their web browsers which is hardly good security practice.
Unless you work in a controlled environment, and all your users are internal, or you have a very suggestible group of users who will do whatever you say - I would recommend you forget this idea.

Using the "Service Account" certificate store with .NET 2.0 HttpWebRequest

I have a .net 2.0 windows service application written in C# that access a non-soap web service via SSL with HttpWebRequest. My windows service runs under the NETWORK SERVICE account.
I am able to make SSL work by issuing a cert to the web server that my windows service talks to from a CA, then installing the CA's cert to the Local Machine\trusted root store.
What I would like to be able to do is to install the CA's cert to the "service account" trusted root cert store instead of the "local machine" store, and have this "just work."
In other words, it seems that the SSL authentication used by the .net framework is hard coded to check the current user store, and the local machine store for trusted roots when validating an SSL certificate, but is there any clean way to get it to check the "service account" store instead of (or in addition to) the other stores?
The only solution I can come up with is to override the ServicePointManager.ServerCertificateValidationCallback and then P/Invoke to the Crypto API to open the "service account" cert store in Win32, and manually search for the root in there. I'd rather not do that, since it would seem to be a pretty large performance penalty, having to wait for failure from 2 cert stores I don't intend to use anyway.
Possibly, i'm taking entirely the wrong approach here, but it really seems like I'm missing a simply way to solve my problem.
If your code controls the server it is talking to, then why dont you just return "true" from the CertValidationCallback? It is not as if the server cert will change every time you make a request?
Unless you really need the system to also verify other things related to the cert, for eg CRL, expiry etc, you might just make it work by implementing a custom cert validation callback.
If you really want to install the cert into the NETWORK_SERVICE a/c context, then there are tools from Microsoft to help you do that.
http://support.microsoft.com/kb/901183
http://web.asu.edu/community/installing-client-certificate-windows-machine
http://www.derkeiler.com/Newsgroups/microsoft.public.dotnet.security/2008-03/msg00011.html
good luck!

Categories