Problem With Crypt::CBC

H

Hal Vaughan

I've been using Crypt::CBC in Perl on Linux, Debian Sarge, for about 4 years
or so and I haven't had a problem. My Perl script has to output data that
is later read in by a Java program. The Java program is on a number of
different computers for friends and other people I work with and updating
the Java program would be a nightmare, so I want to be sure any changes I
make to fix this problem do not require me to change things on the Java end
of the situation.

I just recently had to upgrade my system from Debian Sarge to Etch, or, more
accurately, the system drive crashed and I decided I might as well put Etch
on the new one (since Lenny is expected out soon anyway). Etch uses
Crypt::CBC version 2.22. I don't remember what version was being used
previously.

Also, I am NOT a crypto person. When I set this up, I had to go over a lot
of examples and do a fair amount of testing and basically used what I could
easily get to work with the Perl and Java programs sending data back and
forth to each other. I've had a particularly hard time grasping
cryptography issues for some reason.

Here's the problem: My code that used to work doesn't and here's the
offending line:

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

Now when the interpreter gets here, I get this error message:

If specified by -literal_key, then the key length must be equal to the
chosen cipher's key length of 56 bytes at threshPerl/Encryption.pm line 82

I wasn't using literal_key and I put in:

'literal_key' => 0

Then ran it and finally figured out from the error that using
the 'regenerate_key' as false forced literal_key to be true, since the two
apparently have to match.

The passwords I am currently using are 8 bytes, or 64 characters and
changing them would be as much of a pain right now as updating the Java
program. Here's the code I use on the Java end for decrypting this same
data:

byte[] bDecrypted;
String cryptoKey, cryptoVector;
....
try {
SecretKeySpec oKey = new
SecretKeySpec(cryptoKey.getBytes("UTF8"), "Blowfish");
IvParameterSpec oIV = new
IvParameterSpec(cryptoVector.getBytes("UTF8"));
Cipher oCipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
oCipher.init(Cipher.DECRYPT_MODE, oKey, oIV );
bDecrypted = oCipher.doFinal(bCrypto);
} catch (Exception e) {
// do error stuff, details don't matter here
}

What I'd like to be able to do is fix this one line of Perl code so I can
continue using the passwords and vectors I'm using (both 8 bytes, or 64
bits) and not have to change the Java code to get it to receive the data.

Also, I'm figuring I'm going to have the same problem with incoming data as
well, but I would expect the solution in that case to be almost the same.

Is there a way I can change this one line of code without having to change
anything on the Java end and still be able to use my current passwords?:

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

I know I should replace regenerate_key with literal_key, but is the actual
difference between using the literal key and and a hash? I take it if I
use the hash, then the Java program on the other end will not be able to
decode with the same password -- that it would need the hashed form of it.
Is that right?

Thanks for any help and insight on this!


Hal
 
S

sln

I've been using Crypt::CBC in Perl on Linux, Debian Sarge, for about 4 years
or so and I haven't had a problem. My Perl script has to output data that
is later read in by a Java program. The Java program is on a number of
different computers for friends and other people I work with and updating
the Java program would be a nightmare, so I want to be sure any changes I
make to fix this problem do not require me to change things on the Java end
of the situation.

I just recently had to upgrade my system from Debian Sarge to Etch, or, more
accurately, the system drive crashed and I decided I might as well put Etch
on the new one (since Lenny is expected out soon anyway). Etch uses
Crypt::CBC version 2.22. I don't remember what version was being used
previously.

Also, I am NOT a crypto person. When I set this up, I had to go over a lot
of examples and do a fair amount of testing and basically used what I could
easily get to work with the Perl and Java programs sending data back and
forth to each other. I've had a particularly hard time grasping
cryptography issues for some reason.

Here's the problem: My code that used to work doesn't and here's the
offending line:

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

Now when the interpreter gets here, I get this error message:

If specified by -literal_key, then the key length must be equal to the
chosen cipher's key length of 56 bytes at threshPerl/Encryption.pm line 82

I wasn't using literal_key and I put in:

'literal_key' => 0

Then ran it and finally figured out from the error that using
the 'regenerate_key' as false forced literal_key to be true, since the two
apparently have to match.

The passwords I am currently using are 8 bytes, or 64 characters and
changing them would be as much of a pain right now as updating the Java
program. Here's the code I use on the Java end for decrypting this same
data:

byte[] bDecrypted;
String cryptoKey, cryptoVector;
...
try {
SecretKeySpec oKey = new
SecretKeySpec(cryptoKey.getBytes("UTF8"), "Blowfish");
IvParameterSpec oIV = new
IvParameterSpec(cryptoVector.getBytes("UTF8"));
Cipher oCipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
oCipher.init(Cipher.DECRYPT_MODE, oKey, oIV );
bDecrypted = oCipher.doFinal(bCrypto);
} catch (Exception e) {
// do error stuff, details don't matter here
}

What I'd like to be able to do is fix this one line of Perl code so I can
continue using the passwords and vectors I'm using (both 8 bytes, or 64
bits) and not have to change the Java code to get it to receive the data.

Also, I'm figuring I'm going to have the same problem with incoming data as
well, but I would expect the solution in that case to be almost the same.

Is there a way I can change this one line of code without having to change
anything on the Java end and still be able to use my current passwords?:

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

I know I should replace regenerate_key with literal_key, but is the actual
difference between using the literal key and and a hash? I take it if I
use the hash, then the Java program on the other end will not be able to
decode with the same password -- that it would need the hashed form of it.
Is that right?

Thanks for any help and insight on this!


Hal

I'm not a crypt expert, but try this:

$cipher = Crypt::CBC->new( -key => $pw,
-cipher => 'Blowfish',
-iv => $vector,
-header => 'none',
-literal_key => 1,
-padding => 'standard',
-keysize => 8,
);
#-blocksize => 8,

http://search.cpan.org/~lds/Crypt-CBC-2.29/CBC.pm

The -key argument provides either a passphrase to use
to generate the encryption key, or the literal value of
the block cipher key. If used in passphrase mode
(which is the default), -key can be any number of
characters; the actual key will be derived by passing
the passphrase through a series of MD5 hash operations.
To take full advantage of a given block cipher, the
length of the passphrase should be at least equal to
the cipher's blocksize. To skip this hashing operation
and specify the key directly, pass a true value to the
-literal_key option. In this case, you should choose a
key of length exactly equal to the cipher's key length.
You should also specify the IV yourself and a
-header mode of 'none'.

--------------------------

Making a hash of a key phrase just generates a MD5 hash to be used
as a key, that is the default.

Your not doing that, so basically, the -keysize should be equal
to the length of $pw, 8 bytes.

To switch from literal key, you would have to initialize your Java objects
to make hashes of the key.


sln
 
H

Hal Vaughan

I've been using Crypt::CBC in Perl on Linux, Debian Sarge, for about 4
years
or so and I haven't had a problem. My Perl script has to output data that
is later read in by a Java program. The Java program is on a number of
different computers for friends and other people I work with and updating
the Java program would be a nightmare, so I want to be sure any changes I
make to fix this problem do not require me to change things on the Java
end of the situation.

I just recently had to upgrade my system from Debian Sarge to Etch, or,
more accurately, the system drive crashed and I decided I might as well
put Etch
on the new one (since Lenny is expected out soon anyway). Etch uses
Crypt::CBC version 2.22. I don't remember what version was being used
previously.

Also, I am NOT a crypto person. When I set this up, I had to go over a
lot of examples and do a fair amount of testing and basically used what I
could easily get to work with the Perl and Java programs sending data back
and
forth to each other. I've had a particularly hard time grasping
cryptography issues for some reason.

Here's the problem: My code that used to work doesn't and here's the
offending line:

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

Now when the interpreter gets here, I get this error message:

If specified by -literal_key, then the key length must be equal to the
chosen cipher's key length of 56 bytes at threshPerl/Encryption.pm line 82

I wasn't using literal_key and I put in:

'literal_key' => 0

Then ran it and finally figured out from the error that using
the 'regenerate_key' as false forced literal_key to be true, since the two
apparently have to match.

The passwords I am currently using are 8 bytes, or 64 characters and
changing them would be as much of a pain right now as updating the Java
program. Here's the code I use on the Java end for decrypting this same
data:

byte[] bDecrypted;
String cryptoKey, cryptoVector;
...
try {
SecretKeySpec oKey = new
SecretKeySpec(cryptoKey.getBytes("UTF8"), "Blowfish");
IvParameterSpec oIV = new
IvParameterSpec(cryptoVector.getBytes("UTF8"));
Cipher oCipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
oCipher.init(Cipher.DECRYPT_MODE, oKey, oIV );
bDecrypted = oCipher.doFinal(bCrypto);
} catch (Exception e) {
// do error stuff, details don't matter here
}

What I'd like to be able to do is fix this one line of Perl code so I can
continue using the passwords and vectors I'm using (both 8 bytes, or 64
bits) and not have to change the Java code to get it to receive the data.

Also, I'm figuring I'm going to have the same problem with incoming data
as well, but I would expect the solution in that case to be almost the
same.

Is there a way I can change this one line of code without having to change
anything on the Java end and still be able to use my current passwords?:

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

I know I should replace regenerate_key with literal_key, but is the actual
difference between using the literal key and and a hash? I take it if I
use the hash, then the Java program on the other end will not be able to
decode with the same password -- that it would need the hashed form of it.
Is that right?

Thanks for any help and insight on this!


Hal

I'm not a crypt expert, but try this:

$cipher = Crypt::CBC->new( -key => $pw,
-cipher => 'Blowfish',
-iv => $vector,
-header => 'none',
-literal_key => 1,
-padding => 'standard',
-keysize => 8,
);
#-blocksize => 8,

http://search.cpan.org/~lds/Crypt-CBC-2.29/CBC.pm

The -key argument provides either a passphrase to use
to generate the encryption key, or the literal value of
the block cipher key. If used in passphrase mode
(which is the default), -key can be any number of
characters; the actual key will be derived by passing
the passphrase through a series of MD5 hash operations.
To take full advantage of a given block cipher, the
length of the passphrase should be at least equal to
the cipher's blocksize. To skip this hashing operation
and specify the key directly, pass a true value to the
-literal_key option. In this case, you should choose a
key of length exactly equal to the cipher's key length.
You should also specify the IV yourself and a
-header mode of 'none'.

I guess I was in a bit if a hurry or thinking too fast. I read the options
about the key and literal_key, but missed keysize and had already been
Googling for other possibilities. I have a bad tendency to start looking
in the tougher places first instead of the obvious.

Adding the keysize argument fixed it. In case the passwords change, I
used "keysize => length($pw)" for flexibility. I didn't need to try the
blocksize argument. It works fine if I specify the key size. My guess is
that in the older version, it compensated for that by just assuming the
keysize was whatever the key string length was.

I figured that and that's what I was avoiding.
Your not doing that, so basically, the -keysize should be equal
to the length of $pw, 8 bytes.

To switch from literal key, you would have to initialize your Java objects
to make hashes of the key.

Which would be a real pain. That's always possible for the next version,
but if I ever revisit crypto on this system I'll be upgrading it to use
PGP. I haven't done that so far because I have bypasses in so a person can
enter the password manually and PGP keys are kind of long!

Thanks! This took care if it. If I had read the Crypt::CBC docs more
closely before jumping off to Google, then I would have found it. I
appreciate your help and also you not rubbing in that I missed the obvious!

Thank you!


Hal
 
E

Eric Pozharski

Hal Vaughan said:
anyway). Etch uses Crypt::CBC version 2.22. I don't remember what
version was being used previously.

2.12 (exactly 2.12-1sarge2)

*SKIP*
$cipher = Crypt::CBC->new( { 'key' => $pw, 'iv' => $vector,
'prepend_iv' => 0, 'cipher' => 'Blowfish',
'regenerate_key' => 0 , 'padding' => 'standard'} );
Now when the interpreter gets here, I get this error message:
If specified by -literal_key, then the key length must be equal to the
chosen cipher's key length of 56 bytes at threshPerl/Encryption.pm
line 82

(all I say hereby is absolutely unauthoritative, needs verifing, and
better should be forgotten; I've just read L<Crypt::CBC> for the first
time) If my understanding of descriptions of I<-literal_key> and
I<-regenerate_key> is correct, then consider replacing(!)
C<-regenerate_key => 0> with C<-literal_key => 1>

One more. As of I<2.22> B<Crypt::CBC>'s B<new> has hyphen prepended
keys. Maybe that wasn't the case before, maybe it eats them hyphenles
happily. Maybe not. Consider prepending keys with hyphens.

*CUT*
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top