After reading the following, I'm still stuck on making the barest-minimum https://localhost stand-alone install-free webserver java app. It needs to be library-free, use Java 8, and accept connections from the browser without first installing any special client certs. I'm unclear if this is at all possible with self-signed certs because it only has to work for "localhost".
How make SSL server socket support both http & https in java?
My simple java HTTPS server only works for localhost
Simple Java HTTPS server
So far I've generated some key files using
openssl genrsa -aes128 -out privkey.pem 2048 # makes privkey.pem
openssl req -new -x509 -key privkey.pem # makes cert.crt
and I've cobbled together the bare minimum Kotlin setup function
private fun ssl():SSLServerSocketFactory {
val password = "MYPASSWORD".toCharArray()
val kmf = KeyManagerFactory.getInstance("SunX509")
val tmf = TrustManagerFactory.getInstance("SunX509")
val sslContext = SSLContext.getInstance("TLS")
// initialise the keystore
KeyStore.getInstance("JKS").let { ks->
FileInputStream("lig.keystore").use {
ks.load(it, password)
}
kmf.init(ks, password)
tmf.init(ks)
}
// setup the HTTPS context and parameters
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null)
return sslContext.serverSocketFactory
}
ssl().createServerSocket().use { serverSocket ->
serverSocket.reuseAddress = true
serverSocket.bind(InetSocketAddress(port))
logger.info { "WebServer ready and listening on ${serverSocket.localPort}" }
But I'm having trouble how to finish it off: Do I need to make a lig.keystore file? Can this even be done without installing certs on the client's browser?
There are two common approaches to getting a secure connection between a client (browser) and server via HTTPS:
You can obtain SSL certificate for the server that is signed by a Root Certification Authority (CA) that is trusted by the user's web browser by default.
You can generate a self-signed SSL certificate, and have the user import it into their web browser as a trusted cert.
What you have done so far seems to be to generate a server-side keystore with a self-signed cert in it and (more or less) configured the Kotlin server to use it. The problem is the client (browser). There is no safe way to get the browser to trust the self-signed cert without the involvement of the user or the user's sysadmin. (Safe ... as in safe for the user!)
And no legitimate CA should ever issue an SSL cert for "localhost"; e.g. https://www.ssl2buy.com/wiki/how-to-get-ssl-certificate-for-web-applications-that-runs-on-localhost
Impasse.
OK, so lets step back. The purpose of using HTTPS / SSL is to ensure that:
The user's web browser is talking to the correct server, and not some other server that is impersonating it.
The connection between the browser and the server is encrypted so that no third party can snoop on the traffic.
But you are trying to do this for a localhost connection. The localhost IP address is a loopback address. Unless the OS kernel is compromised, you are guaranteed that network packets sent via a loopback connection will not leave the host.
You can dismiss the "impersonation" problem. Assuming that the user's machine has not been compromised, nobody else can launch a "fake" server on the user's machine.
You can dismiss the "snooping" problem. Assuming that the user's machine has not been compromised:
The packets won't go off-host, so they can't be snooped on any "external" networks.
The only person who can "snoop" the packets on the loopback network is the user him / herself.
So, the solution is simple. Use "http" for your "localhost" connection. It should be secure ... assuming that the user's machine has not been compromised.
Note: if the user's machine has been compromised, then the bad guys have other ways to intercept the traffic that SSL won't protect against.
Another specific case:
I'm facing a web app from https that would load local data at http://localhost
Safari web browser blocks because of unsecure communication (http) in a secure flow (https).
This behavour could be discussed, but in that case self signed certificate for localhost would help., even with a warning from Safari browser.
Related
I have a server that is sending an HTTPPost request with the Apache HttpClient in Java. I am trying to send the post with my cert attached for validation and the other side is saying they are not receiving anything SSL information. I inherited this code/server setup with minimal documentation so I don't necessarily know it was set up properly in the first place.
Here is the setup.
AWS EC2 server. Linux
Elastic Load balancer setup with SSL Cert.
a. Verified this is working as intended when I visit the server via port 443
Tomcat7 running API server
Java 1.8.0_251
Apache httpclient-4.5.9
Being that there are ways to attach the certificate to each level of this I don't fully understand where the problem is.
Most of the ways I have found revolve around attaching the SSL to the outgoing request in the httpclient object but have been unsuccessful. They are a variation on the following...
KeyStore identityKeyStore = KeyStore.getInstance("JKS");
identityKeyStore.load(identity_file, CERTPASSWORD.toCharArray());
SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial(identityKeyStore, CERTPASSWORD.toCharArray()).build(); // load client certificate
sslConnectionSocketFactory = new SSLConnectionSocketFactory(
sslContext,
new String[]{"TLSv1.2", "TLSv1.1"},
null,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
This has not worked and I have verified the .jks file is properly formatted and verified the password. Although if this works as I test on a windows machine I would assume this would be the best option.
This server only has outgoing requests to a few sources all of which will need to be SSL verified so I don't mind if it is sent on every outgoing https request.
Is there somewhere else in my setup that I should be looking into attaching the certificate?
If there is a Load balancer with SSL configured then the SSL stops at the load balancer, and your client certificate is never making it to the server. Client SSL certificates only get passed to the server when the server has an SSL certificate installed on it, and the load balancer is in TCP passthrough mode.
I am using the Bot Connector REST API and am having trouble with the Kik channel. When I try to respond to a message, I am receiving this error:
javax.net.ssl.SSLException: hostname in certificate didn't match: <kik.botframework.com> != <*.azurewebsites.net> OR <*.azurewebsites.net> OR <*.scm.azurewebsites.net> OR <*.azure-mobile.net> OR <*.scm.azure-mobile.net>
The service URL I am using is "https://kik.botframework.com".
I am running this off of a local server at the moment. I did not have any trouble connecting with the Skype channel in this configuration, but Kik is giving me trouble.
I don't exactly have a solution, but I can explain what is the reason behind this and what you may have to double check on your side.
So, in short, this is happening because of SNI (Server Name Indication) and because of the client's inability to support SNI.
Check this answer for some insight into this issue https://serverfault.com/questions/594368/openssl-returns-different-ssl-certificate-to-that-shown-by-chrome
In this case, the same IP is hosting a bunch of domains and certificates. Most of the modern browsers support SNI and will be able to detect this and show you the right certificate (try firefox).
However, when the SSL client of a server is trying to do a handshake (without specifying 'server name'/'host name') it doesn't know which certificate to fetch, and hence fetches the core certificate.
Solution?
The client should 'indicate' that this is the host name and then it'll fetch the right certificate.
Example:
openssl s_client -connect dev.botframework.com:443
VS
openssl s_client -servername dev.botframework.com -connect dev.botframework.com:443
How to Solve this?
Skip the host name verification phase. Disabling SSL Certificate Validation in Spring RestTemplate or another Example:
Registry<ConnectionSocketFactory> registry = RegistryBuilder. <ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", new SSLConnectionSocketFactory(SSLContexts.createDefault(), new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
})).build();
The problem ended up being that the version of the HttpClient library being used my server is fairly old (4.2.5) and did not support Server Name Indication. I was able to patch it to support SNI as per here: Server Name Indication (SNI) Support. Thanks to Arka for pointing out what the issue likely was.
I have a java project that requires us to use a mutual authentication certificate. Our code is supposed to communicate with the server with a given ip address
socket = new Socket("00.000.000.000", 0002);
Since the our code is communicating with the remote system:-
If i create a self signed a certificate in my machine(pc) that is not connected to the internet 24/7 will mutual authentication work if i use this cert
If i generate a certificate using Letsencrypt, will will mutual authentication work. I plan to generate the Letsencrypt certificate in my digital ocean droplet.
If i create a self signed a certificate in my machine(pc) that is not connected to the internet 24/7 will mutual authentication work if i use this cert
Only if the peer trusts it. The Internet connection part is irrelevant. You will need to export your self-signed certificate to the peer and have them import it into their truststore.
If i generate a certificate using Letsencrypt, will will mutual authentication work. I plan to generate the Letsencrypt certificate in my digital ocean droplet.
It will work if the peer's truststore trusts LetsEncrypt's certificate.
the underlying issue is, will mutual authentication always work with self signed certificate signed from an ordinary PC
No, see above.
or will it work when signed by a recognized authority
Yes.
In general you should avoid self-signed certificates. They aren't worth the paper they're printed on.
So i am developing an app which uses a rest connection to a database server. This server uses TLS encryption and has a SSL certificate. Im using OkHttp3.2 to manage my server connection. I can connect to the server without any problems and also encryption works fine.
My question is based on the certificate tester from java's SSL Engine. I can readout everything the Server send about the certificate (Serial, Signature...) but i cant see any information about validation or trust level like a certificate chain.
Does the SSL Engine tests the Certificate independently or do i have to do this manually?
And would OkHttp's certificate pinning do the Job?
And how would i readout the SHA checksum of the certificate like some ssl tester do? e.g. ssllabs.com
So Thanks to Pravin's comment i think i know everything i need.
If someone is intrested a little conclusion of the article:
Android's SSL Engine checkes validity of the Certificate at every Request. The Certificate is compared with trustet root certificates in local system storage (Settings -> Security -> Trusted credentials).
Certificate pinning would add a second security level, in fact it checkes if a certificate in the certificate-chain has a fringerprint which is equal to your setting. Usefull if you would only want to allow a certifiace of a specified provider to communicade with your app.
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.