I have this:
SSLSocketFactory factory = HttpsURLConnection.getDefaultSSLSocketFactory();
SSLSocket socket = (SSLSocket) factory.createSocket("www.verisign.com", 443);
This is failing on the 2nd line with a "Connection refused" error.
Now, would I have to install verisign's certificate in my trust store before I can even do the above? I was under the impression that I could connect to an SSL server and execute getPeerCertificates() to get the certificates. Is this not what our browsers do? Otherwise how would they know which signing authority to use?
(Obviously I'm using Verisign as an example. My real URL is far too fugly to use here...)
Connection refused means nothing was listening at the target host:port, or a firewall got in the way. This is logically and temporally prior to anything SSL does.
Have you checked that the remote service is actually up and running, and that you can connect to it? Perhaps the "Connection refused" error is actually a refused connection. :-)
Usually you don't need to install server's certificate on your computer explicitly. PKI works in the way that your system should be able to validate server's certificate without any prior knowledge about it. However this will work only when your server's certificate has it's roots in on of the "known CAs", i.e. certificate authorities, whose root or other certificates are already listed on the client system. If this is not the case (eg. you have a self-signed or some other custom certificate on the server), you really need to install the certificate on your client system before the mentioned classes can validate server certificate properly.
You can read about certificates and how they are used in SSL here.
Related
this question might sound I bit dummy but I have researched many questions/answers here and can't find the answer for my case.
Currently I am using RestTemplate library to make HTTP requests for my java library that I am currently working on. In order to have successful HTTP call to HTTPS URLs i needed to add a SSL configuration for my HTTP client. Something like this:
clientBuilder
.disableCookieManagement()
.setDefaultRequestConfig(requestConfig)
.setSSLSocketFactory(new SSLConnectionSocketFactory(SSLContexts.custom()
.loadTrustMaterial(null, new TrustSelfSignedStrategy())
.build()));
So this library is supposed to be shipped to the user as a jar executable application and I know that using self-signed SSL certificates is not a good idea for general usage since there might have web servers that do not acknowledge it. I read that If I get a signed SSL certificate then I should save the proper keys on Keystore and also use Trustore to acknowledge the server's certificate. I do not think I can just pass Keystore and Trustore to the client who executes my java library, so my question here is, does Java has a built-in SSL certificate, so I could somehow just do some configuration on HTTP client and the built-in certificates would be used. As far as I know, node.js offers something like that.
Could anyone just give me a explanation of how this works for java spring-boot?
There are two separate certificate verifications that could be happening. To connect to a server using https, you need to receive the server's certificate and validate it using a truststore.
In addition, it is possible for you to have a client certificate, and to pass that to the server so it can authenticate your client. Unless you have been told you need to do that, you don't. Unless the server has been specifically configured to do it, it isn't possible. If it is what you need to do, you need to obtain a client certificate, install it into a keystore and use that keystore in your client.
So for normal https, you do not need a keystore.
Whether you need "TrustSelfSignedStrategy" depends on the server.
If the server has a valid signed SSL certificate, you do not need to do anything special, RestTemplate will just work.
If the server has a self-signed certificate, you need to either configure the client to accept any self-signed certificate, or load the server's certificate into a truststore so the client knows to accept that specific certificate.
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.
I'm trying to write a service in Grails to send push notifications to update passbook passes. I got to the point where I could test to see if the code to connect to the APN server was working, however, I cannot seem to establish a connection using the Java SSLSocket methods.
The first part of the connection works, I receive the certificate from the server and find a trusted certificate in the certificate chain; however, after that, for some reason my client certificate / certificate chain is not ever sent to the server, and hence the connection fails.
I can't seem to figure out why the certificate is not being sent, I use the following code to set up the keystore:
void setupSSLPropertiesForConnection() {
System.setProperty("javax.net.ssl.keyStore", "superSecretFile.p12")
System.setProperty("javax.net.ssl.keyStorePassword", "superSecretPassword")
System.setProperty("javax.net.ssl.keyStoreType", "PKCS12")
System.setProperty("javax.net.ssl.trustStore", "trustStoreFile")
System.setProperty("javax.net.ssl.trustStorePassword", "trustStorePassword")
System.setProperty("javax.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol")
}
and then to try and connect to the APN server:
setupSSLPropertiesForConnection()
SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault()
SSLSocket socket = (SSLSocket)factory.createSocket("gateway.push.apple.com", 2195)
I've looked at the PKCS12 file using Java's keytool and there is only one alias, which contains the entire certificate chain for my passbook certificate (certificate, WWDR, Apple Certificate), so I'm stuck on why the certificate isn't being sent when it's requested. Any help as to why it's not sending the certificate information would be muchly appreciated!
Edit: Also, if someone were to post a method of getting a SSL certificate from a .p12 used to sign passes or simply from the passbook certificate downloaded from the iOS dev portal, that is known to work, then I might be able to work backwards from that to figure out what it is I'm doing wrong.
Now I feel silly, apparently the filenames for my client PKCS12 file and the trust store file were both wrong, but in setting the keystore and truststore using the System.setProperty, it doesn't throw any error if the files cannot be found or opened.
I tried changing my code so that I am creating SSLSocketFactory from an SSLContext created with a TrustManagerFactory and a KeyManagerFactory, and when I tried that it threw FileNotFoundError. Now it seems to be working at least. Sigh.
I'm working on a Server and Client based app which require two way SSL authentication. (Client authenticates server and Server authenticate client both using SSL Certificates.)
I'm quite new to Netty and have few doubts regarding this.
Is two way authentication possible using Netty?
Can it be simply achievable by adding another SslHandler to the pipelinefactories of both server and client?
If the above is true, how can I grab the required SslHandler at the ChannelConnected() method to do the SslHandshake? And Is it possible to invoke the second handshake at the ChannelConected() method by calling the pipeline back again?
Are there any examples I could refer to regarding this?
I really appreciate any help regarding this, answers or a push in right direction.
Is two way authentication possible using Netty?
Yes
Can it be simply achievable by adding another SslHandler to the pipelinefactories of both server and client?
Yes
If the above is true, how can I grab the required SslHandler at the ChannelConnected() method to do the SslHandshake?
You need the setup the keystore and the truststore correctly when creating your SSLContext.
And Is it possible to invoke the second handshake at the ChannelConected() method by calling the pipeline back again?
From memory, client and server authentication is done in the 1st handshake.
On the client, install the client's private key in the keystore and the server's public key in the truststore.
On the server, install the server's private key in the keystore and the client's public key in the truststore.
Are there any examples I could refer to regarding this?
Here's an example I did for websockets. It only shows you how to setup the server keystore. You will have to add a truststore as the 2nd parameter of serverContext.init(kmf.getKeyManagers(), null, null);
Here's a similar example in Scala with trust store setup.
Here's a good java guide on how to setup SSLContext.
Hope this helps.
Two way authentication requires that both server and client have certificates that the other trusts. The client needs to generate a private key, store it in his keystore, and get it signed by somebody that the server's truststore trusts.
It isn't just a matter of what code you write.
SSL is a presentation layer protocol and the SSL handshake happens right after the socket connection is established and the before the application layer gets a usable socket connection. No matter what application you are using, if you have the SSL protocol layer in place then you can work over SSL.
Two way authentication is just a matter of configuration as mentioned by #EJP above. If both the parties can establish and validate each other trust chain then the handshake succeeds. Refer the netty configuration manual for configuring SSL truststores.
I have an app that runs on GlassFish 3.x. It communicates to a remote server over https. In my cacerts file I've added the server certs. In my keystore.jks I added the private key the company running the remote server issued me. This works great on Glassfish 2.x, however on 3.x they remote server keeps complaining that the key I have is invalid.
If I remove the key from the keystore I get the same error. It's as if it's not even loading the key, which has got me wondering how does the app / container know which key I need
My connection code looks like this:
public class SSLSocket {
private static Logger logger = LoggerFactory.getLogger(SSLSocket.class);
private ConnectionProperties connectionProperties;
public TuSSLSocket(ConnectionProperties connectionProperties) {
this.connectionProperties = connectionProperties;
}
public SSLSocket getSSLSocket() throws Exception{
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) factory.createSocket(connectionProperties.getHost(), connectionProperties.getPort());
socket.setSoTimeout(90000);
return socket;
}
}
I set the Host and Port accordingly, but no where do I say go look for this alias in the keystore. So... how does the app know what alias to grab?
Explaining two way ssl and all that jazz is exhausting. I will try to find a useful link. However, for your information when an applicaiton deployed in glassfish acts as a client to communicating with a server over SSL ( for instance LDAP server realm configured through an SSL port), it will use glassfish server's identity certificate (from its keystore) as its client certificate.
But if you are explicitly coding for SSL handshake, client application is responsible for selecting the keystore, and presenting the certificate as part of the handshake.
Since it is working in a previous version of Glassfish, the same code should work for you. It is very likely that your problem is related to configuration. I am a bit confused about what you had added to server's keystore.jks generally the other server's certificate is added to the trust store cacerts.jks
A useful glassfish ssl example
An SSL Socket client example
Example of choosing keystore in client.
There are two ways to accomplish this
The first:
Open the following path from the admin console page.
configuration
your cluster/instance configuration.
jvm settings
jvm options
you will find this line some where in the list of items
-Dcom.sun.enterprise.security.httpsOutboundKeyAlias=s1as
Change the s1as value to the certificate alias you want to use.
The other option is to add a system property to your code
System.setProperty("com.sun.enterprise.security.httpsOutboundKeyAlias", "your certificate alias");