Best approach to pass the public key from client to server - c#-4.0

I have a tcp server and using cms/pkcs#7 to secure the message passed between the client and server. Would it be normal practice to pass the clients public key to the server, as part of initial session? As its the public key, when the session starts up, the initial clp command, would pass the key, along with other salient details that the server needs to know about the client. It's the public, so it doesn't need to be encrypted, it public.
The client/server communication is secured with ssl/tls.
Thanks.
Bob.

Don't you trust SSL/TLS or why do you encrypt again within the secure channel? That only makes sense if the server will pass the message on to other nodes and it will be decrypted somewhere else, thereby creating end-to-end security.
In any case, you should not have the client pass just the public key to the server. Instead it should pass a certificate to the server, which should authenticate the client based on a signature made with the private key matching the public key contained in the certificate. Also, the server will need to check the certificate itself (is it from a trusted CA, do the signatures in the chain verify, etc.).
If you can, you should do all this on the SSL/TLS layer by using SSL/TLS mutual authentication (client cert authentication). If you cannot, then make sure you design a secure application layer protocol for authenticating the client and it's public key. Otherwise it may be possible to impersonate other clients.

Related

How to secure access token beyond XSS and CSRF

I understand the XSS vulnerability of using web storage and the CSRF vulnerability of using cookies. So I store the access token in memory and for persistence I have a refresh token in a cookie which I use to silently refresh my access token when we lose it. I feel somewhat better about XSS and CSRF threats... BUT how do we secure the token from a packet sniffer? A packet sniffer would find the token in the request. I see a lot of discussion on XSS and CSRF but how do we keep safe from packet sniffers, and are there even more threats we do not commonly think about?
You use HTTPS to defend against packet sniffers.
Fiddler as a proxy will not be able to decrypt HTTPS traffic in the cloud unless the fiddlers built in root certificate is added to the browser or client making the request.
Fiddler is able to decrypt HTTPS because you have added Fiddlers root certificate to your trusted store in YOUR computer. without this a proper HTTPS connections can't be made.
So , don't worry about Fidler in the cloud.
https provides an end to end encryption. Its implenented on the application level by browsers so no other users on the same network doesnt break https security.
The below is a short explanation of how ssl and https (http over ssl) works
Ssl:
The key idea is that mathematically you can generate a public key A and a private key B in a way that if you encrypt something with A you can only decrypt it with B.
So let's say the server google has a pair of public key A and private key B.
A client wants to send some data to google. The idea is if the client has key B he can encrypt the data he wants to send and he doesnt care anymore of network threats such as a man in the middle fishing the packet or data because only the owner of key B (google) can decrypt the data. So the man in the middle will only have encrypted data which has no use.
Note that from above it is clear that servers (google here) should keep their private key unshared, but should distribute their public key so that clients can use to communicate safely (with encryption) with the server.
How to distribute the public key ?
Using the public key infrastructure (PKI) which is a set of roles, entities, definitions, etc. used to manage and distribute public keys.
Again in short, a server request a certificate from a certificate authority (CA). That certificate contains information on the server (name, ip, etc.) And the public key and private key generated for that server (note here there are several procedures that a server might request to generate the keys, one of which is the server generates the private key and the CA only responsible for generating the public key).
Finally, there is a list of trusted CAs built into the browsers, so that these browsers such as chrome can go to and get google's public key A, and use it to encrypt the data it wants to send to google.
The above is how ssl communication protocol works (ssl certificates). Ssl is simply a protocol that provides secure communication. It provides no routing and networking capabilities.
Https:
Https is basically HTTP connection which is delivering the data secured using SSL.
That means SSL encrypted data will be routed using protocols like HTTP for communication.

Why does mutual SSL require a key pair on the client side instead of just a public certificate?

I'm doing my best to understand mutual SSL. One question I can't find a good answer to is why you need to create a key pair on the client instead of just providing a public client certificate.
So far I understand the following (very oversimplified):
Regular SSL:
The server has a key pair and sends the public part (certificate) so the client can use that public key to encrypt messages so they can share a symmetric key and eventually secure all communication.
To verify that the server is actually the server the issuer of the certificate has to be trusted (in a truststore) of the client by default.
Mutual SSL:
Exactly the same, only this time the server asks the client to authenticate itself.
The client sends its public certificate, which is verified against some kind of list of "known certificates" on the server. If it matches, communication can continue.
I don't understand why I have to include the entire key pair (the private part as well) in the key store I use on the client side. Where is the client's private key used in the process?
The server has a key pair and sends the public part (certificate) so the client can use that public key to encrypt messages so they can share a symmetric key and eventually secure all communication.
That's not the main point of the server certificate and with modern key exchange methods (i.e. Diffie-Hellman) the certificate is not involved at all in the key exchange. What you describe is only true for the obsolete RSA key exchange.
The main point of the certificate is to be used for authentication. Authentication means that the server proves that it owns the provided certificate and then that the client verifies that the certificate matches its expectations, i.e. issued by a trusted CA, expected subject/SAN, not expired etc.
The proof of ownership is done by signing some data (which is at least in part provided by the peer, i.e. client) with the private key matching the public key in the certificate. The peer (client) then can verify this signature using the public key of the certificate and if the verification passes the other side (server) is obviously in possession of the secret private key which means it owns the certificate.
With a client certificate used in mutual authentication the procedure is exactly the same, only with switched roles. That's why the private key is needed on the client side.

It is possible to copy the server certificate to attackers server to misuse it?

I aks myself if it is possible to copy the server certificate to another server to misuse it. Example: An attacker visits https website X and copies the X.509 certificate. He placed the stolen X.509 certificate on his own server and would like being trustworthy.
Of course, the attacker does not have the private key, but the private key is only required to decrypt the encrypted message from the client. In terms of authentification there is no reason to be doubtfully. Or?
The server responses with the X.509 certificate. The client receives the certificate and validates successfully using the stored root certificates. Why should the server not be authentificated? Only when the client sends an encrypted message using the public key the server is not able to decrypt the message - because he does not own the private key.
It is right so far?
Only when the client sends an encrypted message using the public key the server is not able to decrypt the message - because he does not own the private key.
The server also needs the private key to sign messages being sent to the client.
The SSL/TLS handshake protocol itself effectively involves such an authenticated message being sent to the client. If the private key is unavailable then this step will fail before any 'real' payload message gets sent.
Why should the server not be authentificated?
The certificate is tied to a domain name.
The web browser will download the certificate and validate it. One of the steps in the validation is to compare the domain the certificate is for to the domain that the browser actually downloaded it from. If there is a mismatch (and there will be, since the attacker is on their own domain, not the original site's domain) then the browser will present the user with a certificate error and ask them to make the call about whether or not to accept it.
You're probably used to seeing this in action on bad web server configurations. Ever seen an error saying, "This certificate was intended for www.example.com" when you were trying to visit "example.com"?
Of course, the attacker does not have the private key, but the private key is only required to decrypt the encrypted message from the client.
Public/private key pairs have other uses than that. In this case, the private key signs the certificate and the public key verifies it. There is no encryption involved. (What you described is more like a normal encryption scheme, like RSA.)
No, the certificate is a pubic element and it is just a way to bind a public key to a name (here, a DNS name). During the authentication process (in the TLS protocol) the server sends its certificate along with signs some data with the associated private key. In order to verify that the server is the legitimate owner of the certificate, the client have to verify the validity of this signature with the sent certificate. A rogue server can try to use the certificate but without the private key it cannot prove it is the real holder.

SSL encryption without validation (SSH Like)

I'm building a network authentication system in java.
I want to have my connection encrypted with SSL, so i use SSLServerSocket for it.
I've generated a keystore with keytool: (in ssl directory)
keytool -genkey -keystore myKeystore -keyalg RSA
Then in my Server class:
System.setProperty("javax.net.ssl.keyStore", "ssl/myKeystore");
System.setProperty("javax.net.ssl.keyStorePassword", "123456");
Then in my Client:
System.setProperty("javax.net.ssl.trustStore", "ssl/myKeystore");
System.setProperty("javax.net.ssl.trustStorePassword", "123456");
This works, but I can't rely on the client to make a keystore.
My aim is a SSH-like model: The client has a private key which it will send to the server, and the server verifies it using the public key.
Can't I use simple RSA key files instead of keystores?
You seem to be confusing a number of aspects here. Although SSH doesn't rely on SSL/TLS, theses concepts are indeed broadly similar.
What you've done by setting a truststore on your client matching the keystore on the server is making the client trust the server's public key (within its certificate).
This is the SSH equivalent of having pre-loaded trusted server keys fingerprints. Most SSH clients will learn the server's public key or its fingerprint when you establish the first connection (and you're meant to verify this fingerprint manually in principle): you could implement this with SSL/TLS in Java, this is more or less what Andreas Sterbenz's InstallCert does.
The aim of this is to allow the client to verify the server's identity (without which a MITM attack could be possible).
The client has a private key which it will send to the server, and the
server verifies it using the public key.
When the client has a private key (which it actually uses, but never sends to the server), it's only used for authenticating the client. The aim of this is to allow the server to verify the client's identity (as an alternative to password authentication, for example).
This can also be done with SSL/TLS using client-certificate authentication.
The main difference (protocol aside) between SSH and SSL/TLS in all this is that SSL/TLS tends to use X.509 certificates (which contain public keys and additional attributes describing the entity's identity), whereas SSH tends to use raw public keys directly. (There are extensions to SSH to use X.509 certificate there too, but they're rather uncommon.)
In both cases, the client will need to verify the server's identity to prevent MITM attacks. This is more conventionally done with SSL/TLS using a Public Key Infrastructure (and X.509 certificates), but you could also learn the key upon first connection, like SSH: this requires more work (you'd need a custom trust manager). A reasonable compromise (in a controlled environment) is to use a trust store on the client, pre-loaded with the server's certificate. This is more or less what you've already done, except that you should never give the server's private key away. You really shouldn't use the same keystore here, since the server's keystore will contain its private key: instead, export only the certificate and import it into a keystore which you'll use as trust store on the other side.

Secure client server channel

I'm building an application that needs to establish a secure connection between a client and a server, providing web services.
I need to guarantee authenticity for both (client and server), the server will also be handling the client authorization to access the data and files.
If thought to do it using an EKE-like algorithm to authenticate both, but these relies on a previously shared secret.
I could use the client password as the shared secret, but I would need to securely establish that password upon the client sign up, in this case I would need a secure channel, and authenticate the server (the client needs to know which server he is registering into).
I would rather avoid using a CA to provide certificates with the server public keys, because its a lot of extra code for just one small job, and it wouldn't be the best solution, because I would just have to trust the CA.
Ultimately this is to let the client send (client-)encrypted files to the server and share them.
Any alternatives that I'm missing out?
Tl;Dr How to stablish a secure client/server channel, authenticating the server, without CA, know public keys, or previous
SSL/TLS offers wide choice of authentication mechanisms, including pre-shared secrets, OpenPGP keys etc. So you can go for SSL and avoid reinventing the wheel.
Also you can sign and encrypt individual data messages (again using OpenPGP as a variant).

Resources