iud_key_imp10/Quellcodes/iud_key_rsachat/ChatClient.java
2024-12-29 14:26:34 +01:00

658 lines
20 KiB
Java

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
import java.awt.image.BufferedImage;
import java.math.BigInteger;
/**
*
* Beschreibung
*
* @version 1.1 vom 30.01.2020
* @author Thomas Schaller
* Version 1.1: Hash-Funkion ausgetauscht, damit Hashes unterschiedlicher. , Ö/P-Schlüssel in der gleichen Farbe
*/
public class ChatClient extends JFrame implements MySocketListener {
//
protected int HOEHE = 60;
// Anfang Attribute
protected JPanel jPanel1 = new JPanel(null, true);
protected JLabel jLabel2 = new JLabel();
protected JTextField jTFName = new JTextField();
protected JTextField jTFAdress = new JTextField();
protected JLabel jLabel3 = new JLabel();
protected JButton jBVerbinden = new JButton();
protected JLabel jLabel1 = new JLabel();
protected JNumberField jNFPort = new JNumberField();
protected JTextField jTFNachricht = new JTextField();
protected MySocket client = null;
protected JLabel jLabel5 = new JLabel();
protected JScrollPane jScrollPane1 = new JScrollPane();
protected JScrollPane jScrollPane2 = new JScrollPane();
protected JPanel jp;
protected ArrayList<Nachricht> nachrichten;
protected ArrayList<Key> keys;
protected ArrayList<String> kontakte;
protected Key dragKey = null;
protected JLabel jLabel4 = new JLabel();
protected GridBagLayout gbl;
protected int keyColor = 0;
private JLabel jLabel6 = new JLabel();
// Ende Attribute
public ChatClient(String title) {
// Frame-Initialisierung
super(title);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
addWindowListener(new WindowListener() {
public void windowActivated(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
public void windowClosing(WindowEvent e) {
if (client != null) {
client.sendeNachricht("exit");
client.trenneVerbindung();
} // end of if
}
public void windowDeactivated(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowIconified(WindowEvent e){}
public void windowOpened(WindowEvent e){}
});
int frameWidth = 1081;
int frameHeight = 683;
setSize(frameWidth, frameHeight);
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int x = (d.width - getSize().width) / 2;
int y = (d.height - getSize().height) / 2;
setLocation(x, y);
setResizable(false);
Container cp = getContentPane();
cp.setLayout(null);
// Anfang Komponenten
jPanel1.setBounds(8, 8, 1041, 41);
jPanel1.setOpaque(false);
jPanel1.setBorder(BorderFactory.createBevelBorder(1, Color.WHITE, Color.DARK_GRAY));
cp.add(jPanel1);
jLabel2.setBounds(264, 11, 62, 20);
jLabel2.setText("Server");
jPanel1.add(jLabel2);
jTFName.setBounds(80, 11, 150, 20);
jTFName.setText("anonymous");
jPanel1.add(jTFName);
jTFAdress.setBounds(312, 11, 150, 20);
jTFAdress.setText("localhost");
jPanel1.add(jTFAdress);
jLabel3.setBounds(496, 11, 62, 20);
jLabel3.setText("Port");
jPanel1.add(jLabel3);
jBVerbinden.setBounds(936, 8, 99, 25);
jBVerbinden.setText("Verbinden");
jBVerbinden.setMargin(new Insets(2, 2, 2, 2));
jBVerbinden.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
jBVerbinden_ActionPerformed(evt);
}
});
jPanel1.add(jBVerbinden);
jLabel1.setBounds(8, 12, 62, 18);
jLabel1.setText("Name");
jPanel1.add(jLabel1);
jNFPort.setBounds(528, 11, 75, 20);
jNFPort.setText("44444");
jPanel1.add(jNFPort);
jLabel5.setBounds(8, 64, 62, 20);
jLabel5.setText("Schlüssel");
cp.add(jLabel5);
keys = new ArrayList<Key>();
JPanel jp2 = new PicPanel(keys);
jp2.setToolTipText("");
jScrollPane2 = new JScrollPane(jp2);
jScrollPane2.setBounds(96, 64, 953, 57);
jp2.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent evt) {
keyCached(evt);
}
public void mouseReleased(MouseEvent evt) {
keyDropped(evt);
}
});
cp.add(jScrollPane2);
jLabel4.setBounds(8, 144, 86, 20);
jLabel4.setText("Nachrichten");
cp.add(jLabel4);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
ChatClient_WindowClosing(evt);
}
});
jLabel6.setBounds(816, 624, 229, 20);
jLabel6.setText("(cc) 2020, Thomas Schaller, Version 1.1");
jLabel6.setForeground(Color.GRAY);
cp.add(jLabel6);
// Ende Komponenten
jTFNachricht.setBounds(10, 20, 358, 20);
jTFNachricht.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
jTFNachricht_ActionPerformed(evt);
}
});
Random ran = new Random();
nachrichten = new ArrayList<Nachricht>();
kontakte = new ArrayList<String>();
kontakte.add("alle");
jp = new JPanel();
jScrollPane1 = new JScrollPane(jp);
jScrollPane1.setBounds(96, 136, 953, 481);
jScrollPane1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
jp.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent evt) {
keyMessageCached(evt);
}
public void mouseReleased(MouseEvent evt) {
keyMessageDropped(evt);
}
});
cp.add(jScrollPane1);
gbl = new GridBagLayout();
jp.setLayout(gbl);
this.updateNachrichtenListe();
setVisible(true);
} // end of public ChatClient
// Anfang Methoden
public void jBVerbinden_ActionPerformed(ActionEvent evt) {
String a = jTFAdress.getText();
int p = jNFPort.getInt();
if (client != null && client.isAktiv()) {
jTFName.setEnabled(true);
jTFAdress.setEnabled(true);
jNFPort.setEnabled(true);
jBVerbinden.setText("Verbinden");
client.sendeNachricht("exit");
client.trenneVerbindung();
} else {
client = new MySocket(a, p, this);
if (client.isAktiv()) {
jTFName.setEnabled(false);
jTFAdress.setEnabled(false);
jNFPort.setEnabled(false);
jBVerbinden.setText("Trennen");
client.sendeNachricht(("user:"+jTFName.getText()+":alle"));
}
} // end of if-else
} // end of jBVerbinden_ActionPerformed
public byte[] appendOther(byte[] a1, byte[] a2){
byte[] a3 = new byte[a1.length + a2.length];
System.arraycopy(a1, 0, a3, 0, a1.length);
System.arraycopy(a2, 0, a3, a1.length, a2.length);
return a3;
}
public void jBSend_ActionPerformed(ActionEvent evt) {
if (client != null && client.isAktiv()) {
JMyButton button = (JMyButton) evt.getSource();
Nachricht n = button.getNachricht();
n.setEmpfaenger((String) button.getEmpfaenger().getSelectedItem());
String b = "mess:"+n.getAbsender()+":"+n.getEmpfaenger()+":"+Base64.encode(n.getInhalt())+":"+Base64.encode(n.getHashCode());
client.sendeNachricht(b);
this.updateNachrichtenListe();
} else {
jTFName.setEnabled(true);
jTFAdress.setEnabled(true);
jNFPort.setEnabled(true);
jBVerbinden.setEnabled(true);
} // end of if
} // end of jBSend_ActionPerformed
public void generateKeyPair(int bits) {
RSA rsa = new RSA(bits);
rsa.generateKey();
int c = keyColor;
addKey(rsa.getPublicKey());
keyColor = c;
addKey(rsa.getPrivateKey());
}
public void addKey(Key k) {
boolean schonda = false;
for (Key kk : keys) {
if (kk.getN().equals(k.getN()) && kk.getE().equals(k.getE())) {
JOptionPane.showMessageDialog(this,
"Dieser Schlüssel entspricht dem schon vorhandenen Schlüssel "+kk.getName(),
"Achtung",
JOptionPane.WARNING_MESSAGE);
break;
} // end of if
} // end of for
k.setImage("key"+keyColor);
keyColor = (keyColor+1)%10;
keys.add(k);
jScrollPane2.repaint();
}
public void showPublicZertKey() {
Key k = RSA.getPublicKeyZert();
addKey(k);
}
public void signKey(Key k) {
Key nk = new Key(k.getName()+"(z)",k.getE(),k.getN());
nk.sign(RSA.getPrivateKeyZert(),jTFName.getText());
nk.setImage(k.getFilename()+"s");
keys.add(keys.indexOf(k)+1,nk);
jScrollPane2.repaint();
}
public void deleteKey(Key k) {
keys.remove(k);
jScrollPane2.repaint();
}
public void neuerClient(MySocket client) {
}
public void nachrichtEmpfangen(MySocket client) {
String s = client.holeNachricht();
String[] ss = s.split(":");
if (ss[0].equals("user")) {
kontakte.add(ss[1]);
Nachricht n = new Nachricht("Server","alle","Neuer User: "+ss[1]);
n.setSended(true);
nachrichten.add(0,n);
this.updateNachrichtenListe();
}
if(ss[0].equals("mess")) {
String hash;
if (ss.length==5) {
hash = ss[4];
} else {
hash = "";
}// end of if
Nachricht n = new Nachricht(ss[1],ss[2],Base64.decode(ss[3]),Base64.decode(hash));
nachrichten.add(0,n);
this.updateNachrichtenListe();
} // end of if
}
public void verbindungBeendet(MySocket client) {
jTFName.setEnabled(true);
jTFAdress.setEnabled(true);
jNFPort.setEnabled(true);
jBVerbinden.setText("Verbinden");
client = null;
}
public void jTFNachricht_ActionPerformed(ActionEvent evt) {
Nachricht n = new Nachricht(jTFName.getText(),"", jTFNachricht.getText());
jTFNachricht.setText("");
nachrichten.add(0,n);
this.updateNachrichtenListe();
jTFNachricht.requestFocus();
} // end of jTFNachricht_ActionPerformed
public void keyCached(MouseEvent evt) {
Key k = null;
if (evt.getX()>10 && evt.getX()< keys.size()*32+10) {
int k_nr = (int) ((evt.getX()-10) /32);
k = keys.get(k_nr);
}
if (evt.getButton() == evt.BUTTON1) {
if (k != null) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
dragKey = k;
Cursor c = toolkit.createCustomCursor(dragKey.getImage() , new Point(0, 0), "img");
setCursor (c);
}
} else {
new KeyPopup(evt,this, k);
} // end of if
}
public void keyDropped(MouseEvent evt) {
GridBagConstraints c = new GridBagConstraints();
Point p = evt.getPoint();
Point pp = SwingUtilities.convertPoint(jScrollPane2, p, jScrollPane2.getParent());
Point pp2 = SwingUtilities.convertPoint(jScrollPane2, p, jScrollPane1);
if (pp2.getY()>0 && pp2.getY() < jScrollPane1.getHeight() && pp2.getX()>=0 && pp2.getX() < jScrollPane1.getWidth() && dragKey!=null) {
Point ppp = SwingUtilities.convertPoint(jScrollPane2, p, jp);
Component cc = jp.getComponentAt(ppp.x,ppp.y);
GridBagLayout gbl = (GridBagLayout) jp.getLayout();
c = gbl.getConstraints(cc);
int n_nr = c.gridy-1;
if (n_nr == -1) {
Nachricht n;
if (dragKey.isSigned()) {
n = new Nachricht(jTFName.getText(),"",dragKey.toString(jTFName.getText()).getBytes(),dragKey.getHashCode());
} else {
n = new Nachricht(jTFName.getText(),"",dragKey.toString(jTFName.getText()));
} // end of if-else
nachrichten.add(0,n);
this.updateNachrichtenListe();
}
if (n_nr >= 0 && n_nr < nachrichten.size() && c.gridx==1) {
byte[] klar = nachrichten.get(n_nr).getInhalt();
if (dragKey.calcBlocksize()<klar.length) {
JOptionPane.showMessageDialog(this,
"Die Nachricht ist zu lang für diesen Schlüssel. Es können nur "+dragKey.calcBlocksize()+" Zeichen verschlüsselt werden.",
"Fehler",
JOptionPane.WARNING_MESSAGE);
} else {
// end of if
byte[] krypt = dragKey.encrypt(klar);
Nachricht n = nachrichten.get(n_nr).copy();
n.setInhalt(krypt);
n.addKey(dragKey);
nachrichten.add(n_nr+1,n);
this.updateNachrichtenListe();
}
}
if (n_nr >= 0 && n_nr < nachrichten.size() && c.gridx==2) {
byte[] klar = nachrichten.get(n_nr).getHashCode();
if (dragKey.calcBlocksize()<klar.length) {
JOptionPane.showMessageDialog(this,
"Der Schlüssel ist zu kurz für diesen Hashcode. Es können nur "+dragKey.calcBlocksize()+" Zeichen verschlüsselt werden.",
"Fehler",
JOptionPane.WARNING_MESSAGE);
} else {
// end of if
byte[] krypt = dragKey.encrypt(klar);
Nachricht n = nachrichten.get(n_nr).copy();
n.setHashCode(krypt);
n.addHashKey(dragKey);
nachrichten.add(n_nr+1,n);
this.updateNachrichtenListe();
}
}
}
dragKey = null;
Cursor dc = new Cursor(Cursor.DEFAULT_CURSOR);
setCursor (dc);
} // end of jLabel5_MouseClicked
public void keyMessageCached(MouseEvent evt) {
Point p = evt.getPoint();
Point pp = SwingUtilities.convertPoint(jScrollPane1, p, jp);
GridBagLayout gbl = (GridBagLayout) jp.getLayout();
Component cp = jp.getComponentAt(evt.getX(),evt.getY());
GridBagConstraints gbc = gbl.getConstraints(cp);
System.out.println(evt.getY());
if (evt.getButton() == evt.BUTTON1 && gbc.gridx == 1) {
if (gbc.gridy-1< nachrichten.size() && gbc.gridy-1 >= 0) {
int n_nr = gbc.gridy-1;
String[] teile = nachrichten.get(n_nr).getInhaltString().split(",|=");
if (teile[0].equals("Key:Name")) {
BigInteger e = new BigInteger(teile[3]);
BigInteger n = new BigInteger(teile[5]);
dragKey = new Key(teile[1],e,n) ;
dragKey.setImage("key"+keyColor);
Toolkit toolkit = Toolkit.getDefaultToolkit();
Cursor c = toolkit.createCustomCursor(dragKey.getImage() , new Point(0, 0), "img");
setCursor (c);
} // end of if
}
} // end of if
if (evt.getButton() == evt.BUTTON3 && gbc.gridx == 1) {
int n_nr = gbc.gridy-1;
makeMessagePopup(evt,nachrichten.get(n_nr));
} // end of if
}
protected void makeMessagePopup(MouseEvent evt, Nachricht n) {
new MessagePopup(evt, this, n);
}
public void keyMessageDropped(MouseEvent evt) {
Point p = evt.getPoint();
Point pp = SwingUtilities.convertPoint(jp, p, jScrollPane2);
if (pp.getY()>0 && pp.getY() < jScrollPane2.getHeight() && pp.getX()>=0 && pp.getX() < jScrollPane2.getWidth() && dragKey!=null) {
this.addKey(dragKey);
}
dragKey = null;
Cursor dc = new Cursor(Cursor.DEFAULT_CURSOR);
setCursor (dc);
} // end of jLabel5_MouseClicked
public void updateNachrichtenListe() {
//jp.setBounds(jScrollPane1.getViewport().getBounds());
GridBagConstraints c = new GridBagConstraints();
while (jp.getComponentCount()>1) {
jp.remove(1);
} // end of while
//jp.removeAll();
if (jp.getComponentCount()==0) {
JPanel eingabe = new JPanel();
eingabe.setBorder(BorderFactory.createBevelBorder(0));
eingabe.setLayout(null);
eingabe.setBackground(new Color(250,255,200));
eingabe.setOpaque(true);
eingabe.setPreferredSize(new Dimension(150,HOEHE));
c.gridx=0; c.gridy = 0;
c.gridwidth=5;
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
jTFNachricht.setBounds(100,20,800,20);
JLabel nn = new JLabel();
nn.setText("Neue Nachricht");
nn.setBounds(2,20,90,20);
eingabe.add(nn);
eingabe.add(jTFNachricht);
jp.add(eingabe,c);
} // end of if
c.weightx=0;
c.gridwidth=1;
int xx = 1;
JLabel name = null;
for (Nachricht n : nachrichten) {
if (n.getKeys().size()>0 && name != null) {
GridBagConstraints c2 = gbl.getConstraints(name);
c2.gridheight++;
gbl.setConstraints(name,c2);
} else {
name = new JLabel();
name.setText("<html>Von "+n.getAbsender()+"</html>");
name.setBorder(BorderFactory.createBevelBorder(0));
name.setBackground(new Color(250,255,200));
name.setOpaque(true);
c.gridx=0; c.gridy = xx;
c.fill = GridBagConstraints.BOTH;
jp.add(name,c);
} // end of if-else
JPanel nnn = new JPanel();
nnn.setLayout(new GridBagLayout());
nnn.setBorder(BorderFactory.createBevelBorder(0));
nnn.setBackground(new Color(250,255,200));
nnn.setOpaque(true);
PicPanel pp = new PicPanel(n.getKeys());
pp.setPreferredSize(new Dimension(n.getKeys().size()*32,HOEHE));
pp.setBackground(new Color(250,255,200));
JMyLabel nachricht = new JMyLabel(n,"");
if (n.getInhaltString().trim().length()>65) {
nachricht.setText("<html>"+n.getInhaltString().trim().substring(0,62)+"...</html>");
} else {
nachricht.setText("<html>"+n.getInhaltString().trim()+"</html>");
} // end of if-else
c.gridx=0; c.gridy = 0;
c.weightx=1.0; c.weighty= 0;
nnn.add(nachricht,c);
c.gridx=1; c.gridy = 0;
c.weightx=0.0; c.weighty= 0;
nnn.add(pp,c);
c.gridx=1; c.gridy = xx;
c.weightx = 1.0;
jp.add(nnn,c);
nnn = new JPanel();
nnn.setLayout(new GridBagLayout());
nnn.setBorder(BorderFactory.createBevelBorder(0));
nnn.setBackground(new Color(250,255,200));
nnn.setOpaque(true);
pp = new PicPanel(n.getHashKeys());
pp.setPreferredSize(new Dimension(n.getHashKeys().size()*32,HOEHE));
pp.setBackground(new Color(250,255,200));
String hc = new String(n.getHashCode());
if (hc.trim().length()>15) {
hc = hc.substring(0,15)+"...";
} //end of if-else
JMyLabel hash = new JMyLabel(n, hc);
c.gridx=0; c.gridy = 0;
c.weightx=1.0; c.weighty= 0;
nnn.add(hash,c);
c.gridx=1; c.gridy = 0;
c.weightx=0.0; c.weighty= 0;
nnn.add(pp,c);
c.gridx=2; c.gridy = xx;
c.weightx = 0.0;
jp.add(nnn,c);
JPanel abspanel = new JPanel();
abspanel.setPreferredSize(new Dimension(150,HOEHE));
abspanel.setBorder(BorderFactory.createBevelBorder(0));
abspanel.setBackground(new Color(250,255,200));
abspanel.setOpaque(true);
abspanel.setLayout(new FlowLayout());
if (n.getEmpfaenger().equals("")) {
String[] stringlist = new String[100];
JComboBox cb = new JComboBox(kontakte.toArray(stringlist));
abspanel.add(cb);
ImageIcon water = new ImageIcon("arrow.png");
JMyButton button = new JMyButton(n, cb, water);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
jBSend_ActionPerformed(evt);
}
});
abspanel.add(button);
} else {
abspanel.add(new JLabel("an "+n.getEmpfaenger()));
}
c.gridx=4; c.gridy = xx;
c.weightx = 0.0;
jp.add(abspanel,c);
xx++;
}
JPanel dummy = new JPanel();
dummy.setBorder(BorderFactory.createBevelBorder(0));
dummy.setLayout(null);
dummy.setBackground(new Color(250,255,200));
dummy.setOpaque(true);
dummy.setPreferredSize(new Dimension(150,HOEHE));
c.gridx=0; c.gridy = xx;
c.gridwidth=5;
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
c.weighty = 1.0;
jp.add(dummy,c);
jp.revalidate();
jp.repaint();
}
public void ChatClient_WindowClosing(WindowEvent evt) {
// TODO hier Quelltext einfügen
} // end of ChatClient_WindowClosing
// Ende Methoden
public static void main(String[] args) {
new ChatClient("ChatClient");
} // end of main
} // end of class ChatClient