home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / perl / DH1.pm < prev    next >
Encoding:
Perl POD Document  |  2003-12-03  |  4.7 KB  |  179 lines

  1. # $Id: DH1.pm,v 1.17 2003/12/03 15:35:21 autarch Exp $
  2.  
  3. package Net::SSH::Perl::Kex::DH1;
  4. use strict;
  5.  
  6. use Net::SSH::Perl::Buffer;
  7. use Net::SSH::Perl::Packet;
  8. use Net::SSH::Perl::Constants qw( :msg2 :kex );
  9. use Net::SSH::Perl::Key;
  10. use Net::SSH::Perl::Util qw( bitsize );
  11.  
  12. use Carp qw( croak );
  13. use Crypt::DH;
  14. use Math::Pari;
  15. use Digest::SHA1 qw( sha1 );
  16. use Scalar::Util qw(weaken);
  17.  
  18. use Net::SSH::Perl::Kex;
  19. use base qw( Net::SSH::Perl::Kex );
  20.  
  21. sub new {
  22.     my $class = shift;
  23.     my $ssh = shift;
  24.     my $kex = bless { ssh => $ssh }, $class;
  25.     weaken $kex->{ssh};
  26.     $kex;
  27. }
  28.  
  29. sub exchange {
  30.     my $kex = shift;
  31.     my $ssh = $kex->{ssh};
  32.     my $packet;
  33.     my $dh = _dh_new_group1();
  34.  
  35.     $ssh->debug("Entering Diffie-Hellman Group 1 key exchange.");
  36.     $packet = $ssh->packet_start(SSH2_MSG_KEXDH_INIT);
  37.     $packet->put_mp_int($dh->pub_key);
  38.     $packet->send;
  39.  
  40.     $ssh->debug("Sent DH public key, waiting for reply.");
  41.     $packet = Net::SSH::Perl::Packet->read_expect($ssh,
  42.         SSH2_MSG_KEXDH_REPLY);
  43.  
  44.     my $host_key_blob = $packet->get_str;
  45.     my $s_host_key = Net::SSH::Perl::Key->new_from_blob($host_key_blob,
  46.         \$ssh->{datafellows});
  47.     $ssh->debug("Received host key, type '" . $s_host_key->ssh_name . "'.");
  48.  
  49.     $ssh->check_host_key($s_host_key);
  50.  
  51.     my $dh_server_pub = $packet->get_mp_int;
  52.     my $signature = $packet->get_str;
  53.  
  54.     $ssh->fatal_disconnect("Bad server public DH value")
  55.         unless _pub_is_valid($dh, $dh_server_pub);
  56.  
  57.     $ssh->debug("Computing shared secret key.");
  58.     my $shared_secret = $dh->compute_key($dh_server_pub);
  59.  
  60.     my $hash = $kex->kex_hash(
  61.         $ssh->client_version_string,
  62.         $ssh->server_version_string,
  63.         $kex->client_kexinit,
  64.         $kex->server_kexinit,
  65.         $host_key_blob,
  66.         $dh->pub_key,
  67.         $dh_server_pub,
  68.         $shared_secret);
  69.  
  70.     $ssh->debug("Verifying server signature.");
  71.     croak "Key verification failed for server host key"
  72.         unless $s_host_key->verify($signature, $hash);
  73.  
  74.     $kex->derive_keys($hash, $shared_secret);
  75.     $ssh->{kex} = $kex;
  76.  
  77.     $ssh->session_id($hash);
  78. }
  79.  
  80. sub kex_hash {
  81.     my $kex = shift;
  82.     my($c_vs, $s_vs, $c_kexinit, $s_kexinit, $s_host_key_blob,
  83.        $c_dh_pub, $s_dh_pub, $shared_secret) = @_;
  84.     my $b = Net::SSH::Perl::Buffer->new( MP => 'SSH2' );
  85.     $b->put_str($c_vs);
  86.     $b->put_str($s_vs);
  87.  
  88.     $b->put_int32($c_kexinit->length + 1);
  89.     $b->put_int8(SSH2_MSG_KEXINIT);
  90.     $b->put_chars($c_kexinit->bytes);
  91.     $b->put_int32($s_kexinit->length + 1);
  92.     $b->put_int8(SSH2_MSG_KEXINIT);
  93.     $b->put_chars($s_kexinit->bytes);
  94.  
  95.     $b->put_str($s_host_key_blob);
  96.     $b->put_mp_int($c_dh_pub);
  97.     $b->put_mp_int($s_dh_pub);
  98.     $b->put_mp_int($shared_secret);
  99.  
  100.     sha1($b->bytes);
  101. }
  102.  
  103. sub _dh_new_group1 {
  104.     my $dh = Crypt::DH->new;
  105.     $dh->g(2);
  106.     $dh->p("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF");
  107.     _gen_key($dh);
  108.     $dh;
  109. }
  110.  
  111. sub _pub_is_valid {
  112.     my($dh, $dh_pub) = @_;
  113.     return if $dh_pub < 0;
  114.  
  115.     my $bits_set = 0;
  116.     my $n = bitsize($dh_pub);
  117.     for my $i (0..$n) {
  118.     $bits_set++ if $dh_pub & (PARI(1) << PARI($i));
  119.         last if $bits_set > 1;
  120.     }
  121.  
  122.     $bits_set > 1 && $dh_pub < $dh->p;
  123. }
  124.  
  125. sub _gen_key {
  126.     my $dh = shift;
  127.     my $tries = 0;
  128.     {
  129.     $dh->generate_keys;
  130.     last if _pub_is_valid($dh, $dh->pub_key);
  131.     croak "Too many bad keys: giving up" if $tries++ > 10;
  132.     }
  133. }
  134.  
  135. 1;
  136. __END__
  137.  
  138. =head1 NAME
  139.  
  140. Net::SSH::Perl::Kex::DH1 - Diffie-Hellman Group 1 Key Exchange
  141.  
  142. =head1 SYNOPSIS
  143.  
  144.     use Net::SSH::Perl::Kex;
  145.     my $kex = Net::SSH::Perl::Kex->new;
  146.     my $dh1 = bless $kex, 'Net::SSH::Perl::Kex::DH1';
  147.  
  148.     $dh1->exchange;
  149.  
  150. =head1 DESCRIPTION
  151.  
  152. I<Net::SSH::Perl::Kex::DH1> implements Diffie-Hellman Group 1 Key
  153. Exchange for I<Net::SSH::Perl>. It is a subclass of
  154. I<Net::SSH::Perl::Kex>.
  155.  
  156. Group 1 Key Exchange uses the Diffie-Hellman key exchange algorithm
  157. to produce a shared seret key between client and server, without
  158. ever sending the shared secret over the insecure network. All that is
  159. sent are the client and server public keys.
  160.  
  161. I<Net::SSH::Perl::Kex::DH1> uses I<Crypt::DH> for the Diffie-Hellman
  162. implementation. The I<p> value is set to
  163.  
  164.       FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
  165.       29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
  166.       EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
  167.       E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
  168.       EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381
  169.       FFFFFFFF FFFFFFFF
  170.  
  171. And the generator I<g> is set to I<2>.
  172.  
  173. =head1 AUTHOR & COPYRIGHTS
  174.  
  175. Please see the Net::SSH::Perl manpage for author, copyright, and
  176. license information.
  177.  
  178. =cut
  179.