File Coverage

lib/Crypt/RSA/Key/Private.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -sw
2             ##
3             ## Crypt::RSA::Key::Private
4             ##
5             ## Copyright (c) 2001, Vipul Ved Prakash. All rights reserved.
6             ## This code is free software; you can redistribute it and/or modify
7             ## it under the same terms as Perl itself.
8             ##
9             ## $Id: Private.pm,v 1.15 2001/09/25 14:11:22 vipul Exp $
10              
11             package Crypt::RSA::Key::Private;
12 1     1   4960 use strict;
  1         2  
  1         44  
13 1     1   5 use vars qw($AUTOLOAD $VERSION);
  1         1  
  1         187  
14 1     1   6 use base 'Crypt::RSA::Errorhandler';
  1         3  
  1         656  
15 1     1   991 use Tie::EncryptedHash;
  1         22710  
  1         36  
16 1     1   9 use Data::Dumper;
  1         1  
  1         47  
17 1     1   1631 use Math::Pari qw(PARI pari2pv Mod isprime lcm lift);
  0            
  0            
18             use Carp;
19              
20             $Crypt::RSA::Key::Private::VERSION = '1.99';
21              
22             sub new {
23              
24             my ($class, %params) = @_;
25             my $self = { Version => $Crypt::RSA::Key::Private::VERSION };
26             if ($params{Filename}) {
27             bless $self, $class;
28             $self = $self->read (%params);
29             return bless $self, $class;
30             } else {
31             bless $self, $class;
32             $self->Identity ($params{Identity}) if $params{Identity};
33             $self->Cipher ($params{Cipher}||"Blowfish");
34             $self->Password ($params{Password}) if $params{Password};
35             return $self;
36             }
37              
38             }
39              
40              
41             sub AUTOLOAD {
42              
43             my ($self, $value) = @_;
44             my $key = $AUTOLOAD; $key =~ s/.*:://;
45             if ($key =~ /^(e|n|d|p|q|dp|dq|u|phi)$/) {
46             if (ref $value eq 'Math::Pari') {
47             $self->{private}{"_$key"} = $value;
48             $self->{Checked} = 0;
49             } elsif ($value && !(ref $value)) {
50             if ($value =~ /^0x/) {
51             $self->{private}->{"_$key"} =
52             Math::Pari::_hex_cvt($value);
53             $self->{Checked} = 0;
54             } else { $self->{private}{"_$key"} = PARI($value) }
55             }
56             return $self->{private}{"_$key"} ||
57             $self->{private_encrypted}{"_$key"} ||
58             "";
59             } elsif ($key =~ /^Identity|Cipher|Password$/) {
60             $self->{$key} = $value if $value;
61             return $self->{$key};
62             } elsif ($key =~ /^Checked$/) {
63             my ($package) = caller();
64             $self->{Checked} = $value if ($value && $package eq "Crypt::RSA::Key::Private") ;
65             return $self->{Checked};
66             }
67             }
68              
69              
70             sub hide {
71              
72             my ($self) = @_;
73              
74             return undef unless $$self{Password};
75              
76             $self->{private_encrypted} = new Tie::EncryptedHash
77             __password => $self->{Password},
78             __cipher => $self->{Cipher};
79              
80             for (keys %{$$self{private}}) {
81             $$self{private_encrypted}{$_} = pari2pv($$self{private}{$_});
82             }
83              
84             my $private = $self->{private_encrypted};
85             delete $private->{__password};
86             delete $$self{private};
87             delete $$self{Password};
88              
89             }
90              
91              
92             sub reveal {
93              
94             my ($self, %params) = @_;
95             $$self{Password} = $params{Password} if $params{Password};
96             return undef unless $$self{Password};
97             $$self{private_encrypted}{__password} = $params{Password};
98             for (keys %{$$self{private_encrypted}}) {
99             $$self{private}{$_} = PARI($$self{private_encrypted}{$_});
100             }
101            
102             }
103              
104              
105             sub check {
106              
107             my ($self) = @_;
108              
109             return 1 if $self->{Checked};
110              
111             return $self->error ("Incomplete key.") unless
112             ($self->n && $self->d) || ($self->n && $self->p && $self->q);
113              
114             if ($self->p && $self->q) {
115             return $self->error ("n is not a number.") if $self->n =~ /\D/;
116             return $self->error ("p is not a number.") if $self->p =~ /\D/;
117             return $self->error ("p is not a number.") if $self->p =~ /\D/;
118             return $self->error ("n is not p*q." ) unless $self->n == $self->p * $self->q;
119             return $self->error ("p is not prime.") unless isprime($self->p);
120             return $self->error ("q is not prime.") unless isprime($self->q);
121             }
122              
123             if ($self->e) {
124             # d * e == 1 mod lcm(p-1, q-1)
125             return $self->error ("e is not a number.") if $self->e =~ /\D/;
126             my $k = lcm (($self->p -1), ($self->q -1));
127             my $K = Mod (1, $k); my $KI = lift($K * $self->d * $self->e);
128             return $self->error ("Bad `d'.") unless $KI == 1;
129             }
130              
131             if ($self->dp) {
132             # dp == d mod (p-1)
133             return $self->error ("Bad `dp'.") unless $self->dp == $self->d % ($self->p - 1);
134             }
135              
136             if ($self->dq) {
137             # dq == d mod (q-1)
138             return $self->error ("Bad `dq'.") unless $self->dq == $self->d % ($self->q - 1);
139             }
140              
141             if ($self->u && $self->q && $self->p) {
142             my $m = Mod (1,$self->q); $m = lift ($m / $self->p);
143             return $self->error ("Bad `u'.") unless $self->u == $m;
144             }
145              
146             $self->Checked(1);
147             return 1;
148              
149             }
150              
151              
152             sub DESTROY {
153              
154             my $self = shift;
155             delete $$self{private_encrypted}{__password};
156             delete $$self{private_encrypted};
157             delete $$self{private};
158             delete $$self{Password};
159             undef $self;
160              
161             }
162              
163              
164             sub write {
165              
166             my ($self, %params) = @_;
167             $self->hide();
168             my $string = $self->serialize (%params);
169             open DISK, ">$params{Filename}" or
170             croak "Can't open $params{Filename} for writing.";
171             binmode DISK;
172             print DISK $string;
173             close DISK;
174              
175             }
176              
177              
178             sub read {
179             my ($self, %params) = @_;
180             open DISK, $params{Filename} or
181             croak "Can't open $params{Filename} to read.";
182             binmode DISK;
183             my @key = ;
184             close DISK;
185             $self = $self->deserialize (String => \@key);
186             $self->reveal(%params);
187             return $self;
188             }
189              
190              
191             sub serialize {
192              
193             my ($self, %params) = @_;
194             if ($$self{private}) { # this is an unencrypted key
195             for (keys %{$$self{private}}) {
196             $$self{private}{$_} = pari2pv($$self{private}{$_});
197             }
198             }
199             return Dumper $self;
200              
201             }
202              
203              
204             sub deserialize {
205              
206             my ($self, %params) = @_;
207             my $string = join'', @{$params{String}};
208             $string =~ s/\$VAR1 =//;
209             $self = eval $string;
210             if ($$self{private}) { # the key is unencrypted
211             for (keys %{$$self{private}}) {
212             $$self{private}{$_} = PARI($$self{private}{$_});
213             }
214             return $self;
215             }
216             my $private = new Tie::EncryptedHash;
217             %$private = %{$$self{private_encrypted}};
218             $self->{private_encrypted} = $private;
219             return $self;
220              
221             }
222              
223            
224             1;
225              
226             =head1 NAME
227              
228             Crypt::RSA::Key::Private -- RSA Private Key Management.
229              
230             =head1 SYNOPSIS
231              
232             $key = new Crypt::RSA::Key::Private (
233             Identity => 'Lord Banquo ',
234             Password => 'The earth hath bubbles',
235             );
236              
237             $key->hide();
238              
239             $key->write( Filename => 'rsakeys/banquo.private' );
240              
241             $akey = new Crypt::RSA::Key::Private (
242             Filename => 'rsakeys/banquo.private'
243             );
244              
245             $akey->reveal ( Password => 'The earth hath bubbles' );
246              
247             =head1 DESCRIPTION
248              
249             Crypt::RSA::Key::Private provides basic private key management
250             functionality for Crypt::RSA private keys. Following methods are
251             available:
252              
253             =over 4
254              
255             =item B
256              
257             The constructor. Takes a hash, usually with two arguments: C and
258             C. C indicates a file from which the private key
259             should be read. More often than not, private keys are kept encrypted with
260             a symmetric cipher and MUST be decrypted before use. When a C
261             argument is provided, the key is also decrypted before it is returned by
262             C. Here's a complete list of arguments accepted by C (all of
263             which are optional):
264              
265             =over 4
266              
267             =item Identity
268              
269             A string identifying the owner of the key. Canonically, a name and
270             email address.
271              
272             =item Filename
273              
274             Name of the file that contains the private key.
275              
276             =item Password
277              
278             Password with which the private key is encrypted, or should be encrypted
279             (in case of a new key).
280              
281             =item Cipher
282              
283             Name of the symmetric cipher in which the private key is encrypted (or
284             should be encrypted). The default is "Blowfish" and possible values
285             include DES, IDEA, Twofish and other ciphers supported by Crypt::CBC.
286              
287             =back
288              
289             =item B
290              
291             If the key is not decrypted at C, it can be decrypted by
292             calling C with a C argument.
293              
294             =item B
295              
296             C causes the key to be encrypted by the chosen symmetric cipher
297             and password.
298              
299             =item B
300              
301             Causes the key to be written to a disk file specified by the
302             C argument. C will call C before
303             writing the key to disk. If you wish to store the key in plain,
304             don't specify a password at C.
305              
306             =item B
307              
308             Causes the key to be read from a disk file specified by
309             C into the object. If C is provided, the
310             method automatically calls reveal() to decrypt the key.
311              
312             =item B
313              
314             Creates a Data::Dumper(3) serialization of the private key and
315             returns the string representation.
316              
317             =item B
318              
319             Accepts a serialized key under the C parameter and
320             coverts it into the perl representation stored in the object.
321              
322             =item C
323              
324             Check the consistency of the key. If the key checks out, it sets
325             $self->{Checked} = 1. Returns undef on failure.
326              
327             =back
328              
329             =head1 AUTHOR
330              
331             Vipul Ved Prakash, Email@vipul.netE
332              
333             =head1 SEE ALSO
334              
335             Crypt::RSA::Key(3), Crypt::RSA::Public(3)
336              
337             =cut
338              
339