Reputation: 31
My three problems are as follows:
I can't figure out how to pad the bytes and have it work without the error: javax.crypto.BadPaddingException: Given final block not properly padded
If I switch it to NoPadding, I have to use a string thats a multiple of 8
And lastly and most importantly, I can't get the Server to decrypt it correctly. I prove in the CipherClient.java that the decryption works before it gets sent over the socket.
Using the asHex, I can prove the CipherServer.java gets the same bytes, but when decrypting the message, it doesn't decrypt correctly.
Am I missing something? I don't understand how the Client can decrypt it correctly but once passed through the stream, the Server cannot.
I've been looking around the Internet all day at examples and I can't figure it out. And before someone says something, I know DES isn't wise to use, however, this is just for a project, where DES is the requirement.
CIPHERCLIENT.java
import java.io.*;
import java.net.*;
import java.security.*;
import javax.crypto.*;
public class CipherClient
{public static void main(String[] args) throws Exception
{
try {
//Starts socket
String host = "localhost";
int port = 8001;
Socket s = new Socket(host, port);
//Generate a DES key.
KeyGenerator keygen = KeyGenerator.getInstance("DES");
keygen.init(56, new SecureRandom());
SecretKey key = keygen.generateKey();
//Store the key in a file
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("KeyFile.xx"));
oos.writeObject(key);
oos.close();
//Start Cipher Instance and cipher the message
//Cipher c = Cipher.getInstance("DES/ECB/PKCS5Padding");
Cipher c = Cipher.getInstance("DES/ECB/NoPadding");
c.init(Cipher.ENCRYPT_MODE,key);
//Get string and encrypted version
//String message = "The quick brown fox jumps over the lazy dog.";
String message = "12345678";
byte[] encryptedMsg = c.doFinal(message.getBytes("UTF-8"));
System.out.println("Client - Message: " + message);
System.out.println("Client - Encrypted: " + CipherServer.asHex(encryptedMsg));
//TEST DECRYPT W/ KEY FILE W/O SERVER (WORKS!)
//-------------------------------
//Read key from file test
ObjectInputStream file = new ObjectInputStream(new FileInputStream("KeyFile.xx"));
SecretKey key2 = (SecretKey) file.readObject();
System.out.println("Key Used: " + file.toString());
file.close();
//Decrypt Test
c.init(Cipher.DECRYPT_MODE,key2);
byte[] plainText = c.doFinal(encryptedMsg);
System.out.println("Decrypted Message: " + new String(plainText));
//Open stream to cipher server
DataOutputStream os = new DataOutputStream(s.getOutputStream());
os.writeInt(encryptedMsg.length);
os.write(encryptedMsg);
os.flush();
os.close();
//Close socket
s.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
CIPHERSERVER.java
import java.io.*;
import java.net.*;
import java.security.NoSuchAlgorithmException;
import javax.crypto.*;
public class CipherServer
{
public static void main(String[] args) throws Exception
{
//Start socket server
int port = 8001;
ServerSocket s = new ServerSocket();
s.setReuseAddress(true);
s.bind(new InetSocketAddress(port));
Socket client = s.accept();
CipherServer server = new CipherServer();
server.decryptMessage(client.getInputStream());
s.close();
}
public void decryptMessage(InputStream inStream) throws IOException, NoSuchAlgorithmException
{
try {
//Create the Data input stream from the socket
DataInputStream in = new DataInputStream(inStream);
//Get the key
ObjectInputStream file = new ObjectInputStream(new FileInputStream("KeyFile.xx"));
SecretKey key = (SecretKey) file.readObject();
System.out.println("Key Used: " + file.toString());
file.close();
//Initiate the cipher
//Cipher d = Cipher.getInstance("DES/ECB/PKCS5Padding");
Cipher d = Cipher.getInstance("DES/ECB/NoPadding");
d.init(Cipher.DECRYPT_MODE,key);
int len = in.readInt();
byte[] encryptedMsg = new byte[len];
in.readFully(encryptedMsg);
System.out.println("Server - Msg Length: " + len);
System.out.println("Server - Encrypted: " + asHex(encryptedMsg));
//String demsg = new String(d.doFinal(encryptedMsg), "UTF-8");
//System.out.println("Decrypted Message: " + demsg);
// -Print out the decrypt String to see if it matches the orignal message.
byte[] plainText = d.doFinal(encryptedMsg);
System.out.println("Decrypted Message: " + new String(plainText, "UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
}
//Function to make the bytes printable (hex format)
public static String asHex(byte buf[]) {
StringBuilder strbuf = new StringBuilder(buf.length * 2);
int i;
for (i = 0; i < buf.length; i++) {
if (((int) buf[i] & 0xff) < 0x10) {
strbuf.append("0");
}
strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
}
return strbuf.toString();
}
}
Upvotes: 4
Views: 1611
Reputation: 7488
You create your socket to the server before you create the key file, and the server properly read the key from last run.
Try moving the Socket s = new Socket(host, port);
to after you have closed the key file.
The events is as follows:
Client Server
----------------- ------------------
Connect to server
Accept connection
Read key file
(block on receive)
Generate Key
Write Key File
Send message
Receive message
etc.
Upvotes: 1
Reputation: 93948
Looking at the code I can only presume that the key is not correct. Maybe you are using a wrong folder or similar. BadPaddingException
normally only occurs if the padding was incorrect, if the last block of the data has been corrupted or if you are using the wrong key. Maybe you could use a debugger or SecretKey.getEncoded()
to check out if the keys together with your hexadecimal encoder.
Upvotes: 0