📄 chat.java
字号:
/*
Chat program
last update 14th September 2006
uses RSA to exchange an AES session key
things to do:
don't use PORT+1 for file transmission
file send/receive gauge
option for local addr/port
better handling of disconnects/errors
about box
*/
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
public class chat extends Applet implements ActionListener, KeyListener, WindowListener
{
/** frame to run the applet in if run from command line */
static JFrame appletFrame;
/** properties file */
Properties props = new Properties();
/** name of properties file */
protected static final String PROP_FILENAME = "chat.properties";
/** buttons */
Button btnConnect, btnListen, btnDisconnect, btnSendFile, btnReceiveFile, btnGenerateRSAkey;
/** text fields */
TextField txtRemoteMachine, txtPort, txtMessage, txtTimeout, txtRSAkeyLength, txtAESKeyLength;
/** main area showing details of conversation and any errors */
TextArea txtConversation;
/** socket to remote machine */
Socket remoteSocket;
/** thread that listens for incoming messages */
listener incomingDataListener;
/** input stream for receiving data from remote machine */
BufferedInputStream in;
/** output stream for sending data to remote machine */
BufferedOutputStream out;
/** encryption manager to handle all encryption/decryption */
encryptionManager encMan = new encryptionManager(this);
/** flag indicating whether we are connected or not */
boolean connected;
/** a file being transmitted to the remote machine */
sendFile outFile;
/** a file being received from the remote machine */
receiveFile inFile;
/** transfer buffer size to use when transmitting/receiving files */
int BUFFER_SIZE = 65535;
/** entry point if class is run as an application */
public static void main(String args[])
{
// create the frame this applet will run in
appletFrame = new JFrame("Crypto chat program");
Applet myApplet = new chat();
myApplet.init();
myApplet.start();
appletFrame.getContentPane().add(myApplet);
appletFrame.setResizable(true);
appletFrame.setSize(800,550);
appletFrame.addWindowListener((WindowListener)myApplet);
appletFrame.show();
}
/** adds a gui component to the grid */
private void addToGrid(Panel p, Component c, int x, int y)
{
GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = x;
gridBagConstraints.gridy = y;
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.insets = new Insets(5, 2, 5, 2);
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
p.add(c, gridBagConstraints);
}
/** adds a gui component to the grid */
private void addToGrid(Panel p, Component c, int x, int y, int xWeight, int yWeight)
{
GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = x;
gridBagConstraints.gridy = y;
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.insets = new Insets(5, 0, 5, 0);
gridBagConstraints.weightx = xWeight;
gridBagConstraints.weighty = yWeight;
p.add(c, gridBagConstraints);
}
/** applet initialisation */
public void init()
{
setLayout(null);
readPropertiesFile();
setLayout(new GridBagLayout());
createInputsPanel();
createButtonsPanel();
createMessagesPanel();
}
private void createInputsPanel()
{
Panel pnlInputs = new Panel();
pnlInputs.setLayout(new GridBagLayout());
GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
gridBagConstraints.insets = new Insets(2, 5, 5, 2);
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
add(pnlInputs, gridBagConstraints);
// label for remote machine name
Label lblServerName = new Label("Remote machine");
addToGrid(pnlInputs, lblServerName, 0, 0);
// remote machine name
txtRemoteMachine = new TextField((String)props.get("peerAddress"));
addToGrid(pnlInputs, txtRemoteMachine, 1, 0);
// label for port
Label lblPort = new Label("Port");
addToGrid(pnlInputs, lblPort, 2, 0);
// port
txtPort = new TextField((String)props.get("port"));
addToGrid(pnlInputs, txtPort, 3, 0);
// label for timeout
Label lblTimeout = new Label("Timeout");
addToGrid(pnlInputs, lblTimeout, 4, 0);
// timeout
txtTimeout = new TextField((String)props.get("timeout"));
addToGrid(pnlInputs, txtTimeout, 5, 0);
// label for RSA key length
Label lblRSAkeyLength = new Label("RSA key length");
addToGrid(pnlInputs, lblRSAkeyLength, 0, 1);
// RSA key length
txtRSAkeyLength = new TextField((String)props.get("RSAKeyLength"));
addToGrid(pnlInputs, txtRSAkeyLength, 1, 1);
// label for AES key length
Label lblAESKeyLength = new Label("AES key length");
addToGrid(pnlInputs, lblAESKeyLength, 2, 1);
// AES key length
txtAESKeyLength = new TextField((String)props.get("AESKeyLength"));
addToGrid(pnlInputs, txtAESKeyLength, 3, 1);
}
private void createButtonsPanel()
{
Panel pnlButtons = new Panel();
pnlButtons.setLayout(new GridBagLayout());
GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.insets = new Insets(5, 0, 5, 0);
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
add(pnlButtons, gridBagConstraints);
// button for connecting to remote machine
btnConnect = new Button("Connect");
btnConnect.addActionListener(this);
addToGrid(pnlButtons, btnConnect, 0, 0);
// button for listening for remote machine
btnListen = new Button("Listen");
btnListen.addActionListener(this);
addToGrid(pnlButtons, btnListen, 1, 0);
// button for disconnecting
btnDisconnect = new Button("Disconnect");
btnDisconnect.addActionListener(this);
addToGrid(pnlButtons, btnDisconnect, 2, 0);
// button for sending file
btnSendFile = new Button("Send file");
btnSendFile.addActionListener(this);
addToGrid(pnlButtons, btnSendFile, 3, 0);
// button for receiving file
btnReceiveFile = new Button("Receive file");
btnReceiveFile.addActionListener(this);
addToGrid(pnlButtons, btnReceiveFile, 4, 0);
// button to generate new RSA key
btnGenerateRSAkey = new Button("Generate key");
btnGenerateRSAkey.addActionListener(this);
addToGrid(pnlButtons, btnGenerateRSAkey, 5, 0);
}
private void createMessagesPanel()
{
Panel pnlMessages = new Panel();
pnlMessages.setLayout(new GridBagLayout());
GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 2;
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.insets = new Insets(5, 0, 5, 0);
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 5.0;
add(pnlMessages, gridBagConstraints);
Label lblMessage = new Label("Enter message to send & press <Return>");
addToGrid(pnlMessages, lblMessage, 0, 0, 1, 1);
// message to send to the remote machine
txtMessage = new TextField();
txtMessage.addKeyListener(this);
addToGrid(pnlMessages, txtMessage, 0, 1, 1, 1);
// all messages between both machines
txtConversation = new TextArea(10,60);
txtConversation.setEditable(false);
addToGrid(pnlMessages, txtConversation, 0, 2, 1, 10);
// set connected state
setConnected(false);
}
/** reads the properties file */
private void readPropertiesFile()
{
// look for one in current directory
try
{
props.load(new FileInputStream(PROP_FILENAME));
// get hidden properties
BUFFER_SIZE = Integer.parseInt((String)props.get("bufferSize"));
rsa.privateKey.PRIME_PROBABILITY = Integer.parseInt((String)props.get("primeProbability"));
}
catch (Exception e)
{
// never mind, this must be the first time the user has run the application
// set all default properties
props.put("port", "1701");
props.put("peerAddress", "");
props.put("RSAKeyLength", "1024");
props.put("AESKeyLength", "256");
props.put("timeout", "60");
// hidden properties
props.put("primeProbability", "100");
props.put("bufferSize", String.valueOf(BUFFER_SIZE));
}
}
/** window event handler */
public void actionPerformed (ActionEvent anEvent)
{
// make connection
if (anEvent.getSource() == btnConnect)
connect();
// listen for incoming connection
if (anEvent.getSource() == btnListen)
listen();
// disconnect
if (anEvent.getSource() == btnDisconnect)
disconnect();
// send file
if (anEvent.getSource() == btnSendFile)
sendFile();
// receive file
if (anEvent.getSource() == btnReceiveFile)
receiveFile();
// generate RSA key
if (anEvent.getSource() == btnGenerateRSAkey)
generateRSAkey();
}
/** connect to the remote machine */
private void connect()
{
try
{
// inform user connection being attempted
log("Attempting to contact " + txtRemoteMachine.getText());
// open a socket to the server
remoteSocket = new Socket(txtRemoteMachine.getText(), new Integer(txtPort.getText()).intValue());
// inform user connection made
log("Established connection with " + remoteSocket.getInetAddress().getHostName() + " (" + remoteSocket.getInetAddress().getHostAddress() + ")");
// create the input/output streams
initStreams(false);
}
catch(Exception e)
{
reportException("connect()", e);
}
}
/** listen for incoming connection */
private void listen()
{
// make sure we have generated a private key
encMan.ensurePrivateKeyExists();
try
{
// create a server socket
ServerSocket listenSocket = new ServerSocket(new Integer(txtPort.getText()).intValue(), 1);
try
{
// set timeout
listenSocket.setSoTimeout(new Integer(txtTimeout.getText()).intValue() * 1000);
// inform user we are listening for a connection
log("Listening on port " + txtPort.getText().trim() + "...");
// accept an incoming connection
remoteSocket = listenSocket.accept();
// inform user connection received
log("Received connection from " + remoteSocket.getInetAddress().getHostName() + " (" + remoteSocket.getInetAddress().getHostAddress() + ")");
// set remote machine textbox
txtRemoteMachine.setText(remoteSocket.getInetAddress().getHostName());
// create the input/output streams
initStreams(true);
}
finally
{
// close the listener socket
listenSocket.close();
}
}
catch(Exception e)
{
reportException("listen()", e);
}
}
/** creates the input & output streams on the socket */
private void initStreams(boolean server) throws IOException, ClassNotFoundException, java.security.InvalidKeyException
{
in = new BufferedInputStream(remoteSocket.getInputStream());
out = new BufferedOutputStream(remoteSocket.getOutputStream());
// initialise the exchange of keys
if (server)
{
// generate private key
log("Transmitting public key");
encMan.initialiseHandshaking(in, out);
log("Public key transmission complete");
}
else
{
// set the size of the AES key & wait for the RSA key to arrive
encMan.RijndaelKeySize = Integer.parseInt(txtAESKeyLength.getText());
encMan.RijndaelKeySize = encMan.RijndaelKeySize - (encMan.RijndaelKeySize % 8); // ensure multiple of 8, discard any excess
log("Receiving remote public key");
encMan.waitForHandshaking(in, out);
//log("Received remote public key of " + encMan.getRemotePublicKeyLength() + " bits");
}
// create a new listener
incomingDataListener = new listener(this);
incomingDataListener.setPriority(Thread.MIN_PRIORITY);
incomingDataListener.start();
// inform user connection closed
log("** HANDSHAKING COMPLETED **");
// set connected state
setConnected(true);
}
/** transmit a message to the remote machine */
private void transmitMsg()
{
// send the message
sendString(txtMessage.getText());
// display the line of text
log("YOU: " + txtMessage.getText());
// reset the message box
txtMessage.setText("");
}
/** sends a line of text to the remote machine */
protected void sendString(String s)
{
try
{
// encrypt the string using AES
String cipherText = encMan.encryptWithRijndael(s);
// transmit the encrypted text
ObjectOutput outStream = new ObjectOutputStream(out);
outStream.writeObject(cipherText);
outStream.flush();
}
catch (IOException e)
{
reportException("Error sending text", e);
}
}
/** reads a line of text from the remote machine */
protected String readString()
{
String plainText = null;
try
{
// read the encrypted text
ObjectInputStream inStream = new ObjectInputStream(in);
String cipherText = (String)inStream.readObject();
// decrypt it using AES
plainText = encMan.decryptWithRijndael(cipherText);
}
catch (Exception e)
{
reportException("Error reading text", e);
}
return plainText;
}
/** logs a message */
public void log(String s)
{
txtConversation.append("\r\n" + s);
// System.out.println(s);
}
/** disconnect from remote machine */
private void disconnect()
{
// send a disconnect message to the remote machine
sendString(listener.DISCONNECT);
// kill the listening thread
incomingDataListener.setState(listener.STOP);
// the listener thread closes the streams so we don't need to do it here
}
/** closes the input & output streams */
protected void closeStreams()
{
try
{
out.close();
in.close();
remoteSocket.close();
}
catch(Exception e)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -