I am developing an application in C# that will communicate with a server over HTTP and SSL. Is there some way that I can have the program trust the certificate supplied by the server? This certificate would be distributed together with the software, so that it can identify the server without involving an external CA.
Clarification: I want my client application to trust a single certificate that has been hard-coded in the client so that it will only ever trust my own server.
You can use BouncyCastle.
Load your CA certificate into BC usign DotNetUtilities class using the FromX509Certificate(X509Certificate) function
Load the public key from the server certificate into BC.
Call Verify on the server certificates public key
This way you check the signature of the certificate. Which is the safest way. And also gives you the possibility to update the server certificate without updating the client. (As long as the CA is valid off course)
Source of Verify here: http://www.bouncycastle.org/viewcvs/viewcvs.cgi/csharp/crypto/src/x509/X509Certificate.cs?view=markup Line:540
In my opinion, I don't think you can do this and trust that you have a secure channel. Someone correct me if I'm wrong, but the CA trust chain in SSL isn't to just to verify that the thumbprint is a particular value (or some other part of the certificate). It proves that the the client is communicating with the correct server (due to a shared CA key). This illustration is a good reference. Skipping step 3, will not allow the server to prove its identity to the client (throw certificate validation).
so that it will only ever trust my own server
SSL guarantees this by using a shared CA certificate (like verisign etc). Maybe I don't understand why you would choose not to just use SSL as it was intended.
EDIT:
As the_ajp points out in his answer, there are libraries (like bouncy castle) that will do a full verification on the certificate chain. These can be called manually.
Related
I'm curious to know why HttpWebRequest.ClientCertificates is a collection?
As far as I know, only one client certificate can be used (Is this merely true?) in client authentication.
An example of an application uses multiple client certificates, please?
While you can use only one leaf certificate for authentication you might want or need to send additional intermediate certificates so that the peer can build the trust path to the locally trusted CA certificate. This is true for both server and client certificates.
I'm writing a system in C#, which consists of REST API server, written with HttpListener and WPF client app, with HttpClient and I want to use HTTPS.
As far as I know, on the server side all I have to do is run HttpListener with prefix with https and bind my certificate (creted for example with makecert) to proper port - now all communication is encrypted.
On the client side, I have to put the public part of certificate in Current User store, so that it can be trusted.
The server is not public, each client has his own instance accesible only after logging in to their VPN.
My questions:
1. Are self-signed certificates secure enough? Is generating new certificate for new client more secure(for example, from license data)?
2. How do I generate the "public part" and "private part" of certificate? How do I ship it?
It isn't a bank, so I don't want to overkill security, but I don't want to go "trust all certificates" way.
Security in general hinges on how well protected your private key is. The algorithm used can be the same as on a public signed certificate.
There is no inherit security gain or loss in using a self signed certificate.
The bigger problem is the distribution of your public key among the member systems. If you run a domain wide CA on your domain controller, it should be relatively easy.
If you do not, you might be able to do it via Group Policy.
In any case it requires admin intervention to get it to run on all your systems and again should the private key be compromised.
The problem arises should you have external clients not connected to your DC. Then LetsEncrypt is definitely the better choice.
I believe that you'll have to add the public key of the self signed certificate to the Trusted Root Certification Authorities store as well.
That is offcourse cumbersome since you'll have to do this on every client ...
Can't you use certificates issued by LetsEncrypt ?
I have looked at about 10-15 different pages about the SSlStream class and about certificates and I haven't found one that completely explains everything to me. So I have a bunch of questions.
I am currently working on some SslStream code and I have a question about certificates. From my research it appears that the server requires a certificate if we are using TSL12. And it appears optional that the client needs a certificate.
1) Now if we design a system that the client needs a certificate do we use the same certificate for the client and the server? Or do they both use different ones?
2) Also looking at the Microsoft SslStream help page:
https://msdn.microsoft.com/en-us/library/system.net.security.sslstream(v=vs.110).aspx
How does the code know if those are the expected certificates?
3) In the Property page on a project under Signing you can Create a Test Certificate. When you click that button it asks for a Password. If a password is used how would that affect the SslStream code? The code on the Microsoft help page above doesn't deal with that at all?
4) Once I have a certificate for the server and the client can I just place them in a directory or do I need to put them in the store?
Thanks.
You can find most answers to your questions here
These are the different certificates. Client certificate used to check client identity. Server certificate used to encrypt key materials and to authenticate itself.
What means expected? You mean whether the client certificate is correct? You can write your own login to check client and certificate. By default expiration date is checked, where it's revoked or not etc. Read there to clarify.
It will create certificate and to use private key you will need to provide password to get it from storage
The base usage is to put it into the store. But you can also get it from .pfx file. You can read there about geting the key from file
1) Now if we design a system that the client needs a certificate do we use the same certificate for the client and the server? Or do they both use different ones?
The best practice is "one certificate per purpose". Think of a server authentication certificate as the "Warner Bros. Studios" sign hanging on the building as you pull up to the guard shack, and a client authentication certificate as an employee ID badge. They both inform the other party what's going on, but it feels a little out of place to then walk down the street to Universal and show your big Warner Bros. sign as identification.
2) Also looking at the Microsoft SslStream help page: https://msdn.microsoft.com/en-us/library/system.net.security.sslstream(v=vs.110).aspx How does the code know if those are the expected certificates?
The server authentication certificate you provide is correct, because you provided it.
If you give only one client auth cert, that's correct, because you provided it.
If you give multiple client auth certs then it will use an acceptable CAs list provided by the server TLS handshake to reduce the list, then it takes the first one that was acceptable.
3) In the Property page on a project under Signing you can Create a Test Certificate. When you click that button it asks for a Password. If a password is used how would that affect the SslStream code? The code on the Microsoft help page above doesn't deal with that at all?
Certificates don't have passwords, but PFX/PKCS#12 files do. You need that password to load the file into an X509Certificate2 instance (e.g. new X509Certificate2("servercert.pfx", "1Potato2Potato3Potato4")). Since SslStream won't do the loading for you, it doesn't talk about passwords.
4) Once I have a certificate for the server and the client can I just place them in a directory or do I need to put them in the store?
They should work fine when loaded from a PFX (you need the private key, so it can't be just a .cer). If the certificates can be one-time loaded into cert stores you can avoid the problem of loading or hard-coding PFX passwords... but that just depends on your deployment needs.
I have a C# console app that consumes a web service that is outside of my network. I am told that the web services uses self-signed certificate for SSL. I am not familiar with the certificate and I am wondering what I need to do in .net/windows server environment.
Thanks.
Self signed certificates will not be viewed by your application as valid by default because there is not a trusted third party validating the certificate. Typically you'll see self signed certificates on test servers, and you can find more info on self signed versus signed certificates here.
If you are having trouble calling the web services then you'll need to either install the certificate on the machine that your application is running on, or create a custom validator that you can use to tell your application to accept the self signed certificate. From .NET 2.0 onward, custom SSL validation is done by specifying a custom method on the ServicePointManager.ServerCertificateValidationCallback property.
An example of using the ServerCertificateValidationCallback property can be found here:
http://weblogs.asp.net/smehaffie/archive/2009/09/10/calling-web-services-that-use-self-signed-certificates.aspx
That's a large question especially regarding X.509 security. Usually with self-signed certificate, you have to import the initial CA used to sign this certificate (usually the self-signed CA used by the application) into your keyring (to be sure that you are connecting to the right server). It's usually required because your client application will check at the connection if the certificate is signed by a known and trusted CA or matching an existing certificate in your keyring.
In C#, you can check the System.Net.Security namespace and especially the SSlStream class for more details.
If you need to import certificate in your keyring, you can use various interfaces to access the keyring from the GUI, using the command line "Certutil.exe" or via the various APIs.
I am having a lot of trouble setting up an X509 certificate scheme in C#.NET. SSL is enabled on the server and the connection is being made over SSL. Certificates are being added to the request's store via request.ClientCertificates.Add(). However, no client certificate is being attached to the handshake request (which I am both confirming by both checking the server's code through HttpRequest.ClientCertificate and by analyzing the handshake in Fiddler).
As nearly as I can tell, the problem here is that the server is not requesting a client certificate. The certificates are definitely in the outgoing request, but I see none on the handshake and none on the server side - they simply disappear into the ether. I'm aware of the semantics behind choosing a certificate (thanks to this page), but it hasn't resolved my problem. The CAs should be the same; I am using the same self-signed, private key secured certificate for each end of the test.
Apparantly I can use certutil.exe to check which certificates will be chosen when used with a given server certificate. This would be a huge help if I could figure out how to use it like this. Certutil is a big program that is poorly documented. Any help would be appreciated.
If you're using IIS serverside you MUST provide certificate that is trusted by your server. So you MUST add client cert' CA cert into server computer 'Root certificate authorities' storage. IIS doesnt work with self-signed certificates. It requests client cert providing list of CAs it trusts to.