Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Crypt::CBC losing its RandomIV

by Solostian (Beadle)
on Mar 16, 2006 at 21:21 UTC ( #537288=perlquestion: print w/ replies, xml ) Need Help??
Solostian has asked for the wisdom of the Perl Monks concerning the following question:

I'm currently putting the finishing touch on a massive file transfer utility. The files are ZIPped, encrypted and attached to email then sent. On reception, the files are detached, decrypted then unZIPped.

I'm using the combo Crypt:CBC and Crypt::Twofish for the encryption.

Sending the files works flawlessly. Partway trough reception, I get the following error:
Cipher stream did not contain IV or salt, and you did not specify thes +e values in new() at (...)

The file's beginning looks like this:
RandomIV$gѓ

So, I can decrypt a couple of files and then the programs fails even though the "RandomIV" is there...

The hard part is handled within a custom object.
sub _symmetric { #Applies symmetric cipher caller eq __PACKAGE__ or die "_symmetric is a private method\n"; die "instance method only" unless ref (my $self = shift); my $ifname = shift; my ($tfname, $ofname, $fh_plain, $fh_cipher); my $cipher = Crypt::CBC->new($self->{SYMMKEY}, 'Twofish') # Usi +ng AES-level cipher or die "Unable to create cipher: $@\n"; if ($self->{MODE} eq TRANSMIT) { $tfname = $ifname . ZIP; $ofname = $ifname . ENC; # A - compress $self->_compressor($ifname, $tfname); die "Unable to delete ${ifname}: $!\n" unless (unlink $ifname) +; # B - encrypt $fh_plain = IO::File->new($tfname, O_RDONLY) or die "Unable to + open ${tfname}: $!\n"; $fh_plain->binmode; $fh_cipher = IO::File->new($ofname, O_WRONLY | O_CREAT) or die + "Unable to create ${ofname}: $!\n"; $fh_cipher->binmode; $cipher->start('encrypting'); $fh_cipher->write($cipher->crypt($fh_plain->getline)) until ($ +fh_plain->eof); $fh_cipher->write($cipher->finish); $fh_cipher->flush; $fh_plain->close; $fh_cipher->close; die "Unable to delete ${tfname}: $!\n" unless (unlink $tfname) +; } else { my @name_parts = split(/\./, $ifname); $ofname = shift(@name_parts); $tfname = $ofname . ZIP; # A - decrypt if ( (stat($ifname))[7] ) { $fh_cipher = IO::File->new($ifname, O_RDONLY) or die "Unab +le to open ${ifname}: $!\n"; $fh_cipher->binmode; $fh_plain = IO::File->new($tfname, O_WRONLY | O_CREAT) or +die "Unable to create ${tfname}: $!\n"; $fh_plain->binmode; # # It fails on the following line # $cipher->start('decrypting'); $fh_plain->write($cipher->crypt($fh_cipher->getline)) unti +l ($fh_cipher->eof); $fh_plain->write($cipher->finish); $fh_plain->flush; $fh_cipher->close; $fh_plain->close; # B - restore if ( (stat($tfname))[7] ) { $self->_compressor($tfname, $ofname); } die "Unable to delete ${tfname}: $!\n" unless (unlink $tfn +ame); } die "Unable to delete ${ifname}: $!\n" unless (unlink $ifname) +; } return $ofname; }

Does anyone has an idea why it happens?

Solostian

Readmore tags added by GrandFather

Comment on Crypt::CBC losing its RandomIV
Select or Download Code
Replies are listed 'Best First'.
Re: Crypt::CBC losing its RandomIV
by jimbojones (Friar) on Mar 17, 2006 at 21:07 UTC
    Hi

    Haven't had time to get deep into this problem, but one thought: you have both filehandles in binmode and you are reading encrypted data that may not have "\n" characters. Perhaps you should do a $fh_cipher->read instead of $fh_cipher->getline?

    HTH, J

      I just got to a point where I don't get errors anymore. Here's what I did.

      First, I modified the way I create the Crypt::CBC object to:
      my $cipher = Crypt::CBC->new(-key => $self->{SYMMKEY}, -cipher => 'Twofish', -salt => 1) or die "Unable to create cipher:\n$@\n";

      My undertsanding is that CBC is now using a random Salt instead of a random IV. Correct me if I am wrong.

      Doing that solved the decryption error I was getting. It was replaced by an EOCD error during the unzip operation.

      I then followed your suggestion and replaced the getline with read:
      # $fh_cipher->write($cipher->crypt($fh_plain->getline)) until ($fh_pla +in->eof); do { $fh_plain->read($buf, length($self->{SYMMKEY})); $fh_cipher->write($cipher->crypt($buf)) } until ($fh_plain->eof);
      and:
      # $fh_plain->write($cipher->crypt($fh_cipher->getline)) until ($fh_cip +her->eof); do { $fh_cipher->read($buf, length($self->{SYMMKEY})); $fh_plain->write($cipher->crypt($buf)) } until ($fh_cipher->eof);
      That got rid of the EOCD error. My app now runs as expected. Thanks for the tip!

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://537288]
Approved by Corion
Front-paged by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (6)
As of 2015-07-30 10:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (271 votes), past polls