Reputation: 31
I am having a tremendous difficulty implementing SSL in a basic java chat. I was able to do the server and the client as well, but when it comes to implementing ssl, it always crashes and I can not continue.
Where should I start to do the implementation next to my code? The code I'm showing here has a very simple graphical interface using swing.
ClientChat
package clientchat;
import javax.swing.JOptionPane;
import static javax.swing.JOptionPane.*;
public class ClientChat {
public static void main(String[] args) {
String nome = JOptionPane.showInputDialog(null, "Type your name: ", PLAIN_MESSAGE);
InterfaceChat chat = new InterfaceChat(name);
chat.setVisible(true);
}
}
Interface Client
package clientchat;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import static javax.swing.JOptionPane.ERROR_MESSAGE;
public class InterfaceChat extends javax.swing.JFrame {
private BufferedReader b;
private InputStreamReader i;
private String nome;
private Socket s;
public InterfaceChat(String nome) {
this.nome = nome;
try {
s = new Socket("127.0.0.1", 5000);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Não se conectou ao servidor", "", ERROR_MESSAGE);
System.exit(0);
}
initComponents();
Thread();
}
private void Thread(){
Thread t = new Thread(new Runnable() {
String mensagem;
@Override
public void run() {
try{
i = new InputStreamReader(s.getInputStream());
b = new BufferedReader(i);
while((mensagem = b.readLine())!= null){
mensagemRecebida.setText(mensagemRecebida.getText() + mensagem + "\n");
}
}catch(IOException e){
JOptionPane.showMessageDialog(null, "Erro na conexão com o servidor","",ERROR_MESSAGE);
}
}
});
t.start();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
mensagemRecebida = new javax.swing.JTextArea();
jScrollPane2 = new javax.swing.JScrollPane();
enviarMensagem = new javax.swing.JTextArea();
jButton1 = new javax.swing.JButton();
jButton2 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
mensagemRecebida.setColumns(20);
mensagemRecebida.setRows(5);
jScrollPane1.setViewportView(mensagemRecebida);
enviarMensagem.setColumns(20);
enviarMensagem.setRows(5);
enviarMensagem.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyPressed(java.awt.event.KeyEvent evt) {
enviarMensagemKeyPressed(evt);
}
});
jScrollPane2.setViewportView(enviarMensagem);
jButton1.setText("Enviar");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
jButton2.setText("Sair");
jButton2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton2ActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 312, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, 99, Short.MAX_VALUE)
.addComponent(jButton2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 252, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(layout.createSequentialGroup()
.addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButton2))
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)))
);
pack();
}// </editor-fold>
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String mensagem = nome + ": ";
try {
PrintStream ps = new PrintStream(s.getOutputStream());
mensagem += enviarMensagem.getText();
ps.println(mensagem);
ps.flush();
enviarMensagem.setText("");
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "Não conseguiu enviar a mensagem", "", ERROR_MESSAGE);
}
}
private void enviarMensagemKeyPressed(java.awt.event.KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
String mensagem = nome + ": ";
try {
PrintStream ps = new PrintStream(s.getOutputStream());
mensagem += enviarMensagem.getText();
ps.println(mensagem);
ps.flush();
enviarMensagem.setText("");
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "Não conseguiu enviar a mensagem", "", ERROR_MESSAGE);
}
}
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
try{
s.close();
System.exit(0);
}
catch(IOException e){
e.printStackTrace();
}
}
// Variables declaration - do not modify
private javax.swing.JTextArea enviarMensagem;
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTextArea mensagemRecebida;
// End of variables declaration
}
Server
import java.io.IOException;
import java.io.PrintStream;
import java.net.*;
import java.util.ArrayList;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
public class ServidorChat {
public static void main(String[] args) {
ArrayList<PrintStream> clientes = new ArrayList<>();
try{
SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket server = (SSLServerSocket) factory.createServerSocket(5000);
while(true){
SSLSocket sslsocket = (SSLSocket) server.accept();
//guarda o endereço dos clientes
clientes.add(new PrintStream(sslsocket.getOutputStream()));
Mensagem mensagem = new Mensagem(sslsocket, clientes);
}
}
catch(IOException e){
e.printStackTrace();
}
}}
Message Server
public class Mensagem {
private SSLSocket s;
private ArrayList<PrintStream> clientes;
public Mensagem(SSLSocket s, ArrayList<PrintStream> clientes) {
this.s = s;
this.clientes = clientes;
Thread();
}
private void Thread() {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
String mensagem = "";
try {
InputStreamReader i = new InputStreamReader(s.getInputStream());
BufferedReader b = new BufferedReader(i);
while ((mensagem = b.readLine()) != null) {
enviarMensagem(mensagem);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.start();
}
private void enviarMensagem(String mensagem) {
for (int i = 0; i < clientes.size(); i++) {
clientes.get(i).println(mensagem);
clientes.get(i).flush();
Server Error
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
at sun.security.ssl.InputRecord.handleUnknownRecord(InputRecord.java:710)
at sun.security.ssl.InputRecord.read(InputRecord.java:527)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:928)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:105)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at servidorchat.Mensagem$1.run(Mensagem.java:31)
at java.lang.Thread.run(Thread.java:745)
Upvotes: 0
Views: 380
Reputation: 310913
s = new Socket("127.0.0.1", 5000);
You created a plaintext connection, just as it says in the error message. You need
s = SSLSocketFactory.getInstance().createSocket("127.0.0.1", 5000);
After that everything should work, provided your server certificate is trusted by the client.
Upvotes: 1
Reputation: 21124
You will have to use SSLContext for this purpose. Check out the sample code which I implemented in one of my applications below. Client context means you become the client and call some back end. Server context means you accept the client requests.
public class SSLUtil {
private static String KEY_STORE_TYPE = "JKS";
private static String TRUST_STORE_TYPE = "JKS";
private static String KEY_MANAGER_TYPE = "SunX509";
private static String TRUST_MANAGER_TYPE = "SunX509";
private static String PROTOCOL = "TLS";
private static SSLContext serverSSLCtx = null;
private static SSLContext clientSSLCtx = null;
public static SSLContext createServerSSLContext(final String keyStoreLocation,
final String keyStorePwd)
throws KeyStoreException,
NoSuchAlgorithmException,
CertificateException,
FileNotFoundException,
IOException,
UnrecoverableKeyException,
KeyManagementException {
if (serverSSLCtx == null) {
KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE);
keyStore.load(new FileInputStream(keyStoreLocation), keyStorePwd.toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KEY_MANAGER_TYPE);
keyManagerFactory.init(keyStore, keyStorePwd.toCharArray());
serverSSLCtx = SSLContext.getInstance(PROTOCOL);
serverSSLCtx.init(keyManagerFactory.getKeyManagers(), null, null);
}
return serverSSLCtx;
}
public static SSLContext createClientSSLContext(final String trustStoreLocation,
final String trustStorePwd)
throws KeyStoreException,
NoSuchAlgorithmException,
CertificateException,
FileNotFoundException,
IOException,
KeyManagementException {
if (clientSSLCtx == null) {
KeyStore trustStore = KeyStore.getInstance(TRUST_STORE_TYPE);
trustStore.load(new FileInputStream(trustStoreLocation), trustStorePwd.toCharArray());
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TRUST_MANAGER_TYPE);
trustManagerFactory.init(trustStore);
clientSSLCtx = SSLContext.getInstance(PROTOCOL);
clientSSLCtx.init(null, trustManagerFactory.getTrustManagers(), null);
}
return clientSSLCtx;
}
}
Hope this helps. Happy coding !
Upvotes: 0