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.
Related
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 ?
We want to implement https to our website. But given that our team have no experience with https/ssl things, it will take us a bit time to learn how to use encrypted connection on our website.
We want to make our website the more secure as possible during the time we try to implement an SSL certificate.
So, we heard about a temporary solution we could use. Something like to ask the user (With a popup confirmation) each time he goes our website if he want to use a secure connection (Like a new certificate for each connection to our website).
I don't know anything about this "method", I don't even know what to search on google.
Is this even possible ? If yes, how you call this ?
You probably refer to self-signed certificates as the temporary solution.
To implement them you already have to implement https at your server and the only difference to "real" https is that you don't buy a certificate from an established CA, but that you create your own. In this case the browser will not trust the certificate by default and need to ask the user to trust the certificate. Of course, not all users will simply trust some stranger so expect to loose more users of your site this way than you would loose if you don't use https at all.
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.
I asked a question here a while back on how to hide my http request calls and make them more secure in my application. I did not want people to use fiddler 2 to see the call and set up an auto responder. Everyone told me to go SSL and calls will be hidden and information kept safe.
I bought and installed an SSL Certificate and got everything set up. I booted up fiddler 2 and ran a test application that connect to an https web service as well as connected to an https php script.
Fiddler 2 was able to not only detect both requests, but decrypt them as well! I was able to see all information going back and fourth, which brings me to my question.
What is the point of having SSL if it made zero difference to security. With or without SSL I can see all information going back and fourth and STILL set up an auto responder.
Is there something in .NET I am missing to better hide my calls going over SSL?
EDIT
I am adding a new part to this question due to some of the responses I have received. What if an app connects to a web service to login. The app sends the web service a username and a password. The web service then sends data back to the app saying good login data or bad. Even if going over SSL the person using fiddler 2 could just set up an auto responder and the application is then "cracked". I understand how it could be useful to see the data in debugging, but my question is what exactly should one do to make sure the SSL is connecting to the one it was requesting. Basically saying there cannot be a middle man.
This is covered here: http://www.fiddlerbook.com/fiddler/help/httpsdecryption.asp
Fiddler2 relies on a "man-in-the-middle" approach to HTTPS interception. To your web browser, Fiddler2 claims to be the secure web server, and to the web server, Fiddler2 mimics the web browser. In order to pretend to be the web server, Fiddler2 dynamically generates a HTTPS certificate.
Essentially, you manually trust whatever certificate Fiddler provides, the same will be true if you manually accept certificate from random person that does not match domain name.
EDIT:
There are ways to prevent Fiddler/man-in-the-middle attack - i.e. in custom application, using SSL, one can require particular certificates to be used for communication. In case of browsers, they have UI to notify user of certificate mismatch, but eventually allow such communication.
As a publicly available sample for explicit certificates, you can try to use Azure services (i.e. with PowerShell tools for Azure) and sniff traffic with Fiddler. It fails due to explicit cert requirement.
You could set up your web-service to require a Client-side certification for SSL authentication, as well as the server side. This way Fiddler wouldn't be able to connect to your service. Only your application, which has the required certificate would be able to connect.
Of course, then you have the problem of how to protect the certificate within the app, but you've got that problem now with your username & password, anyway. Someone who really wants to crack your app could have a go with Reflector, or even do a memory search for the private key associated with the client-side cert.
There's no real way to make this 100% bullet proof. It's the same problem the movie industry has with securing DVD content. If you've got software capable of decrypting the DVD and playing back the content, then someone can do a memory dump while that software is in action and find the decryption key.
The point of SSL/TLS in general is so that the occasional eavesdropper with Wireshark isn't able to see your payloads. Fiddler/Burp means that you interacted with the system. Yes, it is a very simple interaction, but it does require (one) of the systems to be compromised.
If you want to enhance the security by rendering these MITM programs useless at such a basic level, you would require client certificate authentication (2-way SSL) and pin both the server and client certificates (e.g. require that only the particular certificate is valid for the comms). You would also encrypt the payloads transferred on the wire with the public keys of each party, and ensure that the private keys only reside on the systems they belong to. This way even if one party (Bob) is compromised the attacker can only see what is sent to Bob, and not what Bob sent to Alice.
You would then take the encrypted payloads and sign the data with a verifiable certificate to ensure the data has not been tampered with (there is a lot of debate on whether to encrypt first or sign first, btw).
On top of that, you can hash the signature using several passes of something like sha2 to ensure the signature is 'as-sent' (although this is largely an obscure step).
This would get you about as far in the security way as achievable reasonably when you do not control (one) of the communicating systems.
As others mentioned, if an attacker controls the system, they control the RAM and can modify all method calls in memory.
I'd like to use client certificates to verify the identity of administrative callers to my web service. Then I can issue certificates only to the people I want to call my web service and be pretty sure noone else can call it. This is in a very controlled scenario where only one or two people will get the client certificate, so distribution isn't a hard problem.
This article provides a good example of how to call a web service using a client certificate.
But how can I check details of the client certificate from within my web service? This old article talks about configuring IIS to do it, but I'd like to do it programmatically within my app. I think?
thanks for any suggestions!
The incoming Request has a ClientCertificates collection that you can interrogate -- you can check the various fields in the cert or check the actual raw byte data (perhaps against a datastore or other source) if you want to completely validate it.
Note, if you issue the certs from your own private CA, you will need to install the CA's cert on your webserver into a store that is visible to all users, otherwise IIS won't request those certs from the user (due to the nature of how the server/client interaction works.)