#!/usr/bin/perl -w # encode_msg.pl - Don Yang (uguu.org) # # Generate filler text for 3-way XOR encoding, to be embedded in akari1.c # # 12/25/11 use strict; # Extra bits to toggle my $xor_key = 4; # Filler text for 2+ unknowns my $fill_text = "yuriyurarararayuruyuri"; my $fill_index = 0; sub is_valid_char($) { my ($c) = @_; return $c >= 33 && $c < 127 && $c != ord('\\') && $c != ord('"'); } sub solve_unknown($$$$$$) { my ($index, $unknowns, $x, $y, $z, $t) = @_; my $x0 = ord($x); my $y0 = ord($y); my $z0 = ord($z); my $t0 = ord($t); if( $x eq 'X' ) { $x0 = $y0 ^ $z0 ^ $t0 ^ $xor_key; unless( is_valid_char($x0) ) { die "Unsolvable: offset=$index, unknowns=$unknowns, input=$x^$y^$z^($xor_key), target=$t, candidate=$x0\n"; } } elsif( $y eq 'X' ) { $y0 = $x0 ^ $z0 ^ $t0 ^ $xor_key; unless( is_valid_char($y0) ) { die "Unsolvable: offset=$index, unknowns=$unknowns, input=$x^$y^$z^($xor_key), target=$t, candidate=$y0\n"; } } elsif( $z eq 'X' ) { $z0 = $x0 ^ $y0 ^ $t0 ^ $xor_key; unless( is_valid_char($z0) ) { die "Unsolvable: offset=$index, unknowns=$unknowns, input=$x^$y^$z^($xor_key), target=$t, candidate=$z0\n"; } } return (chr($x0), chr($y0), chr($z0)); } sub generate_filler($) { my ($index) = @_; if( $index == 41 || $index == 52 || $index == 59 ) { return '*'; } my $c = substr($fill_text, $fill_index, 1); $fill_index++; if( $fill_index == length($fill_text) ) { $fill_index = 0; } return $c; } my $a = # 1 2 #0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 "yuriyurarararayuruyuri*daijiken**akkari~n**" . # 3 4 5 # 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 "/X*X*X/XiXnXtX(XyX)X,XuX,XrX[X1X2X8X*X2X/X*X{XXX}XXXcXXXhXXXaXXXrXXX*XXXyXXX=" . #6 7 8 9 10 #0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" . # 11 12 13 # 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 "*X/f]`;hvroaiXdp/f*i*s/Xii(f)a{tpguatXcahfaurh(Xuf)a;f}vivnXtf/g*`*w/jmaaXi`ni(" . #14 #0 1 2 3 4 5 6 7 8 9 "iXkXXXbXiXXXbXXXlXrb"; my $b = # 1 2 #01234567890123456789012 "XXXXXXXXXXXXXXXXXXXXXXX" . # 3 4 5 6 7 8 9 10 #34567 89012345678901234567890123456789012345678901234567890123456 789 012345678901 "X(XX\"XXX)XXXXXXX{XXXXXXXpXXXXXXXuXXXXXXXtXXXXX XsXXXXXXX(XXXXXX\"XX\"XXXYURUYURI"; my $target = "vuwicucaeaaapavugueuXi`diihikek*j*wkfrf~c*m" . "/e*a*h/himnntd(dyv)f,fue,`r`[g1q2n8g*`2X/`*a{oXo}XXXchXhhqXtahXhr`Xp*sXjyXXX=" . "hX`XkXuXjXXXhXiXbXbXlXlXhXhXbXbXxXlXfXgXdXcX`XaXfXfXfXdX`X`XfXgXpXpXrXiX`X`XgXqXX" . "*X/f]`;hvroaiXdp/f*i*s/Xii(f)a{tpguatXcahfaurh(Xuf)a;f}vivnXtf/g*`*w/jmaaXi`ni(" . "iXkXXXbXiXXXbXXXlXrb"; # Output original print "a=\n$a\nb=\n$b\n"; # XOR pad is only so long, so check that the unpadded parts are # solvable if( substr($a, length($b) * 2) ne substr($target, length($b) * 2) ) { die "Prefix of \$a requires longer \$b\n"; } for(my $i = 0; $i < length($b); $i++) { my $x = substr($a, $i * 2, 1); my $y = substr($a, $i * 2 + 1, 1); my $z = substr($b, $i, 1); my $t = substr($target, $i * 2, 1); # Check number of unknowns my $unknowns = 0; $unknowns++ if $x eq 'X'; $unknowns++ if $y eq 'X'; $unknowns++ if $z eq 'X'; if( $unknowns == 0 ) { # All 3 bytes are set, verify that they check out unless( ord($t) == (ord($x) ^ ord($y) ^ ord($z) ^ $xor_key) ) { die "Invalid: offset=$i, input=$x^$y^$z^$xor_key, target=$t\n"; } } elsif( $unknowns == 1 ) { # One unknown, pick a byte that's reasonable ($x, $y, $z) = solve_unknown($i, $unknowns, $x, $y, $z, $t); substr($a, $i * 2, 1) = $x; substr($a, $i * 2 + 1, 1) = $y; substr($b, $i, 1) = $z; } elsif( $unknowns == 2 ) { # 2 unknowns, replace one with filler byte if( $x eq 'X' ) { $x = generate_filler($i); } elsif( $y eq 'X' ) { $y = generate_filler($i); } else { die; } ($x, $y, $z) = solve_unknown($i, $unknowns, $x, $y, $z, $t); substr($a, $i * 2, 1) = $x; substr($a, $i * 2 + 1, 1) = $y; substr($b, $i, 1) = $z; } else { # All 3 bytes can be unknowns, don't care about any of them die unless $unknowns == 3; $x = generate_filler($i); $y = generate_filler($i); ($x, $y, $z) = solve_unknown($i, $unknowns, $x, $y, $z, $t); substr($a, $i * 2, 1) = $x; substr($a, $i * 2 + 1, 1) = $y; substr($b, $i, 1) = $z; } } print "length=", length($b), "\n"; print "a=\n$a\nb=\n$b\n";