self signed certificate in windows server - c#

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.

Related

C# gRPC client SslCredentials without root rootCertificates

I have an internal application of clients & servers which uses a self signed certificates for Server SSL (each server has it's own ssl certificate)
Because I'm using self signed certificate I have a custom verification logic.
I was able to implement it using .net standard (Grpc.Net.Client)
however I also have clients using .net framework 4.7.2 and I can't figure out how to accomplish it there.
I saw I can use the gRPC.Core library and create SslCredentials with arguments verifyPeerCallback which I can use to add custom certificate validation.
However I must pass the rootCertificates argument which means every client must have access to the public certificate which is what I want to avoid (for example certificate rotation / multiple server behind a FW)

Certificate chain contained within the public key exposed by RabbitMQ

I have a c# .net client consuming messages from a RabbitMQ instance (using RabbitMQ.Client) secured using TLS. I got everything working nicely using a self signed certificate.
We've purchased a wildcard certificate from an accredited CA to use going forward. This certificate has actually been signed by an intermediary authority of the Root CA which is trusted by the root CA itself.
Because the intermediary CA will not be trusted by the client machine (the certificate won't be installed into the local machine certificate store), we downloaded a PEM file that contains all the certificates that make up the chain of trust. However, the .net client will not validate this certificate, failing because it cannot establish the chain of trust.
I've had a look around and can find nothing that says .net cannot validate PEM certificates that themselves contain multiple certificates. If I assign a custom delegate to the CertificateValidationCallback property of the RabbitMQ ConnectionFactory I can see that the certificate chain contains only one certificate, which is the certificate that is signed by the intermediate CA.
The client will ultimately be deployed to hundreds of machines so we'd rather not have to deploy the intermediate certificate to all of them and then have to manage them going forward. I'm aware that I can set turn off chain validation by setting the AcceptablePolicyErrors property to SslPolicyErrors.RemoteCertificateChainErrors but this seems to me to be making things a little less secure.
So, there are two main questions I have here:
Does .net cryptographic validation simply not support certificates that contain all the other certificates in the chain (at least if that certificate is a PEM)?
Is there a way of working round this?
I'm using .net 4.5.2 although the same problem occurs in .net 4.6.2 and .net 4.7.1.
I'm running it on a Windows 7 machine. The RabbitMQ node is running on a windows 2012 server.
The RabbitMQ team monitors the rabbitmq-users mailing list](https://groups.google.com/forum/#!forum/rabbitmq-users) and only sometimes answers questions on StackOverflow.
You should concatenate the Root CA certificate and Intermediate CA certificate (both pem format) into a single file, and use that as the cacertfile for RabbitMQ. The Erlang VM should then present both certificates during the handshake phase of session establishment and they should be used by the .NET TLS/SSL code to verify the server's certificate.
You can use these instructions to assist in troubleshooting your environment. If something still doesn't work, follow up on the mailing list and we'll help out. Thanks!

SSL Self-Signed Certificate

First of all I know that I have a lot of misconceptions about fundamentals of SSL.
But before, I want to give information about my goal; There is a Windows forms application written in C# and there is a asp.net WebApi that is integrated to this Windows app. Clients those are connecting to API are written in several programming languages. We need to add SSL somehow. this is not a public application and clients will build their client apps with the client certificate we will give them.
And here are lines of my knowledge about SSL those can be wrong or right;
-Self-Signed Certificates are more secure than bought ones. Becuase some known certificates can made unsecure by apps like Charles.
-For this scenario that i mentioned above as goal, there must be three certificates separately;
root cert,
a server side cert related to root cert,
a client side cert related to server cert.
-Every client can have same client side certificate.
-Visiual Studio Command Prompt is enough to create these certificates.
Also I need a source of documents to complete all these steps.
Self-Signed Certificates are more secure than bought ones.
nope ... self signed certs are just certs that a client can not verify on its own because there is no trusted third party saying: "this cert is ok"
you have to have your own way of securely delivering the cert to the client, possibly by having an admin manually installing them or bundling them with your app...
if you have no control over some of the clients, things tend to get ugly with self signed certs...
For this scenario, there must be three certificates separately;
root cert,
a server side cert related to root cert,
a client side cert related to server cert.
as far as i understood, you want x509 certs for SSL/TLS to authenticate the server and to avoid MITM attacks, not for client recognition by the server
in this kind of scenario you need only one certificate, or maybe two if you want to base your own PKI on this later ...
the case with one cert:
create a keypair and selfsign a x509 cert with that ... private key stays with your server, the public key will be included in the cert, which is shipped with your application and also handed out to other developers for their clients to authenticate the server...
this certificate will be required to be used in the client application to authenticate the server during SSL/TLS handshake
this is basically certificate pinning
darwback: depending on the size of the clientbase it will become challanging to replace this cert
case with 2 certs:
same as above, but the self signed cert is actually a root cert that can be used to sign other certs, in this use case in particular: the server cert...
the self signed root cert can then be used by the client to verify that the root cert was used to sign the server cert, which makes replacing the server cert easier ...
you might want to do the later and also setup a certificate revocation list in case you need to invalidate a cert ...
-Every client can have same client side certificate.
all the client needs is (as #john already pointed out) the self signed server cert (case 1) / self signed root cert (case 2)
-Visiual Studio Command Prompt is enough to create these certificates.
please notice that the documentation of makecert states "The Certificate Creation tool generates X.509 certificates for testing purposes only."
apparently this limitation was lifted ...
I think what you are after is called certificate pinning.
SSL certificates are used in the following way by default:
Certificate is issued by some authority. Client (browser, operating system such as Windows, Android etc) has a list of authorities it trusts. If certificate is valid (not expired, issued for domain we are connecting to etc) and is issued by trusted authority - all is fine
There are a ton of different authorities and client cannot trust them all. Instead, it trusts certain selected "root" authorities.
Those "root" authorities delegate ability to issue certificates to other, smaller, authorities, to which those root authorities themselves trust.
This might go on, so there is a chain of trust: certificate is issued by authority A, which is trusted by authority B, which is trusted by "root" authority, which in turn is trusted by client (your operating system).
That model has several weak points, one of them is list of "root" authorities your client trusts. Someone, like your corporate admin, or your government, or ISP provider, can install or force you to install custom certificate to your trusted "root" authorities list. Then it can perform man-in-the-middle attack by intercepting your SSL traffic and reencrypt it with this custom certificate that was installed to the trusted list.
That way client will think that all is still secure, while in reality your traffic is intercepted and responses are recorded and\or modified.
If you don't like this - you can use certificate pinning. Idea is simple - you just embed expected certificate for your api endpoint in your software.
By doing that you don't any more need to trust any authorities or verifying chain of trust above. All you need to verify is that certificate presented during SSL handshake is exactly the same as you embed into software.
For that reason - you don't really need certificate issued by some authority and you can use self-signed certificate.
So if you follow this path - issue self-signed certificate and embed it (without private key of course) to software (send to clients) and instruct them to verify your server certificate presented during SSL handshake is exactly this certificate.
Drawback is of course that if your certificate is compromised or expired - you need to update all software. It's not a big problem if said software is controlled by you, but it might be a problem if software is controlled by third party.

Manually trust SSL certificate in C#

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.

Certificate authentication with a self-signed certificate

I have a client application (windows service) which sends a request (WebClient.UploadString()) to a web service. I've created a certificate through IIS. This I attach to the WebClient before sending the request. However, I get the following message:
The remote certificate is invalid according to the validation procedure.
I believe this is referring to the server having an invalid certificate, but I am unsure of the best way to make the client trust the server. Eventaully, this web service will be installed on a number of servers as will the windows service so I can't attach the certificate to a single computer. Any ideas?
I don't know your exact situation/setup, but here is some general info on using self-signed certificates.
If you want to use a self-signed certificate you will need to add that certificate to the server's trusted root certificate store.
Basically the server does not trust the certificate used to sign your certificate, which is the certificate itself since it is self-signed.
As an alternative, you can create your own root certificate and add it to the server's trusted root, then use that to sign additional client certificates. This will make it easier because you won't have to install each client certificate on the server, just the root one used to do the signing.
Of course, you can always buy a certificate from a company (GoDaddy, Verisign, etc). These will be signed by a certificate that is already trusted.
Also, there might be ways to bypass the checking, but you probably don't want to do that.

Categories

Resources