Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Math::XOR problem

by kuratkull (Acolyte)
on Apr 07, 2007 at 21:49 UTC ( [id://608863]=perlquestion: print w/replies, xml ) Need Help??

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

Hello, I am trying to solve the problem: http://projecteuler.net/index.php?section=problems&id=59

The task is to decrypt ASCII text using brute force. The password is 3 characters long, all lower caps.

So the code I have here will print out a small portion of the text using brute force of all versions of [a..w][a..w][a..w]. But I am having a problem here:
until ($numcount==24) { $pass = @list[$count3].@list[$count2].@list[$count1]; #a combination o +f three letters $foo = "@s[$numcount]"; #a ASCII character to try to decrypt $karp = xor_buf($foo,$pass); # put these together using the XOR module push @lister,$karp; $numcount++; }
The line where I use the XOR module to combine the two strings isn't working. For example, $pass = abc; but the code output doesn't change when the last letter changes, so the output will be the same when $pass=abd or $pass=abx. But if the first or second letter change, the output changes too. I tested and saw that for some reason, the XOR module doesn't read the last letter, only the two first ones, but when I try a simple version only with strings, it works.

NB! The code is using "while" because it worked even less with "foreach" loops(it only read the first letter).

Any help is immencely appreciated :) Thanks.

Output sample:
0M@O@KKHM@ILBHAHIHILABCLANLJKKCLNLANMOHJHNKHHM@BLMAM@BLMHIAKIMHHNKKH - +- zyy 0M@O@KKHM@ILBHAHIHILABCLANLJKKCLNLANMOHJHNKHHM@BLMAM@BLMHIAKIMHHNKKH - +- zyz 0MCOCKHHMCIOBHBHJHILBBCLBNOJKHCLMLBNMOHIHMKHKMCBOMBMCBOMKIBKJMKHMKHH - +- zza 0MCOCKHHMCIOBHBHJHILBBCLBNOJKHCLMLBNMOHIHMKHKMCBOMBMCBOMKIBKJMKHMKHH - +- zzb
Full code:
#!/usr/bin/perl use Math::XOR; #$outfile = "output.txt"; #open(HANDLE, ">>$outfile"); @list = (a..z); $count1 = 0; $count2 = 0; $count3 = 0; @s=(79,59,12,2,79,35,8,28,20,2,3,68,8,9,68,45,0,12,9,67,68,4,7,5,23,27 +,1,21,79,85,78,79,85,71,38,10,71,27,12,2,79,6,2,8,13,9); until ($count3==26) { until ($count2==26) { until ($count1==26) { until ($numcount==40) { $pass = @list[$count3].@list[$count2].@list[$count1]; $foo = "@s[$numcount]"; $karp = xor_buf($foo, $pass); push @lister,$karp; $numcount++; } print @lister," -- $pass\n"; @lister = 0; $numcount=0; $count1++; } $count1=0; $count2++; } $count2=0; $count3++; }

Replies are listed 'Best First'.
Re: Math::XOR problem
by ikegami (Patriarch) on Apr 07, 2007 at 22:17 UTC

    Your link is somewhat broken. It only works if you have an account on that site.

    I don't know Math::XOR, and I don't really see the need for it when Perl has a string xor operator.

    # Assumes ASCII. $string1 = "@@@@@"; $string2 = "ABCDE"; $xored = $string1 ^ $string2; print($xored eq "\x01\x02\x03\x04\x05" ? "ok\n" : "not ok\n");

    In practice: (Added)

    my $repeats = (length($cipher_text) / length($pass)) + 1; my $pass_stream = substr($pass x $repeats, 0, length($cipher_text)); my $plain_text = $cipher_text ^ $pass_stream;

    Also, I'm not sure why you aren't using a foreach loop.

    foreach my $c1 ('a'..'z') { foreach my $c2 ('a'..'z') { foreach my $c3 ('a'..'z') { my $pass = $c1 . $c2 . $c3; ... }}}

    Finally, @list[$count1] should be $list[$count1]. Use $ when you want a scalar (single element). Use @ when you want a list (multiple elements).

      ...and speaking (? piling on ?) re ikegami's note re the link,
      kuratkull: Could you tell us, please, what the dickens "all lower caps" means, because what's echoing through my minds is that "lower (case) CAPITALS" is an oxymoron of the first order.

      "Small Caps" is a legit (ie, "meaningful") phrase, but isn't relevant in any way to your question (It's a designation for a font style with letters that look like conventional capital - upper case - letters, but are less tall). However, "small caps" is NOT a character-set in the meaning of your question.

        The phrase in the problem description was "lower case characters".

        I don't see the rationale in drolling over a first time poster (assumed non-native in English, judging by his profile) in this way.

      Thank you mate for helping, this helped me a lot and this helped me closer to completing my task :)
      I implemented your method, and then instantly googled it, so now im familiar with it; I just couldn't find an implemented operator for dealing with XOR, sorry, I new :)

      PS! I didn't use the foreach loop:
      NB! The code is using "while" because it worked even less with "foreach" loops(it only read the first letter). Thanks!
      #!/usr/bin/perl #$outfile = "output.txt"; #open(HANDLE, ">>$outfile"); @s=(79,59,12,2,79,35,8,28,20,2,3,68,8,9,68,45,0,12,9,67,68,4,7,5,23,27 +,1); foreach my $c1 ('a'..'z') { foreach my $c2 ('a'..'z') { foreach my $c3 ('a'..'z') { until ($numcount==27) { $pass = $c1.$c2.$c3; $foo = $s[$numcount]; $string1 = "$foo"; $string2 = "$pass"; $xored = $string1^$string2; $numcount++; push @lister,$xored; } print @lister, " - $foo - $pass\n"; @lister = 0; $numcount=0; } } }
Re: Math::XOR problem
by jwkrahn (Abbot) on Apr 07, 2007 at 23:32 UTC
    This seems to work pretty well:
    #!/usr/bin/perl use warnings; use strict; my $msg = join '', map chr, ( 79, 59, 12, 2, 79, 35, 8, 28, 20, 2, 3, 68, 8, 9, 68, 45, 0 +, 12, 9, 67, 68, 4, 7, 5, 23, 27, 1, 21, 79, 85, 78, 79, 85, 71, 38, 10, 71, 27, 12, 2, 79, 6 +, 2, 8, 13, 9, 1, 13, 9, 8, 68, 19, 7, 1, 71, 56, 11, 21, 11, 68, 6, 3, 22, 2, 14, 0, 30 +, 79, 1, 31, 6, 23, 19, 10, 0, 73, 79, 44, 2, 79, 19, 6, 28, 68, 16, 6, 16, 15, 79, 35, 8, 11 +, 72, 71, 14, 10, 3, 79, 12, 2, 79, 19, 6, 28, 68, 32, 0, 0, 73, 79, 86, 71, 39, 1, 71, 24, 5 +, 20, 79, 13, 9, 79, 16, 15, 10, 68, 5, 10, 3, 14, 1, 10, 14, 1, 3, 71, 24, 13, 19, 7, 68, 32 +, 0, 0, 73, 79, 87, 71, 39, 1, 71, 12, 22, 2, 14, 16, 2, 11, 68, 2, 25, 1, 21, 22, 16, 15, 6 +, 10, 0, 79, 16, 15, 10, 22, 2, 79, 13, 20, 65, 68, 41, 0, 16, 15, 6, 10, 0, 79, 1, 31, 6, 23 +, 19, 28, 68, 19, 7, 5, 19, 79, 12, 2, 79, 0, 14, 11, 10, 64, 27, 68, 10, 14, 15, 2, 65, 68, 83 +, 79, 40, 14, 9, 1, 71, 6, 16, 20, 10, 8, 1, 79, 19, 6, 28, 68, 14, 1, 68, 15, 6, 9, 75, 79 +, 5, 9, 11, 68, 19, 7, 13, 20, 79, 8, 14, 9, 1, 71, 8, 13, 17, 10, 23, 71, 3, 13, 0, 7, 16 +, 71, 27, 11, 71, 10, 18, 2, 29, 29, 8, 1, 1, 73, 79, 81, 71, 59, 12, 2, 79, 8, 14, 8, 12, 19 +, 79, 23, 15, 6, 10, 2, 28, 68, 19, 7, 22, 8, 26, 3, 15, 79, 16, 15, 10, 68, 3, 14, 22, 12, 1 +, 1, 20, 28, 72, 71, 14, 10, 3, 79, 16, 15, 10, 68, 3, 14, 22, 12, 1, 1, 20, 28, 68, 4, 14, 10 +, 71, 1, 1, 17, 10, 22, 71, 10, 28, 19, 6, 10, 0, 26, 13, 20, 7, 68, 14, 27, 74, 71, 89, 68, 32 +, 0, 0, 71, 28, 1, 9, 27, 68, 45, 0, 12, 9, 79, 16, 15, 10, 68, 37, 14, 20, 19, 6, 23, 19, 79 +, 83, 71, 27, 11, 71, 27, 1, 11, 3, 68, 2, 25, 1, 21, 22, 11, 9, 10, 68, 6, 13, 11, 18, 27, 68 +, 19, 7, 1, 71, 3, 13, 0, 7, 16, 71, 28, 11, 71, 27, 12, 6, 27, 68, 2, 25, 1, 21, 22, 11, 9 +, 10, 68, 10, 6, 3, 15, 27, 68, 5, 10, 8, 14, 10, 18, 2, 79, 6, 2, 12, 5, 18, 28, 1, 71, 0 +, 2, 71, 7, 13, 20, 79, 16, 2, 28, 16, 14, 2, 11, 9, 22, 74, 71, 87, 68, 45, 0, 12, 9, 79, 12 +, 14, 2, 23, 2, 3, 2, 71, 24, 5, 20, 79, 10, 8, 27, 68, 19, 7, 1, 71, 3, 13, 0, 7, 16, 92 +, 79, 12, 2, 79, 19, 6, 28, 68, 8, 1, 8, 30, 79, 5, 71, 24, 13, 19, 1, 1, 20, 28, 68, 19, 0 +, 68, 19, 7, 1, 71, 3, 13, 0, 7, 16, 73, 79, 93, 71, 59, 12, 2, 79, 11, 9, 10, 68, 16, 7, 11 +, 71, 6, 23, 71, 27, 12, 2, 79, 16, 21, 26, 1, 71, 3, 13, 0, 7, 16, 75, 79, 19, 15, 0, 68, 0 +, 6, 18, 2, 28, 68, 11, 6, 3, 15, 27, 68, 19, 0, 68, 2, 25, 1, 21, 22, 11, 9, 10, 72, 71, 24 +, 5, 20, 79, 3, 8, 6, 10, 0, 79, 16, 8, 79, 7, 8, 2, 1, 71, 6, 10, 19, 0, 68, 19, 7, 1 +, 71, 24, 11, 21, 3, 0, 73, 79, 85, 87, 79, 38, 18, 27, 68, 6, 3, 16, 15, 0, 17, 0, 7, 68, 19 +, 7, 1, 71, 24, 11, 21, 3, 0, 71, 24, 5, 20, 79, 9, 6, 11, 1, 71, 27, 12, 21, 0, 17, 0, 7 +, 68, 15, 6, 9, 75, 79, 16, 15, 10, 68, 16, 0, 22, 11, 11, 68, 3, 6, 0, 9, 72, 16, 71, 29, 1 +, 4, 0, 3, 9, 6, 30, 2, 79, 12, 14, 2, 68, 16, 7, 1, 9, 79, 12, 2, 79, 7, 6, 2, 1, 73 +, 79, 85, 86, 79, 33, 17, 10, 10, 71, 6, 10, 71, 7, 13, 20, 79, 11, 16, 1, 68, 11, 14, 10, 3, 79 +, 5, 9, 11, 68, 6, 2, 11, 9, 8, 68, 15, 6, 23, 71, 0, 19, 9, 79, 20, 2, 0, 20, 11, 10, 72 +, 71, 7, 1, 71, 24, 5, 20, 79, 10, 8, 27, 68, 6, 12, 7, 2, 31, 16, 2, 11, 74, 71, 94, 86, 71 +, 45, 17, 19, 79, 16, 8, 79, 5, 11, 3, 68, 16, 7, 11, 71, 13, 1, 11, 6, 1, 17, 10, 0, 71, 7 +, 13, 10, 79, 5, 9, 11, 68, 6, 12, 7, 2, 31, 16, 2, 11, 68, 15, 6, 9, 75, 79, 12, 2, 79, 3 +, 6, 25, 1, 71, 27, 12, 2, 79, 22, 14, 8, 12, 19, 79, 16, 8, 79, 6, 2, 12, 11, 10, 10, 68, 4 +, 7, 13, 11, 11, 22, 2, 1, 68, 8, 9, 68, 32, 0, 0, 73, 79, 85, 84, 79, 48, 15, 10, 29, 71, 14 +, 22, 2, 79, 22, 2, 13, 11, 21, 1, 69, 71, 59, 12, 14, 28, 68, 14, 28, 68, 9, 0, 16, 71, 14, 68 +, 23, 7, 29, 20, 6, 7, 6, 3, 68, 5, 6, 22, 19, 7, 68, 21, 10, 23, 18, 3, 16, 14, 1, 3, 71 +, 9, 22, 8, 2, 68, 15, 26, 9, 6, 1, 68, 23, 14, 23, 20, 6, 11, 9, 79, 11, 21, 79, 20, 11, 14 +, 10, 75, 79, 16, 15, 6, 23, 71, 29, 1, 5, 6, 22, 19, 7, 68, 4, 0, 9, 2, 28, 68, 1, 29, 11 +, 10, 79, 35, 8, 11, 74, 86, 91, 68, 52, 0, 68, 19, 7, 1, 71, 56, 11, 21, 11, 68, 5, 10, 7, 6 +, 2, 1, 71, 7, 17, 10, 14, 10, 71, 14, 10, 3, 79, 8, 14, 25, 1, 3, 79, 12, 2, 29, 1, 71, 0 +, 10, 71, 10, 5, 21, 27, 12, 71, 14, 9, 8, 1, 3, 71, 26, 23, 73, 79, 44, 2, 79, 19, 6, 28, 68 +, 1, 26, 8, 11, 79, 11, 1, 79, 17, 9, 9, 5, 14, 3, 13, 9, 8, 68, 11, 0, 18, 2, 79, 5, 9 +, 11, 68, 1, 14, 13, 19, 7, 2, 18, 3, 10, 2, 28, 23, 73, 79, 37, 9, 11, 68, 16, 10, 68, 15, 14 +, 18, 2, 79, 23, 2, 10, 10, 71, 7, 13, 20, 79, 3, 11, 0, 22, 30, 67, 68, 19, 7, 1, 71, 8, 8 +, 8, 29, 29, 71, 0, 2, 71, 27, 12, 2, 79, 11, 9, 3, 29, 71, 60, 11, 9, 79, 11, 1, 79, 16, 15 +, 10, 68, 33, 14, 16, 15, 10, 22, 73 ); for my $key ( 'aaa' .. 'zzz' ) { my $plain = $msg ^ substr $key x length $msg, 0, length $msg; my @words = split ' ', $plain; # some heuristics to weed out bad plain text next if @words > length( $msg ) / 3 or @words < length( $msg ) / 8 +; next if $plain =~ /[^[:print:]]/; next if grep( /\b\W+\b/, @words ) > @words / 10; print "Key: $key\n$plain\n\n"; } __END__
      TIMTOWTDI:
      my $msg = pack('C'.@s, @s);
      Or even 'C*' as template.
      :D
      Thanks mate, this is wonderful; though I will keep digging through my own crappy code to see what i did differently and incorrectly.

      Thank you again!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://608863]
Approved by Joost
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (6)
As of 2024-04-25 08:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found