File Coverage

blib/lib/Crypt/DSA.pm
Criterion Covered Total %
statement 83 83 100.0
branch 12 24 50.0
condition 2 6 33.3
subroutine 14 14 100.0
pod 4 4 100.0
total 115 131 87.7


line stmt bran cond sub pod time code
1             package Crypt::DSA;
2              
3 5     5   962509 use 5.006;
  5         20  
4 5     5   29 use strict;
  5         25  
  5         232  
5 5     5   3194 use Digest::SHA qw( sha1 );
  5         22012  
  5         564  
6 5     5   89 use Carp qw( croak );
  5         25  
  5         339  
7 5     5   2974 use Crypt::DSA::KeyChain;
  5         23  
  5         236  
8 5     5   34 use Crypt::DSA::Key;
  5         10  
  5         152  
9 5     5   2841 use Crypt::DSA::Signature;
  5         19  
  5         237  
10 5     5   36 use Crypt::DSA::Util qw( bitsize bin2mp mod_inverse mod_exp makerandom );
  5         10  
  5         465  
11              
12             our $VERSION = '1.19'; #VERSION
13              
14 5     5   33 use vars qw( $VERSION );
  5         9  
  5         4394  
15              
16             sub new {
17 2     2 1 406949 my $class = shift;
18 2         10 my $dsa = bless { @_ }, $class;
19 2         24 $dsa->{_keychain} = Crypt::DSA::KeyChain->new(@_);
20 2         7 $dsa;
21             }
22              
23             sub keygen {
24 1     1 1 6 my $dsa = shift;
25 1         7 my $key = $dsa->{_keychain}->generate_params(@_);
26 1         30 $dsa->{_keychain}->generate_keys($key);
27 1         59 $key;
28             }
29              
30             sub sign {
31 1     1 1 59 my $dsa = shift;
32 1         42 my %param = @_;
33 1         29 my($key, $dgst);
34 1 50       27 croak __PACKAGE__, "->sign: Need a Key" unless $key = $param{Key};
35 1 50       16 unless ($dgst = $param{Digest}) {
36             croak __PACKAGE__, "->sign: Need either Message or Digest"
37 1 50       14 unless $param{Message};
38 1         13 $dgst = sha1($param{Message});
39             }
40 1         3 my $dlen = length $dgst;
41              
42 1         33 my $i = bitsize($key->q) / 8;
43 1 50 33     934 croak "Data too large for key size"
44             if $dlen > $i || $dlen > 50;
45              
46 1 50 33     6 $dsa->_sign_setup($key)
47             unless $key->kinv && $key->r;
48              
49 1         21 my $m = bin2mp($dgst);
50 1         583 my $xr = ($key->priv_key * $key->r) % $key->q;
51 1         344 my $s = $xr + $m;
52 1 50       114 $s -= $key->q if $s > $key->q;
53 1         68 $s = ($s * $key->kinv) % $key->q;
54              
55 1         377 my $sig = Crypt::DSA::Signature->new;
56 1         15 $sig->r($key->r);
57 1         5 $sig->s($s);
58 1         7 $sig;
59             }
60              
61             sub _sign_setup {
62 1     1   24 my $dsa = shift;
63 1         25 my $key = shift;
64 1         3 my($k, $r);
65             {
66 1         2 $k = makerandom(Size => bitsize($key->q));
  1         29  
67 1 50       755 $k -= $key->q if $k >= $key->q;
68 1 50       228 redo if $k == 0;
69             }
70 1         295 $r = mod_exp($key->g, $k, $key->p);
71 1         713737 $r %= $key->q;
72 1         513 my $kinv = mod_inverse($k, $key->q);
73 1         10823 $key->r($r);
74 1         22 $key->kinv($kinv);
75             }
76              
77             sub verify {
78 1     1 1 3 my $dsa = shift;
79 1         7 my %param = @_;
80 1         3 my($key, $dgst, $sig);
81 1 50       6 croak __PACKAGE__, "->verify: Need a Key" unless $key = $param{Key};
82 1 50       5 unless ($dgst = $param{Digest}) {
83             croak __PACKAGE__, "->verify: Need either Message or Digest"
84 1 50       8 unless $param{Message};
85 1         11 $dgst = sha1($param{Message});
86             }
87             croak __PACKAGE__, "->verify: Need a Signature"
88 1 50       6 unless $sig = $param{Signature};
89 1         5 my $u2 = mod_inverse($sig->s, $key->q);
90 1         21056 my $u1 = bin2mp($dgst);
91 1         1398 $u1 = ($u1 * $u2) % $key->q;
92 1         735 $u2 = ($sig->r * $u2) % $key->q;
93 1         706 my $t1 = mod_exp($key->g, $u1, $key->p);
94 1         2549475 my $t2 = mod_exp($key->pub_key, $u2, $key->p);
95 1         2260113 $u1 = ($t1 * $t2) % $key->p;
96 1         6845 $u1 %= $key->q;
97 1         1759 $u1 == $sig->r;
98             }
99              
100             1;
101              
102             __END__