为什么我的AESencryption会抛出一个InvalidKeyException?

我目前正在研究一个function,用一个密钥encryption/解密一个特定的文件。 我写了三个类,一个是生成一个密钥,一个是用密钥encryption文件,另一个是解密文件。

生成密钥和encryption文件工作正常,但是当我尝试解密文件时,会引发一个exception: c.init(Cipher.DECRYPT_MODE, keySpec);

java.security.InvalidKeyException:缺less参数

我把它解密时,我已经做了一些错误,当解密文件时,将密钥stream到我的byte[]或者是错误的。

快速解释三个类:KeyHandler创build一个AES密钥并将其存储在硬盘上。 为了testing目的,密钥/明文/encryption/解密文件的名称目前被硬编码。

EncryptionHandler将磁盘上的.txt文件转换为字节,使用密钥encryption文件,然后使用CipherOutputStream将encryption的字节写入磁盘。

DecryptionHandler当然和EncryptionHandler相反。

代码如下:

  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(); } } 

如果使用CBC等块链模式,则还需要为Cipher提供IvParameterSpec。

所以你可以像这样初始化一个IvParameterSpec:

  // 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); 

然后为了encryption,把你的密码改成你的密码:

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

在你解密的地方:

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

所以你的完整的代码应该是这样的(它适用于我):

  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(); } }