Java 使用bouncy castle进行AES解密

Java 使用bouncy castle进行AES解密,java,encryption,cryptography,aes,bouncycastle,Java,Encryption,Cryptography,Aes,Bouncycastle,我正在尝试修改的示例代码必须使用3个参数调用,模式(加密或解密)、IV和密钥。它还读取和写入特定文件 从现在起,我忽略了给定的IV和钥匙,直到我得到了其余的启动和运行。我的代码成功地对文件中的明文进行加密,并将密文写入文件,但解密不起作用。解密模式读取的字节数似乎比加密写入的字节数还要多,并且我得到了块对齐错误 我确信在解密部分的某个地方有一些基本错误,但我不知道它是什么。如果任何人能够识别问题,或者看到任何可能导致问题的明显错误,请让我知道 错误发生在 try{ ctLength += cip

我正在尝试修改的示例代码必须使用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(�).

密码文本实际上不是文本。不要使用像
Writer
Reader
这样的API来处理文本。使用像
OutputStream
InputStream
这样的API来处理字节数组

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

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

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

确切的异常是什么以及在哪里引发的?请将此信息添加到您的问题中。错误发生在try{ctLength+=cipher.doFinal(cipherText,ctLength);}catch{IllegalBlockSizeException e)@Artjom B.该加密示例非常基本,既不安全也不正确。将密文显示为字符串的错误已出现在“示例”中。不要信任互联网上的随机代码样本,尤其是当涉及加密时。@MaartenBodewes谢谢你的建议,我会给你一个向上的投票,但我认为我在这里的排名太低了,不能这么做。好的,谢谢。请注意,我甚至不记得为什么我发布了那个评论;ECB和CTR都可以在Java SE中随时获得(
“AES/CTR/NOP添加”
)。你所指的例子出于某种原因使用了Bouncy Castle。当然,这并不意味着自己尝试并实现它不是一个好的做法。感谢你解决了这个问题,这个例子是由我的教授提供的,所以我不确定为什么它使用了不正确的方法。从一开始就注定了哈哈@erickson@erickson它是黏液吗d在加密之前读取UTF-8编码的明文文件,并将解密后的文件也写入UTF-8,还是将其视为字节文件well@CSjunkie这取决于写入纯文本文件时使用的编码;它们应该匹配。如果您自己编写文件,则很可能是系统上的默认编码tem被使用。在linux上,
locale charmap
会告诉你这一点。在Windows上,我认为它是
chcp