Java JCA - 输入长度必须是填充解密器的 8 的倍数

Java JCA - Input length must be multiple of 8 for padded decypher

我目前正在使用 Java 的 JCA 完成大学课程的作业。 应用程序接收文件并使用 DES-ECB 对其进行加密(或解密)。 我完全知道这不是一种安全的加密算法。

我相信它加密得很好,但是在解密时它会爆炸并显示“输入长度必须是 8 的倍数”,即使原始消息是用 PKCS5 填充的。

我已经在 Whosebug 上阅读了所有关于这个问题的文献和问题,但是 none 的答案似乎解决了这个问题,这让我相信我在某种程度上破坏了 message/file。 ..

对于加密:

    Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
    
    cipher.init(Cipher.ENCRYPT_MODE, symmetricKey);

    
    File file = new File(filePath);
    
    FileOutputStream outputStream = new FileOutputStream("encrypted_"+file.getName());

    
    CipherInputStream cipherStream = new CipherInputStream( new FileInputStream(file), cipher);


    byte[] buffer = new byte[MAX_BUFFER]; //buffer para leitura
    int bytes; //bytes a ler

    //Encoder base64 - Apache Commons Codec
    Base64 encoder = new Base64();

    
    while ( (bytes = cipherStream.read(buffer)) != -1 ) {
        
        byte[] encodedBuffer = encoder.encode(buffer);
        
        outputStream.write(encodedBuffer, 0, bytes);
    }

    
    cipherStream.close();
    outputStream.flush();

    return outputStream;

解密用:

    Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
    
    cipher.init(Cipher.DECRYPT_MODE, symmetricKey);

    
    File file = new File(filePath);
    FileInputStream cipheredStream = new FileInputStream(file);

    
    FileOutputStream outputStream = new FileOutputStream("decrypted_"+file.getName());

    
    CipherOutputStream cipherOutStream = new CipherOutputStream(outputStream, cipher);

    byte[] buffer = new byte[MAX_BUFFER];
    int bytes;

    //Decoder base 64 - Apache Commons Codec
    Base64 decoder = new Base64();

    cipheredStream.read(buffer);
    byte[] decodedBuffer = decoder.decode(buffer);
    byte[] output = cipher.doFinal(decodedBuffer);
    cipherOutStream.write(output);

    //TODO bug here -> use this for big files
    /*while ( (bytes = cipheredStream.read(buffer)) != -1 ) {
        byte[] decodedBuffer = decoder.decode(buffer);
        cipherOutStream.write(decodedBuffer, 0, bytes);
    }*/

    cipherOutStream.close();
    cipheredStream.close();

    return outputStream;

我试过使用 AES 无济于事;我试过不用padding,显然不行。

我只是迷路了,很高兴知道我做错了什么。

感谢@Topaco,使用 Base64InputStream 找到了解决方案。

因为解密是在解码之前完成的,所以它产生了那个错误。它通过执行此加密方面得到修复:

        Base64OutputStream encoder = new Base64OutputStream(outputStream);

        
        while ( (nBytes = cipherStream.read(buffer, 0, MAX_BUFFER)) != -1 )
            encoder.write(buffer, 0, nBytes);

与解密方完全相反:

Base64InputStream decoder = new Base64InputStream(fileInputStream);


while ( (nBytes = decoder.read(buffer, 0, MAX_BUFFER)) != -1 )
    cipherOutStream.write(buffer, 0, nBytes);