Trust a self signed certificate without a cer file? - java

So this mobile app I'm working on is primarily in flutter but I have some API callbacks in native Android and Swift that I would like to keep, however the thing is the actual api calls can be to custom servers. After realizing that Flutter cannot read manually installed user certificates on Android, I tried to figure out a way to do it like chrome and ask the user "Do you want to trust this certificate y/n", however I can't figure out a way to do it on Java.
On the flutter side, theres a callback part of HttpClient called badCertificateCallback, where if anywhere in the app a certificate is unsafe it will automatically refer to there no matter where the certificate is called, currently on the flutter side I have it set so that if the user trusts a certain link, it will trust that certificates information, is there something similar on Android I can do? Most of the other solutions I found wanted to either trust all certificates which isn't ideal or required the user to have a cer file somewhere.

You have several ways that you can go:
Either you add your self-signed certificate to your client's truststore.
Or you use your own certificate authority to sign the server's certificate signing request (CSR) and add that certificate authority's certificate to the truststore of your client. Even here you could decide to just add the server's certificate to the truststore directly, but then why did you use the CA?
Or you use an official certificate authority (let's encrypt, geocerts, digicert, ...) to sign the certificate. Since the official certificate authorities are already installed in your client's truststore, no additional step would be necessary.
Short answer: You will not succeed without a certificate. But it does not have to be a .cer file.
Since you are denying the 'no certificate check/trust all': checking certificates is the better way, even if you use a self-signed certificate. But the client needs something to check against, and that data usually is transported in certificates. You can store such a certificate in different file formats. Check this page: https://www.ssls.com/knowledgebase/what-are-certificate-formats-and-what-is-the-difference-between-them/

Related

Configure additional truststore in Spring Boot Tomcat Server

I have a spring boot client application and a server application. I am implementing MTLS client authentication part. I have a client certificate that is self signed and this needs to be added to a custom truststore in the server. Basically I am looking for a mechanism to add my custom truststore at runtime.
I want the default truststore and the custom truststore to be picked up. I implemented this using TomcatServletWebServerFactory but I did not have any luck. Can someone please help. I am looking for a programmatic solution.
I do not want to change the default java truststore. I still need that.
Since you do not want to replace the existing truststore with your custom one (that could be done by running the JVM with a few system properties) you need to add code that trusts a peer if the builtin or a custom trusttore approve the client.
For this you need to create and install your own Trustmanager. See an example here: https://community.oracle.com/tech/developers/discussion/1535342/java-ssl-trustmanager
If the checkClientTrusted and checkServerTrusted methods do not raise an exception the certificate is approved. Leaving the methods empty would even turn off any certificate validation - not to be recommended.
In order to establish a SSL connection with client certificates between a Spring client application and a Spring server application, there are a few things to note:
Involved Trust Stores
There are two very different trust stores relevant in this context:
The trust store used by the client to determine whether it can trust the server's SSL certificate. When using the java.net package for client requests, the trust store is configured via the JVM property "javax.net.ssl.trustStore" - see e.g. https://docs.oracle.com/javadb/10.8.3.0/adminguide/cadminsslclient.html
The trust store used by Tomcat (the underlying servlet container used by Spring Boot in its default configuration) to determine whether it shall trust a client. This is configured via the spring application property "server.ssl.trust-store" - see https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties.server.server.ssl.trust-store
In the context of a Spring server application the first one is relevant for connections which the server makes to a second server - so only when the server acts as client as well - e.g. when acting as a proxy server.
The second trust store is relevant for connections between the server and its clients. This is the one you need to deal with.
Certificates in the Tomcat Trust Store
The trust store which is used by Tomcat does NOT contain the client certificates. Instead, it must contain the certificate of the Certificate Authority who has signed the client certificate. So when using self-signed certificates, you need to install the CA certificate which you have generated on your own.
The big advantage of this is, that you do not need to change the server trust store, when you grant access to new clients.
The downside is, that you have to handle a certificate revocation. The CRL (certificate revocation list) is also stored in the trust store. See:
CRL Explained: What Is a Certificate Revocation List?
Merging the Default Trust Store and the Custom Trust Store
As now should be clear, this is not a good idea and would constitute a major security flaw, as it would allow any client which has a certificate signed by a CA in the default trust store (which can be easily obtained) to connect to the server. The server trust store must only contain those certificates which you use to sign your client certificates!
And there is no need to merge the two, as this are totally separate trust stores with totally different functions.
But, of course it is technically feasible to merge trust stores. This can all be done by keytool - see below.
Managing Trust Stores
Adding, deleting, exporting, listing, and printing certificates and CRLs can all be done via the Oracle command line tool "keytool", which is part of the OpenJDK. See
keytool Reference

Jetty - Dynamic MTLS

I was curious if anyone knew how to implement a Dynamic MTLS solution in Jetty? We have a use case where we need to do device authentication. We want each device to have a different client certificate for security reasons. Is there a way to dynamically pull and validate the server certificate with the one the client sent in? I was combing through the SslContextFactory and ServerConnector java classes, but could not quite figure out which method to override if I extended them. Any help would be greatly appreciated.
The canonical way would be for each device to have a certificate D signed with a server certificate SS.
Note that the server's signing certificate SS may be different (and typically is) from the server's domain certificate.
The server (or a similar authority that you control) emits signed certificates for new devices (a certificate Dn signed with SS).
Basically the server acts as a standard Certificate Authority.
Certificate SS need not to be signed by another authority, as long as it's trusted by the server (i.e. it's in the server TrustStore).
There is no need to extend any Jetty class, just use the standard PKI processes and tools, and then the only thing you need to do is to configure Jetty accordingly.
I would recommend deploying your own PKI and have server and devices certificated issued by your own authority. Simone's answer on using server certificate to sign clients will stop working if you change server certificate and you do not want server certificate with long validity.

SSL rules when client and server are hosted separately

I'm hosting a web game on github pages. It's a react app that connects to a websocket server (via wss) running off of a linux box in my living room. I've generated a self-signed certificate for the server, and github-pages already has a Let's Encrypt certificate by default. Presumably because the cert is self signed, the client refuses to connect to the "insecure" server and I am not prompted to install the certificate or anything, because the client does have it's own separate certificate. Would just buying a real certificate solve all my problems? Should I just host the website from the same server and figure out all the stuff associated with that (I realize this is probably the best answer)? What's the public opinion on having separate ssl certificates for client and server?
you can add your self signed certificate to your local truststore, but it's a little work and everyone connecting to your site would have to do it.
buying a certificate would solve this problem, because it is then signed by a trusted certificate authority which allows everyone to verify your servers identity.
on the other hand, if you move your ui to the self signed server too, the web browser will prompt (respectively warn) the user about the untrusted certificate and the user is about to say wether he wants to advance to the site or not. this would "solve" the problem too.
last, but not least. it's quite common to have ui and backend separated and therefore having separated certificates too, but not in such little applications. in a big environment definitely worth it, because it's a separation of concerns.

How should I go about authenticating an application via HTTP?

I'm making an application that requires it to be authenticated on startup with a "secret key" as defined in a configuration file. I can't have the app call to a database so I'm thinking I need to do a HTTP request, however I am not sure how I should go about doing this and how it can't be exploited.
I just need somewhere to start, thanks!
You can use SSL. Then to manage trusted certs, you can implement your own javax.net.ssl.X509TrustManager. You can use the javax.net.ssl.X509TrustManager to manage your .keystore file via standard Java mechanisms. The keystore will contain private keys.
From JavaDoc:
Instance of this interface manage which X509 certificates may be used to authenticate the >remote side of a secure socket. Decisions may be based on trusted certificate authorities, >certificate revocation lists, online status checking or other means.
Also note that:
TrustManagers are responsible for managing the trust material that is used when making trust
decisions, and for deciding whether credentials presented by a peer should be accepted.
If you extend the X509TrustManager, you can read in certificates your private .keystore file as well as certificates trusted by Java. Those live in JAVA_HOME\lib\security\cacerts

SSL and Tomcat using Java

I'm new to SSL connections so here goes my question.
I have a desktop Java program in a JAR file. This JAR sends sensitive information over the internet to a remote Tomcat server. Of course I need to encrypt the data.
If I purchase an SSL cerfiticate say from Verisign, will the data sent over SSL be automatically encrypted?
I mean in my JAR, will I still need to do extra work like use Java encryption extensions API to manually encrypt my data over the SSL connection?
Thank you.
I mean in my JAR, will I still need to do extra work like use Java encryption extensions API to manually encrypt my data over the SSL connection?
Encryption will be done for you (with the Java Secure Socket Extension). Just establish your connection using https://. Maybe have a look at HTTP Client for a higher level API.
By the way, the certificate goes on the server side (unless you want to do client-authentication too in which case, well, you'll need a client certificate too).
And yes, you could use a self-signed certificate but one of the benefits of using a certificate signed by a well known Certificate Authority (CA) like Verisign, Thawte, etc is that you won't have to add it to the trust store of the client VM (unless you disable the verification mechanism).
Follow the SSL Configuration HOW-TO on how to setup https.
If your goal is just to get the encryptian, you don't need to buy a certificate. You can make your own. Buying a certificate just creates the verification chain back to verisign (or whomever) to give users a warm fuzzy that you're really who you say you are.
SSLSocket should handle most of the work for you.
All data sent over SSL is by definition encrypted, you do not need to worry about encryption at all. Also, you do not need to by a certificate to achieve that: you can issue one on your own.
If you'll set up the SSL on Tomcat and send your data over HTTPS then the encryption will be done for you. But you don't actually need to purchase a certificate if you only need encryption for your data channel, you could generate a self-signed certificate. Have a look at this page http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html on how to configure SSL for Tomcat. But note that HTTPS can be configured not to use encryption at all (at least on Apache httpd).
To answer your question, SSL implementations automatically encrypt the data. You don't need to worry about using additional encryption routines.
It might be easiest to purchase an SSL certificate because SSL implementations provide easy certification authentication using common root certificates and provide a verification service. However, you could save some money by using a self-signed certificate.
Even with a self-signed certificate, it's important to validate the signature on the server certificate from the desktop application when you connect to the server. This will prevent man in the middle attacks.
You won't have to add your self signed certificate to the store because you should be able to disable the automatic verification mechanism and use your own.

Categories

Resources