Reputation: 131
I am currently working on a summer project which encrypts or decrypts a file using AES. However when using the same key used to encrypt objects, I get an Illegal Block Size Exception while trying to decrypt. I'm very new to cryptography, but a fairly seasoned Java programmer.
Cryptographer Class:
package com.spencergang.fem;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
public class Cryptographer {
private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES";
//Method for cryptography
public static void crypto(int cipherMode, String key, File inputFile, File outputFile) throws CryptoException {
try{
Key secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM);
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(cipherMode, secretKey);
FileInputStream inputStream = new FileInputStream(inputFile);
byte[] inputBytes = new byte[(int) inputFile.length()];
inputStream.read(inputBytes);
byte[] outputBytes = cipher.doFinal(inputBytes);
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(outputBytes);
inputStream.close();
outputStream.close();
}catch(NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException | IOException ex){
throw new CryptoException("ERROR ENCRYPTING / DECRYPTING FILE", ex);
}
}
//Encryption
public static void encrypt(String key, File inputFile, File outputFile) throws CryptoException {
crypto(Cipher.ENCRYPT_MODE, key, inputFile, outputFile);
}
//Decryption
public static void decrypt(String key, File inputFile, File outputFile) throws CryptoException {
crypto(Cipher.DECRYPT_MODE, key, inputFile, outputFile);
}
}
CryptoException Class:
package com.spencergang.fem;
public class CryptoException extends Exception {
public CryptoException(){
}
public CryptoException(String message, Throwable throwable){
super(message, throwable);
}
}
And finally, my controller class, using FXML I have created a very nice GUI:
package com.spencergang.fem;
import java.io.File;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TextField;
import javafx.stage.FileChooser;
public class Controller {
@FXML
private TextField path;
@FXML
private TextField destination;
@FXML
private TextField key;
@FXML
private CheckBox encryption;
@FXML
private CheckBox decryption;
@FXML
private Button begin;
@FXML
private Button browse;
private MainApp mainApp;
private Cryptographer crypto;
String selectedKey;
File input;
File output;
String filePath;
String fileName;
String destinationPath;
String destinationFile;
String finalDestinationPath;
//Default Constructor;
public Controller(){
}
@FXML
private void initalize(){
}
public void setMainApp(MainApp mainApp){
this.mainApp = mainApp;
}
////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////ENCRYPTION AND DECRYPTION METHODS/////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
private void handleEncryption(String key, File inputFile, File outputFile) throws CryptoException{
crypto.encrypt(key, inputFile, outputFile);
}
private void handleDecryption(String key, File inputFile, File outputFile) throws CryptoException{
crypto.decrypt(key, inputFile, outputFile);
}
////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////BUTTON HANDLER METHODS////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
@FXML
private void handleBegin() throws CryptoException{
if(!(destination.getText().trim().isEmpty() || destination.getText() == "" || destination.getText() == null)){
finalDestinationPath = destinationPath + destination.getText();
output = new File(finalDestinationPath);
}
if(checkFields() == true){
selectedKey = key.getText();
}else{
fieldAlert();
}
if(checkBoxes() == 1){
handleEncryption(selectedKey, input, output);
}else if(checkBoxes() == 2){
handleDecryption(selectedKey, input, output);
}else if(checkBoxes() == 3){
doubleCheckAlert();
}else if(checkBoxes() == 4){
noCheckAlert();
}
}
@FXML
private void handleBrowse(){
FileChooser fileChooser = new FileChooser();
File file;
fileChooser.setTitle("Select File");
file = fileChooser.showOpenDialog(mainApp.getPrimaryStage());
filePath = file.getAbsolutePath();
fileName = file.getName();
System.out.println(fileName);
path.setText(filePath);
destinationPath = filePath.replace(fileName, "");
input = file;
}
////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////HELPER METHODS////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
private boolean checkFields(){
if(path.getText().trim().isEmpty() || destination.getText().trim().isEmpty() || key.getText().trim().isEmpty() || destination.getText() == "" || key.getText() == "" || path.getText() == null || destination.getText() == null || key.getText() == null){
return false;
}else{
return true;
}
}
private int checkBoxes(){
if(encryption.isSelected() && decryption.isSelected()){
return 3;
}else if(decryption.isSelected()){
return 2;
}else if(encryption.isSelected()){
return 1;
}else{
return 4;
}
}
////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////ERROR AND CONFIRMATION ALERTS/////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
private void encryptionAlert(){
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.initOwner(mainApp.getPrimaryStage());
alert.setTitle("Encryption Successful");
alert.setHeaderText("File Encrypted");
alert.setContentText("Your file has been successfully encrypted!");
alert.showAndWait();
}
private void fieldAlert(){
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.initOwner(mainApp.getPrimaryStage());
alert.setTitle("ERROR");
alert.setHeaderText("Empty Field(s)");
alert.setContentText("Check that you have filled out all fields");
alert.showAndWait();
}
private void decryptionAlert(){
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.initOwner(mainApp.getPrimaryStage());
alert.setTitle("Decryption Successful");
alert.setHeaderText("File Decrypted");
alert.setContentText("Your file has been successfully decrypted!");
alert.showAndWait();
}
private void failureAlert(){
Alert alert = new Alert(AlertType.ERROR);
alert.initOwner(mainApp.getPrimaryStage());
alert.setTitle("ERROR");
alert.setHeaderText("File Not Found");
alert.setContentText("Please check your path values");
alert.showAndWait();
}
private void doubleCheckAlert(){
Alert alert = new Alert(AlertType.ERROR);
alert.initOwner(mainApp.getPrimaryStage());
alert.setTitle("ERROR");
alert.setHeaderText("Selection Error");
alert.setContentText("Please select only one option");
alert.showAndWait();
}
private void noCheckAlert(){
Alert alert = new Alert(AlertType.ERROR);
alert.initOwner(mainApp.getPrimaryStage());
alert.setTitle("ERROR");
alert.setHeaderText("Selection Error");
alert.setContentText("Please select an option");
alert.showAndWait();
}
}
Error Message:
Caused by: javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:913)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
at javax.crypto.Cipher.doFinal(Cipher.java:2165)
at com.spencergang.fem.Cryptographer.crypto(Cryptographer.java:32)
... 61 more
This IS NOT for class in any way, just a summer project to keep me busy and fresh. Please help!
Upvotes: 1
Views: 4324
Reputation: 8467
Encrypt the data, then without writing it to a file, decrypt the bytes immediately. Does that work? Or, read the bytes immediately after writing and compare to the original. Do they match? The problem could be with your FileOutputStream writing the bytes to the file in some character encoding instead of as binary. In that case, illegal sequences (in that given encoding) might be modified on the way to the file, changing your ciphertext unexpectedly.
Upvotes: 1