使用填充密码解密时,输入长度必须是16的倍数

时间:2023-01-13 18:33:13

I have a server and client socket program, a server send a encrypted message to client, i.e. the server side code:

我有一个服务器和客户端套接字程序,服务器向客户端发送加密消息,即服务器端代码:

cipher2 = Cipher.getInstance("AES"); 
secretKeySpec = new SecretKeySpec(decryptedText, "AES");
cipher2.init(Cipher.ENCRYPT_MODE, secretKeySpec);
feedback = "Your answer is wrong".getBytes();
cipher2.doFinal(feedback);
dos.writeInt(feedback.length);
dos.write(feedback);

the client side code:

客户端代码:

int result_len = 0;
result_len = din.readInt();            
byte[] result_Bytes = new byte[result_len];
din.readFully(result_Bytes);
cipher2 = Cipher.getInstance("AES");
cipher2.init(Cipher.DECRYPT_MODE, aesKey);             
byte[] encrypt = cipher2.doFinal(result_Bytes);

Exception throw at byte[] encrypt = cipher2.doFinal(result_Bytes);

异常抛出byte [] encrypt = cipher2.doFinal(result_Bytes);

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:750)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
    at javax.crypto.Cipher.doFinal(Cipher.java:2086)

what is the problem?

问题是什么?

4 个解决方案

#1


6  

Had a similar issue. But it is important to understand the root cause and it may vary for different use cases.

有一个类似的问题。但重要的是要了解根本原因,并且可能因不同的用例而异。

Scenario 1
You are trying to decrypt a value which was not encoded correctly in the first place.

场景1您试图解密首先未正确编码的值。

byte[] encryptedBytes = Base64.decodeBase64(encryptedBase64String);

If the String is misconfigured for certain reason or has not been encoded correctly, you would see the error " Input length must be multiple of 16 when decrypting with padded cipher"

如果String由于某种原因配置错误或者编码不正确,您会看到错误“使用填充密码解密时输入长度必须是16的倍数”

Scenario 2
Now if by any chance you are using this encoded string in url (trying to pass in the base64Encoded value in url, it will fail. You should do URLEncoding and then pass in the token, it will work.

场景2现在,如果你有可能在url中使用这个编码的字符串(尝试在url中传入base64Encoded值,它将失败。你应该做URLEncoding然后传入令牌,它会工作。

Scenario 3
When integrating with one of the vendors, we found that we had to do encryption of Base64 using URLEncoder but then we need not decode it because it was done internally by the Vendor

场景3当与其中一个供应商集成时,我们发现我们必须使用URLEncoder对Base64进行加密,但是我们不需要解码它,因为它是由供应商在内部完成的

#2


2  

Have a look at this answer: Encrypt and decrypt with AES and Base64 encoding

看看这个答案:使用AES和Base64编码加密和解密

#3


2  

I know this message is old and was a long time ago - but i also had problem with with the exact same error:

我知道这条消息已经很久了很久以前 - 但我也遇到了完全相同的错误:

the problem I had was relates to the fact the encrypted text was converted to String and to byte[] when trying to DECRYPT it.

我遇到的问题与加密文本在尝试解密时转换为字符串和字节[]的事实有关。

    private Key getAesKey() throws Exception {
    return new SecretKeySpec(Arrays.copyOf(key.getBytes("UTF-8"), 16), "AES");
}

private Cipher getMutual() throws Exception {
    Cipher cipher = Cipher.getInstance("AES");
    return cipher;// cipher.doFinal(pass.getBytes());
}

public byte[] getEncryptedPass(String pass) throws Exception {
    Cipher cipher = getMutual();
    cipher.init(Cipher.ENCRYPT_MODE, getAesKey());
    byte[] encrypted = cipher.doFinal(pass.getBytes("UTF-8"));
    return encrypted;

}

public String getDecryptedPass(byte[] encrypted) throws Exception {
    Cipher cipher = getMutual();
    cipher.init(Cipher.DECRYPT_MODE, getAesKey());
    String realPass = new String(cipher.doFinal(encrypted));
    return realPass;
}

#4


-3  

I had this problem once. Actually my code was correct and working when I am running it without server. The mistake was, when I was getting the parameter from the url the encrypted url having plus(+) symbol changed to space automatically. That might be ur problem check it once. Here is my encryption and decryption logic with key generator, if you want you can use it too.

我曾经遇到过这个问题。实际上我的代码是正确的,当我在没有服务器的情况下运行它时工作。错误是,当我从url获取参数时,加号(+)符号的加密url会自动更改为空格。这可能是你的问题检查一次。这是我的密钥生成器的加密和解密逻辑,如果你想也可以使用它。

public class Anything
{
    private static final String ALGO = "AES";
    //generate 128bit key
    private static final String keyStr = "Z8LSq0wWwB5v+6YJzurcP463H3F12iZh74fDj4S74oUH4EONkiKb2FmiWUbtFh97GG/c/lbDE47mvw6j94yXxKHOpoqu6zpLKMKPcOoSppcVWb2q34qENBJkudXUh4MWcreondLmLL2UyydtFKuU9Sa5VgY/CzGaVGJABK2ZR94=";

    private static Key generateKey() throws Exception {
        byte[] keyValue = keyStr.getBytes("UTF-8");
        MessageDigest sha = MessageDigest.getInstance("SHA-1");
        keyValue = sha.digest(keyValue);
        keyValue = Arrays.copyOf(keyValue, 16); // use only first 128 bit       
        Key key = new SecretKeySpec(keyValue, ALGO);
        return key;
    }

    public static String encrypt(String Data) throws Exception {
            Key key = generateKey();
            Cipher c = Cipher.getInstance(ALGO);
            c.init(Cipher.ENCRYPT_MODE, key);
            byte[] encVal = c.doFinal(Data.getBytes());
            String encryptedValue = DatatypeConverter.printBase64Binary(encVal);
            return encryptedValue;
    }

    public static String decrypt(String encryptedData) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.DECRYPT_MODE, key);       
        byte[] decordedValue = DatatypeConverter.parseBase64Binary(encryptedData);
        byte[] decValue = c.doFinal(decordedValue);
        String decryptedValue = new String(decValue);
        return decryptedValue;
    }
}

#1


6  

Had a similar issue. But it is important to understand the root cause and it may vary for different use cases.

有一个类似的问题。但重要的是要了解根本原因,并且可能因不同的用例而异。

Scenario 1
You are trying to decrypt a value which was not encoded correctly in the first place.

场景1您试图解密首先未正确编码的值。

byte[] encryptedBytes = Base64.decodeBase64(encryptedBase64String);

If the String is misconfigured for certain reason or has not been encoded correctly, you would see the error " Input length must be multiple of 16 when decrypting with padded cipher"

如果String由于某种原因配置错误或者编码不正确,您会看到错误“使用填充密码解密时输入长度必须是16的倍数”

Scenario 2
Now if by any chance you are using this encoded string in url (trying to pass in the base64Encoded value in url, it will fail. You should do URLEncoding and then pass in the token, it will work.

场景2现在,如果你有可能在url中使用这个编码的字符串(尝试在url中传入base64Encoded值,它将失败。你应该做URLEncoding然后传入令牌,它会工作。

Scenario 3
When integrating with one of the vendors, we found that we had to do encryption of Base64 using URLEncoder but then we need not decode it because it was done internally by the Vendor

场景3当与其中一个供应商集成时,我们发现我们必须使用URLEncoder对Base64进行加密,但是我们不需要解码它,因为它是由供应商在内部完成的

#2


2  

Have a look at this answer: Encrypt and decrypt with AES and Base64 encoding

看看这个答案:使用AES和Base64编码加密和解密

#3


2  

I know this message is old and was a long time ago - but i also had problem with with the exact same error:

我知道这条消息已经很久了很久以前 - 但我也遇到了完全相同的错误:

the problem I had was relates to the fact the encrypted text was converted to String and to byte[] when trying to DECRYPT it.

我遇到的问题与加密文本在尝试解密时转换为字符串和字节[]的事实有关。

    private Key getAesKey() throws Exception {
    return new SecretKeySpec(Arrays.copyOf(key.getBytes("UTF-8"), 16), "AES");
}

private Cipher getMutual() throws Exception {
    Cipher cipher = Cipher.getInstance("AES");
    return cipher;// cipher.doFinal(pass.getBytes());
}

public byte[] getEncryptedPass(String pass) throws Exception {
    Cipher cipher = getMutual();
    cipher.init(Cipher.ENCRYPT_MODE, getAesKey());
    byte[] encrypted = cipher.doFinal(pass.getBytes("UTF-8"));
    return encrypted;

}

public String getDecryptedPass(byte[] encrypted) throws Exception {
    Cipher cipher = getMutual();
    cipher.init(Cipher.DECRYPT_MODE, getAesKey());
    String realPass = new String(cipher.doFinal(encrypted));
    return realPass;
}

#4


-3  

I had this problem once. Actually my code was correct and working when I am running it without server. The mistake was, when I was getting the parameter from the url the encrypted url having plus(+) symbol changed to space automatically. That might be ur problem check it once. Here is my encryption and decryption logic with key generator, if you want you can use it too.

我曾经遇到过这个问题。实际上我的代码是正确的,当我在没有服务器的情况下运行它时工作。错误是,当我从url获取参数时,加号(+)符号的加密url会自动更改为空格。这可能是你的问题检查一次。这是我的密钥生成器的加密和解密逻辑,如果你想也可以使用它。

public class Anything
{
    private static final String ALGO = "AES";
    //generate 128bit key
    private static final String keyStr = "Z8LSq0wWwB5v+6YJzurcP463H3F12iZh74fDj4S74oUH4EONkiKb2FmiWUbtFh97GG/c/lbDE47mvw6j94yXxKHOpoqu6zpLKMKPcOoSppcVWb2q34qENBJkudXUh4MWcreondLmLL2UyydtFKuU9Sa5VgY/CzGaVGJABK2ZR94=";

    private static Key generateKey() throws Exception {
        byte[] keyValue = keyStr.getBytes("UTF-8");
        MessageDigest sha = MessageDigest.getInstance("SHA-1");
        keyValue = sha.digest(keyValue);
        keyValue = Arrays.copyOf(keyValue, 16); // use only first 128 bit       
        Key key = new SecretKeySpec(keyValue, ALGO);
        return key;
    }

    public static String encrypt(String Data) throws Exception {
            Key key = generateKey();
            Cipher c = Cipher.getInstance(ALGO);
            c.init(Cipher.ENCRYPT_MODE, key);
            byte[] encVal = c.doFinal(Data.getBytes());
            String encryptedValue = DatatypeConverter.printBase64Binary(encVal);
            return encryptedValue;
    }

    public static String decrypt(String encryptedData) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.DECRYPT_MODE, key);       
        byte[] decordedValue = DatatypeConverter.parseBase64Binary(encryptedData);
        byte[] decValue = c.doFinal(decordedValue);
        String decryptedValue = new String(decValue);
        return decryptedValue;
    }
}