Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I was using Crypt::CBC successfully for a long time, then when the server apache was upgraded all of a sudden I get this error:

Ciphertext does not begin with a valid header for 'salt' header mode

Here is my encryption and decryption subroutine:
sub encrypt { my $plaintext = shift; my $key = "lkjsdfkjkalsjdfn239asdifh4389jbaksdf 09324ni5ansdkfn2193rjlkasndfkn239jas dknsd23r09jasdflknasdi823oiasdflknas dlkn3249ijasdfknoi2oinklnsd9u345knfv knnalknq234ij9rnadks0934klajlkjdsnkl ansdkjsdimnvnkansdkj43938hiohsakasoi jwenkasdlknaskdiojiqwejoinasdlknqweo inasdlknf9034pojfjasdflknvlknasflkjn asddasflknewfqo9ijwernasdlknasdflkj2 eijasdlnasdknvkxlcvnaslkjqwerknzxvcm nweoiuwr098u345oijsfdlkn241389asdfr0 9u34oijasdfklnvsdoi32098u34oisdfklas fdklnasdk934nzslzWQPLIWNCZAEI30SN20S"; my $cipher = Crypt::CBC->new( -key => $key, -cipher => 'Blowfish', -salt => 1 ); return ($cipher->encrypt_hex ($plaintext)); } sub decrypt { my $ciphertext = shift; my $key = "lkjsdfkjkalsjdfn239asdifh4389jbaksdf 09324ni5ansdkfn2193rjlkasndfkn239jas dknsd23r09jasdflknasdi823oiasdflknas dlkn3249ijasdfknoi2oinklnsd9u345knfv knnalknq234ij9rnadks0934klajlkjdsnkl ansdkjsdimnvnkansdkj43938hiohsakasoi jwenkasdlknaskdiojiqwejoinasdlknqweo inasdlknf9034pojfjasdflknvlknasflkjn asddasflknewfqo9ijwernasdlknasdflkj2 eijasdlnasdknvkxlcvnaslkjqwerknzxvcm nweoiuwr098u345oijsfdlkn241389asdfr0 9u34oijasdfklnvsdoi32098u34oisdfklas fdklnasdk934nzslzWQPLIWNCZAEI30SN20S"; my $cipher = Crypt::CBC->new( -key => $key, -cipher => 'Blowfish', -salt => 1 ); return ($cipher->decrypt_hex ($ciphertext)); }
Of course I changed the key to a test one, but that is not the problem, my key did not change at all... in fact nothing at all changed... only the server was upgraded...

My question is this, is there a way to recover from this? There is a lot of information encrypted in my database, passwords of members and so forth, so I need to recover this instead of just having to start over. I have used this method for at least 4 years, maybe 3 but seems like 4 or 5.

Thank you much,
Richard

Replies are listed 'Best First'.
Re: Crypt::CBC, Blowfish and Salt problem
by samtregar (Abbot) on Feb 18, 2008 at 22:21 UTC
    Please tell me that's not your real encryption key!

    But to answer your question, you need to add an option to tell Crypt::CBC to use the old-style header, setting "randomiv" for the "-header" option. From the Crypt::CBC docs describing values for the "-header" option:

     
    "randomiv" -- Generate the block cipher key from the passphrase, and
               choose a random 8-byte value to use as the IV. The IV will
               be prepended to the data stream. This method is compatible
               with ciphertext produced by versions of the library prior to
               2.17, but is incompatible with block ciphers that have non
               8-byte block sizes, such as Rijndael. Crypt::CBC will exit
               with a fatal error if you try to use this header mode with a
               non 8-byte cipher.
    

    -sam

      Ok, I added that but was told by the system that salt was incompatible with randomiv, so I removed the salt entry and get this message now:

      "Ciphertext does not begin with a valid header for 'randomiv' header mode"

      Here is my new code at the bottom of the subroutine:
      my $cipher = Crypt::CBC->new( -key => $key, -cipher => 'Blowfish', -header => 'randomiv' );
      Any other ideas?

      Richard
      PS> Thank you for your assistance... and No those are not my real keys, I put some testing ones in... Mine are like 250 bytes long or so.
        Huh. Maybe you've got a mix of 'salt' and 'randomiv' data? Your encrypt routine has presumably been working since the change - only decryption has been bombing. You might try wrapping the first try in an eval - if it fails, try again with the alternate option.

        -sam

Re: Crypt::CBC, Blowfish and Salt problem
by olus (Curate) on Feb 18, 2008 at 22:36 UTC

    I recently upgraded a server, Perl modules included, and went through a similar problem. Scripts that were there for ages suddenly failed with a message like yours. I solved my problem by including the header key in the call to new with the value 'randomiv'.

    my $cipher = Crypt::CBC->new( -key => $key, -cipher => 'Blowfish', -header => 'randomiv', -salt => 1, );
Re: Crypt::CBC, Blowfish and Salt problem
by almut (Canon) on Feb 18, 2008 at 22:36 UTC

    From the Crypt::CBC Changes file (emphasis added):

    2.17    Mon Jan  9 18:22:51 EST 2006
            -IMPORTANT NOTE: Versions of this module prior to 2.17 were incorrectly
            using 8 byte IVs when generating the old-style RandomIV style header
            (as opposed to the new-style random salt header). This affects data
            encrypted using the Rijndael algorithm, which has a 16 byte blocksize,
            and is a significant security issue.
    
            The bug has been corrected in versions 2.17 and higher by making it
            impossible to use 16-byte block ciphers with RandomIV headers. You may
            still read legacy encrypted data by explicitly passing the 
            -insecure_legacy_decrypt option to Crypt::CBC->new().
    
      I think that's just for Rinjdael. He's using Blowfish, so he shouldn't need that.

      -sam

      Thanks... I tried that, here is my new code at the end of the subroutine:
      my $cipher = Crypt::CBC->new( -key => $key, -cipher => 'Blowfish', -salt => 1, -insecure_legacy_decrypt => 1 );
      Now I get the following message, even if I take out the -salt=>1
      Ciphertext does not begin with a valid header for 'salt' header mode

      Any other ideas?

      Thank you,
      Richard

        What Sam wrote above sounds like a good hypothesis... Have you tried that?

        If all else fails, you might also consider downgrading to pre-2.17 (temporarily, to get operational again) and then work out a way to migrate your old encrypted data to the new style usage/encoding.  For that, it's probably a good idea to install the old version into some private location, and then put use lib "/path/to/old/module"; at the top of the script.