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

Hi, I've been trying to write a simple script to encrypt and decrypt data from a file. I was trying to use the RC4.pm module. I'm running Redhat Enterprise on an Intel P4 machine. The version of Perl on my machine is 5.8.0. Here's the problem. I've written some code that will correctly encrypt and decrypt a message when the message is a string that is defined in the program, but fails to work properly with the string is read in from a file. Here's the code
#!/usr/bin/perl -w use strict; use diagnostics; use Crypt::RC4; #grab command line args and get keyphrase my $key_phrase = $ARGV[0]; my $cleartext_file = $ARGV[1]; my $cyphertext_file = $ARGV[2]; chomp($key_phrase); #define some variables my $plaintext; my $cyphertext; my $plaintext2; #complain if mis-used if ($#ARGV <2) { die "Usage crypt_file.pl <key phrase> <cleartext file> <cyphertext f +ile> "; } #open the plaintext file open INFILE, "<$cleartext_file" or die "Can't open input file: ",$cleartext_file,"\n"; my $cph_in = new Crypt::RC4($key_phrase); undef $/; #$plaintext = <INFILE>; close(INFILE); $plaintext = "This is a test\n with a line-break in it\n"; print the plaintext to check it print "+++++++++++++++plain text+++++++++++++++++++++++\n"; print $plaintext; $cyphertext = $cph_in->RC4($plaintext); my $cph_out = new Crypt::RC4($key_phrase); $plaintext2 = $cph_out->RC4($cyphertext); open OUTFILE, ">$cyphertext_file"; print OUTFILE $cyphertext; print "\n----------------cypher text---------------------\n"; print $cyphertext; close(OUTFILE); print "\n++++++++++++++plain text again +++++++++++++++++\n"; print $plaintext2;
Looking at the line that says $plaintext = "This is a test \n with a line-break in it\n";. If I leave this line in, the script works fine, prints out the plain text, then the encrypted text and then the correct plaintext again. If I now comment out this line and uncomment out the file read statement, and then read from a file containing exactly the same text, the program does not create the same encryption, and cannot decrypt what it produces back to clear text. I looked at the output of RC4.pm and it looks to me like it inserts some ascii codes into the output string when the string is read from a file, but not when the string is defined as a variable in the program. At this point, I am stumped and am likely missing something very obvious. Any insight would be greatly appreciated. Could it be something in my perl installation is hosed? thanks j.

Replies are listed 'Best First'.
Re: Help with RC4
by PodMaster (Abbot) on Jul 26, 2004 at 05:30 UTC
    Heard of binmode? Sounds very much like you need to apply it.

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

      Thank you! I'd read that binmode wasn't needed on *nix systems -- apparently, I over interpreted what I read. Seems that what I needed was a combination of undef $/; and binmode(INFILE); and then $plaintext = <INFILE>. Binmode was also needed for the output file. thank you, thank you, thank, you! j.
        Hmm, binmode should not be needed on Linux (or Unix.) From perldoc -f binmode:
        Arranges for FILEHANDLE to be read or written in "binary" or "text" mode on systems where the run-time libraries distinguish between binary and text files..
        But the libraries on Unix-like systems make no such distinction. I'm guessing that the measures you took worked around the bug I mentioned below.

        "Even if you are on the right track, you'll get run over if you just sit there." - Will Rogers
Re: Help with RC4
by hbo (Monk) on Jul 26, 2004 at 05:58 UTC
    I assume you have RHEL3, given that version of Perl. There is a bug in that Perl that shows up when reading data from a file. It's releated to unicode. RHEL3's default locale is 'lang.UTF8'. If you set the LANG to 'C' before running your script, it works around that particular problem. You can't do $ENV{LANG}='C'; in your script; by then it's too late. You have to do something like this (example in bash):
    > export LANG=C > perl myscript.pl
    So you could write a bash wrapper that did that as a workaround.

    Unfortunately, bugzilla.redhat.com is down at the moment or I'd chase down the entry for you. The last I heard, it was supposed to be fixed in update 3. I have just confirmed that that is the problem here.

    If you can't get by with a bash wrapper, I suggest that you build Perl yourself from source.

    "Even if you are on the right track, you'll get run over if you just sit there." - Will Rogers
Re: Help with RC4
by iburrell (Chaplain) on Jul 26, 2004 at 16:35 UTC
    Don't use RC4 for general purpose encryption. RC4 is a stream cipher which means it is easy to use improperly and compromise security. The most important thing about a stream cipher is never use the same key twice, because the ciphertext can be recovered.

    Steam ciphers are useful when a random key is generated for each session, and fast performance and low overhead is needed. RC4 is used this way is SSL, but SSL is very careful to use it properly. A good example of using RC4 improperly is WEP. Through flaws in the protocol, it is possible to discover the key by sniffing the wireless network.

    I would suggest using a block cipher, like AES or Blowfish. The Crypt::CBC module handles all the details of chaining modes.

      FYI: The AES or Advanced Encryption Standard is also known as Crypt::Rijndael

      TStanley
      --------
      The only thing necessary for the triumph of evil is for good men to do nothing -- Edmund Burke
      Thank you. I had been pondering just this point. I liked RC4 because the package was a "pure perl" implementation and therefore would be transportable outside of the unix perl world. On the otherhand I had my doubts about RC4, but did not know that it was the culprit behind the problems with WEP. Looks like CBC + some block cypher (blowfish, IDEA, etc) is the way to go. regards j.
        IIRC IDEA is still patented in the US. You may want to take that into account when choosing a cipher.