Problem With Crypt::CBC

Discussion in 'Perl Misc' started by Hal Vaughan, Aug 20, 2008.

  1. Hal Vaughan

    Hal Vaughan Guest

    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
     
    Hal Vaughan, Aug 20, 2008
    #1
    1. Advertising

  2. Hal Vaughan

    Guest

    On Wed, 20 Aug 2008 16:27:09 GMT, Hal Vaughan <> wrote:

    >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
     
    , Aug 20, 2008
    #2
    1. Advertising

  3. Hal Vaughan

    Hal Vaughan Guest

    wrote:

    > On Wed, 20 Aug 2008 16:27:09 GMT, Hal Vaughan <> wrote:
    >
    >>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.

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


    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
     
    Hal Vaughan, Aug 20, 2008
    #3
  4. Hal Vaughan <> wrote:
    *SKIP*
    > 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*

    --
    Torvalds' goal for Linux is very simple: World Domination
     
    Eric Pozharski, Aug 20, 2008
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. AdrianK
    Replies:
    0
    Views:
    1,540
    AdrianK
    Jul 9, 2003
  2. Cosmia Luna
    Replies:
    4
    Views:
    330
    Cosmia Luna
    Mar 11, 2012
  3. Hal Vaughan
    Replies:
    6
    Views:
    1,077
    Hal Vaughan
    Sep 5, 2005
  4. Replies:
    1
    Views:
    182
  5. Waylen Gumbal

    Crypt::CBC vs individual cipher module differs?

    Waylen Gumbal, Mar 3, 2008, in forum: Perl Misc
    Replies:
    3
    Views:
    158
    Waylen Gumbal
    Mar 8, 2008
Loading...

Share This Page