File Coverage

blib/lib/Crypt/DSA.pm
Criterion Covered Total %
statement 81 81 100.0
branch 14 24 58.3
condition 3 6 50.0
subroutine 13 13 100.0
pod 4 4 100.0
total 115 128 89.8


line stmt bran cond sub pod time code
1             # $Id: DSA.pm 1938 2006-05-03 06:20:36Z btrott $
2              
3             package Crypt::DSA;
4 6     6   91 use strict;
  6         128  
  6         98  
5              
6 6     6   210 use Digest::SHA1 qw( sha1 );
  6         63  
  6         86  
7 6     6   111 use Carp qw( croak );
  6         55  
  6         1139  
8              
9 6     6   213 use Crypt::DSA::KeyChain;
  6         85  
  6         181  
10 6     6   104 use Crypt::DSA::Key;
  6         56  
  6         100  
11 6     6   212 use Crypt::DSA::Signature;
  6         66  
  6         132  
12 6     6   102 use Crypt::DSA::Util qw( bitsize bin2mp mod_inverse mod_exp makerandom );
  6         58  
  6         121  
13              
14 6     6   96 use vars qw( $VERSION );
  6         54  
  6         96  
15             $VERSION = '0.14';
16              
17             sub new {
18 5     5 1 49     my $class = shift;
19 5         113     my $dsa = bless { @_ }, $class;
20 5         83     $dsa->{_keychain} = Crypt::DSA::KeyChain->new(@_);
21 5         58     $dsa;
22             }
23              
24             sub keygen {
25 5     5 1 77     my $dsa = shift;
26 5         96     my $key = $dsa->{_keychain}->generate_params(@_);
27 5         156     $dsa->{_keychain}->generate_keys($key);
28 5         337     $key;
29             }
30              
31             sub sign {
32 6     6 1 97     my $dsa = shift;
33 6         87     my %param = @_;
34 6         55     my($key, $dgst);
35 6 50       80     croak __PACKAGE__, "->sign: Need a Key" unless $key = $param{Key};
36 6 50       10386     unless ($dgst = $param{Digest}) {
37 6 50       128         croak __PACKAGE__, "->sign: Need either Message or Digest"
38                         unless $param{Message};
39 6         161         $dgst = sha1($param{Message});
40                 }
41 6         59     my $dlen = length $dgst;
42              
43 6         125     my $i = bitsize($key->q) / 8;
44 6 50 33     11514     croak "Data too large for key size"
45                     if $dlen > $i || $dlen > 50;
46              
47 6 100 66     167     $dsa->_sign_setup($key)
48                     unless $key->kinv && $key->r;
49              
50 6         262     my $m = bin2mp($dgst);
51 6         34162     my $xr = ($key->priv_key * $key->r) % $key->q;
52 6         71     my $s = $xr + $m;
53 6 100       1684     $s -= $key->q if $s > $key->q;
54 6         4695     $s = ($s * $key->kinv) % $key->q;
55              
56 6         10752     my $sig = Crypt::DSA::Signature->new;
57 6         79     $sig->r($key->r);
58 6         94     $sig->s($s);
59 6         120     $sig;
60             }
61              
62             sub _sign_setup {
63 3     3   34     my $dsa = shift;
64 3         31     my $key = shift;
65 3         32     my($k, $r);
66                 {
67 3         31         $k = makerandom(Size => bitsize($key->q));
  3         82  
68 3 50       8648         $k -= $key->q if $k >= $key->q;
69 3 50       31         redo if $k == 0;
70                 }
71 3         1271     $r = mod_exp($key->g, $k, $key->p);
72 3         33711905     $r %= $key->q;
73 3         12147     my $kinv = mod_inverse($k, $key->q);
74 3         427608     $key->r($r);
75 3         54     $key->kinv($kinv);
76             }
77              
78             sub verify {
79 6     6 1 65     my $dsa = shift;
80 6         83     my %param = @_;
81 6         60     my($key, $dgst, $sig);
82 6 50       78     croak __PACKAGE__, "->verify: Need a Key" unless $key = $param{Key};
83 6 50       106     unless ($dgst = $param{Digest}) {
84 6 50       87         croak __PACKAGE__, "->verify: Need either Message or Digest"
85                         unless $param{Message};
86 6         174         $dgst = sha1($param{Message});
87                 }
88 6 50       70     croak __PACKAGE__, "->verify: Need a Signature"
89                     unless $sig = $param{Signature};
90 6         516     my $u2 = mod_inverse($sig->s, $key->q);
91 6         534260     my $u1 = bin2mp($dgst);
92 6         104     $u1 = ($u1 * $u2) % $key->q;
93 6         23734     $u2 = ($sig->r * $u2) % $key->q;
94 6         23789     my $t1 = mod_exp($key->g, $u1, $key->p);
95 6         102646139     my $t2 = mod_exp($key->pub_key, $u2, $key->p);
96 6         357     $u1 = ($t1 * $t2) % $key->p;
97 6         225488     $u1 %= $key->q;
98 6         57580     $u1 == $sig->r;
99             }
100              
101             1;
102             __END__
103            
104             =head1 NAME
105            
106             Crypt::DSA - DSA Signatures and Key Generation
107            
108             =head1 SYNOPSIS
109            
110             use Crypt::DSA;
111             my $dsa = Crypt::DSA->new;
112            
113             my $key = $dsa->keygen(
114             Size => 512,
115             Seed => $seed,
116             Verbosity => 1
117             );
118            
119             my $sig = $dsa->sign(
120             Message => "foo bar",
121             Key => $key
122             );
123            
124             my $verified = $dsa->verify(
125             Message => "foo bar",
126             Signature => $sig,
127             Key => $key,
128             );
129            
130             =head1 DESCRIPTION
131            
132             I<Crypt::DSA> is an implementation of the DSA (Digital Signature
133             Algorithm) signature verification system. The implementation
134             itself is pure Perl, although the heavy-duty mathematics underneath
135             are provided by the I<Math::Pari> library.
136            
137             This package provides DSA signing, signature verification, and key
138             generation.
139            
140             =head1 USAGE
141            
142             The I<Crypt::DSA> public interface is similar to that of
143             I<Crypt::RSA>. This was done intentionally.
144            
145             =head2 Crypt::DSA->new
146            
147             Constructs a new I<Crypt::DSA> object. At the moment this isn't
148             particularly useful in itself, other than being the object you
149             need to do much else in the system.
150            
151             Returns the new object.
152            
153             =head2 $key = $dsa->keygen(%arg)
154            
155             Generates a new set of DSA keys, including both the public and
156             private portions of the key.
157            
158             I<%arg> can contain:
159            
160             =over 4
161            
162             =item * Size
163            
164             The size in bits of the I<p> value to generate. The I<q> and
165             I<g> values are always 160 bits each.
166            
167             This argument is mandatory.
168            
169             =item * Seed
170            
171             A seed with which I<q> generation will begin. If this seed does
172             not lead to a suitable prime, it will be discarded, and a new
173             random seed chosen in its place, until a suitable prime can be
174             found.
175            
176             This is entirely optional, and if not provided a random seed will
177             be generated automatically.
178            
179             =item * Verbosity
180            
181             Should be either 0 or 1. A value of 1 will give you a progress
182             meter during I<p> and I<q> generation--this can be useful, since
183             the process can be relatively long.
184            
185             The default is 0.
186            
187             =back
188            
189             =head2 $signature = $dsa->sign(%arg)
190            
191             Signs a message (or the digest of a message) using the private
192             portion of the DSA key and returns the signature.
193            
194             The return value--the signature--is a I<Crypt::DSA::Signature>
195             object.
196            
197             I<%arg> can include:
198            
199             =over 4
200            
201             =item * Digest
202            
203             A digest to be signed. The digest should be 20 bytes in length
204             or less.
205            
206             You must provide either this argument or I<Message> (see below).
207            
208             =item * Key
209            
210             The I<Crypt::DSA::Key> object with which the signature will be
211             generated. Should contain a private key attribute (I<priv_key>).
212            
213             This argument is required.
214            
215             =item * Message
216            
217             A plaintext message to be signed. If you provide this argument,
218             I<sign> will first produce a SHA1 digest of the plaintext, then
219             use that as the digest to sign. Thus writing
220            
221             my $sign = $dsa->sign(Message => $message, ... );
222            
223             is a shorter way of writing
224            
225             use Digest::SHA1 qw( sha1 );
226             my $sig = $dsa->sign(Digest => sha1( $message ), ... );
227            
228             =back
229            
230             =head2 $verified = $dsa->verify(%arg)
231            
232             Verifies a signature generated with I<sign>. Returns a true
233             value on success and false on failure.
234            
235             I<%arg> can contain:
236            
237             =over 4
238            
239             =item * Key
240            
241             Key of the signer of the message; a I<Crypt::DSA::Key> object.
242             The public portion of the key is used to verify the signature.
243            
244             This argument is required.
245            
246             =item * Signature
247            
248             The signature itself. Should be in the same format as returned
249             from I<sign>, a I<Crypt::DSA::Signature> object.
250            
251             This argument is required.
252            
253             =item * Digest
254            
255             The original signed digest whose length is less than or equal to
256             20 bytes.
257            
258             Either this argument or I<Message> (see below) must be present.
259            
260             =item * Message
261            
262             As above in I<sign>, the plaintext message that was signed, a
263             string of arbitrary length. A SHA1 digest of this message will
264             be created and used in the verification process.
265            
266             =back
267            
268             =head1 AUTHOR
269            
270             Benjamin Trott, ben@sixapart.com
271            
272             =head1 COPYRIGHT
273            
274             Except where otherwise noted, Crypt::DSA is Copyright 2006
275             Benjamin Trott. All rights reserved. Crypt::DSA is free
276             software; you may redistribute it and/or modify it
277             under the same terms as Perl itself.
278            
279             =cut
280