File Coverage

blib/lib/Crypt/DSA/Key.pm
Criterion Covered Total %
statement 64 89 71.9
branch 21 34 61.8
condition 9 11 81.8
subroutine 15 17 88.2
pod 3 4 75.0
total 112 155 72.3


line stmt bran cond sub pod time code
1             # $Id: Key.pm 1830 2005-05-25 21:58:57Z btrott $
2              
3             package Crypt::DSA::Key;
4 6     6   90 use strict;
  6         87  
  6         86  
5              
6 6     6   90 use Math::BigInt lib => 'GMP';
  6         56  
  6         90  
7 6     6   105 use Carp qw( croak );
  6         107  
  6         108  
8 6     6   278 use Crypt::DSA::Util qw( bitsize );
  6         65  
  6         147  
9              
10             sub new {
11 10     10 1 146     my $class = shift;
12 10         131     my %param = @_;
13 10         545     my $key = bless { }, $class;
14              
15 10 100 100     294     if ($param{Filename} || $param{Content}) {
16 4 50 66     65         if ($param{Filename} && $param{Content}) {
17 0         0             croak "Filename and Content are mutually exclusive.";
18                     }
19 4         89         return $key->read(%param);
20                 }
21 6         78     $key;
22             }
23              
24 3     3 1 35 sub size { bitsize($_[0]->p) }
25              
26             BEGIN {
27 6     6   109     no strict 'refs';
  6         55  
  6         86  
28 6     6   96     for my $meth (qw( p q g pub_key priv_key r kinv )) {
29                     *$meth = sub {
30 300     300   878046             my($key, $value) = @_;
31 300 50 66     7672             if (ref $value eq 'Math::Pari') {
    100          
    50          
    100          
32 0         0                 $key->{$meth} = Math::Pari::pari2pv($value);
33                         }
34                         elsif (ref $value) {
35 54         790                 $key->{$meth} = "$value";
36                         }
37                         elsif ($value) {
38 0 0       0                 if ($value =~ /^0x/) {
39 0         0                     $key->{$meth} = Math::BigInt->new($value)->bstr;
40                             }
41                             else {
42 0         0                     $key->{$meth} = $value;
43                             }
44                         } elsif (@_ > 1 && !defined $value) {
45 1         12                 delete $key->{$meth};
46                         }
47 300   100     119269             my $ret = $key->{$meth} || "";
48 300 100       8131             $ret = Math::BigInt->new("$ret") if $ret =~ /^\d+$/;
49 300         37087             $ret;
50 42         2530         };
51                 }
52             }
53              
54             sub read {
55 4     4 0 39     my $key = shift;
56 4         47     my %param = @_;
57 4 50       48     my $type = $param{Type} or croak "read: Need a key file 'Type'";
58 4         45     my $class = join '::', __PACKAGE__, $type;
59 4     0   47     eval "use $class;";
  0     2   0  
  0     1   0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
60 4 50       114     croak "Invalid key file type '$type': $@" if $@;
61 4         86     bless $key, $class;
62 4         40     local *FH;
63 4 100       49     if (my $fname = delete $param{Filename}) {
64 3 50       262         open FH, $fname or return;
65 3         30         my $blob = do { local $/; <FH> };
  3         32  
  3         149  
66 3         53         close FH;
67 3         33         $param{Content} = $blob;
68                 }
69 4         66     $key->deserialize(%param);
70             }
71              
72             sub write {
73 3     3 1 43     my $key = shift;
74 3         40     my %param = @_;
75 3         149     my $type;
76 3 50       143     unless ($type = $param{Type}) {
77 0         0         my $pkg = __PACKAGE__;
78 0         0         ($type) = ref($key) =~ /^${pkg}::(\w+)$/;
79                 }
80 3 50       31     croak "write: Need a key file 'Type'" unless $type;
81 3         32     my $class = join '::', __PACKAGE__, $type;
82 3     0   37     eval "use $class;";
  0     1   0  
  0     1   0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
83 3 50       90     croak "Invalid key file type '$type': $@" if $@;
84 3         68     bless $key, $class;
85 3         53     my $blob = $key->serialize(%param);
86 3 50       67     if (my $fname = delete $param{Filename}) {
87 3         28         local *FH;
88 3 50       655         open FH, ">$fname" or croak "Can't open $fname: $!";
89 3         195         print FH $blob;
90 3         334         close FH;
91                 }
92 3         62     $blob;
93             }
94              
95             1;
96             __END__
97            
98             =head1 NAME
99            
100             Crypt::DSA::Key - DSA key
101            
102             =head1 SYNOPSIS
103            
104             use Crypt::DSA::Key;
105             my $key = Crypt::DSA::Key->new;
106            
107             $key->p($p);
108            
109             =head1 DESCRIPTION
110            
111             I<Crypt::DSA::Key> contains a DSA key, both the public and
112             private portions. Subclasses of I<Crypt::DSA::Key> implement
113             I<read> and I<write> methods, such that you can store DSA
114             keys on disk, and read them back into your application.
115            
116             =head1 USAGE
117            
118             Any of the key attributes can be accessed through combination
119             get/set methods. The key attributes are: I<p>, I<q>, I<g>,
120             I<priv_key>, and I<pub_key>. For example:
121            
122             $key->p($p);
123             my $p2 = $key->p;
124            
125             =head2 $key = Crypt::DSA::Key->new(%arg)
126            
127             Creates a new (empty) key object. All of the attributes are
128             initialized to 0.
129            
130             Alternately, if you provide the I<Filename> parameter (see
131             below), the key will be read in from disk. If you provide
132             the I<Type> parameter (mandatory if I<Filename> is provided),
133             be aware that your key will actually be blessed into a subclass
134             of I<Crypt::DSA::Key>. Specifically, it will be the class
135             implementing the specific read functionality for that type,
136             eg. I<Crypt::DSA::Key::PEM>.
137            
138             Returns the key on success, C<undef> otherwise. (See I<Password>
139             for one reason why I<new> might return C<undef>).
140            
141             I<%arg> can contain:
142            
143             =over 4
144            
145             =item * Type
146            
147             The type of file where the key is stored. Currently the only
148             option is I<PEM>, which indicates a PEM file (optionally
149             encrypted, ASN.1-encoded object). Support for reading/writing
150             PEM files comes from I<Convert::PEM>; if you don't have this
151             module installed, the I<new> method will die.
152            
153             This argument is mandatory, I<if> you're either reading the file from
154             disk (ie. you provide a I<Filename> argument) or you've specified the
155             I<Content> argument.
156            
157             =item * Filename
158            
159             The location of the file from which you'd like to read the key.
160             Requires a I<Type> argument so the decoder knows what type of file it
161             is. You can't specify I<Content> and I<Filename> at the same time.
162            
163             =item * Content
164            
165             The serialized version of the key. Requires a I<Type> argument so the
166             decoder knows how to decode it. You can't specify I<Content> and
167             I<Filename> at the same time.
168            
169             =item * Password
170            
171             If your key file is encrypted, you'll need to supply a
172             passphrase to decrypt it. You can do that here.
173            
174             If your passphrase is incorrect, I<new> will return C<undef>.
175            
176             =back
177            
178             =head2 $key->write(%arg)
179            
180             Writes a key (optionally) to disk, using a format that you
181             define with the I<Type> parameter.
182            
183             If your I<$key> object has a defined I<priv_key> (private key portion),
184             the key will be written as a DSA private key object; otherwise, it will
185             be written out as a public key. Note that not all serialization mechanisms
186             can produce public keys in this version--currently, only PEM public keys
187             are supported.
188            
189             I<%arg> can include:
190            
191             =over 4
192            
193             =item * Type
194            
195             The type of file format that you wish to write. I<PEM> is one
196             example (in fact, currently, it's the only example).
197            
198             This argument is mandatory, I<unless> your I<$key> object is
199             already blessed into a subclass (eg. I<Crypt::DSA::Key::PEM>),
200             and you wish to write the file using the same subclass.
201            
202             =item * Filename
203            
204             The location of the file on disk where you want the key file
205             to be written.
206            
207             =item * Password
208            
209             If you want the key file to be encrypted, provide this
210             argument, and the ASN.1-encoded string will be encrypted using
211             the passphrase as a key.
212            
213             =back
214            
215             =head2 $key->size
216            
217             Returns the size of the key, in bits. This is actually the
218             number of bits in the large prime I<p>.
219            
220             =head1 AUTHOR & COPYRIGHTS
221            
222             Please see the Crypt::DSA manpage for author, copyright,
223             and license information.
224            
225             =cut
226