Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Padding Problem with Blowfish and Crypt::CBC and Java Cipher

661 views
Skip to first unread message

Hal Vaughan

unread,
Aug 12, 2005, 4:21:45 PM8/12/05
to
I have to admit I barely understand any cryptography beyond the simple A=1
type codes my friends and I used in grammar school. I have a server,
running Perl, that takes a file, encrypts it with Blowfish, then MIME
encodes it, sends it out via e-mail. Then I have a Java program that
retrieves the e-mail, MIME decodes it, then decrypts it. I am having no
problem on the Perl end, and any encrypted e-mail I create I can retrieve
and decode. There seems to be no problem with MIME encoding/decoding. The
problem comes when my Java program tries to decrypt the file created and
sent by Perl. I always get:

javax.crypto.BadPaddingException: Given final block not properly padded

When I first set this up, with the Perl code on another computer, I got
errors like that. They stopped, but I was never sure exactly what I did to
solve the problem (and I'm never comfortable with a situation like that).
I tried to examine my changes, and I could never be sure just what fixed
it. Now the Perl code is running on a new system. I'm using a later
version of Crypt::CBC (from 2.08 to 2.12), but I can't see anything in the
changelog that should effect the problem I'm having. I'd also like to
solve the problem once and for all, which means either understanding what
is going wrong with the BadPaddingException, or knowing what to do so Java
has no problem reading the encrypted data Perl sends.

My Perl code to encrypt the data is this:

$cipher = Crypt::CBC->new( { 'key' => $key, iv => $vector,
prepend_iv => 0, 'cipher' => 'Blowfish', 'regenerate_key' => 0 } );
$data = $cipher->encrypt($rawdata);

My Java code to decrypt the data is this:

//sCryptoKey and sCryptoVector are strings with the key and vector
//bCrypto is byte[] of encrypted data
//bDecrypted is byte[] of decrypted data
try {
SecretKeySpec oKey = new SecretKeySpec(sCryptoKey.getBytes("UTF8"),
"Blowfish");
IvParameterSpec oIV = new
IvParameterSpec(sCryptoVector.getBytes("UTF8"));
Cipher oCipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
oCipher.init(Cipher.DECRYPT_MODE, oKey, oIV );
bDecrypted = oCipher.doFinal(bCrypto);
} catch (Exception e) {
//Log the error
sysConfig.log("error", "error decrypting incoming file -- saving to
log
directory: " + e);
}

I'd like to have some better understanding of why I'm getting errors. I'm
not even fully clear on what padding is. I've tried reading up on how
Blowfish works, but I really don't follow it. From what I can see, I
suspect if I change the PKCS5Padding to NoPadding in the Java code should
work, but I'm assuming Padding is just the padding of data on the end. Is
there a way to tell Cipher to figure out the padding, or to take the data
"as is"? I'm also trying to find if there is a way to specify padding on
the Perl end. According to the docs for CBC on CPAN, the padding() method
in CBC is read-only, and I don't see a way to specify the padding in CBC.
I would think as long as I can specify the same padding on both ends there
should be no problem, but, again, there seems to be no way to specify
padding for Crypt::CBC.

Thanks for any help!

Hal

Hal Vaughan

unread,
Aug 12, 2005, 4:53:51 PM8/12/05
to
Hal Vaughan wrote:

I found the "padding" setting, and now use this to encrypt:

$cipher = Crypt::CBC->new( { 'key' => $key, iv => $vector,

prepend_iv => 0, 'cipher' => 'Blowfish', 'regenerate_key' => 0,
padding => 'standard' });
$data = $cipher->encrypt($rawdata);

And now I get a different error on the Java end:

javax.crypto.BadPaddingException: Given final block not properly padded

So now it's padding properly (which is should have done anyway, since it is
supposed to default to "standard") but the last block is not being padded
properly. At first I thought I had to change and use the sequence of
"start, crypt, finish" for encoding, but according to the docs, encrypt()
does it all. So is there something I can do to make sure the last block is
padded? Apparently Crypt::CBC isn't doing that.

Thanks!

Hal

Jim Gibson

unread,
Aug 12, 2005, 7:20:16 PM8/12/05
to
In article <r_adnYren7j...@comcast.com>, Hal Vaughan
<h...@thresholddigital.com> wrote:

> Hal Vaughan wrote:
>
>
[problem description snipped]

> I found the "padding" setting, and now use this to encrypt:
>
> $cipher = Crypt::CBC->new( { 'key' => $key, iv => $vector,
> prepend_iv => 0, 'cipher' => 'Blowfish', 'regenerate_key' => 0,
> padding => 'standard' });
> $data = $cipher->encrypt($rawdata);
>
> And now I get a different error on the Java end:
>
> javax.crypto.BadPaddingException: Given final block not properly padded
>
> So now it's padding properly (which is should have done anyway, since it is
> supposed to default to "standard") but the last block is not being padded
> properly. At first I thought I had to change and use the sequence of
> "start, crypt, finish" for encoding, but according to the docs, encrypt()
> does it all. So is there something I can do to make sure the last block is
> padded? Apparently Crypt::CBC isn't doing that.

Have you tried the other values of the padding setting ('space',
'onesandzeroes', 'null')?

Padding applies only to the last block. Block cipher algorithms like
Blowfish work on blocks of bits. Blowfish uses blocks of size 64 bits.
If the last block is short, padding is added to make it a full block.
The 'standard' padding method is to add 1 to 8 bytes, depending upon
the length of the original data, each byte containing the number of
bytes being added. That way the padding bytes may be unambiguously
removed from the decrypted message. Note that if your message is a
multiple of 64 bits, an extra block of '0808080808080808' will be
added. All of this is explained in the documentation for Crpyt::CBC and
in the references below.

You might try 'null' or 'spaces' on the Perl side and
'Blowfish/CBC/Nopadding' on the Java side. I have not used either
Crypt::CBC nor javax.crypto, so can't give much additional help.

References:

<http://www.faqs.org/rfcs/rfc1423.html>
<http://java.sun.com/j2se/1.4.2/docs/guide/security/jce/JCERefGuide.html
#AppA>


----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= East/West-Coast Server Farms - Total Privacy via Encryption =---

Hal Vaughan

unread,
Aug 23, 2005, 3:34:45 PM8/23/05
to
Jim,

Encryption is not something I understand or do well. Your answers were not
only helpful, but your sources were good ones for me to learn from.

Between your post and the sources you cited, I was able to take care of
several tweaks and get everything working.

Hal

sgillett

unread,
Sep 2, 2005, 6:29:00 AM9/2/05
to
Hal,

I am having a similar problem where I am able to decrypt using perl but
not java and wondered if you could help?

With perl I am using:
my $cipher = Crypt::CBC->new($keyword, 'Blowfish');
my $decrypted = $cipher->decrypt($string);

With java I am using:
Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] decrypted = cipher.doFinal(string);

but get the following error:


javax.crypto.BadPaddingException: Given final block not properly padded

Please can you let me know how you got it working?

Thanks for any help,

Steve.

-------------------------------------
Hal Vaughan wrote:


> Jim,

> Hal

##-----------------------------------------------##
Article posted with Web Developer's USENET Archive
http://www.1-script.com/forums
no-spam read and post WWW interface to your favorite newsgroup -
comp.lang.perl.misc - 36524 messages and counting!
##-----------------------------------------------##

Hal Vaughan

unread,
Sep 2, 2005, 9:04:39 AM9/2/05
to
sgillett wrote:

> Hal,
>
> I am having a similar problem where I am able to decrypt using perl but
> not java and wondered if you could help?
>
> With perl I am using:
> my $cipher = Crypt::CBC->new($keyword, 'Blowfish');
> my $decrypted = $cipher->decrypt($string);

First I have to add that, like I said in my first post, I have very little
idea what I'm doing with cryptography. I did a search to find an example
of someone sending data back and forth from Perl to Java (and back again),
and basically copied what they did. (That's why I used Blowfish -- I
really have no idea exactly how Blowfish works, but when I did a search on
it, I felt I had every reason to trust it as much as almost anything. I
still hope, someday, to change it to PGP.)

With that having been said, I noticed that you're not setting the padding in
Perl. I'd suggest going back through this thread (use Google Groups if
you're server has expired the earlier articles), and see what I have in my
first posts. That might help.

Hal

sgillett

unread,
Sep 5, 2005, 3:16:06 AM9/5/05
to
Hi Hal,

Thanks for your suggestion, I am now using
padding => 'standard'
but still get the following error from the java side:


javax.crypto.BadPaddingException: Given final block not properly padded

I have taken a look back at this thread as you suggested, and noticed that
in your earlier posts you had the same problem, and in your post on 23rd
August you were able to get it working with several tweaks.

Can you remember what changes you needed to make?

Thanks,

Steve.

--


##-----------------------------------------------##
Article posted with Web Developer's USENET Archive
http://www.1-script.com/forums
no-spam read and post WWW interface to your favorite newsgroup -

comp.lang.perl.misc - 36738 messages and counting!
##-----------------------------------------------##

Hal Vaughan

unread,
Sep 5, 2005, 12:40:25 PM9/5/05
to
sgillett wrote:

> Hi Hal,
>
> Thanks for your suggestion, I am now using
> padding => 'standard'
> but still get the following error from the java side:
> javax.crypto.BadPaddingException: Given final block not properly padded
>
> I have taken a look back at this thread as you suggested, and noticed that
> in your earlier posts you had the same problem, and in your post on 23rd
> August you were able to get it working with several tweaks.
>
> Can you remember what changes you needed to make?
>
> Thanks,
>
> Steve.

My best guess is it was a typo (I have a slight learning disability that
makes it very hard, if not almost impossible to spot some typos if
spellchecking or syntax highlighting doesn't catch them). My reasoning for
that is that I looked up the padding info for Perl and Java, experimented
with changing them around, then ended up with putting them both back to
what I had, and after that, it worked. Since the settings were the same as
they were originally, my guess is that I must have mistyped something I
couldn't catch. I never had a problem with Perl decrypting the data,
always with Java decrypting. I guess that's because Java is so picky about
everything and has to have things perfect, whereas Perl is loose enough to
make allowances for, for example, a string not being what was expected.

Below, I've included the important program lines. That includes setting up
the encryption in Perl (the en/de-crypt call is a simple call), and setting
up and using en/de-cryption for Java. I hope that helps!

Hal
===========================

Here's the line I'm using for setting up encryption in Perl:

$cipher = Crypt::CBC->new( { 'key' => $pw, iv => $vector, prepend_iv => 0,
'cipher' => 'Blowfish', 'regenerate_key' => 0 , padding => 'standard'} );

And here's the one I use for setting up decryption in Perl:

$cipher = Crypt::CBC->new( { 'key' => $pw, iv => $vector, prepend_iv => 0,


'cipher' => 'Blowfish', 'regenerate_key' => 0 } );

On the Java side, here's how I set up and call encryption:

//myKey, myVector are strings, bEncrypted is byte[]
try {
SecretKeySpec oKey = new SecretKeySpec(myKey.getBytes(), "Blowfish");
IvParameterSpec oIV = new IvParameterSpec(myVector.getBytes());


Cipher oCipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");

oCipher.init(Cipher.ENCRYPT_MODE, oKey, oIV );
bEncrypted = oCipher.doFinal(bData);
} catch (Exception e) {
return "error encrypting string";
}

And here's how I setup and call decryption in Java:

//sCryptoKey, sCryptoVector are strings, bDecrypted is byte[]


try {
SecretKeySpec oKey = new SecretKeySpec(sCryptoKey.getBytes("UTF8"),
"Blowfish");
IvParameterSpec oIV = new IvParameterSpec(sCryptoVector.getBytes("UTF8"));
Cipher oCipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
oCipher.init(Cipher.DECRYPT_MODE, oKey, oIV );
bDecrypted = oCipher.doFinal(bCrypto);
} catch (Exception e) {

return "error decrypting incoming file".getBytes();
}

0 new messages