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

I've written the following simple program using Crypt:CBC to encrypt/decrypt the contents of a file. The file has multiple lines of data (with a newline character terminating each line) The problem is that once we encrypt the data file and then decrypt it..... the last line in the data file is only partially reproduced. It basically truncates the last line in the file. Here is the code:
#!/usr/perl5/bin -w use Crypt::CBC; $inFile = "test.dat"; $cryptFile = "Crypt.dat"; $decrypFile = "DeCrypt.dat"; if ($#ARGV < 0) { print STDOUT "Invalid number of command line parameters! \n"; exit(1); } $mode = shift @ARGV; unless (($mode == 0) || ($mode == 1)) { print STDOUT "Invalid command line argument1 \n"; exit(2); } $cipher = Crypt::CBC->new( { 'key' => '18829298', 'cipher' => 'DES', 'iv' => '87654321', 'regenerate_key' => 0, 'prepend_iv' => 0 } ); if ($mode == 0) { open(INFILE, "<$inFile") || die "Error opening source file for inp +ut! \n"; open(CRYPTFILE, ">$cryptFile") || die "Error opening crypt file fo +r output! \n"; $cipher->start('encrypting'); while (<INFILE>) { print CRYPTFILE $cipher->crypt($_); } close INFILE; close CRYPTFILE; } else { open(CRYPTFILE, "<$cryptFile") || die "Error opening crypt file fo +r input! \n"; open(DECRYPFILE, ">$decrypFile") || die "Error opening decrypt fil +e for output! \n"; $cipher->start("decrypting"); while (<CRYPTFILE>) { print DECRYPFILE $cipher->crypt($_); } close CRYPTFILE; close DECRYPFILE; }
Any inputs as to why this is happening would be great to have! Thanks, KM

Replies are listed 'Best First'.
Re: Crypt::CBC help!
by BMaximus (Chaplain) on Mar 13, 2002 at 00:19 UTC
    I don't see $cipher->finish anywhere. Read the Crypt::CBC man page. $cipher->finish must be called after the last $cipher->crypt() to flush the buffer out. That's why the last line isn't making it to the file.

    Update:I think I need to elaborate.

    if ($mode == 0) { open(INFILE, "<$inFile") || die "Error opening source file for inp +ut! \n"; open(CRYPTFILE, ">$cryptFile") || die "Error opening crypt file fo +r output! \n"; $cipher->start('encrypting'); while (<INFILE>) { print CRYPTFILE $cipher->crypt($_); } print CRYPTFILE $cipher->finish; close INFILE; close CRYPTFILE;

    BMaximus
      Duh! I really was clumsy there. Didn't read the documentation all the way through. Thanks for your input ...it worked.
Re: Crypt::CBC help!
by Ryszard (Priest) on Mar 13, 2002 at 00:24 UTC
    I havent used Crypt::CBC before, but how about the theory its terminating on a "funny" character?

    You could avoid this by using pack/unpack on the reads before you crypt.

    For example:

    while (<INFILE>) { print CRYPTFILE $cipher->crypt($_); }
    Becomes:
    while (<INFILE>) { print CRYPTFILE $cipher->crypt( pack("H*",$_) ); }

    Obviously you'd then reverse it when reading the cyphertext. I'm not sure if you'd then get into the situation of double <cr>'s at the end of every decrypted line.

    Even so, this is a bit of a hack, as you would really like to understand *why* the event is occuring.

    As a slight aside, plaintext and cyphertext would generally be used as jargon.

Re: Crypt::CBC help!
by webadept (Pilgrim) on Mar 13, 2002 at 02:51 UTC
    The bug is you don't end the cypher with  $cipher->finish.. it needs that to complete the encryption buffer. Hope that helps

    Glenn H.