'AES Encryption and Decryption not getting decrypted word in print statements but shows up in debugger
Hi I'm working on a socket programming project where it is a encrypted client and server. I have all the code working to create public keys, private keys, aes secret encryption and decryption. The issue is when I sent my encrypted values over to the server, it is missing the first few values of the encrypted values. But when I run it through the debugger and add breakpoints it prints the right decrypted value.
For this say my text is "jesus" this is my client class for example.
Client.java
try {
IvParameterSpec iv = new IvParameterSpec(initVector);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] encrypted = cipher.doFinal(value.getBytes(StandardCharsets.UTF_8));
System.out.println("encrypted string: "
+ Base64.getEncoder().encodeToString(encrypted));
return Base64.getEncoder().encodeToString(encrypted);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static void main(Strings[] args) {
// I have all the code for making keys and creating the Socket connection ( all of this stuff works)
System.out.println("What is your port number");
port = scanner.nextInt();
System.out.println("What is your ip address");
ipAddress = scanner.next();
System.out.println("What is your client's private key file");
privateKeyFile = scanner.next();
System.out.println("What is your server's public key file");
publicKeyFile = scanner.next();
System.out.println("What is your text string");
textString = scanner.next();
Socket socket = new Socket(ipAddress, port);
DataInputStream input = new DataInputStream(socket.getInputStream());
// sends output to the socket
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
PrivateKey clientPrivateKey = loadPrivateKey(privateKeyFile, "RSA");
PublicKey serverPublicKey = loadPublicKey(publicKeyFile, "RSA");
// I have more but essentially that is part of it
// stuff that isn't working
SecureRandom sr = new SecureRandom();
KeyGenerator kg= KeyGenerator.getInstance("AES");
kg.init(256, sr);
SecretKey key256AES = kg.generateKey();
String encodedTextString = new String(Base64.getEncoder().encode(
textString.getBytes(StandardCharsets.UTF_8)));
Integer textStringLengthFromBytes = textByte.length;
byte[] textSignature = signDigitalSignature(textByte, clientPrivateKey, "SHA512withRSA");
byte[] IV = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
String cipherText = encrypt(key256AES, IV, textString);
System.out.println("Cipher" + cipherText);
output.write(textStringLengthFromBytes);
output.write(textSignature);
output.write(cipherText.getBytes(StandardCharsets.UTF_8));
}
Server.java
public static String decrypt(SecretKey key, byte[] initVector, String encrypted) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] plainText = cipher.doFinal(Base64.getDecoder()
.decode(encrypted));
return new String(plainText);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static void main(String args[]){
// round 2 for this project I have to get the size of the plaintext string and //the aesEncryptedString and the actual cipher text
Integer size = in.readInt();
System.out.println("size" + size);
byte[] textSignatureFromClient = new byte[256];
in.readFully(textSignatureFromClient);
System.out.println("textSignatureFromClient" +
Arrays.toString(textSignatureFromClient));
// having issues with this part below
String cipherText = in.readLine();
System.out.println("Cipher " + cipherText);
byte[] IV = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
String decryptedVal = decrypt(AESSecretKey, IV, cipherText);
System.out.println("Text" + decryptedVal);
}
Here is an output of what values are stored in the ciphers: Client ciphertext says: V5VoP7K/Bzzj5291kd3WYg== Server ciphertext says: oP7K/Bzzj5291kd3WYg==
Here is the error I get as well: java.lang.IllegalArgumentException: Input byte array has incorrect ending byte at 20
But when I debug, I pass over the decrypt line in the the server and it gets me the word jesus in plaintext both in the debugger variables and in the console. Also I apologize for how messy my code is. I'm going to clean it and modularize it more once all my requirements are met.
Solution 1:[1]
I have absolutely no idea why this worked but I this is what my Server.java looks like now. I just added "" at the end of in.readline() because I noticed when I added comments it got the full cipher. Additionally, it is receiving the text signature before the cipher with no issues.
Server.java
byte[] textSignatureFromClient = new byte[256];
in.readFully(textSignatureFromClient);
String cipherText = in.readLine() + "";
try {
byte[] IV = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
String decryptedVal = decrypt(AESSecretKey, IV, cipherText.trim());
System.out.println("Decrypted Text: " + decryptedVal);
}
catch(Exception e){
System.out.println("Decryption error" + e);
}
Client.java
String encodedTextString = new String(Base64.getEncoder().encode(
textString.getBytes(StandardCharsets.UTF_8)));
byte[] textByte = encodedTextString.getBytes();
byte[] textSignature = signDigitalSignature(textByte, clientPrivateKey, "SHA512withRSA");
output.write(textSignature);
output.flush();
String cipherText = encrypt(key256AES, IV, textString);
System.out.println("Cipher" + cipherText);
output.write(cipherText.getBytes(StandardCharsets.UTF_8));
output.flush(); ```
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Swechha Ghimire |
