Net-BitTorrent

 view release on metacpan or  search on metacpan

lib/Net/BitTorrent/Protocol/MSE/KeyExchange.pm  view on Meta::CPAN

class Net::BitTorrent::Protocol::MSE::KeyExchange v2.1.1 : isa(Net::BitTorrent::Emitter) {
    use Digest::SHA qw[sha1];
    use Crypt::URandom qw[urandom];
    use Math::BigInt try => 'GMP';

    # Parameters
    field $infohash     : param : reader;
    field $is_initiator : param : reader;

    # Internal state
    field $private_key;
    field $public_key : reader;
    field $shared_secret;

    # Cipher state
    field $encrypt_rc4 : reader;
    field $decrypt_rc4 : reader;

    # Store the initial state (post-discard) for the decryptor
    # to optimize the scan_for_vc loop.
    field $decrypt_restore_point;

lib/Net/BitTorrent/Protocol/MSE/KeyExchange.pm  view on Meta::CPAN

    # 768-bit Safe Prime (Big Endian)
    my $P_STR
        = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
        '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
        '4FE1356D6D51C245E485B576625E7EC6F44C42E9A63A36210000000000090563';
    ADJUST {
        my $p = Math::BigInt->from_hex($P_STR);
        my $g = Math::BigInt->new(2);

        # Private Key: Random 160 bits
        $private_key = Math::BigInt->from_bytes( urandom(20) );

        # Public Key: Y = G^X mod P
        my $pub_val = $g->copy->bmodpow( $private_key, $p );
        $public_key = $self->_int_to_bytes($pub_val);
    }

    method _int_to_bytes ($num) {
        my $hex = $num->to_hex;
        $hex =~ s/^0x//i;
        $hex = "0$hex" if length($hex) % 2;
        my $bin = pack( 'H*', $hex );
        if ( length($bin) < 96 ) {
            $bin = ( "\0" x ( 96 - length($bin) ) ) . $bin;

lib/Net/BitTorrent/Protocol/MSE/KeyExchange.pm  view on Meta::CPAN


        # Reject degenerate keys that defeat forward secrecy (RFC 2631 / FIPS 186-4)
        my $two       = Math::BigInt->new(2);
        my $p_minus_2 = $p->copy->bsub($two);
        if ( $remote_val < $two || $remote_val > $p_minus_2 ) {
            $self->_emit_log( 'fatal', 'Remote public key out of valid range [2, P-2]' );
            return undef;
        }

        # S = Y_remote ^ X_local mod P
        my $s_val = $remote_val->copy->bmodpow( $private_key, $p );
        $shared_secret = $self->_int_to_bytes($s_val);
        return $shared_secret;
    }
    method get_secret () { return $shared_secret }

    method get_sync_data ( $override_ih = undef ) {
        my $ih = $override_ih // $infohash;
        return undef unless $ih;
        my $s         = $shared_secret;
        my $sk        = $ih;



( run in 0.888 second using v1.01-cache-2.11-cpan-8dfa8b56332 )