Close but no cigar, you can't xor arbitrary strings that way. The following will cipher STDIN to STDOUT using the contents of the keyfile on the command line. Assumption is that the key file is much smaller than memory (maybe 5% or less):
use warnings;
use strict;
@ARGV or die "Usage: cipher keyfile < source > dest\n";
open K,shift or die "Can't open keyfile: $!\n";
undef $/; my $k = <K>; close K; # slurp
length $k or die "error reading key file\n";
while (read STDIN, my $t, length $k)
{
my @k = unpack "C*", $k;
print pack "C*", map { $_^shift @k } unpack "C*", $t;
}
Now let's try it:
# make a key file, ok for demo purposes
$ perl -e 'print chr int rand 256 for 0..10000' > key.file
# make a test source file
$ ls -al /dev > plain.txt
# encipher
$ perl cipher.pl key.file < plain.txt > cipher.txt
# decipher
$ perl cipher.pl key.file < cipher.txt > deciphered.txt
# verify
$ diff -s plain.txt deciphered.txt
Files plain.txt and deciphered.txt are identical
~%{${@_[0]}}->{0}&&+++ NO CARRIER