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

Hi Monks!

I am seeking for wisdom.

I have the problem that i must use only Crypt::Blowfish to encrypt a large file. Use of modules other than the standard-modules is not allowed. Because of the hints on cpan regarding Blowfish, i am in doubt, that a large file can be handled with this module. So the question is not only whether it is possible but also if anybody knows a snippet where the 8byte-fragmentation is handled.

Thanks,

PeterE

2005-10-24 Retitled by Arunbear, as per Monastery guidelines
Original title: 'crypt::Blowfish'

  • Comment on Encrypting large files with Crypt::Blowfish

Replies are listed 'Best First'.
Re: Encrypting large files with Crypt::Blowfish
by Moron (Curate) on Oct 24, 2005 at 15:47 UTC
    Crypt::Blowfish is a block cipher operating on only an 8 byte block at a time. In order to expand that capability, you need the cipher block chaining capability that happens to be available in Crypt::CBC. The linked documentation also describes how to parametrically induce Crypt::CBC to use Crypt::Blowfish implicitly for each block, thereby delivering blowfish capability for arbitrarily large files.

    -M

    Free your mind

Re: Encrypting large files with Crypt::Blowfish
by thor (Priest) on Oct 24, 2005 at 16:15 UTC
    In the perldoc for Crypt::Blowfish, I see that it mentions using Crypt::CBC as a helper module. In looking at Crypt::CBC, it says the following:
    In combination with a block cipher such as DES or IDEA, you can encrypt and decrypt messages of arbitrarily long length.
    That seems promising enough. Also, the example code that they have there actually uses Blowfish, so you've got that going for you. I see, however, that you've place a seemingly arbitrary restriction on using core modules (of which Crypt::Blowfish is not one). I suppose you could do something like this:
    use Crypt::Blowfish my $file = "your file name here"; my $key = "magick"; open(my $in, "<", $file ) or die "Couldn't open '$file' for re +ad: $!"; open(my $out, ">", "$file.crypt") or die "Couldn't open '$file.crypt' +for write: $!"; my $cipher = Crypt::Blowfish->new($key); my $buffer; while( read($in, $buffer, 1024) ) { print $out $cipher->encrypt($buffer); }
    Of course, the docs on Crypt::Blowfish say to make sure that the block that you're encrypting is exactly 8 bytes long (which confuses me, so I didn't address it in my example code)

    thor

    Feel the white light, the light within
    Be your own disciple, fan the sparks of will
    For all of us waiting, your kingdom will come

      Two things:

      1. The OP isn't saying "only core modules"; rather only "standard" modules. That might be those that come with his distribution, but I bet it means only those available on CPAN.
      2. Crypt::Blowfish can only deal with 8-byte blocks. That means, you need code like this:
        my $cipher = Crypt::Blowfish->new($key); my $buffer; while( read($in, $buffer, 8) ) { print $out $cipher->encrypt($buffer); }

        The OP seems to be asking about dealing with the last few bytes of the file, since the Crypt::Blowfish module requires exactly 8 bytes to operate.

      The answer, OP, is to pad the last chunk. Something like this:

      my $cipher = Crypt::Blowfish->new($key); my $buffer; while( read($in, $buffer, 8) ) { if ( length($buffer) < 8 ) { for (1..8-length($buffer)) { $buffer.=chr(0) } } print $out $cipher->encrypt($buffer); }

      However, the best way to take care of the issue is to do as others have suggested and use Crypt::CBC to handle the mechanics for you.

      <-radiant.matrix->
      A collection of thoughts and links from the minds of geeks
      The Code that can be seen is not the true Code
      "In any sufficiently large group of people, most are idiots" - Kaa's Law
        Thanks to anybody replyed to my question :)

        Indeed, i have to use core modules except the crypt::Blowfish.
        This is the only module additional installed on the machine.

        The way radiant.matrix mentioned works fine.

        Except one little problem:
        The decrypted file contains some characters additional to the original file: ^@
        I tried various ways to analyse the problem, but get only a change of the amount of ^@

        So please give me a hint: what am i doing wrong?

        crypting:

        use Crypt::Blowfish; my $key = 'ThisIsMyKey'; my $cipher = Crypt::Blowfish->new($key); my $buffer; my $file = 'TestFile.txt'; open(my $in, "<", $file) or die "Couldn't open '$file' for read: $!"; open(my $out, ">", "$file.crypt") or die "Couldn't open '$file.crypt' +for write: $!"; while( read($in, $buffer, 8) ) { if ( length($buffer) < 8 ) { for (1..8-length($buffer)) { $buffer.=chr(0); print length($buffer); } } print $out $cipher->encrypt($buffer); }
        decrypting:
        my $key = 'ThisIsMyKey'; my $cipher = Crypt::Blowfish->new($key); my $buffer; my $file = 'TestFile.txt'; open(my $in, "<", "$file.crypt") or die "Couldn't open '$file' for re +ad: $!"; open(my $out, ">", "$file.decrypt") or die "Couldn't open '$file.decry +pt' for write: $!"; while( read($in, $buffer, 8) ) { print $out $cipher->decrypt($buffer); }
        Thanks a lot, PeterE
      I see, however, that you've place a seemingly arbitrary restriction on using core modules

      Actually, he placed a seemingly arbitrary restriction on using non-core modules. Some may argue that that's more understandable... but then one wonders whether he would be allowed to write a module himself and install it. Once you realize that you could just copy and paste code into your program, restrictions like that do indeed seem arbitrary, at least when simply toolsmithing. They do make sense, however, when creating an application for commercial distribution where you may be trying to avoid licensing pollution, reduce footprint, and/or ease installation.

      -sauoq
      "My two cents aren't worth a dime.";
      
        My mistake...I mis-spoke. What I meant was that the OP placed a restriction that only core modules be used.

        thor

        Feel the white light, the light within
        Be your own disciple, fan the sparks of will
        For all of us waiting, your kingdom will come

Re: Encrypting large files with Crypt::Blowfish
by fauria (Deacon) on Oct 24, 2005 at 15:39 UTC
    Hi,
    If you want to encrypt the content of a file using Crypt::Blowfish, you can slurp it, and pass the cypher as it where a "normal scalar", and then you can handle the content writing it back to disk, sending it, etc.

    You can deal with files as large as you want, given the required system resources.

    As Crypt::Blowfish relies on an external C library (Blowfish.so) it is faster than the "Pure Perl" implementation, Crypt::Blowfish_PP

    Update: Sorry about this. I did not explained as i should. I was meaning that when encrypting with Blowfish, it does not matter weather you use text coming from a string, file or whatever, thinking always about chunking it before attempting to encrypt it. As it has been replied, you need to split the content as you encrypt it, but i was centered on the no limitation for the size of the file being encrypted, and the possibility of this module for handling unlimited chunks of data.

      That's entirely false. Crypt::Blowfish only encrypts blocks of exactly 8 bytes. Passing an entire file will result in an error (unless, of course, the file happens to be 8 bytes long).

      if (input_len != 8) croak("input must be 8 bytes long");

      The Pure Perl version doesn't croak, but it only encrypts the first 8 bytes of data passed to it.

      Crypt::CBC is the solution to this, as mentioned in the Crypt::Blowfish docs.