Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does my AES encryption throws an InvalidKeyException?

I'm currently working on a function that encrypt/decrypts a specific file with a secret key. I have written three classes, one which generates a key, one which encrypts a file with the key and one that decrypts.

Generating the key and encrypting the file works fine, but when I try to decrypt the file, an exception is thrown at line: c.init(Cipher.DECRYPT_MODE, keySpec);:

java.security.InvalidKeyException: Parameters missing

I take it I've done something wrong when streaming the secret key to my byte[] or something is wrong when decrypting the file.

Quick explanation of the three classes: KeyHandler creates a AES key and stores it on the harddrive. The name of the key/plaintext/encrypted/decrypted files is currently hardcoded for testing purposes.

EncryptionHandler transfers a .txt file on the disk into bytes, encrypts the file with the secret key and then writes the encrypted bytes to the disk using CipherOutputStream.

DecryptionHandler of course does the opposite of EncryptionHandler.

Here's the code:

    public class KeyHandler {         Scanner scan = new Scanner(System.in);          public KeyHandler(){             try {                 startMenu();             } catch (Exception e) {                 System.out.println("fel någonstanns :)");             }         }          public void startMenu() throws Exception{              System.out.println("Hej. Med detta program kan du generera en hemlig nyckel"+"\n"+"Vill du:"+"\n"+ "1. Generera en nyckel"+"\n"+"2. Avsluta");             int val=Integer.parseInt(scan.nextLine());         do{              switch (val){             case 1: generateKey(); break;             case 2: System.exit(1);              default: System.out.println("Du måste välja val 1 eller 2");             }         }             while (val!=3);         }          public void generateKey() throws Exception{             try {                 KeyGenerator gen = KeyGenerator.getInstance("AES");                 gen.init(128);                  SecretKey key=gen.generateKey();                 byte[] keyBytes = key.getEncoded();                 System.out.print("Ge nyckeln ett filnamn: ");                 String filename = scan.next();                 System.out.println("Genererar nyckeln...");                 FileOutputStream fileOut = new FileOutputStream(filename);                 fileOut.write(keyBytes);                 fileOut.close();                 System.out.println("Nyckeln är genererad med filnamnet: "+filename+"...");                 System.exit(1);                  } catch (NoSuchAlgorithmException e) {                     }          }          public static void main(String[] args){             new KeyHandler();         }      }       public class EncryptHandler {         private String encryptedDataString;         private Cipher ecipher;           AlgorithmParameterSpec paramSpec;         byte[] iv;          public EncryptHandler(String dataString, String secretKey, String encryptedDataString){             this.encryptedDataString=encryptedDataString;             try {                 encryptFile(dataString, secretKey);             } catch (Exception e) {              }         }              public void encryptFile(String dataString, String secretKey) throws Exception{                      FileInputStream fis = new FileInputStream(secretKey);                     ByteArrayOutputStream baos = new ByteArrayOutputStream();                      int theByte = 0;                     while ((theByte = fis.read()) != -1)                     {                       baos.write(theByte);                     }                     fis.close();                      byte[] keyBytes = baos.toByteArray();                     baos.close();                     SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");                  try                  {                  ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");                  ecipher.init(Cipher.ENCRYPT_MODE, keySpec);                       }                  catch (Exception e)                      {                  e.printStackTrace();              }                   System.out.println("Encrypting file...");                 try                  {                       encryptStream(new FileInputStream(dataString),new FileOutputStream(encryptedDataString));                  }                 catch(Exception e){                 e.printStackTrace();                 }                  }     public void encryptStream(InputStream in, OutputStream out){                 ByteArrayOutputStream bOut = new ByteArrayOutputStream();                 byte[] buf = new byte[1024];                  try {                  out = new CipherOutputStream(out, ecipher);                // read the cleartext and write it to out                 int numRead = 0;                  while ((numRead = in.read(buf)) >= 0) {                 out.write(buf, 0, numRead);                   }                 bOut.writeTo(out);                 out.close();                 bOut.reset();                  }                  catch (java.io.IOException e)                  {                  }                   }           public static void main(String[] args){             String data = "test.txt";             String keyFileName="a";             String encryptedFile="krypterad.txt";             //String encryptedFile =args[2];             new EncryptHandler(data, keyFileName, encryptedFile);         }      }   public class DecryptHandler {     public DecryptHandler(){      try {         decryptFile();     } catch (Exception e) {         System.out.println("något gick fel :) ");         }     }       public void decryptFile()throws Exception{         byte[] buf = new byte[1024];          String keyFilename = "hemlig";         FileInputStream fis = new FileInputStream(keyFilename);         ByteArrayOutputStream baos = new ByteArrayOutputStream();          int theByte = 0;         while ((theByte = fis.read()) != -1)         {           baos.write(theByte);         }         fis.close();          byte[] keyBytes = baos.toByteArray();         baos.close();         SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");           Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");                 System.out.println("här");         c.init(Cipher.DECRYPT_MODE, keySpec);           System.out.println("Decrypting file...");         try{         decryptStream(new FileInputStream("krypterad.txt"),new FileOutputStream("Dekryperad.txt"), c, buf);         }             catch (java.io.IOException e){              }             System.out.println("File decrypted!");         }     public void decryptStream(InputStream in, OutputStream out, Cipher dcipher, byte[] buf){         try          {           in = new CipherInputStream(in, dcipher);           // Read in the decrypted bytes and write the cleartext to out          int numRead = 0;            while ((numRead = in.read(buf)) >= 0)          {          out.write(buf, 0, numRead);          }          out.close();           }          catch (java.io.IOException e){           }      }      public static void main(String[]args){         new DecryptHandler();     } } 
like image 641
John Snow Avatar asked Jul 12 '11 18:07

John Snow


People also ask

How to decrypt AES encrypted password in Java?

We can do the AES encryption and decryption using the secret key that is derived from a given password. For generating a secret key, we use the getKeyFromPassword() method. The encryption and decryption steps are the same as those shown in the string input section.

Is AES decryption the same as encryption?

AES is a symmetric encryption, and is the same speed whether encrypting or decrypting. In fact in some streaming modes, AES simply generates a stream of bits that are xored with the data to encrypt, with the reciever running the exact same AES to produce the exact same bitstream to xor in to decrypt.


1 Answers

If you use a block-chaining mode like CBC, you need to provide an IvParameterSpec to the Cipher as well.

So you can initialize an IvParameterSpec like this:

    // build the initialization vector.  This example is all zeros, but it      // could be any value or generated using a random number generator.     byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };     IvParameterSpec ivspec = new IvParameterSpec(iv); 

Then for encryption, change your code where you init the cipher to this:

ecipher.init(Cipher.ENCRYPT_MODE, keySpec, ivspec); 

And where you decrypt:

c.init(Cipher.DECRYPT_MODE, keySpec, ivspec); 

So your complete code should look like this (It works for me):

    public class KeyHandler {      Scanner scan = new Scanner(System.in);      public KeyHandler() {         try {             startMenu();         } catch (Exception e) {             System.out.println("fel någonstanns :)");         }     }      public void startMenu() throws Exception {          System.out.println("Hej. Med detta program kan du generera en hemlig nyckel" + "\n" + "Vill du:" + "\n" + "1. Generera en nyckel" + "\n" + "2. Avsluta");         int val = Integer.parseInt(scan.nextLine());         do {             switch (val) {                 case 1:                     generateKey();                     break;                 case 2:                     System.exit(1);                  default:                     System.out.println("Du måste välja val 1 eller 2");             }         } while (val != 3);     }      public void generateKey() throws Exception {         try {             KeyGenerator gen = KeyGenerator.getInstance("AES");             gen.init(128);              SecretKey key = gen.generateKey();             byte[] keyBytes = key.getEncoded();             System.out.print("Ge nyckeln ett filnamn: ");             String filename = scan.next();             System.out.println("Genererar nyckeln...");             FileOutputStream fileOut = new FileOutputStream(filename);             fileOut.write(keyBytes);             fileOut.close();             System.out.println("Nyckeln är genererad med filnamnet: " + filename + "...");             System.exit(1);         } catch (NoSuchAlgorithmException e) {         }      }      public static void main(String[] args) {         new KeyHandler();     } }  public class EncryptHandler {      private String encryptedDataString;     private Cipher ecipher;     AlgorithmParameterSpec paramSpec;     byte[] iv;      public EncryptHandler(String dataString, String secretKey, String encryptedDataString) {         this.encryptedDataString = encryptedDataString;         try {             encryptFile(dataString, secretKey);         } catch (Exception e) {         }     }      public void encryptFile(String dataString, String secretKey) throws Exception {          FileInputStream fis = new FileInputStream(secretKey);         ByteArrayOutputStream baos = new ByteArrayOutputStream();          int theByte = 0;         while ((theByte = fis.read()) != -1) {             baos.write(theByte);         }         fis.close();          byte[] keyBytes = baos.toByteArray();         baos.close();         SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");          // build the initialization vector.  This example is all zeros, but it          // could be any value or generated using a random number generator.         byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };         IvParameterSpec ivspec = new IvParameterSpec(iv);          try {             ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");             ecipher.init(Cipher.ENCRYPT_MODE, keySpec, ivspec);          } catch (Exception e) {             e.printStackTrace();         }          System.out.println("Encrypting file...");         try {              encryptStream(new FileInputStream(dataString), new FileOutputStream(encryptedDataString));         } catch (Exception e) {             e.printStackTrace();         }      }      public void encryptStream(InputStream in, OutputStream out) {         ByteArrayOutputStream bOut = new ByteArrayOutputStream();         byte[] buf = new byte[1024];         try {             out = new CipherOutputStream(out, ecipher);              // read the cleartext and write it to out             int numRead = 0;             while ((numRead = in.read(buf)) >= 0) {                 out.write(buf, 0, numRead);              }             bOut.writeTo(out);             out.close();             bOut.reset();          } catch (java.io.IOException e) {         }      }      public static void main(String[] args) {         String data = "test.txt";         String keyFileName = "a";         String encryptedFile = "krypterad.txt";         //String encryptedFile =args[2];         new EncryptHandler(data, keyFileName, encryptedFile);     } }  public class DecryptHandler {      public DecryptHandler() {          try {             decryptFile();         } catch (Exception e) {             e.printStackTrace();             System.out.println("något gick fel :) ");         }     }      public void decryptFile() throws Exception {         byte[] buf = new byte[1024];         String keyFilename = "hemlig";         FileInputStream fis = new FileInputStream(keyFilename);         ByteArrayOutputStream baos = new ByteArrayOutputStream();          int theByte = 0;         while ((theByte = fis.read()) != -1) {             baos.write(theByte);         }         fis.close();          byte[] keyBytes = baos.toByteArray();         baos.close();         SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");          // build the initialization vector.  This example is all zeros, but it          // could be any value or generated using a random number generator.         byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };         IvParameterSpec ivspec = new IvParameterSpec(iv);          Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");         System.out.println("här");         c.init(Cipher.DECRYPT_MODE, keySpec, ivspec);          System.out.println("Decrypting file...");         try {             decryptStream(new FileInputStream("krypterad.txt"), new FileOutputStream("Dekryperad.txt"), c, buf);         } catch (java.io.IOException e) {         }         System.out.println("File decrypted!");     }      public void decryptStream(InputStream in, OutputStream out, Cipher dcipher, byte[] buf) {         try {              in = new CipherInputStream(in, dcipher);              // Read in the decrypted bytes and write the cleartext to out              int numRead = 0;               while ((numRead = in.read(buf)) >= 0) {                 out.write(buf, 0, numRead);              }             out.close();           } catch (java.io.IOException e) {         }     }      public static void main(String[] args) {         new DecryptHandler();     } } 
like image 144
Riaan Cornelius Avatar answered Sep 29 '22 11:09

Riaan Cornelius