Glassfish Https on Servlet without server delivering public keys? - java

Is it possible to create a HTTPS connection to a java-servlet with a static name (like https://.../logonServlet) so that only clients who already own the public key/certificate can access the servlet? I would like to prevent the server from delivering public certificates and refusing all other clients?
To my knowledge:
I read about the java keytool and the different stores (keystore (certs and private keys) and truststore (client side, public keys)). I am currently reading the book "Glassfish Security" by Masoud Kalali to learn about user groups and different security realms and stuff like different xml options for server configuration but I feel like I start mixing everything in my head so I would like to ask if you could help me with my desire from above.
A big question that is still open to me is "Why do we need certificates?". Shouldn't be a private key which will be kept secret enough and a public key for the clients?
#Edit
What you may want to check is SSL/TLS with client authentication. In this setup, the clients need a certificate and a private key as well. The server will refuse connections if they are not from a client with a trusted certificate. This means that server and client need both a keystore and a truststore.
Seems like you are correct, that is what I am looking for.

Asymetric cryptography works with two elements by design:
Public key: Shared with everybody, so they can know it's you who send the messages. Also to cipher messages that only can be read with the private key.
Private key: Only known to you, so you can guarantee that you are who send the messages. Also to read messages sent to you ciphered using your public key.
In a typical HTTPS setup, the server has the certificate (with a public key) and the private key, but the public part is shared with anyone who connects (you can see the certificate of any HTTPS site in the browser).
This is because usually, the client needs to know who the server is, but the server doesn't need to know who the user is (and if it does, other ways like passwords are cheaper and more convenient for the average user).
Sharing the server's public certificate is necessary for SSL/TLS to work, so there is no way to hide those keys and completing the handshake at the same time.
So no, the server's public key cannot be used to authenticate the clients, as it is assumed by design that everybody can get it.
What you may want to check is SSL/TLS with client authentication. In this setup, the clients need a certificate and a private key as well. The server will refuse connections if they are not from a client with a trusted certificate. This means that server and client need both a keystore and a truststore.
Note that keystore and truststore are conceptual terms. A single file (.jks, for example) can act as both, as it can contain private keys and public certificates at the same time. That said, they tend to be in different files.

Related

Https vs ssl pinning

I would like to know how does a regular SSL protocol differ from SSL pining. By setting up https, we are able to encrypt the request using SSL. Man in middle attack will not be able to see the raw payload. I also know SSL pinning is another way to prevent man in middle attack. But my question is if a proxy will always see the encrypted data only under https protocol, why do we still need to bundle certificate at client side and have SSL pinning? What advantage can SSL pining give us ?
Certificate pinning means the client has the server's certificate "built-in" and doesn't use your computer's trusted store. This means that even if your IT dept installs their own root cert, it won't be used.
A particularly clever IT department could install their root cert on your computer, use a proxy like Charles to create fake site certs on the fly, and re-write your downloaded program on the fly, replacing the pinned cert, but most aren't sophisticated enough to do that final step.
And you could probably just download the software from home too, in which case the pinned cert will be okay, and IT would never see the content on the transmissions.

Get certificate by alias in keystore with multiple entries in Java

Ok! We are trying to implement a client server aplication (chatroom) . Of course the server is multithreaded. We wanted the communication to be secure so we used ssl sockets and certificates. I have read that you can store multiple certificates and keys in one keystore. When a client enters the chat he needs to fill in his username.
Do we have to connect the username to the alias of the certificate/key?
If yes, how can we use the specific certificate/key from the keystore from the alias? Or is there another way? I mean how can we "pick" the specific certificate depending on the name
Is there a way for the clients to create their certificates at the time of they enter? (We want the certificates to be signed by a CA we have already implemented)
Thank you!
Basically what you want is Mutual or 2 way SSL. Read these for more information - here and here
In short - the SSL communication works (in context of certificates for authentication) is server will send the certificate to the client and if that certificate is present in the client's certificate store or Java's keystore in your case, then it authenticates the server.
Typically server never asks client to send certificate but in your case you wants it so it makes it Mutual or 2 way SSL. So, while handshake process, server will ask client also to send its certificate and it will also check in its keystore if that certificate is present, if so then it will be happy else it will end SSL handshake.
What you need:
Your each client and your server should have a valid certificate.
Your server should have those client certificate present in its "trust keystore", so that it can authenticate client.
Your each client should have server's certificate in its "trust keystore", so that it can authenticate server.
Your server should be configured to support 2 way SSL. Read here for Weblogic.
Answering your questions specifically:
Do we have to connect the username to the alias of the
certificate/key?
No, only this you want is that client certificate should present in the server's "trust keystore". But since your client app and server is on same machine, so I would recommend that have different JVM's installations to run client and server so that you have support different certificates.
If yes, how can we use the specific certificate/key from the keystore
from the alias? Or is there another way? I mean how can we "pick" the
specific certificate depending on the name
Not applicable.
Is there a way for the clients to create their certificates at the
time of they enter? (We want the certificates to be signed by a CA we
have already implemented)
Certificate should be prepared beforehand, and certificate creation and signing is a complex process, you have to generate a CSR etc.
Please do read my this answer for other details you may require while doing all this.

How SSL works in case of self signed certificates in Java

I am working on a HTTPS service which will be deployed on a server with a self signed certificate and a client which will accept all certificates.I am new to SSL.
I have gone through this post and this post and understand how to configure trust manager to accept all certificates.
If I understand correctly a java client will use server's public key(installed by using server's public certificate) to encrypt data to be sent to a server.And a server then uses it's private key to decrypt the data.
My questions are:
1.In a common scenario ,we install the server.cer in truststore of client machine(cacerts in java). How does the java client code links to this installed public key to encrypt data while communicating to such server? Who does the SSL encryption here? Is it Java APIs that do it or do i have to handle encryption in my client code before sending data to server?
2.As given in one of the above mentioned post ,we can make client accept all certificates.How will the encryption and decryption work in this scenario? How will the client know which public key to use for encryption as we are not installing any server specific key in client's truststore?
I am looking for more technical details.
I am working on a HTTPS service which will be deployed on a server with a self signed certificate and a client which will accept all certificates. I am new to SSL.
Clearly. You're working on an insecure system. It's a waste of time. You may as well not use SSL at all. The client should accept this certificate and all CA certificates, not all certificates. As described, your system is vulnerable to man-in-the-middle attacks.
If I understand correctly a java client will use server's public key(installed by using server's public certificate) to encrypt data to be sent to a server.
You don't. It doesn't. The certificate is used to authenticate the identity of the server, but SSL encryption is symmetric via a secretly negotiated session key and has nothing to do with the public key in the certificate.
And a server then uses it's private key to decrypt the data.
No.
How does the java client code links to this installed public key to encrypt data while communicating to such server?
Usually via the javax.net.ssl.trustStore property, but again it doesn't use that for encryption, only for authentication.
Who does the SSL encryption here? Is it Java APIs that do it
Yes. It is done by HttpsURLConnection using a javax.net.ssl.SSLSocket.
or do i have to handle encryption in my client code before sending data to server?
No.
As given in one of the above mentioned post ,we can make client accept all certificates.
You can, but it is radically insecure and should never be done that way.
How will the encryption and decryption work in this scenario? How will the client know which public key to use for encryption as we are not installing any server specific key in client's truststore?
See above, you have a misunderstanding here, but when you accept all certificates you have no idea who you're talking to, so any encryption is completely pointless anyway. Don't do this.

Handling password updates in Java SSL

I have a client-server java application, where communication happens over SSL. Right now I am generating keypairs by hand, but I need a programmatic system for key management.
The server maintains a user database, and on the client side I do not want to store a copy of the password. Somehow the client will log in to the server using a password. If the password is correct, the server and client will set up keys. From then on they can use those keys and not have to use the password. This brings me to my first question:
When the user enters the password the first time, how do I encrypt that transmission? Because there will be no keys and thus no SSL at this point.
Then there is the issue of the user changing their password. The idea is they will go through a web interface to change their password on the server. Then the next time a client connects, their old keys should not work and they should be asked to enter the new password. Which brings me to my next question:
What is the best practice for
handling the password change when
dealing with SSL?
I can just delete the server side key when they change their password. Then the client wont be able to communicate, and then I can have the client ask for a new password. But it seems a little kludgey.
While an SSL connection can authenticate the client using a client-side certificate, it's most often used only to authenticate the server and to create an encrypted connection between an identified server (by virtue of a certificate tied to a domain name), and an anonymous client.
To use client certificates the client must generate the PKCS key-pair, a certificate signing request and get it signed by an authority that the server trusts. Absent that process, authentication of the client is typically done be a protocol on top of SSL which requires some secret that only the client knows. This is typically a password, such as a good ol' website login.
Conversely, what you are describing is actually a machine generated ephemeral (out of thin air) password (these are often called "keys", but it's important that you understand it's really just a special password). That is, after an initial connection authenticated with a password typed by the user, you send the client an ephemeral password to store and use for subsequent connections.
To handle password change, you simply need to change your protocol to allow the ephemeral password. If it's not correct but the server has one, you might want to lock the account, assuming a hack attempt (though that can be a DoS opening). Otherwise, if it's not correct because the server has no ephemeral key (i.e. the server side has blanked it because the password was changed), then you simple send a response to the client to challenge the user for the current password. The user then enters the password, and assuming it matches, the server then generates and transmits a new ephemeral password.
EDIT: To clarify, even though your are generating PKCS key-pairs, without doing that client-side and binding them into a certificate, this is not client-side certificate authentication. It's merely a cryptographically strong machine generated ephemeral password.
And, beware, that at the end of the day, your system is only as strong as the initial password which caused the key-pair to be generated (or, subsequently, replaced).
You still can have SSL between client and server. In fact, you should.
The server won't be able to trust the client yet. Client can trust the server, because the server certificate is available to the client.
For example, look how most logins on web are implemented: you are not authenticated yet, but you're going into HTTPS. This is one-way SSL. Client is using a temporal key. Password is passed over the encrypted connection. This protects from eavesdropping.
When the mutual trust (through validation of the password) is established, you can pass client certificate over the same connection and reset the session. From that moment you'll have a two-way SSL, a mutual trust.
UPDATE
I see a bit of confusion in the thread due to not clear wording of "requirements". Let me write down the collaboration between client and server:
Session 1:
Client needs to talk to server
Client generates a temporal pair of private and public key
Client connects to server via SSL and passes public key to server for the session
Client receives server public key/certificate and compares it to one it knows a priori; bail out if mismatched.
One-way SSL connection has been established at this point; client knows for sure it talks to server, while server doesn't know the identity of the client. The connection is encrypted though.
Client passes in credentials (userid and password, likely).
Server validates them and bails out if they do not match.
Server now trusts the client is, say, John Smith from Nebraska.
Client asks server to store current public key as client permanent public key OR generates another key pair and sends the public one to server (I do not see a problem to use the same key, but I may be overlooking something).
End of session.
Session 2:
Client connects to server over SSL
Client provides its public key/certificate
Server compares it to the one stored on server side
Server provides its public key/certificate
Client compares it to the known one.
Mutual trust has been established, connection is encrypted, server knows the client is John Smith from Nebraska.
Still, to be on the safe side, server may still request John to enter the password.
Since using SSL for client authentication requires keys to already be shared, you have two choices: either don't use SSL to provide client authentication, or renegotiate after delivering the client certificate to the client.
In the first model, on first connection, the client first connects over SSL with no client auth, then issues a login command of some sort, and receives a session token. At that point, the server knows that the other party on that SSL connection is that particular user. If the client wishes to reconnect later, it just present that session token to authenticate itself at the start of that second connection (still over SSL, but not using client auth). In this model, revocation of sessions can be done by deleting the server's notion of the session.
In the second model, the the server responds to the login command by providing a client cert that it signs. From there, the client will renegotiate the connection using the new certificate. In this model, revocation can be done by using something akin to a certificate revocation list (keep this from growing too big by using moderate expirations on the certificates).

Opening SSL TCP socket and sending web requests

I have a requirement to open a tcp socket and authenticate using SSLv3 or TLSv1 IP protocol using X.509 digital certificate.
What does this handshake process involve exactly? I know the each message should be encrypted and signed with my private key. What else?
After successful I've to send POST HTTP requests over the socket.
The server may decide to close this socket if inactive after some time. I need to be able to re-open, authenticate and send requests again.
The certificate given to me is in PKCS12 format with the following information.
Certificate Identification
,Certificate Public Key
,Certificate Private Key
,Certification Authority Chain
I'm fairly new to SSL can someone please provide pointers to how to go about implementing this in java or spring integration.
A good start is to see the javax.net.ssl.HttpsURLConnection javadocs: http://download.oracle.com/docs/cd/E17476_01/javase/1.4.2/docs/api/javax/net/ssl/HttpsURLConnection.html
Also you gonna need to use the keytool command to import the certificate into a keystore.
You don't need to know about the handshake, it is all done for you. Read the JSSE Reference as suggested to see what you +do+ have to worry about.
Regarding TLS/SSL details, for client-certificate authentication, compared with the "normal" hanshake, the server sends an extra CertificateRequest TLS message to the client, which responds with its certificate in a subsequent Certificate TLS message (later on, the client sends a CertificateVerify TLS message where it signs the other messages with its private key, so as to prove to the server that it does indeed have the private key for the public key in the certificate it sent.) Note that, once the handshake has finished, the messages are not encrypted with your private key, but with ephemeral keys shared with the server (agreeing on those keys confidentially is part of the handshake too).
In practice, you need a certificate and its private key, contained in the PKCS#12 file (for example) and to configure the client to send it when connecting to the server (the server will ask for it according to its configuration).
It's easier to assume you'll only need one certificate and won't have to make a choice between a number of certificates, otherwise, you need to set up your own X509TrustManager within the SSLContext.
If all your connections are likely to use this certificate, you may use the default settings, which HttpsURLConnection (and the default SSLSocketFactory) will pick up.
This can be done by:
setting the javax.net.ssl.keyStore, javax.net.ssl.keyStoreType and javax.net.ssl.keyStorePassword system properties on the command line with your settings. I would recommend against that because someone else on the machine could potentially see the command line and your settings by listing the processes (depending on the configuration of the machine),
setting those system properties within your application,
initialising an SSLContext and setting it as the default one via SSLContext.setDefault(..) (Java 6).
Note that .p12 (PKCS#12) files are a supported keystore out of the box, so you don't need to do any conversion with keytool, just use PKCS12 as the store type.
If you need these settings or, you may initialise an SSLContext, create an SSLSocketFactory from it and then configure the instance of HttpsURLConnection (if that's what you're using) with setSSLSocketFactory.
(You may be able to use tools like jSSLutils to help build the SSLContext.)

Categories