AES解密与充气城堡

我试图调整http://www.java2s.com/Code/Java/Security/Basicsymmetricencryptionexample.htm中的示例代码,必须使用3个参数调用,模式(加密或解密),IV和密钥。 它还可以读取和写入特定文件。

到目前为止,我忽略了给定的IV和键,直到我完成其余的运行。 我的代码成功地从文件加密明文,并将密文写入文件,但解密不起作用。 似乎解密模式读取的字节数多于加密写入的字节数,并且我得到块对齐错误。

我确定解密部分的某处存在一些基本错误,但我不知道它是什么。 如果有人能够识别问题或者可以看到任何可能导致它的明显错误,请告诉我。

错误发生在

try{ ctLength += cipher.doFinal(cipherText, ctLength);}catch{IllegalBlockSizeException e) 

代码行:

 import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.BufferedReader; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.Writer; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; import java.util.Arrays; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.ShortBufferException; import javax.crypto.spec.SecretKeySpec; @SuppressWarnings("unused") public class AESCTR { static String inputFile = "plain-in.txt"; static String outputFile = "cipher-out.txt"; static String cInputFile = "cipher-in.txt"; static String cOutputFile = "plain-out.txt"; static String mode; static String IV; static String key; public static void main(String[] args) { if (Security.getProvider("BC") == null){ System.out.println("Bouncy Castle provider is NOT available"); System.exit(-1); } else{ System.out.println("Bouncy Castle provider is available"); } Security.addProvider(Security.getProvider("BC")); // TODO Auto-generated method stub if (args.length != 3){ System.out.println("Invalid number of arguments\n"); System.exit(-1); } mode = args[0]; IV = args[1]; key = args[2]; if ((!mode.equals("enc")) && (!mode.equals("dec"))){ System.out.println("Invalid mode\n"); System.exit(-1); } byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; System.out.println(keyBytes.length); SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); System.out.println("Mode: " + mode + " IV: " + IV + " Key: " + key); if(mode.equals("enc")){ int ctLength = 0; byte[] data = null; try { Path path = Paths.get(inputFile); data = Files.readAllBytes(path); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("Invalid Path\n"); System.exit(-1); } while((data.length % 16) != 0){ //Padding byte[] dest = new byte[data.length + 1]; byte[] pad = new byte[] {0x00}; System.arraycopy(data, 0, dest, 0, data.length); System.arraycopy(pad, 0, dest, data.length, pad.length); data = dest; } System.out.println(data.length); byte[] cipherText = new byte[data.length]; Cipher cipher = null; try { cipher = Cipher.getInstance("AES/ECB/NoPadding", "BC"); } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchProviderException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchPaddingException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("input text : " + new String(data)); try { cipher.init(Cipher.ENCRYPT_MODE, key); } catch (InvalidKeyException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { ctLength = cipher.update(data, 0, data.length, cipherText, 0); } catch (ShortBufferException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { ctLength += cipher.doFinal(cipherText, ctLength); } catch (IllegalBlockSizeException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ShortBufferException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (BadPaddingException e) { // TODO Auto-generated catch block e.printStackTrace(); } Writer writer = null; try{ writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(cInputFile), "utf-8")); writer.write(new String(cipherText)); } catch (IOException ex){ System.out.println("File Write Error\n"); System.exit(-1); } finally{ try{writer.close();}catch (Exception ex){} } byte[] c = null; try { Path path = Paths.get(cInputFile); c = Files.readAllBytes(path); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("Invalid Path\n"); System.exit(-1); } System.out.println("cipher text: " + new String(c) + " bytes: " + ctLength); } else if (mode.equals("dec")){ byte[] c = null; try { Path path = Paths.get(cInputFile); c = Files.readAllBytes(path); File f = new File(cInputFile); System.out.println("In Bytes: " + c.length); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("Invalid Path\n"); System.exit(-1); } Cipher cipher = null; try { cipher = Cipher.getInstance("AES/ECB/NoPadding", "BC"); } catch (NoSuchAlgorithmException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (NoSuchProviderException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (NoSuchPaddingException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } byte[] plainText = new byte[c.length]; try { cipher.init(Cipher.DECRYPT_MODE, key); } catch (InvalidKeyException e) { // TODO Auto-generated catch block e.printStackTrace(); } int ptLength = 0; try { ptLength = cipher.update(c, 0, c.length, plainText, 0); System.out.println(ptLength); } catch (ShortBufferException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { ptLength += cipher.doFinal(plainText, ptLength); } catch (IllegalBlockSizeException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ShortBufferException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (BadPaddingException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("plain text : " + new String(plainText) + " bytes: " + ptLength); } } } 

您正在尝试将大量随机字节解码为UTF-8编码文本。 那不行。 您的密文文本已损坏,因为任何不能形成字符的有效UTF-8编码的字节序列都将替换为替换字符0 + FFFD( )。

密文实际上不是文本。 不要使用像WriterReader这样的API来处理文本。 使用与字节数组一起使用的OutputStreamInputStream等API。

如果需要将密文存储为文本,请使用二进制文本编码(如Base64)对其进行编码。

具体来说,您应该使用以下内容替换密文的写入:

 try { Files.write(Paths.get(cInputFile), cipherText); } catch (IOException ex) { System.out.println("File Write Error"); System.exit(-1); }