Getting javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher?

后端 未结 4 1526
猫巷女王i
猫巷女王i 2020-12-01 16:25

Using tomcat, I have two web-applications i.e app1 and app2. I sent url from app1 in encrypted form (using below code) to app2 . Then at app2 I decrypted this encrypted url

相关标签:
4条回答
  • 2020-12-01 16:41

    Works on my machine. Does it help if you use `UNICODE_FORMAT' in every instance where you transform bytes to Strings and vice versa? This line could be a problem:

    byte[] encValue = c.doFinal(valueToEnc.getBytes()); 
    

    should be

    byte[] encValue = c.doFinal(valueToEnc.getBytes(UNICODE_FORMAT));
    

    Anyway, if you use "AES" as the algorithm and you use the JCE, the algorithm actually being used will be "AES/ECB/PKCS5Padding". Unless you are 100% sure about what you are doing, ECB shouldn't be used for anything. I'd recommend to always specify the algorithm explicitly in order to avoid such confusion. "AES/CBC/PKCS5Padding" would be a good choice. But watch out, with any reasonable algorithm you will also have to provide and manage an IV.

    Using an ECB cipher is even less desirable in the context of encrypting passwords, which is what you seem to be doing with your encryption if I interpret your example correctly. You should use password-based encryption as specified in PKCS#5 for that purpose, in Java this is provided for you in SecretKeyFactory. Be sure to use "PBKDF2WithHmacSHA1" with a high enough iteration count (anything ranging from ~ 5-20 000, depends on your target machine) for using passwords to derive symmetric keys from them.

    The same technique can be used if it is actually password storage instead of password encryption what you are trying to achieve.

    0 讨论(0)
  • 2020-12-01 16:42

    I would suggest instead of working with Strings work with byte[] itself. I am guessing some bytes are modified when you convert it into a String. Following code works for me -

    public static final String ENC_KEY = "abcdefghijklmnop";
    public static final String DATA = "Hello World";
    
    public static void test(){
    
        try {
            Cipher c = Cipher.getInstance("AES");
    
            SecretKeySpec secretKeySpec = new SecretKeySpec(ENC_KEY.getBytes("UTF-8"), "AES");
    
            c.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            byte[] encBytes = c.doFinal(DATA.getBytes("UTF-8"));
            String encStr =  new String(encBytes, "UTF-8");
            System.out.println("Encrypted String: " + encStr);
    
            c.init(Cipher.DECRYPT_MODE, secretKeySpec);
            String decStr = new String(c.doFinal(encBytes),"UTF-8");
            System.out.println("Decrypted String: " + decStr);
    
        } catch (Exception ex) {
            System.out.println("Error in encrypting data");
            ex.printStackTrace();
        }
    }
    

    but if you change it to -

    public static void test(){
    
        try {
            Cipher c = Cipher.getInstance("AES");
    
            SecretKeySpec secretKeySpec = new SecretKeySpec(ENC_KEY.getBytes("UTF-8"), "AES");
    
            c.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            byte[] encBytes = c.doFinal(DATA.getBytes("UTF-8"));
            String encStr =  new String(encBytes, "UTF-8");
            System.out.println("Encrypted String: " + encStr);
    
            c.init(Cipher.DECRYPT_MODE, secretKeySpec);
            String decStr = new String(c.doFinal(encStr.getBytes("UTF-8")),"UTF-8");
            System.out.println("Decrypted String: " + decStr);
    
        } catch (Exception ex) {
            System.out.println("Error in encrypting data");
            ex.printStackTrace();
        }
    }
    

    You will get

    javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:936) at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:847) at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446) at javax.crypto.Cipher.doFinal(Cipher.java:2164) at com.osfg.HelloWorld.test(HelloWorld.java:38) at com.osfg.HelloWorld.main(HelloWorld.java:22)

    Notice

    String decStr = new String(c.doFinal(encBytes),"UTF-8");
    VRS
    String decStr = new String(c.doFinal(encStr.getBytes("UTF-8")),"UTF-8");
    
    0 讨论(0)
  • 2020-12-01 16:48

    I was seeing this error (with the password getting through just fine like you say here) when double-decrypting a value. Be sure to check to see if you are doing the decrypting more than once. (mine was multiple of 8 in the error, but I was using a different scheme there...) In my case I was decrypting when reading a file and then decrypting again when filling out a field. (desktop app)

    0 讨论(0)
  • 2020-12-01 17:00

    This error indicates that you used choice combination requires 16 characters source text only. If you want to encrypt a password, you can truncate or pad the original password to 16-char for encryption, and trim after decryption. This way must limit real password not longer than 16-char, but you may apply longer used password to confuse those who should not know your password.

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