Using triple des(3des) of decrypt in java,get error of"javax.crypto.IllegalBlockSizeException: last block incomplete in decryption"

StackOverflow https://stackoverflow.com/questions/17690611

  •  03-06-2022
  •  | 
  •  

سؤال

I use the code like 3des-encryption-decryption-in-java,but when I use decrypt it,it got a error like this

javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
07-17 11:27:27.580: WARN/System.err(22432): at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(BaseBlockCipher.java:705)
07-17 11:27:27.580: WARN/System.err(22432): at javax.crypto.Cipher.doFinal(Cipher.java:1111)

But if I change final Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); to final Cipher decipher = Cipher.getInstance("DESede/CFB/NoPadding");,the method can run but got a wrong result (the mode is different from server). So I want to know the reason about it.

The decrypt method:

public static String decrypt(byte[] message) throws Exception {
    final MessageDigest md = MessageDigest.getInstance("SHA-1");
    final byte[] digestOfPassword = md.digest(token.getBytes("utf-8"));
    final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
    for (int j = 0, k = 16; j < 8;) {
        keyBytes[k++] = keyBytes[j++];
    }

    final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
    final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
    final Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
    // final Cipher decipher = Cipher.getInstance("DESede/CFB/NoPadding");
    decipher.init(Cipher.DECRYPT_MODE, key, iv);
    final byte[] plainText = decipher.doFinal(message);
    return new String(plainText, "UTF-8");
}

The encrypt method:

public static byte[] encrypt(String message) throws Exception {
        final MessageDigest md = MessageDigest.getInstance("SHA-1");
        final byte[] digestOfPassword = md.digest(token
                .getBytes("utf-8"));
        final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
        for (int j = 0, k = 16; j < 8; ) {
            keyBytes[k++] = keyBytes[j++];
        }

        final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
        final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
        final Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key, iv, new SecureRandom(new byte[5]));
        cipher.init(Cipher.ENCRYPT_MODE, key, iv);

        final byte[] plainTextBytes = message.getBytes("utf-8");
        final byte[] cipherText = cipher.doFinal(plainTextBytes);
        return cipherText;
    }
هل كانت مفيدة؟

المحلول

There are many possibilities
The most common is if you atr encoding the key as a String, especially without specifying the character encoding. If you want to do this, use Base-64, which is designed to encode any binary data, rather than a character encoding
Also make sure that source platform and target platform encoding should be same.As you are using UTF-8 here and then on the other en , UTF-8 must be used

Now have a look under the facts which you are telling that code is running with final Cipher decipher = Cipher.getInstance("DESede/CFB/NoPadding"); but not with final Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
While Decryption, you must know the padding size and mode in which you have selected at encryption time.As you are saying that when you use CBC mode than it throws exception but when you changed it to CFB then it got able to run.In this case you need to make sure which mode you are using at encrytpion time.

As a side note: CBC, OFB and CFB are identical, however OFB/CFB is better because you only need encryption and not decryption, which can save code space.
CBC(Cipher Block Chaining) is used where the data goes through the AES function, and feedback is applied to modify the pre-encrypted data, so that repeated plain data does not yield the same encrypted data. Data can only be processed in blocks which match the block-size of the underlying encryption function (so 128-bit blocks on the case of AES), and synchronisation at this block level must be provided between the encrypting and decrypting engines, otherwise data will be indecipherable
CFB(Cipher FeedBack mode) is also a common mode, and offers the possibility of making an underlying block cipher work like a stream cipher; ie. so that the data being processed can be a stream of shorter values (for example bytes or even individual bits) rather than being processed only as much larger blocks.In CFB mode, the data itself does not go through the AES engine, but gets XORed with a value which the AES engine generates from previous message history. This means that the latency through the CFB function can be minimised, as the only processing applied to the data is an XOR function. Data widths can be set to any size up to the underlying cipher block size, but note that throughput decreases as the widths get smaller in the ratio of the data width to the block size.(Side note ended :D)
If you encrypt using Cipher-Feedback (CFB) or Output-Feedback (OFB) or counter (CTR) modes then the ciphertext will be the same size as the plaintext and so padding is not required. Be careful, though, when using these modes, because the initialisation vectors (IV) must be unique.
Similarly, encrypting using a stream cipher like RC4 or PC1 does not require padding.

Now if we investigate more critically than you should take care about the block size and padding size(already mentioned above).Now the first thing you need to make sure is that the padding size defined by your encryption algorithm.As I mentioned that in CFB case padding is not required so first try it without giving padding.
if issue still resides then check either it is pkcs5 or pkcs7.Try your code by setting decrytpion padding size to pkcs7.If it is pkcs7 then I guess it should work with CBC too.I recommend you to read Using Padding in Encryption

As a additional information

  • PKCS#5 padding is defined in RFC 2898 (PKCS #5: Password-Based Cryptography Specification Version 2.0).

  • PKCS5 padding is a padding scheme for extending arbitrary data to match the block-size of a block cipher in a way that allows the receiving end to reliably remove the padding.

  • PKCS#7 (CMS, RFC 3369) defines a padding scheme, but it is an extension of PKCS#5 padding for block ciphers that have more than 8 bytes for block.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top