Note that there are some explanatory texts on larger screens.

plurals
  1. POCannot send AES encrypted messages of over 47 characters
    primarykey
    data
    text
    <p>Ello mates! I am creating an AES encrypted chat program but have ran into an issue; Whenever a message is over 47 characters, it displays "javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher". I understand the error message but I can't seem to figure out how to fix it. Here is my FULL code: ChatClient.java package Chat.Application;</p> <pre><code>import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.text.*; import java.security.*; import java.util.logging.Level; import java.util.logging.Logger; import javax.crypto.*; import javax.crypto.spec.SecretKeySpec; import sun.misc.*; import java.net.InetAddress; /* * Known Bugs: * Message size is limited to 47 characters */ public class ChatClient { BufferedReader in; PrintWriter out; JFrame frame = new JFrame("ELECTRON Chatroom"); JTextField textField = new JTextField(32); JTextArea messageArea = new JTextArea(8, 40); byte[] keyValue = new byte[]{'5', '7', '3', '4', '5', '6', '3', '4', '9', '8', '5', '6', 'l', '9', '3', '4'}; final String ALGO = "AES"; String name; String myName; InetAddress ip = null; String errorType; /* * Constructs the client by laying out the GUI and registering a listener * with the textfield so that pressing Return in the listener sends the * textfield contents to the server. Note however that the textfield is * initially NOT editable, and only becomes editable AFTER the client * receives the NAMEACCEPTED message from the server. */ public class JTextFieldLimit extends PlainDocument { private int limit; // optional uppercase conversion private boolean toUppercase = false; JTextFieldLimit(int limit) { super(); this.limit = limit; } JTextFieldLimit(int limit, boolean upper) { super(); this.limit = limit; toUppercase = upper; } public void insertString (int offset, String str, AttributeSet attr) throws BadLocationException { if (str == null) return; if ((getLength() + str.length()) &lt;= limit) { if (toUppercase) str = str.toUpperCase(); super.insertString(offset, str, attr); } } } public ChatClient() { // Layout GUI textField.setEditable(false); messageArea.setEditable(false); messageArea.setWrapStyleWord(true); messageArea.setLineWrap(true); frame.getContentPane().add(textField, "North"); frame.getContentPane().add(new JScrollPane(messageArea), "Center"); frame.pack(); // Add Listeners textField.addActionListener(new ActionListener() { /** * Responds to pressing the enter key in the textfield by sending * the contents of the text field to the server. Then clear the text * area in preparation for the next message. */ @Override public void actionPerformed(ActionEvent e) { try { if ((textField.getText()).startsWith("/")) { if ("Electron".equals(myName)) { String command = (textField.getText()); out.println(command); textField.setText(""); } } else { //ENCRYPTION String encrypt = textField.getText(); Key key = generateKey(); Cipher c = Cipher.getInstance(ALGO); c.init(Cipher.ENCRYPT_MODE, key); byte[] encVal = c.doFinal(encrypt.getBytes()); String input = new BASE64Encoder().encode(encVal); out.println(input); textField.setText(""); } } catch (Exception ex) { Logger.getLogger(ChatClient.class.getName()).log(Level.SEVERE, null, ex); } } }); } /** * Prompt for and return the address of the server. */ private String getServerAddress() { return JOptionPane.showInputDialog( frame, "Enter IP Address of the Server:", "ELECTRON Chatroom", JOptionPane.QUESTION_MESSAGE); } /** * Prompt for and return the desired screen name. */ private String getName() { return JOptionPane.showInputDialog( frame, "Choose a screen name:", "Screen name selection", JOptionPane.PLAIN_MESSAGE); } /** * Connects to the server then enters the processing loop. */ private void run() throws IOException { // Make connection and initialize streams String serverAddress = getServerAddress(); Socket socket = new Socket(serverAddress, 9001); in = new BufferedReader(new InputStreamReader( socket.getInputStream())); out = new PrintWriter(socket.getOutputStream(), true); // Process all messages from server, according to the protocol. while (true) { String line = in.readLine(); if (line.startsWith("SUBMITNAME")) { if (line.length() == 18) { line = line.substring(11); System.out.println(line); switch (line) { case "ERROR 1": errorType = "[ERROR: Name cannot be blank]"; JOptionPane.showMessageDialog(frame, errorType); System.exit(0); break; case "ERROR 2": errorType = "[ERROR: Your names 'Admin'? Seems legit...]"; JOptionPane.showMessageDialog(frame, errorType); System.exit(0); break; case "ERROR 3": errorType = "[ERROR: You have been banned]"; JOptionPane.showMessageDialog(frame, errorType); System.exit(0); break; } } else if (line.length() == 10) { out.println(getName()); } } else if (line.startsWith("NAMEACCEPTED")) { myName = line.substring(13); if (myName == "Admin") { errorType = "[ERROR: Your names 'Admin'? Seems legit...]"; JOptionPane.showMessageDialog(frame, errorType); System.exit(0); } else if (myName == "ADMIN") { errorType = "[ERROR: Your names 'Admin'? Seems legit...]"; JOptionPane.showMessageDialog(frame, errorType); System.exit(0); } else if (myName == "admin") { errorType = "[ERROR: Your names 'Admin'? Seems legit...]"; JOptionPane.showMessageDialog(frame, errorType); System.exit(0); } JOptionPane.showMessageDialog(frame, "Welcome " + myName + " (" + ip + ")"); ip = InetAddress.getLocalHost(); textField.setEditable(true); //Limits message length to 47 characters (Disabled for debugging purposes) //textField.setDocument(new JTextFieldLimit(47)); out.println(ip); } else if (line.startsWith("SERVERMESSAGE")) { line = line.substring(14); messageArea.append(line + "\n"); messageArea.setCaretPosition(messageArea.getDocument().getLength()); } else if (line.startsWith("SERVERCOMMAND")) { line = line.substring(14); if (line.startsWith("kick " + ip)) { System.exit(0); } } else if (line.startsWith("FINGERPRINT")) { ip = InetAddress.getLocalHost(); out.println(ip); } else if (line.startsWith("NAME")) { name = line.substring(5); } else if (line.startsWith("MESSAGE")) { try { //DECRYPTION System.out.println(line); line = line.substring(8); String encryptedData = line; System.out.println(line.length()); Key key = generateKey(); Cipher c = Cipher.getInstance(ALGO); c.init(Cipher.DECRYPT_MODE, key); byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData); byte[] decValue = c.doFinal(decordedValue); String decryptedValue = new String(decValue); messageArea.append(name + ": " + decryptedValue + "\n"); messageArea.setCaretPosition(messageArea.getDocument().getLength()); } catch (Exception ex) { Logger.getLogger(ChatClient.class.getName()).log(Level.SEVERE, null, ex); } } } } private Key generateKey() throws Exception { Key key = new SecretKeySpec(keyValue, ALGO); return key; } /** * Runs the client as an application with a closeable frame. */ public static void main(String[] args) throws Exception { ChatClient client = new ChatClient(); client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); client.frame.setVisible(true); client.run(); } } </code></pre> <p>ChatServer.java</p> <pre><code>package Chat.Application; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.HashSet; /** * A multi-threaded chat room server. When a client connects the server requests * a screen name by sending the client the text "SUBMITNAME", and keeps * requesting a name until a unique one is received. After a client submits a * unique name, the server acknowledges with "NAMEACCEPTED". Then all messages * from that client will be broadcast to all other clients that have submitted a * unique screen name. The broadcast messages are prefixed with "MESSAGE ". * * Because this is just a teaching example to illustrate a simple chat server, * there are a few features that have been left out. Two are very useful and * belong in production code: * * 1. The protocol should be enhanced so that the client can send clean * disconnect messages to the server. * * 2. The server should do some logging. */ public class ChatServer { /** * The port that the server listens on. */ private static final int PORT = 9001; /** * The set of all names of clients in the chat room. Maintained so that we * can check that new clients are not registering name already in use. */ private static HashSet&lt;String&gt; names = new HashSet&lt;&gt;(); /** * The set of all the print writers for all the clients. This set is kept so * we can easily broadcast messages. */ private static HashSet&lt;PrintWriter&gt; writers = new HashSet&lt;&gt;(); /** * The set of all the print writers for all the clients. This set is kept so * we can easily broadcast messages. */ private static HashSet&lt;String&gt; bans = new HashSet&lt;&gt;(); private static String[] Names = new String[50]; private static String[] Fingerprints = new String[50]; static int array = 0; static int index; /** * The application main method, which just listens on a port and spawns * handler threads. */ public static void main(String[] args) throws Exception { System.out.println("Chat Server Activated"); ServerSocket listener = new ServerSocket(PORT); try { while (true) { new Handler(listener.accept()).start(); } } finally { listener.close(); } } /** * A handler thread class. Handlers are spawned from the listening loop and * are responsible for a dealing with a single client and broadcasting its * messages. */ private static class Handler extends Thread { private String name; private String ban; private Socket socket; private BufferedReader in; private PrintWriter out; private Integer length; private String fingerprint; /** * Constructs a handler thread, squirreling away the socket. All the * interesting work is done in the run method. */ public Handler(Socket socket) { this.socket = socket; } /** * Services this thread's client by repeatedly requesting a screen name * until a unique one has been submitted, then acknowledges the name and * registers the output stream for the client in a global set, then * repeatedly gets inputs and broadcasts them. */ @Override public void run() { try { // Create character streams for the socket. in = new BufferedReader(new InputStreamReader( socket.getInputStream())); out = new PrintWriter(socket.getOutputStream(), true); // Request a name from this client. Keep requesting until // a name is submitted that is not already used. Note that // checking for the existence of a name and adding the name // must be done while locking the set of names. while (true) { out.println("SUBMITNAME"); name = in.readLine(); length = name.length(); if (length == 0) { out.println("SUBMITNAME ERROR 1"); return; } if (name == "null") { out.println("SUBMITNAME ERROR 1"); return; } if (name == "Admin") { out.println("SUBMITNAME ERROR 2"); return; } if (name == "admin") { out.println("SUBMITNAME ERROR 2"); return; } if (name == "ADMIN") { out.println("SUBMITNAME ERROR 2"); return; } synchronized (bans) { out.println("FINGERPRINT"); fingerprint = in.readLine(); if (bans.contains(fingerprint)) { out.println("SUBMITNAME ERROR 3"); return; } } synchronized (names) { if (!names.contains(name)) { names.add(name); break; } } } // Now that a successful name has been chosen, add the // socket's print writer to the set of all writers so // this client can receive broadcast messages. out.println("NAMEACCEPTED " + name); Names[array] = name; System.out.println(Names[array]); Fingerprints[array] = in.readLine(); System.out.println(Fingerprints[array]); array = array + 1; //Announces that user is Online for (PrintWriter writer : writers) { writer.println("SERVERMESSAGE " + name + " is now Online"); } System.out.println(Names); writers.add(out); // Accept messages from this client and broadcast them. // Ignore other clients that cannot be broadcasted to. while (true) { String input = in.readLine(); System.out.println(input); if (input == null) { return; } for (PrintWriter writer : writers) { if (input.startsWith("/")) { if ("Electron".equals(name)) { //Tracks the hostname and IP address of the user if (input.startsWith("/track")) { input = input.substring(7); index = java.util.Arrays.asList(Names).indexOf(input); out.println("SERVERMESSAGE " + input + ": " + Fingerprints[index]); //Bans the user from returning until Server is deactivated } else if (input.startsWith("/ban")) { input = input.substring(5); index = java.util.Arrays.asList(Names).indexOf(input); synchronized (bans) { bans.add(Fingerprints[index]); } out.println("SERVERMESSAGE " + input + "(" + Fingerprints[index] + ")" + " is now banned"); } else if (input.startsWith("/kick")) { input = input.substring(6); index = java.util.Arrays.asList(Names).indexOf(input); out.println("SERVERCOMMAND kick " + Fingerprints[index]); } else if (input.startsWith("/deactivate")) { writer.println("SERVERMESSAGE The server is now Offline"); System.exit(0); } } } else { writer.println("NAME " + name); writer.println("MESSAGE " + input); } } } } catch (IOException e) { System.out.println(e); } finally { // This client is going down! Remove its name and its print // writer from the sets, and close its socket. for (PrintWriter writer : writers) { writer.println("SERVERMESSAGE " + name + " is now Offline"); } if (name != null) { names.remove(name); } if (out != null) { writers.remove(out); } try { socket.close(); } catch (IOException e) { } } } } } </code></pre> <p>I have tried varying the amount of text I send, adding more padding, even trying every input from 1 - 1000 in order to see if there was a pattern (there wasn't....). I have researched all over the internet but to no avail.</p> <p>Thanks for helping a Noob programmer with his 2nd program (Really.)! Have a great week!</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload