BadPaddingException : Decryption error

后端 未结 3 1256
梦毁少年i
梦毁少年i 2020-12-08 17:00

I\'m writing a program which takes as input from the console - the name of a zip file, name of a zip file to be made containing the (de/en)crypted files generated from the f

相关标签:
3条回答
  • 2020-12-08 17:48

    Jozef is right.

    When you create cipher with default parameters, it defaults to "RSA/ECB/PKCS1Padding". You should specify padding explicitly, if you don't like nasty surprises. Because other security providers might have different default parameters. And you never know in advance which security settings each specific JRE has.

    So PKCS1 padding adds 11 bytes to your original data increasing it from 117 bytes to 128 bytes. You should take into account that these numbers are specific to 1024 bit RSA keys (which are marginally secure) and will be different for longer keys. Since you are loading the key from a file consider checking its length.

    @Test
    public void testPadding() throws Exception {
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
    
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(1024, random);
        KeyPair keyPair = keyGen.generateKeyPair();
    
        /* constant 117 is a public key size - 11 */
        byte[] plaintext = new byte[117];
        random.nextBytes(plaintext);
    
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
        byte[] ciphertext = cipher.doFinal(plaintext);
        System.out.println(plaintext.length + " becomes " + ciphertext.length);
    }
    

    This prints

    117 becomes 128
    

    And finally, consider using AES instead of RSA for file encryption.

    So to fix the problem you need to use buffer of size public key length - 11 (117) for encryption and public key size (128) for decryption.

    Change

    outputFile.write(cipher.doFinal(buffer), 0, read);
    

    to

    outputFile.write(cipher.doFinal(buffer));
    

    because buffer read is 117 bytes and size of doFinal result is 128 bytes.

    Also you need to buffer input streams. When you are reading from file, it can be slow sometimes and then InputStream will read less data than buffer may contain. By using BufferedInputStream one ensures that there is enough data before read call returns. However, for decryption it's crucial to have the full block of data

    InputStream inputEntry = new BufferedInputStream(originalZipFile.getInputStream(entry));
    
    0 讨论(0)
  • 2020-12-08 17:53

    The decrypt method's byte array should be 256 bytes in length as it is the default output size of the algorithm (The extra bytes result in this length). Change byte[] buffer = new byte[128]; to byte[] buffer = new byte[256];.

    0 讨论(0)
  • 2020-12-08 17:56
    while((read = inputEntry.read(buffer)) != -1){              
            outputFile.write(cipher.doFinal(buffer), 0, read);
        }
    

    You have a problem here. read is the size of the plaintext that was read, not the ciphertext. You should remove the 2nd and 3rd parameters altogether.

    It is also a waste of time and space to write the ciphertext to an intermediate file. Just write it straight to the zip stream.

    0 讨论(0)
提交回复
热议问题