Discussion:
"last block incomplete in decryption"
Chris Carter
2012-01-03 00:01:34 UTC
Permalink
Hi there,

I know this issue is probably developer error, but I've been trying
for awhile to figure out where I'm going wrong. I'm attempting to
encrypt some basic text with BC's JCE provider, but can't for the life
of me get it to do anything but spit out the exception in the subject
upon decryption. What I can't figure out is how my last block can be
incomplete on decryption with the padding I've chosen. Here is my
basic unit test I've boiled my functionality down to, and recreates
what I'm trying to do at the application level:

@Test
public final void testBasicEncryptionCapability() throws Exception
{
String testData = "TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST";

Security.addProvider(new BouncyCastleProvider());

SecureRandom r = new SecureRandom();
byte[] iv = new byte[16]; // I'm assuming iv byte size should be
based on crypto algorithm?
r.nextBytes(iv);

KeyGenerator gen = KeyGenerator.getInstance("AES");
gen.init(128);
byte[] key = gen.generateKey().getEncoded();
SecretKeySpec s = new SecretKeySpec(key, "AES");

Cipher encrypt = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
encrypt.init(Cipher.ENCRYPT_MODE, s, new IvParameterSpec(iv));

String encrypted = new
String(encrypt.doFinal(testData.getBytes(Charsets.UTF_8)),
Charsets.UTF_8);

Cipher decrypt = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
decrypt.init(Cipher.DECRYPT_MODE, s, new IvParameterSpec(iv));

String decrypted = new
String(decrypt.doFinal(encrypted.getBytes(Charsets.UTF_8))); // <---
Exception here

Assert.assertTrue(testData.equals(decrypted));
}


Here's the stack trace:

javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
at org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal(Unknown Source)
at javax.crypto.Cipher.doFinal(Cipher.java:2086)
at CryptoTests.testBasicEncryptionCapability

I would really appreciate any enlightenment someone could provide, and
help dispel my misunderstanding! Thank you!
--
Regards,

Chris Carter
Greg Stark
2012-01-03 01:23:38 UTC
Permalink
The line String encrypted = new
String(encrypt.doFinal(testData.getBytes(Charsets.UTF_8)),
Charsets.UTF_8);

is incorrect. The result of an encryption is an arbitrary block of
bytes, not a UTF-8 string. Do you really need to turn the result into
a String? Why not just leave the result as a byte[]?
Post by Chris Carter
Hi there,
I know this issue is probably developer error, but I've been trying
for awhile to figure out where I'm going wrong.  I'm attempting to
encrypt some basic text with BC's JCE provider, but can't for the life
of me get it to do anything but spit out the exception in the subject
upon decryption.  What I can't figure out is how my last block can be
incomplete on decryption with the padding I've chosen.  Here is my
basic unit test I've boiled my functionality down to, and recreates
       public final void testBasicEncryptionCapability() throws Exception
       {
               String testData = "TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST";
               Security.addProvider(new BouncyCastleProvider());
               SecureRandom r = new SecureRandom();
               byte[] iv = new byte[16]; // I'm assuming iv byte size should be
based on crypto algorithm?
               r.nextBytes(iv);
               KeyGenerator gen = KeyGenerator.getInstance("AES");
               gen.init(128);
               byte[] key = gen.generateKey().getEncoded();
               SecretKeySpec s = new SecretKeySpec(key, "AES");
               Cipher encrypt = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
               encrypt.init(Cipher.ENCRYPT_MODE, s, new IvParameterSpec(iv));
               String encrypted = new
String(encrypt.doFinal(testData.getBytes(Charsets.UTF_8)),
Charsets.UTF_8);
               Cipher decrypt = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
               decrypt.init(Cipher.DECRYPT_MODE, s, new IvParameterSpec(iv));
               String decrypted = new
String(decrypt.doFinal(encrypted.getBytes(Charsets.UTF_8))); // <---
Exception here
               Assert.assertTrue(testData.equals(decrypted));
       }
javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
       at org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal(Unknown Source)
       at javax.crypto.Cipher.doFinal(Cipher.java:2086)
       at CryptoTests.testBasicEncryptionCapability
I would really appreciate any enlightenment someone could provide, and
help dispel my misunderstanding!  Thank you!
--
Regards,
Chris Carter
Chris Carter
2012-01-03 05:40:20 UTC
Permalink
Thanks for the nudge Greg, I modified the code to encode the encrypted
bytes to Base64, then decode them before decryption and it works like
a charm now.
Post by Greg Stark
The line String encrypted = new
String(encrypt.doFinal(testData.getBytes(Charsets.UTF_8)),
Charsets.UTF_8);
is incorrect. The result of an encryption is an arbitrary block of
bytes, not a UTF-8 string. Do you really need to turn the result into
a String? Why not just leave the result as a byte[]?
Post by Chris Carter
Hi there,
I know this issue is probably developer error, but I've been trying
for awhile to figure out where I'm going wrong.  I'm attempting to
encrypt some basic text with BC's JCE provider, but can't for the life
of me get it to do anything but spit out the exception in the subject
upon decryption.  What I can't figure out is how my last block can be
incomplete on decryption with the padding I've chosen.  Here is my
basic unit test I've boiled my functionality down to, and recreates
       public final void testBasicEncryptionCapability() throws Exception
       {
               String testData = "TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST";
               Security.addProvider(new BouncyCastleProvider());
               SecureRandom r = new SecureRandom();
               byte[] iv = new byte[16]; // I'm assuming iv byte size should be
based on crypto algorithm?
               r.nextBytes(iv);
               KeyGenerator gen = KeyGenerator.getInstance("AES");
               gen.init(128);
               byte[] key = gen.generateKey().getEncoded();
               SecretKeySpec s = new SecretKeySpec(key, "AES");
               Cipher encrypt = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
               encrypt.init(Cipher.ENCRYPT_MODE, s, new IvParameterSpec(iv));
               String encrypted = new
String(encrypt.doFinal(testData.getBytes(Charsets.UTF_8)),
Charsets.UTF_8);
               Cipher decrypt = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
               decrypt.init(Cipher.DECRYPT_MODE, s, new IvParameterSpec(iv));
               String decrypted = new
String(decrypt.doFinal(encrypted.getBytes(Charsets.UTF_8))); // <---
Exception here
               Assert.assertTrue(testData.equals(decrypted));
       }
javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
       at org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal(Unknown Source)
       at javax.crypto.Cipher.doFinal(Cipher.java:2086)
       at CryptoTests.testBasicEncryptionCapability
I would really appreciate any enlightenment someone could provide, and
help dispel my misunderstanding!  Thank you!
--
Regards,
Chris Carter
--
Regards,

Chris Carter
Carter Ventures, LLC
Continue reading on narkive:
Search results for '"last block incomplete in decryption"' (Questions and Answers)
43
replies
Do they have a yahoo Answers where you live?
started 2006-09-14 15:54:56 UTC
polls & surveys
Loading...