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 / DSA.pm < prev    next >
Encoding:
Perl POD Document  |  2001-07-11  |  5.3 KB  |  209 lines

  1. # $Id: DSA.pm,v 1.23 2001/07/11 21:57:33 btrott Exp $
  2.  
  3. package Net::SSH::Perl::Key::DSA;
  4. use strict;
  5.  
  6. use Net::SSH::Perl::Buffer;
  7. use Net::SSH::Perl::Constants qw( SSH_COMPAT_BUG_SIGBLOB );
  8. use Net::SSH::Perl::Util qw( :ssh2mp );
  9.  
  10. use Net::SSH::Perl::Key;
  11. use base qw( Net::SSH::Perl::Key );
  12.  
  13. use MIME::Base64;
  14. use Crypt::DSA;
  15. use Crypt::DSA::Key;
  16. use Carp qw( croak );
  17. use Digest::SHA1 qw( sha1 );
  18.  
  19. use constant INTBLOB_LEN => 20;
  20.  
  21. sub ssh_name { 'ssh-dss' }
  22.  
  23. sub init {
  24.     my $key = shift;
  25.     $key->{dsa} = Crypt::DSA::Key->new;
  26.  
  27.     my($blob, $datafellows) = @_;
  28.  
  29.     if ($blob) {
  30.         my $b = Net::SSH::Perl::Buffer->new( MP => 'SSH2' );
  31.         $b->append($blob);
  32.         my $ktype = $b->get_str;
  33.         croak __PACKAGE__, "->init: cannot handle type '$ktype'"
  34.             unless $ktype eq $key->ssh_name;
  35.         my $dsa = $key->{dsa};
  36.         $dsa->p( $b->get_mp_int );
  37.         $dsa->q( $b->get_mp_int );
  38.         $dsa->g( $b->get_mp_int );
  39.         $dsa->pub_key( $b->get_mp_int );
  40.     }
  41.  
  42.     if ($datafellows) {
  43.         $key->{datafellows} = $datafellows;
  44.     }
  45. }
  46.  
  47. sub keygen {
  48.     my $class = shift;
  49.     my($bits, $datafellows) = @_;
  50.     my $dsa = Crypt::DSA->new;
  51.     my $key = $class->new(undef, $datafellows);
  52.     $key->{dsa} = $dsa->keygen(Size => $bits, Verbosity => 1);
  53.     $key;
  54. }
  55.  
  56. sub size { $_[0]->{dsa}->size }
  57.  
  58. sub read_private {
  59.     my $class = shift;
  60.     my($key_file, $passphrase, $datafellows, $keytype) = @_;
  61.     $keytype ||= 'PEM';
  62.  
  63.     my $key = $class->new(undef, $datafellows);
  64.     $key->{dsa} = Crypt::DSA::Key->new(
  65.                      Filename => $key_file,
  66.                      Type     => $keytype,
  67.                      Password => $passphrase
  68.             );
  69.     return unless $key->{dsa};
  70.  
  71.     $key;
  72. }
  73.  
  74. sub write_private {
  75.     my $key = shift;
  76.     my($key_file, $passphrase) = @_;
  77.  
  78.     $key->{dsa}->write(
  79.                     Filename => $key_file,
  80.                     Type     => 'PEM',
  81.                     Password => $passphrase
  82.             );
  83. }
  84.  
  85. sub dump_public { $_[0]->ssh_name . ' ' . encode_base64( $_[0]->as_blob, '' ) }
  86.  
  87. sub sign {
  88.     my $key = shift;
  89.     my($data) = @_;
  90.     my $dsa = Crypt::DSA->new;
  91.     my $sig = $dsa->sign(Digest => sha1($data), Key => $key->{dsa});
  92.     my $sigblob = '';
  93.     $sigblob .= mp2bin($sig->r, INTBLOB_LEN);
  94.     $sigblob .= mp2bin($sig->s, INTBLOB_LEN);
  95.  
  96.     if (${$key->{datafellows}} & SSH_COMPAT_BUG_SIGBLOB) {
  97.         return $sigblob;
  98.     }
  99.     else {
  100.         my $b = Net::SSH::Perl::Buffer->new( MP => 'SSH2' );
  101.         $b->put_str($key->ssh_name);
  102.         $b->put_str($sigblob);
  103.         $b->bytes;
  104.     }
  105. }
  106.  
  107. sub verify {
  108.     my $key = shift;
  109.     my($signature, $data) = @_;
  110.     my $sigblob;
  111.  
  112.     if (${$key->{datafellows}} & SSH_COMPAT_BUG_SIGBLOB) {
  113.         $sigblob = $signature;
  114.     }
  115.     else {
  116.         my $b = Net::SSH::Perl::Buffer->new( MP => 'SSH2' );
  117.         $b->append($signature);
  118.         my $ktype = $b->get_str;
  119.         croak "Can't verify type ", $ktype unless $ktype eq $key->ssh_name;
  120.         $sigblob = $b->get_str;
  121.     }
  122.  
  123.     my $sig = Crypt::DSA::Signature->new;
  124.     $sig->r( bin2mp(substr $sigblob, 0, INTBLOB_LEN) );
  125.     $sig->s( bin2mp(substr $sigblob, INTBLOB_LEN) );
  126.  
  127.     my $digest = sha1($data);
  128.     my $dsa = Crypt::DSA->new;
  129.     $dsa->verify( Key => $key->{dsa}, Digest => $digest, Signature => $sig );
  130. }
  131.  
  132. sub equal {
  133.     my($keyA, $keyB) = @_;
  134.     $keyA->{dsa} && $keyB->{dsa} &&
  135.     $keyA->{dsa}->p == $keyB->{dsa}->p &&
  136.     $keyA->{dsa}->q == $keyB->{dsa}->q &&
  137.     $keyA->{dsa}->g == $keyB->{dsa}->g &&
  138.     $keyA->{dsa}->pub_key == $keyB->{dsa}->pub_key;
  139. }
  140.  
  141. sub as_blob {
  142.     my $key = shift;
  143.     my $b = Net::SSH::Perl::Buffer->new( MP => 'SSH2' );
  144.     $b->put_str($key->ssh_name);
  145.     $b->put_mp_int($key->{dsa}->p);
  146.     $b->put_mp_int($key->{dsa}->q);
  147.     $b->put_mp_int($key->{dsa}->g);
  148.     $b->put_mp_int($key->{dsa}->pub_key);
  149.     $b->bytes;
  150. }
  151.  
  152. sub fingerprint_raw { $_[0]->as_blob }
  153.  
  154. 1;
  155. __END__
  156.  
  157. =head1 NAME
  158.  
  159. Net::SSH::Perl::Key::DSA - DSA key object
  160.  
  161. =head1 SYNOPSIS
  162.  
  163.     use Net::SSH::Perl::Key;
  164.     my $key = Net::SSH::Perl::Key->new('DSA');
  165.  
  166. =head1 DESCRIPTION
  167.  
  168. I<Net::SSH::Perl::Key::DSA> subclasses I<Net::SSH::Perl::Key>
  169. to implement a key object, SSH style. This object provides all
  170. of the methods needed for a DSA key object; the underlying
  171. implementation is provided by I<Crypt::DSA>, and this class
  172. wraps around that module to provide SSH-specific functionality
  173. (eg. taking in a I<Net::SSH::Perl::Buffer> blob and transforming
  174. it into a key object).
  175.  
  176. =head1 USAGE
  177.  
  178. I<Net::SSH::Perl::Key::DSA> implements the interface described in
  179. the documentation for I<Net::SSH::Perl::Key>. Any differences or
  180. additions are described here.
  181.  
  182. =head2 $key->sign($data)
  183.  
  184. Wraps around I<Crypt::DSA::sign> to sign I<$data> using the private
  185. key portions of I<$key>, then encodes that signature into an
  186. SSH-compatible signature blob.
  187.  
  188. Returns the signature blob.
  189.  
  190. =head2 $key->verify($signature, $data)
  191.  
  192. Given a signature blob I<$signature> and the original signed data
  193. I<$data>, attempts to verify the signature using the public key
  194. portion of I<$key>. This wraps around I<Crypt::DSA::verify> to
  195. perform the core verification.
  196.  
  197. I<$signature> should be an SSH-compatible signature blob, as
  198. returned from I<sign>; I<$data> should be a string of data, as
  199. passed to I<sign>.
  200.  
  201. Returns true if the verification succeeds, false otherwise.
  202.  
  203. =head1 AUTHOR & COPYRIGHTS
  204.  
  205. Please see the Net::SSH::Perl manpage for author, copyright,
  206. and license information.
  207.  
  208. =cut
  209.