java文件的3des加密/解密

java文件的3des加密/解密,java,encryption,3des,Java,Encryption,3des,我在读取文件(例如*.zip)并使用3DES加密时遇到了一个问题,该3DES使用的是从加密文件名生成的secretKey。 然后我需要解密这个文件,并把它写在硬盘上。 我试图解决这个问题,但在解密文件时卡住了 这是加密机的代码 public class Encryptor { private static String inputFilePath = "D:/1.txt"; public static void main(String[] args) { File

我在读取文件(例如*.zip)并使用3DES加密时遇到了一个问题,该3DES使用的是从加密文件名生成的secretKey。 然后我需要解密这个文件,并把它写在硬盘上。 我试图解决这个问题,但在解密文件时卡住了

这是加密机的代码

public class Encryptor {
    private static String inputFilePath = "D:/1.txt";
    public static void main(String[] args) {
        FileOutputStream fos = null;
        File file = new File(inputFilePath);
        String keyString = "140405PX_0.$88";
        String algorithm = "DESede";
        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            byte[] fileByteArray = new byte[fileInputStream.available()];
            fileInputStream.read(fileByteArray);
            for (byte b : fileByteArray) {
            System.out.println(b);
            }
            SecretKey secretKey = getKey(keyString);
            Cipher cipher = Cipher.getInstance(algorithm);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            ObjectOutputStream objectOutputStream = new ObjectOutputStream
                    (new CipherOutputStream
                            (new FileOutputStream
                                    ("D:/Secret.file"), cipher));
            objectOutputStream.writeObject(fileByteArray);
            objectOutputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static SecretKey getKey(String message) throws Exception {
        String messageToUpperCase = message.toUpperCase();
        byte[] digestOfPassword = messageToUpperCase.getBytes();
        byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
        SecretKey key = new SecretKeySpec(keyBytes, "DESede");
        return key;
    }
}
这是解密程序的代码

public class Decryptor {
    public static void main(String[] args) {
        try {
            File inputFileNAme = new File("d:/Secret.file");
            FileInputStream fileInputStream = new FileInputStream(inputFileNAme);
            FileOutputStream fileOutputStream = new FileOutputStream(outputFilePath);
            SecretKey secretKey = getKey(keyString);
            Cipher cipher = Cipher.getInstance(algorithm);
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            ObjectInputStream objectInputStream = new ObjectInputStream
                    (new CipherInputStream(fileInputStream, cipher));
            System.out.println(objectInputStream.available());
            while (objectInputStream.available() != 0) {
                fileOutputStream.write((Integer) objectInputStream.readObject());
                System.out.println(objectInputStream.readObject());
            }
            fileOutputStream.flush();
            fileOutputStream.close();
            fileInputStream.close();
            objectInputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static SecretKey getKey(String message) throws Exception {
        String messageToUpperCase = message.toUpperCase();
        byte[] digestOfPassword = messageToUpperCase.getBytes();
        byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
        SecretKey key = new SecretKeySpec(keyBytes, "DESede");
        return key;
    }
}
当我试图解密文件时,输出文件中没有任何内容。
我尝试进行调试,发现
objectInputStream.available()
始终包含0。
请告诉我,我如何解决这个问题,以及为什么会发生

  • 用法

    byte[] fileByteArray = new byte[fileInputStream.available()];
    
    is:“使用此方法的返回值分配一个缓冲区以保存此流中的所有数据永远都是不正确的。”

    每次处理文件时应使用记录或缓冲区

  • 该行:

    fileInputStream.read(fileByteArray);
    
    不能保证填充缓冲区。您必须检查返回值:for-1表示文件结束,或>0表示实际传输的字节数。请参阅Javadoc

  • 同样地

    while (objectInputStream.available() != 0) {
    
    不是流结束时的有效测试。您应该调用
    readObject()
    ,直到它抛出
    EOFEException。


  • 作为一种快速修复方法,它可以:

        try {
            File inputFileNAme = new File("d:/Secret.file");
            FileInputStream fileInputStream = new FileInputStream(inputFileNAme);
            FileOutputStream fileOutputStream = new FileOutputStream(outputFilePath);
            SecretKey secretKey = getKey(keyString);
            Cipher cipher = Cipher.getInstance(algorithm);
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            ObjectInputStream objectInputStream = new ObjectInputStream
                    (new CipherInputStream(fileInputStream, cipher));
            System.out.println(objectInputStream.available());
            fileOutputStream.write((byte[]) objectInputStream.readObject());
            fileOutputStream.flush();
            fileOutputStream.close();
            fileInputStream.close();
            objectInputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    
    我所做的是删除“
    .available()
    while循环”,并删除对错误的
    整数的转换

    我同意EJP的回答,特别是关于
    .available()
    的使用


    您还可以使用它为crytpo提供更简单的API。

    flush()
    之前的
    close()
    是多余的,就像关闭其他流中包装的流一样。这些都不能解决发送端的问题。这个解决方案不是一个好的干净的解决方案,它是一个解决OP问题的快速修复。如果需要,可以很好地、干净地重写。(事实上,我希望你的答案是…@EJP)