Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Re: Encrypting large files with Crypt::Blowfish

by thor (Priest)
on Oct 24, 2005 at 16:15 UTC ( [id://502505]=note: print w/replies, xml ) Need Help??


in reply to Encrypting large files with Crypt::Blowfish

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

Replies are listed 'Best First'.
Re^2: Encrypting large files with Crypt::Blowfish
by radiantmatrix (Parson) on Oct 24, 2005 at 18:03 UTC

    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

        Even though you can't use Crypt::CBC, you can learn from it's documentation. From said document, the way to pad is one of these:

        standard: (default) Binary safe pads with the number of bytes that should be truncated. So, if blocksize is 8, then "0A0B0C" will be padded with "05", resultin +g in "0A0B0C0505050505". If the final block is a full block of 8 bytes, then a whole block of "0808080808080808" is appended. oneandzeroes: Binary safe pads with "80" followed by as many "00" necessary to fill the block. If the last block is a full block and blocksize is 8, a block of "8000000000000000" will be appended. null: text only pads with as many "00" necessary to fill the block. If the last block is a full block and blocksize is 8, a block of "0000000000000000" will be appended. space: text only same as "null", but with "20".

        You will, of course, need to choose a method, and then make sure to do the *inverse* after decryption. So lets say you choose the 'oneandzeroes' method:

        sub encrypt { my $FileHandle = shift; my $cipher = shift; my ($buffer, $cyphertext); while ( read($FileHandle, $buffer, 8) ) { if ( length($buffer) == 8 ) { $cyphertext .= $cipher->encrypt($b +uffer) } } # reading is done, now deal with padding of last block if ( length($buffer) < 8 ) { my $len = length($buffer); $buffer .= chr( 8 - $len ); for (2..$len) { $buffer.=chr(0) } } elsif ( length($buffer) == 8 ) { # we add a full padding block! $buffer = chr(8); for (2..8) { $buffer.=chr(0) } } else { warn 'We should never have a buffer bigger than 8!!!' } # now encrypt the final block $cyphertext .= $cipher->encrypt($buffer); return $cyphertext; } #___ sub decrypt { my $FileHandle = shift; my $cipher = shift; my ($buffer, $plaintext); while ( read($FileHandle, $buffer, 8) ) { $plaintext .= $cipher->decrypt($buffer); } # trim the padding my $last_chunk = substr($plaintext, -8, 8, ''); #removes last 8, to +o! # remove for a char followed by a string of chr(00) that's 1-7 long # this should be the padding of 'oneandzeroes' $last_chunk =~ s/(.)(\x00{1,7})/; # check that out to see if it went well warn "Trim went all strange!" if ord($1) != length($2); $plaintext.=$last_chunk; #put it back }

        You should probably do things like binmode the files and the like too. Remember, the above examples are just that: examples. You'll need to do more error-handling and test things out yourself.

        I am curious why you aren't being allowed to use Crypt::CBC for this, since its implementation is much superior to rolling your own, as it considers all kinds of things you might forget to. I strongly suggest you explain to whomever set that rule that making an exception for Crypt::CBC is a really good idea, as Crypt::CBC and Crypt::Blowfish are really a pair.

        <-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
Re^2: Encrypting large files with Crypt::Blowfish
by sauoq (Abbot) on Oct 24, 2005 at 16:42 UTC
    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

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://502505]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (3)
As of 2024-04-23 23:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found