File Coverage

blib/lib/Crypt/DSA.pm
Criterion Covered Total %
statement 86 86 100.0
branch 12 24 50.0
condition 2 6 33.3
subroutine 15 15 100.0
pod 4 4 100.0
total 119 135 88.1


line stmt bran cond sub pod time code
1             package Crypt::DSA;
2              
3 5     5   974022 use 5.006;
  5         21  
4 5     5   26 use strict;
  5         37  
  5         147  
5 5     5   21 use warnings;
  5         8  
  5         308  
6 5     5   2930 use Digest::SHA qw( sha1 );
  5         18280  
  5         579  
7 5     5   38 use Carp qw( croak );
  5         9  
  5         246  
8 5     5   2703 use Crypt::DSA::KeyChain;
  5         21  
  5         242  
9 5     5   71 use Crypt::DSA::Key;
  5         12  
  5         139  
10 5     5   2930 use Crypt::DSA::Signature;
  5         17  
  5         244  
11 5     5   35 use Crypt::DSA::Util qw( bitsize bin2mp mod_inverse mod_exp makerandom );
  5         11  
  5         500  
12              
13             our $VERSION = '1.20'; #VERSION
14              
15 5     5   32 use vars qw( $VERSION );
  5         11  
  5         4857  
16              
17             sub new {
18 2     2 1 428278 my $class = shift;
19 2         10 my $dsa = bless { @_ }, $class;
20 2         28 $dsa->{_keychain} = Crypt::DSA::KeyChain->new(@_);
21 2         8 $dsa;
22             }
23              
24             sub keygen {
25 1     1 1 5 my $dsa = shift;
26 1         8 my $key = $dsa->{_keychain}->generate_params(@_);
27 1         95 $dsa->{_keychain}->generate_keys($key);
28 1         75 $key;
29             }
30              
31             sub sign {
32 1     1 1 39 my $dsa = shift;
33 1         51 my %param = @_;
34 1         3 my($key, $dgst);
35 1 50       15 croak __PACKAGE__, "->sign: Need a Key" unless $key = $param{Key};
36 1 50       30 unless ($dgst = $param{Digest}) {
37             croak __PACKAGE__, "->sign: Need either Message or Digest"
38 1 50       14 unless $param{Message};
39 1         32 $dgst = sha1($param{Message});
40             }
41 1         12 my $dlen = length $dgst;
42              
43 1         7 my $i = bitsize($key->q) / 8;
44 1 50 33     919 croak "Data too large for key size"
45             if $dlen > $i || $dlen > 50;
46              
47 1 50 33     30 $dsa->_sign_setup($key)
48             unless $key->kinv && $key->r;
49              
50 1         23 my $m = bin2mp($dgst);
51 1         1115 my $xr = ($key->priv_key * $key->r) % $key->q;
52 1         675 my $s = $xr + $m;
53 1 50       228 $s -= $key->q if $s > $key->q;
54 1         129 $s = ($s * $key->kinv) % $key->q;
55              
56 1         701 my $sig = Crypt::DSA::Signature->new;
57 1         21 $sig->r($key->r);
58 1         8 $sig->s($s);
59 1         12 $sig;
60             }
61              
62             sub _sign_setup {
63 1     1   3 my $dsa = shift;
64 1         2 my $key = shift;
65 1         3 my($k, $r);
66             {
67 1         18 $k = makerandom(Size => bitsize($key->q));
  1         28  
68 1 50       1022 $k -= $key->q if $k >= $key->q;
69 1 50       229 redo if $k == 0;
70             }
71 1         289 $r = mod_exp($key->g, $k, $key->p);
72 1         561589 $r %= $key->q;
73 1         952 my $kinv = mod_inverse($k, $key->q);
74 1         17612 $key->r($r);
75 1         6 $key->kinv($kinv);
76             }
77              
78             sub verify {
79 1     1 1 4 my $dsa = shift;
80 1         7 my %param = @_;
81 1         3 my($key, $dgst, $sig);
82 1 50       6 croak __PACKAGE__, "->verify: Need a Key" unless $key = $param{Key};
83 1 50       8 unless ($dgst = $param{Digest}) {
84             croak __PACKAGE__, "->verify: Need either Message or Digest"
85 1 50       5 unless $param{Message};
86 1         18 $dgst = sha1($param{Message});
87             }
88             croak __PACKAGE__, "->verify: Need a Signature"
89 1 50       6 unless $sig = $param{Signature};
90 1         4 my $u2 = mod_inverse($sig->s, $key->q);
91 1         18402 my $u1 = bin2mp($dgst);
92 1         1280 $u1 = ($u1 * $u2) % $key->q;
93 1         622 $u2 = ($sig->r * $u2) % $key->q;
94 1         640 my $t1 = mod_exp($key->g, $u1, $key->p);
95 1         2153636 my $t2 = mod_exp($key->pub_key, $u2, $key->p);
96 1         2404080 $u1 = ($t1 * $t2) % $key->p;
97 1         6822 $u1 %= $key->q;
98 1         1746 $u1 == $sig->r;
99             }
100              
101             1;
102              
103             __END__