So I'm wanting to set up an SSL server/client in Java, my knowledge with networking is not very good I've created normal servers/clients in java many times and wanted to up it and setup SSL so a user can't just send false packets to my client thinking its the server sending them.
I've looked up a few examples etc and came across this GitHub repo which shows a basic server with SSL encryption between the client and server and set it up in my IDE. Here is the repo: https://github.com/AlphaGarden/SSL-Client-Server
My question is why does the client and server use both certificates? Can't a user just get the certificates from the client and use them to decrypt the SSL? Also in the client there's 2 strings, password & password2... Am I supposed to hide these from the person using my client too? If not am I supposed to hide anything client sided from the user that could help them decrypt the SSL traffic and feed my client false information?
Just some basics to explain a SSL/TLS connection: Wkipedia https://en.wikipedia.org/wiki/Transport_Layer_Security, for TLS 1.2 RFC5246: https://www.rfc-editor.org/rfc/rfc5246 and for TLS 1.3 RFC8446 https://www.rfc-editor.org/rfc/rfc8446.
The basic principle for a secure connection is to use (each) a certificate on server and client's side and exchange them. The certificate itself is useless as it does not prove that you are whom you say to be. To get trust in the certificate the usual way is to "buy" a certificate from a Certificate Agency (CA) that checks your identity.
The CA's root certificate usually is known to today browsers and so the server and client certificate can get checked by the browser (client) and server against the CA's root certificate.
Let us see the code for the simple SSL Server & Client code. I'm for sure you noticed that the server and client are using "twisted" sources for the keystore and the truststore and therefore they need two (different) passwords to get access to the two stores:
SSLServer:
String password = "abcdefg";
InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("server/certificate-server.p12");
// TrustManagerFactory
String password2 = "aabbcc";
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX", "SunJSSE");
InputStream inputStream1 = ClassLoader.getSystemClassLoader().getResourceAsStream("client/certificate-client.p12");
SSLClient:
String password = "aabbcc";
InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("client/certificate-client.p12");
// TrustManagerFactory ()
String password2 = "abcdefg";
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX", "SunJSSE");
InputStream inputStream1 = ClassLoader.getSystemClassLoader().getResourceAsStream("server/certificate-server.p12");
What are the keystore and the truststore good for? The keystore holds the (own) private key (of server and client) and in the truststore (all) trusted certificates (usually the CA root certificates) are saved. To check the received certificate from the other party the server and client prove the certificate chain up to the root certificate from the CA.
But here is the problem - as the programs are using self signed certificates there is not "real" and saved root certificate available in the trust store. To get the programs to run without an user interaction ("do you trust this certificate ?") both provide use a truststore with the "approved" certifcates and all is running.
To your second question "Can't a user just get the certificates from the client and use them to decrypt the SSL" the answer is simple: YES. But when securing a communication only between "allowed" partners - how should e.g. the servers knows that the client is the real one and not an attacker? For that reason the client is sending a certificate as well that can get checked by the servers truststore.