http://qs1969.pair.com?node_id=493962

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

Hi, I have a brand new encryption/decryption program and I'm trying to improve its execution speed. I have a lot of big files (5Mb) to process and I tought I'd use File::Slurp in order to put everything in main memory. Here are the relevant snipets:
(...) use File::Slurp; use Crypt::CBC; #underlying cipher is Crypt::Twofish_PP (...) my $infilename = shift; my $outfilename = shift; my $cipher = Crypt::CBC->new($self->{SYMMKEY}, 'Twofish_PP'); $cipher->start('decrypting'); my $ref_file_str = read_file($infilename, scalar_ref => 1); my $enc_file_str = $cipher->crypt($$ref_file_str); $enc_file_str .= $cipher->finish; write_file($outfilename, \$enc_file_str); (...)
The end result is a file partially decrypted (a very small portion). If I try to put these lines in a one-liner, I only get the decrypted portion.

This program is executed with ActiveState Perl. Is it possible that a Windows "feature" is preventing this from working properly? Am I asking too much from the CBC/Twofish libraries? Or am I just plain wrong in assuming that this is at all feasible?

Replies are listed 'Best First'.
Re: File::Slurp and encryption
by chester (Hermit) on Sep 21, 2005 at 20:51 UTC
      That shouldn't be a problem, since he should be using binmode anyway. ("These built-ins now always operate in 'binary' mode.")
Re: File::Slurp and encryption
by ikegami (Patriarch) on Sep 21, 2005 at 20:53 UTC

    Try using the binmode => ':raw' option for read_file (if it's not text) and write_file (if crypt can return any byte).

    Any benefit from slurping should be minimal (and null when using Big-Oh notation). You'll get real time savings by switching from the Perl version of the cypher to a C version.

      The encrypted file is an ASCII text originally. But an encrypted file can be handled in binary mode. I'll give it a try

      As for the Pure Perl cipher, I'm still hesitating. I know the biggest benefit would come from there but I still do not know the deployment server's OS... Any suggestion?

        You could try to use the C cypher and fall back on the Perl one. Something like
        my $cypher; if (eval { require Crypt::Twofish }) { $cypher = 'Crypt::Twofish'; } elsif (eval { require Crypt::Twofish_PP }) { warn("Crypt::Twofish not found. Falling back to slower Crypt::Twofi +sh_PP\n") if $DEBUG; $cypher = 'Crypt::Twofish_PP'; } else { die("Neither Crypt::Twofish nor Crypt::Twofish_PP was found. Aborti +ng"); }
        or
        my $cypher; foreach (qw( Crypt::Twofish Crypt::Twofish_PP )) { my $mod = $_; my $file = $_; $file =~ s{::}{/}g; $file .= '.pm'; if (eval { require $file }) { $cypher = $mod; last; } } die("No acceptable encryption algorithm found. Aborting") if not defined $cypher;