no title

P2Pの初期パケットの RC4 key は null 文字(\x00)以降は使ってはいけない件。最初からトラックバックにしておけば良かったわけですが、こんな感じで確認できます。

#!/usr/bin/perl

use warnings;
use strict;
use IO::Socket::INET;
use Crypt::RC4;
use Term::ANSIColor qw(:constants);
$Term::ANSIColor::AUTORESET = 1;

my $host = '';
my $port = 0;

for my $i (1..100) {
    my $socket = IO::Socket::INET->new(
        PeerAddr => $host,
        PeerPort => $port,
        Proto    => 'tcp',
    );

    my $buf;
    $socket->recv( $buf, 11 );
    my( $passphrase, $encrypted );
    eval { ( $passphrase, $encrypted ) = unpack "x2a4a5", $buf; };
    if ($@) {
        warn "failed unpack : $buf : $@\n";
        next;
    }

    my $passphrase2 = ( split /\x00/, $passphrase )[0];
    print "-" x 70, "\n";
    if ( $passphrase =~ /\x00/ ) {
        print YELLOW "passphrase has null\n";
        print RESET;
    }
    printf "count      = %s\n", $i;
    printf "passphrase = %s\n", unpack( "H*", $passphrase );
    printf "encrypted  = %s\n", unpack( "H*", $encrypted );
    my( $decrypted1, $decrypted2 );
    eval {
        $decrypted1 = RC4( $passphrase, $encrypted );
        $decrypted2 = RC4( $passphrase2, $encrypted );
    };
    if ($@) {
        warn "failed RC4 : $@\n";
        next;
    }

    printf "decrypted1 = %s\n", unpack( "H*", $decrypted1 );
    printf "decrypted2 = %s\n", unpack( "H*", $decrypted2 );

    $socket->close;
}

これの実行結果を抜粋します。

count      = 73
passphrase = 56502f18
encrypted  = 113b004d27
decrypted1 = 0100000061
decrypted2 = 0100000061
----------------------------------------------------------------------
passphrase has null
count      = 74
passphrase = d50026d3
encrypted  = 32a174e234
decrypted1 = 5462b63502
decrypted2 = 0100000061
----------------------------------------------------------------------
count      = 75
passphrase = c7b3c526
encrypted  = bd2d8b09cf
decrypted1 = 0100000061
decrypted2 = 0100000061

74 回目の passphase に null が含まれているのですが、そのままだと正しく decode されないので null 文字以降を切捨てる必要があります。
ところで最初が null 文字の時の正しい decode 方法を僕は知りません。なんかあるのかな。