I've tried to gather all possible information about Encryption/Decryption from here. Tinkered with it, some success and failures.
But now I've applied the code and its hit and a miss too. Some files (exe or msi's) are working but they still gives error about BadPaddingException. Moreover, some other media files like (mp4, mkv etc) are stuck at 99% and doesn't go beyond that, although they r fully received (just some minor bytes difference but Size on Disk always matches).
I just want some help to get rid of these both problems. The files r transfering from 1 PC to another via socket programming.
Server: (Edited)
DataInputStream dis = new DataInputStream(msock.getInputStream());
DataOutputStream dos = new DataOutputStream(msock.getOutputStream());
String file2dl = dis.readLine(); //2
File file = new File(sharedDirectory.toString() + "\\" + file2dl);
dos.writeLong(file.length()); //3+
//Get file name without extension.
String fileName = Files.getNameWithoutExtension(file2dl);
//AES-128 bit key initialization.
byte[] keyvalue = "AES128BitPasswd".getBytes();
SecretKey key = new SecretKeySpec(keyvalue, "AES");
//Initialize the Cipher.
Cipher encCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
encCipher.init(Cipher.ENCRYPT_MODE, key);
//Get the IV from cipher.
IvParameterSpec spec = null;
try {
spec = encCipher.getParameters().getParameterSpec(IvParameterSpec.class);
} catch (InvalidParameterSpecException ex) {
Logger.getLogger(PeersController.class.getName()).log(Level.SEVERE, null, ex);
}
byte[] iv = spec.getIV();
dos.write(iv, 0, iv.length);
File tempDir = new File(tempDirectory.toString());
//Encryption Mechanism.
try (FileInputStream fis = new FileInputStream(file)) {
try (CipherOutputStream cos = new CipherOutputStream(dos, encCipher);
FileInputStream stream = new FileInputStream(tempDir + "\\" + fileName + ".encr")) {
int read, r;
byte[] buffer = new byte[1024 * 1024];
while ((read = fis.read(buffer)) != -1) {
cos.write(buffer, 0, read);
}
}
}
}
Client:
long len;
int count = 0;
int dflag = 0;
String size;
dos.writeBytes("Download\r\n"); //1+
dos.writeBytes(filename + "\r\n"); //2+
System.out.println("File to fetch: -> " + filename);
len = dis.readLong(); //3
System.out.println("Size of file: -> " + len);
//Get file name without Extension.
String fileName = Files.getNameWithoutExtension(filename);
//Get Initialization Vector from Encryption Cypher.
byte[] iv = new byte[16];
int j = dis.read(iv, 0, iv.length);
final File encrypted = new File(sharedDirectory.toString() + "\\" + fileName + ".encr");
final File decrypted = new File(sharedDirectory.toString() + "\\" + filename);
try (FileOutputStream fos = new FileOutputStream(encrypted)) {
byte[] b = new byte[1024 * 1024];
while (fetching) {
int r = dis.read(b, 0, b.length); //4
count = count + r;
double p = (double) count / len;
double per = new BigDecimal(p).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue();
fos.write(b, 0, r);
System.out.println("Size Appending: -> " + count);
System.out.println("Percentage: ->" + per);
Platform.runLater(() -> {
pBar.setProgress(per);
});
if (count >= len) {
dflag = 1;
break;
}
}
}
If encrypted data is fully received
if(dflag == 1) {
//AES-128 bit key initialization.
System.out.println("File completely received");
byte[] keyvalue = "AES128PeerBuLLet".getBytes();
Key key = new SecretKeySpec(keyvalue, "AES");
//Initialization Vector initialized
IvParameterSpec ivParameterSpec = null;
//Cipher Initialization.
Cipher decCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
try {
decCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
} catch (InvalidAlgorithmParameterException ex) {
Logger.getLogger(PeersController.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(decCipher.getProvider().getInfo());
//Decryption Mechanism.
try (FileOutputStream stream = new FileOutputStream(decrypted)) {
try (FileInputStream fis = new FileInputStream(encrypted)) {
try (CipherInputStream cis = new CipherInputStream(fis, decCipher)) {
int read, i = 0;
byte[] buffer = new byte[(1024 * 1024) + 16];
while ((read = cis.read(buffer)) != -1) {
stream.write(buffer, 0, read);
i = i + read;
double d = (double) i / len;
double progress = new BigDecimal(d).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue();
Platform.runLater(() -> {
pBar.setProgress(progress);
progressText.setText("Decrypting..");
});
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
Any input is highly appreciated. Thank You.
Edit 1: Added the link to the sizes of encrypted and decrypted file received via stream. Dropbox Link
Edit 2: So finally the problem is solved with the help of three members who participated in helping me to the fullest. I was reviewing other solutions to my problem and I encounter with this solution which helped me to think deep bout the actual scenario happening in the background. Thanks to Artjom B. for his referral solution and @zaph & @jtahlborn for clearing my false assumptions bout padding and Input/Output streams.