in reply to Mod-2 add 2 binary files

It sounds like you're trying to implement a one-time pad. Let me demonstrate with a couple of one-liners:
thulben@bravo:~/perl 125> perl -le 'print "A" ^ "C"' | perl -nle 'print $_^"C"' A thulben@bravo:~/perl 126> perl -le 'print "A" ^ "C"' | perl -nle 'print $_^"A"' C thulben@bravo:~/perl 127>
Basically, (X xor Y) xor X = Y for all X,Y. And, because the xor operation is equivalent to addition modulo 2 (or, as the algebraist might say "addition in the finite field with two elements"), this works. A canned solution? Here's a quicky:
use warnings; use strict; my $cipher = shift; my $key = shift; open( my $cipher_fh, $cipher ) or die $!; open( my $key_fh, $key ) or die $!; my $buffer_length = 4_096; while ( sysread( $cipher_fh, my $cipher_text, $buffer_length, ) && sysread( $key_fh, my $key_text, $buffer_length, ) ) { print $cipher_text ^ $key_text; }
I don't do a lot of error checking here, so there is room to improve.

thor

p.s. In case it wasn't obvious, you'll need to redirect the output from the script that I provided above: it prints to standard out

Replies are listed 'Best First'.
Re: Re: Mod-2 add 2 binary files
by zude (Scribe) on May 19, 2004 at 05:08 UTC
    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
      I'm not sure that I understand why you can't bit-wise xor two strings:
      $foo = "baz"; $bar = "foo"; print unpack("B*", $foo); print unpack("B*", $bar); print unpack("B*", ($bar ^ $foo)); __END__ 011000100110000101111010 011001100110111101101111 000001000000111000010101
      Seems to do the right thing to me...

      thor