I am working on a legacy architecture that has a server that has an existing certificate for communication. Multiple existing services in the legacy architecutre use this for communication. I am working on creating a communication channel on a much newer system that is built for scale that will communicate with our old framework. This will be used to perform a phased migration where we rely on the old architecture for a period of time, while still running the old system.
Due to some internal constraints, we can't simply add the existing certificate to the new architecture. Furthermore, changing the certificate to the new one will require changing every single service that communicates with the server to have retry logic & both certificates. Furthermore, this has the potential to instantly break the old system entirely (as all the services rely on the server to perform - one of the limitations of the old architecture).
So the ideal solution is that the service simply accepts two different certificates for a period of time while we perform the migration. The new services communicate with their certificate and the old services communicate with theirs. Then we can deprecate & decommission the old services
The only way I see to set a certificate is either in config or how we currently do it:
host.Credentials.ServiceCertificate.SetCertificate(System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine,
System.Security.Cryptography.X509Certificates.StoreName.My,
System.Security.Cryptography.X509Certificates.X509FindType.FindByThumbprint,
thumbprint);
Calling this again would overwrite the certificate set on the host. So is there any way that I can add an additional certificate that the server can distinguish between and use the appropriate certificate for communication with the client when it receives a connection?
Thanks for your time
As Ding Peng mentioned in the comments:
This solution is not feasible, if use certificate verification, the server can only bind one certificate, as you said, if you add two certificates, one of the certificates will be overwritten.
This is correct, but I was misunderstanding how certificate encryption worked and it was unnecessary to add an additional certificate.
Simply by adding logic to whitelist the client certificate subject names of the new architecture - it was able to authenticate.
I had assumed that if the server certificate did not share the subject name of the client cert, that there would be an issue with authentication & encryption. However, this is not the case and simply whitelisting the new subject name was enough to perform the auth.
Related
I have a Client & Server application set, both written in C# but some client versions might be distributed in other languages in the future. I want to protect my applications.
I was looking for some kind of advice to stop just random people sending messages to a server and acting like a client, what kind of validation can I put in place?
My client applications I distribute will be obfuscated but is this enough? I'm just looking for some advice in this situation, is it wise for me to add some kind of encryption other than SSL, or am I just being over protective and over curious? Any input is welcomed & accepted.
It is impossible to determine if you are communicating remotely with "your client" or another piece of software that also knows how to communicate in the way that your client does.
What you can do is ensure that you are communicating with someone that is authorized to communicate with you by using client certificates for your SSL session.
The server proves who it is to the client and the client proves who it is to your server. The security then rests in whoever holds the private key to the client certificate (and the password for this key file).
The C# SslStream Class has support for this. Namely the AuthenticateAsClient method is relevant here.
In summary, if your software is only secure when communicating with a client you wrote, then your software isn't secure period. Instead, design your server in such a way that you can serve client requests securely. Using authentication is one of these ways.
You would want to do two things....one is look up certificate pinning. Your app will validate your SSL cert to thwart man in the middle attacks and it makes it hard to circumvent. The other is when making requests to the server have some type of user name / password block on the server side script before the server side does anything so the requests will simply be discarded by the server if they are from an unknown source.
I've read a lot that self-signed certificates should never be used in production because of the lack of security but I wonder if it's still a security risk if I'm the only one who're supposed to connect to the server? Is it for some reason easier to crack a self-signed certificate? I'm creating both the server and client application and the only way for someone else to connect is to create their own client. That means that every time I install the client I also have the possibility to add the certificate to the trusted root certificates.
Or is it safer to continue to use my own encryption implementation using RSA/AES on the message level? The reason I want to use SSL instead is that it's much easier to work with, especially when I want to stream media since I don't have to send it in chunks.
I've read a lot that self-signed certificates should never be used in production because of the lack of security ....
Self-signed certificates by itself are not bad and can also used in production if done properly.
A certificates is safe to use if the peer is able to verify it properly. The usual validation is done based on some trusted root CA contained in the browser or operating system. But that a self-signed certificate can not be validated this way does not mean that it cannot be validated at all because:
You can explicitly add it as trusted to the certificate store of the browser/OS.
You can make an exception on first use after you've verified that the certificate you get in the browser is actually the one which you know (by comparing the fingerprint, not just the subject).
If you have your own application you could ship the application so that it (only) trusts this certificate.
Of course explicitly importing the certificate as trusted or making in exception in the browser does not scale well, because it has do be done for each user. And that's the main point of CA-signed certificates: that the certificate gets implicitly trusted because it is signed by someone trusted instead of that each user has to validate and trust the certificate manually. And this is also the only reason you want to use a CA-signed certificate in production. As long as the certificate is properly validated it does not matter if it was self-signed or not.
Or is it safer to continue to use my own encryption implementation using RSA/AES on the message level?
Never run your own crypto unless you really understand what you are doing.
In this case SSL provides everything you need but you have to know how to use it properly.
I am designing a system in a client server architecture - TCP based. There is a requirement that all the messages between the server & client should be encrypted. So I am thinking of using SslStream class in .NET Framework.
From SslStream MSDN, my understanding is that we need to use Client & server certificates to make a proper channel & communicate.
I don't want to use any certificate specific to particular machine(client) or server. I Just wanted to have a common key between the system.
Is there any possibility to use the SSL stream without certificates??
Whilst not required by the TLS spec, the use of the .NET SslStream implementation requires that the server has a certificate (and its associated private key). This allows any client to confirm that it is communicating with the server it expects to be. Optionally, clients can also be authenticated by having them provide a client certificate to the server. So, if you want to use SslStream, you're at a minimum going to have to create a certificate for the server, because that is how this particular implementation works.
If you don't wish to use certificates at all, then there are other options. E.g. if you are planning on using your application within a Windows domain, and both client/server are Windows based, you may be able to use NegotiateStream instead. This also supports encryption/authentication, but does not use certificates, and will additionally allow you to identify the user on the other side of the connection.
I'm writing a client/server application that requires the server needs to be able to authenticate the client and also requires all comms to be encrypted.
The mechanism to provide this needs to be self contained within the server and client application and also to be fully automated (no human interaction required). SSL seems to be the best way to do this and is also something I am familiar with using.
For each client that needs the client software deploying to it, I planned to create (on the fly) an MSI installer with the application, the clients certificate (signed by the server) and private key and the servers public certificate (so the clients can authenticate the server - the server certificate could be self signed).
I can generate the key for the client and make a CSR, but don't seem to be able to find a way of actually signing the CSR and generating a certificate for the client thou. I have looked into the Win32 Crypto API, but haven't managed to find any examples of how to actually sign a CSR and get a client certificate.
I know how to do all of this from the command line with the openssl tool, but am not sure of how to do it from within an application.
Please note that making system calls out to the openssl tool and passing in the parameters I know to work is not an option as it's a huge security risk to rely on the openssl tool not being compromised in any way. Doing it this way wouldn't for fill the self contained requirement.
I am going about this the right way, or is there a better way to achieve the same thing - basically authentication of the clients connecting to the server and a way of the connecting client to authenticate the server they connect to, all encrypted.
I cannot make any assumptions about the server (or clients) having a static IP or hostname (DNS can be broken anyways), nor can I make any assumptions about any existing PKI infrastructure.
I am writing this primarily in C#.Net, but would consider writing a C++ extension to this if it gives me this functionality.
Finally this is my first post here, so if I've missed out something obvious or have been short on any details, please ask and I'll fill in the gaps :)
Thanks,
James
In C# you can use PKIBlackbox package of our SecureBlackbox product which provides all the functionality you are looking for in .NET. Maybe BouncyCastle library also includes this functionality.
You need to rethink at least part of this. What you are doing is radically insecure. The client's private key needs to be generated at the client. Otherwise it isn't private, so it cannot possibly satisfy any of the tenets of PKI,. including the purpose for which you are issuing it. You lose uniqueness and you also lose non-repudiability. These are both fatal flaws.
Scenario:
A publically available Web Service that I have full control over.
But I only want this specific desktop application (my published application) to have access to the Web Service.
I could store a secret password in the desktop client, but that would be easy to crack.
Is there any known implementation that enforces this?
PKI, assymmetric keys?
If the public will have access to copies of this Desktop App, any good reverser will be able to crack it and "imitate" its transactions with the server. It doens't matter how secure is your cryptography, everything you app needs to encrypt/decrypt data is included in the binaries, so the cracker only needs to dig it out of it.
The objective of cryptography is to protect data while it is being transfered, from "middle-man" hackers, but if you have access to anyone of the peers, you can easily crack it.
Your server must never trust what comes from the client side.
[edit resuming]
Despite you cannot 100% guarantee a supposed client to your server is or isn't your App or some "emulator" made by thirdies, you can complicate things to them. Its a common practice in game anti-cheats to sometimes, randomly, make the client App a trick question like "whats the hash of your main.exe from offset A to offset B?" or "from now on packet type 0x07 swaps with packet type 0x5f". Once a fake is detected, server enter in a "silly mode", act malfunctional, and blacklist their IP/account to this mode for several hours so they cannot have sure of what their program is doing wrong.
If you detect someone is building an emulator, make them start all over again: jumble the packet type tables, cryptography tables, change some packet formats and force your clients to update. You won't see crackers bothering you for a while... LOL
WS-Security provides for X509 encryption.
Part of that implementation includes the possibility of only giving specific clients the generated public key. That way, only your selected clients can connect to the service.
The easiest way is message security using client and server certificates. The best way is to import the client certs in your server machines and hard code the client cert thumbprint in the app.config file. The other way is negotiation of certs which I haven't tried before.
If you are using IIS to host the service then client certificates using SSL is another option.
MSDN link on WCF Security.