Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

strings to number and XOR

by alager (Acolyte)
on Oct 07, 2009 at 00:28 UTC ( #799620=perlquestion: print w/ replies, xml ) Need Help??
alager has asked for the wisdom of the Perl Monks concerning the following question:

I would like to xor every two bytes in an arbitrary string with the same value, or key. Here is one things I've tried, but the result is not correct. For the first two characters (th) xor I expect it to be 0x3ba3, but I'm getting 0x52e7, I can't figure out what is going wrong.
#!/usr/bin/perl 2 3 $msg = "this is a test messagez"; 4 $key = 0x4fcb; 5 print "$msg\n"; 6 7 @array = split(/(..)/, $msg); 8 9 10 printf "key: %x\n", $key; 11 12 $xitem = unpack("H*", $array[1]) ^ $key; 13 print "item: $array[1] = hex " . unpack("H*", $array[1]) . "\n"; 14 printf ("xored item \'%x\', want 0x3ba3\n", $xitem);
Thanks, Aaron

Comment on strings to number and XOR
Download Code
Re: strings to number and XOR
by JavaFan (Canon) on Oct 07, 2009 at 00:40 UTC
    Do you expect 0x3ba3 because 0x3ba3 == 0x7468 ^ 0x4fcb? However, unpack "H*", "th" equals 7468 == 0x1d2c.

    And I don't understand the purpose of your split. Wouldn't @array = $msg =~ /(..)/g be much handier?

Re: strings to number and XOR
by almut (Canon) on Oct 07, 2009 at 00:49 UTC
    $msg = "this is a test messagez"; $key = "\x4f\xcb"; # or $key = pack "n", 0x4fcb; $xored = $msg ^ $key; print join(" ", split(//, $msg)), "\n"; print join(" ", unpack("(H2)*", $msg)), "\n"; print join(" ", unpack("(H2)*", $key)), "\n"; print join(" ", unpack("(H2)*", $xored)), "\n"; __END__ t h i s i s a t e s t m e s s a g e z 74 68 69 73 20 69 73 20 61 20 74 65 73 74 20 6d 65 73 73 61 67 65 7a 4f cb 3b a3 69 73 20 69 73 20 61 20 74 65 73 74 20 6d 65 73 73 61 67 65 7a

    The easiest way to generate your key string for the entire message is probably something like

    $key = "\x4f\xcb" x (length($msg)/2); or $key = pack("n", 0x4fcb) x (length($msg)/2);

    That way you can directly XOR both strings without any further ado:

    t h i s i s a t e s t m e s s a g e z 74 68 69 73 20 69 73 20 61 20 74 65 73 74 20 6d 65 73 73 61 67 65 7a + $msg 4f cb 4f cb 4f cb 4f cb 4f cb 4f cb 4f cb 4f cb 4f cb 4f cb 4f cb + $key 3b a3 26 b8 6f a2 3c eb 2e eb 3b ae 3c bf 6f a6 2a b8 3c aa 28 ae 7a + XOR result


     $xitem =  unpack("H*", $array[1]) ^ $key;

    What this is doing is XORing the hex-string "7468" (i.e. 4 ASCII chars, hex 37 34 36 38) with the Perl internal representation of the number 0x4fcb ...

      Brilliant! Pouring over my books I just couldn't grasp it. You made it crystal clear! Thanks, Aaron
      Okay one last item. Using:$key = "\x4f\xcb" x (length($msg)/2);
      how do I handle odd length messages? We can see in your example too, that the last character is not xored, 0x7a. I would like it to be xored with 0x4f, or the first part of the key. Thanks for your help. Aaron
        I think I solved this. I just added 1 more, since an extra byte or two in the key doesn't hurt anything.
        $key = "\x4f\xcb" x ((length($msg)/2)+1);
      Last question, then I should be done. :)
      For the variable
      $key = "\x4f\xcb"; How can I increment it?
      I've tried directly with $key++, but that starts counting at 0, I would expect \x4f\xcc as the result.

      And I've tried unpacking it. Which starts incrementing with the first number (4 in this case) and loses the rest of the data. eg 4,5,6...
      I would like
      0x4fcb 0x4fcc 0x4fcd ect.


      UPDATE: I've found part of the problem, perl doesn't like to add numbers that aren't "numbers", this works fine as long as my bytes are in the range of ASCII numbers, but fails for values above outside of 0x30-0x39.

        I've tried directly with $key++

        The problem with Perl's string-increment is that the string has to match the pattern /^[a-zA-Z]*[0-9]*\z/ for it to work...(see perlop).  So you'd have to increment the corresponding numeric value, e.g.

        $key = "\x4f\xcb"; for (1..10) { $key = pack('n',unpack('n',$key)+1); # ++ print unpack("H*", $key), "\n"; } __END__ 4fcc 4fcd 4fce 4fcf 4fd0 4fd1 4fd2 4fd3 4fd4 4fd5

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://799620]
Approved by almut
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (14)
As of 2014-08-22 12:43 GMT
Find Nodes?
    Voting Booth?

    The best computer themed movie is:

    Results (156 votes), past polls