File Coverage

PGP/Pipe.pm
Criterion Covered Total %
statement 25 240 10.4
branch 0 106 0.0
condition 0 11 0.0
subroutine 9 26 34.6
pod n/a
total 34 383 8.8


line stmt bran cond sub pod time code
1             package PGP::Pipe;
2              
3             require 5.000;
4              
5 1     1   12237 use English;
  1         6599  
  1         9  
6 1     1   981 use Carp;
  1         2  
  1         135  
7 1     1   8 use File::Basename;
  1         23  
  1         147  
8 1     1   1476 use IPC::Open3;
  1         4921  
  1         48  
9 1     1   8371 use Time::Local;
  1         3001  
  1         97  
10 1     1   6216 use Data::Dumper;
  1         42816  
  1         7806  
11              
12             # $debug = 1;
13              
14             =over 4
15              
16             =head1 NAME
17              
18             PGP - perl module to work with PGP messages
19              
20             =head1 SYNOPSIS
21              
22             use PGP;
23              
24             $message = new PGP $pgppath;
25              
26             =head1 DESCRIPTION
27              
28             The PGP module allow a perl script to work with PGP related files.
29              
30             =cut
31              
32             # $Log: Pipe.pm,v $
33             # Revision 0.3 1996/08/14 19:04:21 hickey
34             # + moved module to PGP::Pipe to prevent conflicts
35             # + upgraded to Data::Dumper
36             # + added the Sign_Key method to PGP::Keyring (not debugged yet)
37             # + PGP::Pipe::Exec places filehandles in caller's package
38             #
39             # Revision 0.2 1996/01/27 15:40:57 hickey
40             # + PGP::Keyring and PGP::Key now inherits PGP object
41             # + PGP::Keyring::Find now correctly works (filter on anything)
42             # + Timestamps are now correctly reported back to caller
43             # + Activated %r (path to keyring) in the PGP::Exec_PGP method
44             # + Added support for multiple ID keys. (PGP::Key::Add_ID)
45             #
46             # Revision 0.1 1996/01/10 02:22:18 hickey
47             # Initial alpha release
48             #
49              
50             $VERSION = '0.3';
51             $RCSID = '$Id: Pipe.pm,v 0.3 1996/08/14 19:04:21 hickey Exp hickey $';
52              
53             =item * PGP::new
54              
55             $pgp = new PGP [$pgppath], [$pgpexec];
56              
57             Create the PGP encapsulation object. The standard location for the
58             PGP executable is /usr/local/bin/pgp.
59              
60             =cut
61              
62             sub new
63             {
64 0     0     my $class = shift;
65 0   0       my $pgppath = shift || "$ENV{HOME}/.pgp";
66 0   0       my $pgpexec = shift || "/usr/local/bin/pgp";
67            
68 0 0 0       if (! -e "$pgppath/config.txt" &&
69             ! -e "/usr/local/lib/pgp/config.txt" )
70             {
71 0           carp "PGP configuration file not found.";
72 0           return (0);
73             };
74            
75 0           $self = { PGPPATH => $pgppath,
76             PGPexec => $pgpexec
77             };
78 0           $ENV{PGPPATH} = $pgppath;
79            
80 0           bless $self, $class;
81             }
82            
83             # The following function was suggested by Alva Couch. Can anyone
84             # think why they would call it rather than the new() method?
85              
86             # projector function eliminates all non-PGP data and
87             # returns a 'pure' PGP instance.
88              
89             sub PGP
90             {
91 0     0     my $self = shift;
92 0           bless { PGPPATH => $self->{PGPPATH},
93             PGPexec => $self->{PGPexec},
94             }, PGP;
95             }
96              
97              
98             sub Debug
99             {
100 0     0     my (@args) = @_;
101              
102 0 0         return if (! defined $PGP::Pipe::debug);
103              
104 0           print STDERR @args, "\n";
105             }
106              
107              
108             =item * PGP::Exec
109              
110             $pid = Exec $pgp $args, $in, $out, $err, $nobatchmode;
111              
112             Execute the PGP command and attach the C<$in>, C<$out>, C<$err> file handles.
113             This should be fine for the moment, but need to look into making
114             sure that data is not written to a temporary file anywhere. The C<$nobatchmode>
115             parameter causes the PGP command to be executed without the +batchmode
116             parameter. This seems to only be necessary when a key is being signed.
117              
118             The $args variable can have several substituted strings:
119              
120             %p PGP path variable
121             %r Path to PGP keyring
122             %k Specified user
123              
124             B The above substitutions may change at any time. It is not
125             advised that you write applications with substitutions. Almost
126             certainly, the next release will not include substitutions.
127              
128             The file handle variables--C<$in>, C<$out> and C<$err>--are send as
129             normal filehandle names, but they reside in the PGP package. For
130             example, the following procedure call is made:
131              
132             PGP->Exec ($args, FIN, FOUT, FERR);
133              
134             Even though the file handles were specified as C, C and
135             C; they must be referred to as C, C and
136             C in the orignal procedure that made the call.
137              
138             =cut
139              
140              
141             sub Exec
142             {
143 0     0     my ($self, $args, $in, $out, $err, $nobatchmode) = @_;
144 0           my ($pgppath, $pgpcmd, $baseopts);
145 0           my ($fin, $fout, $ferr);
146            
147 0 0         if ($nobatchmode)
148 0           { $baseopts = '+force +verbose=1' }
149             else
150 0           { $baseopts = '+force +batchmode +verbose=1' };
151            
152             # Variable substitutions
153 0           $args =~ s/%p/$self->{PGPPATH}/g;
154 0           $args =~ s/%r/$self->{PGPPATH}\/$self->{Keyring}/g; # PGP::Keyring
155 0           $args =~ s/%k/0x$self->{Keyid}/g; # PGP::Key
156            
157             # Put the file descriptors in the callers package
158 0           $fin = (caller)[0] . "::$in";
159 0           $fout = (caller)[0] . "::$out";
160 0           $ferr = (caller)[0] . "::$err";
161            
162 0           Debug ("PGP::Exec=$self->{PGPexec} $baseopts $args");
163            
164             # just to make sure that PGPPATH is exported!
165 0           $ENV{PGPPATH} = $self->{PGPPATH};
166 0   0       $result = open3 ($fin, $fout, $ferr, "$self->{PGPexec} $baseopts $args") || croak "PGP command error";
167             }
168              
169              
170             =item * PGP::Sign
171              
172             $signed_document = Sign $pgp %args;
173              
174             The C procedure will take a file or data and sign with a PGP
175             secret key. The default behavior is to sign the data with the last
176             secret key added to the keyring, but that can be overridden with the
177             I argument. This method always returns the signed document.
178              
179             The C<%args> consist of a series of keys and values. Since there are
180             several variations in the way data can be signed, not all the
181             following options must be specified. This approach also makes it much
182             easier to scale to new versions of PGP with more options.
183              
184             Armor The output should be ASCII armored
185             Clear Produce a "clear" signature
186             Encrypt Encrypt the resulting signed document with
187             the given keyobj
188             Detach Create a detached signature
189             File Sign the specified file
190             Key Sign with the specified key object
191             Nosave Do not allow user to save message
192             Password The password to use for signing
193             Signfile The filename of the signed document
194             Text Data to be signed.
195             Wipe Remove the orignal file
196              
197             The only absolute argument that is always required is the C.
198              
199             B
200              
201             Sign $pgp Password => 'xyz', File => '/etc/motd', Clear => 1, Armor => 1;
202              
203             This would return a signed copy of the F file. In this
204             case, we use a file as the input, but the output is returned at the
205             method's termination. The orignal file remains in the clear, and the
206             signature is ASCII armored (Base64).
207              
208             Sign $pgp Password => 'abc', Text => 'Important info', Armor => 1,
209             Signfile => 'signed.asc', Key => $keyobj;
210              
211             This is sort of the reverse of the first example. It takes what is in
212             the C field and signs it. It then puts the result in the file
213             F and returns it to the caller. In this case, the entire
214             message is ASCII armored including the orignal text (i.e. C).
215             We also specify another secret key to produce the signature. For more
216             information on the the key objects, please see L<"PGP::Key"> section.
217              
218             =cut
219              
220              
221             sub Sign
222             {
223 0     0     my ($self, %args) = @_;
224 0           my ($options, $key, $document);
225            
226 0           Debug ("PGP::Sign Args=", Dumper \%args);
227              
228 0           $options = '-f -s';
229 0 0         $options .= 'a' if ($args{Armor} == 1);
230 0 0         $options .= 'b' if ($args{Detach} == 1);
231 0 0         $options .= 't' if (exists $args{Clear});
232 0 0         $options .= 'w' if ($args{Wipe} == 1);
233 0 0         $options .= 'm' if ($args{Nosave} == 1);
234              
235             # setup of encryption if we are doing any
236 0 0         if (defined $args{Encrypt})
237             {
238 0           $options .= 'e';
239 0           foreach $key (@{$args{Encrypt}})
  0            
240             {
241 0           $options .= " 0x$key->{Keyid}";
242             };
243             };
244            
245             # When signing a document, we always have a password.
246 0           $options .= " -z $args{Password}";
247              
248 0           Debug ("PGP::Sign Options=$options");
249              
250             # procede to send the document to PGP.
251 0           $self->Exec ($options, FIN, FOUT, FERR);
252              
253 0 0         if ($args{File})
254             {
255 0 0         open (PLAIN, "< $args{File}") || carp "$args{File} not found";
256 0           print FIN ;
257 0           close (PLAIN);
258             } else
259             {
260 0           print FIN $args{Text};
261             };
262 0           close (FIN);
263              
264 0           $document = join ('', ());
265              
266 0 0         if ($args{Signfile})
267             {
268 0 0         open (SIGN, "> $args{Signfile}") || carp "Can not create $args{Signfile}";
269 0           print SIGN $document;
270 0           close (SIGN);
271             };
272              
273 0           return ($document);
274             }
275              
276              
277             =item * PGP::Encrypt
278              
279             $encrypted_document = Encrypt $pgp %args;
280              
281             The C method produces an encrypted document with the given
282             public keys specified by C. The C method follow the
283             same conventions as the C method. The data to be encrypted can
284             be sent to the method or can reside in a file. The resulting
285             encrypted data can also reside in a file or be sent back to the caller.
286              
287             In addition to encrypting a document, the document can also be signed
288             by using the C key in the C<%args> array. If the document is to
289             be signed by the default secret key (last key added to the secret
290             keyring), then C can be left undefined or contain something
291             other than a reference to a key object. Otherwise the C key
292             should contain a reference to a specific key object (see
293             L<"PGP::Key">).
294              
295             Armor The output should be ASCII armored
296             Encryptfile The filename of the encrypted document
297             File Encrypt the specified file
298             Key Encrypt with the specified key object
299             Nosave Do not allow user to save message
300             Password The password to use for signing
301             Sign In addition to encrypting, sign the document
302             Text Data to be encrypted
303             Wipe Remove orignal file
304              
305             =cut
306              
307              
308             sub Encrypt
309             {
310 0     0     my ($self, %args) = @_;
311 0           local ($options, $document, $key, @keys);
312            
313 0           Debug ("PGP::Encrypt Args=", Dumper \%args);
314              
315 0           $options = '-f -e';
316 0 0         $options .= 'a' if ($args{'Armor'} == 1);
317 0 0         $options .= 's' if (exists $args{'Sign'});
318 0 0         $options .= 'w' if ($args{'Wipe'} == 1);
319 0 0         $options .= 'm' if ($args{'Nosave'} == 1);
320              
321             # process the Key variable
322 0 0         if (ref $args{'Key'} eq 'ARRAY')
323             {
324 0           foreach $key (@keys)
325             {
326 0           $options .= " 0x$key->{'Keyid'}";
327             };
328             }
329             else
330             {
331 0           $options .= " 0x$args{'Key'}->{'Keyid'}";
332             };
333              
334             # If we are also signing, we need to tell which key and password.
335 0 0         $options .= " -u 0x$args{'Sign'}->{'Keyid'}" if (defined $args{'Sign'}->{'Keyid'});
336 0 0         $options .= " -z '$args{'Password'}'" if (defined $args{'Password'});
337              
338 0           Debug ("PGP::Encrypt Options=$options");
339              
340             # procede to send the document to PGP.
341 0           $self->Exec ($options, FIN, FOUT, FERR);
342              
343 0 0         if ($args{'File'})
344             {
345 0 0         open (PLAIN, "< $args{'File'}") || carp "$args{'File'} not found";
346 0           print FIN ;
347 0           close (PLAIN);
348             } else
349             {
350 0           print FIN $args{'Text'};
351             };
352 0           close (FIN);
353              
354 0           $document = join ('', );
355              
356 0 0         if ($args{'Encryptfile'})
357             {
358 0 0         open (ENCRYPT, "> $args{'Encryptfile'}") || carp "Can not create $args{'Encryptfile'}";
359 0           print ENCRYPT $document;
360 0           close (ENCRYPT);
361             };
362              
363 0           return ($document);
364             }
365              
366            
367             =item * PGP::Decrypt
368              
369             \%stats = Decrypt $pgp %args;
370              
371             C will use a PGP secret key to decrypt a message. The secret
372             key must reside on the secret keyring. The C method follows
373             the same conventions for data transfer that C and C
374             follow. The resulting associative array that is sent back contains
375             three fields:
376              
377             Text The decrypted document
378             Signature PGP::Key object of the signer (if any)
379             Time Time document was signed (if any)
380             Key PGP::Key object used to decrypt document
381              
382             The following are the accepted arguments:
383              
384             Password Password to use for decrypting
385             File File to decrypt
386             Keyring Needed to return info about document
387             Plainfile File to put the data in
388             Text Document to decrypt
389             Wipe Remove original file
390              
391             The C argument is required to perform the decryption of the
392             document. The C argument is also required if any document
393             information is to be returned.
394              
395             =cut
396              
397              
398             sub Decrypt
399             {
400 0     0     my ($self, %args) = @_;
401 0           local ($options, $document, $key, @keys);
402            
403 0           Debug ("PGP::Decrypt Args=", Dumper \%args);
404              
405 0           $options = "-f ";
406 0 0         $options = "-z '$args{Password}'" if (defined $args{Password});
407              
408 0           Debug ("PGP::Decrypt Options=$options");
409              
410             # procede to send the document to PGP.
411 0           $self->Exec ($options, FIN, FOUT, FERR);
412              
413 0 0         if (defined $args{File})
414             {
415 0 0         open (ENCRYPT, "< $args{File}") || carp "$args{File} not found";
416 0           print FIN ;
417 0           close (ENCRYPT);
418             } else
419             {
420 0           print FIN $args{Text};
421             };
422 0           close (FIN);
423              
424 0           $document = join ('', );
425              
426 0 0         if ($args{Plainfile})
427             {
428 0 0         open (PLAIN, "> $args{Plainfile}") || carp "Can not create $args{Plainfile}";
429 0           print PLAIN $document;
430 0           close (PLAIN);
431             };
432              
433 0 0         if (defined $args{Keyring})
434             {
435 0           $keyring = $args{Keyring};
436            
437             # gather stats on the decrypted document
438 0           while ()
439             {
440             # Encryption fields
441             /Key ID (\w+)\,/i && do
442 0 0         { $key = Find $keyring Keyid => $1 };
  0            
443            
444             # Signature fields
445             /^Good signature from user "(.+)"/i && do
446 0 0         { $signature = Find $keyring Desc => $1 };
  0            
447             /^Signature made (\d+)\/(\d+)\/(\d+) (\d+):(\d+)/ && do
448 0 0         { $time = &timegm (0, $5, $4, $3, $2-1, ($1 > 1900) ? $1 - 1900 : $1) };
  0 0          
449             };
450              
451             return ({
452 0           Text => $document,
453             Signature => $signature,
454             Time => $time,
455             Key => $key
456             });
457             }
458             else
459             {
460 0           return ( { Text => $document } );
461             };
462             }
463              
464              
465             =item * PGP::Info
466              
467             \%doc = Info $pgp %args;
468              
469             C returns an associative array or a reference to an
470             associative array to the caller. This returned structure contains
471             information about the document that is sent to the C
472             method. The returned structure is fairly straight forward:
473              
474             Text The decrypted document
475             Signature PGP::Key object of the signer (if any)
476             Time Time document was signed (if any)
477             Key PGP::Key object used to decrypt document
478              
479             The C method currently accepts the following arguments:
480              
481             File File to decrypt
482             Text Document to decrypt
483            
484             At this point, we cheat with the C method. Basically
485             we send the document through the C method and grab the
486             results.
487              
488             =cut
489              
490              
491             sub Info
492             {
493 0     0     my ($self, %args) = @_;
494              
495 0           $info = $self->Decrypt (%args, Plainfile => '/dev/null');
496              
497 0           return ($info);
498             }
499              
500              
501              
502             =head2 PGP::Keyring
503              
504             The C object is used to perform key management functions.
505              
506             =cut
507              
508             package PGP::Keyring;
509             @ISA = qw(PGP::Pipe);
510              
511              
512             =item * PGP::Keyring::new
513              
514             $Keyring = new PGP::Keyring $pgpkeyring;
515              
516              
517             =cut
518              
519              
520             sub new
521             {
522 0     0     my ($class, $keydir) = @_;
523 0           my ($pgp) = new PGP::Pipe $keydir; # inherit the PGP variables
524            
525 0           $self = { %$pgp,
526             Keys => [],
527             Modified => 1
528             };
529              
530 0           bless $self, $class;
531            
532             # Need to update the Keys field so that it is useful.
533 0           $self->List_Keys;
534            
535 0           $self;
536             };
537              
538              
539             =item * PGP::Keyring::Add_Key
540              
541             Add_Key $Keyring %args;
542              
543             Add a signature to the keyring. At this point, there is no error
544             checking or verification that the key has been added.
545              
546             The C<%args> associative array may contain the following:
547              
548             Text The value is the public key
549             File File where the public key is stored
550              
551             =cut
552              
553             sub Add_Key
554             {
555 0     0     my ($self, %args) = @_;
556            
557             # PGP does not seem to like to take a keyring from stdin.
558             # must place everything in a temporary file for processing.
559            
560 0 0         if ($args{Text})
561             {
562 0           open (TEMP, ">/tmp/.pgp.$$");
563 0           print TEMP $args{Text};
564 0           close TEMP;
565             }
566             else
567             {
568             # Is this portable? (i.e. PC-based perl)
569 0           system ("$Config{'cp'} $args{File} /tmp/.pgp.$$");
570             };
571            
572 0           $self->Exec ("-ka /tmp/.pgp.$$", FIN, FOUT, FERR);
573            
574             # # send the key to the PGP process
575             # if ($args{Text})
576             # { print FIN "$args{Text}\n" }
577             # else
578             # {
579             # open (KEY, "<$args{File}");
580             # print FIN ;
581             # close KEY;
582             # };
583             # close FIN;
584            
585 0           $self->{Modified}++;
586             }
587            
588              
589             =item * PGP::Keyring::Remove_Key
590              
591             Remove_Key $Keyring $key;
592              
593             Remove a signature from a keyring.
594              
595             =cut
596              
597              
598             sub Remove_Key
599             {
600 0     0     my ($self, $key) = @_;
601            
602 0           $self->Exec ("-kr -f 0x$key->{Keyid}", FIN, FOUT, FERR);
603            
604 0           $self->{Modified}++;
605             }
606              
607              
608             =item * PGP::Keyring::Extract_Key
609              
610             $key = Extract_Key $Keyring $keyobj;
611              
612             Extract a key from the specified keyring. A real simple dirty way of
613             extracting the key.
614              
615             =cut
616            
617              
618             sub Extract_Key
619             {
620 0     0     my ($self, %args) = @_;
621            
622 0           $self->Exec ("-kxa -f 0x$args{Keyid}", FIN, FOUT, FERR);
623            
624 0           @key = ;
625 0           return (join ('', @key));
626             }
627              
628              
629             =item * PGP::Keyring::Sign_Key
630              
631             Sign_Key $Keyring %args;
632              
633             This method will sign a designated key with the
634              
635              
636             =cut
637              
638             sub Sign_Key
639             {
640 0     0     my ($self, %args) = @_;
641            
642             # We absolutely need a password to continue!
643 0 0         return if (! exists $args{Password});
644            
645 0           $result = $self->Exec ("-ks 0x$args{Keyid}", FIN, FOUT, FERR, 1);
646            
647 0           open (KEYB, ">/dev/tty");
648            
649             # now we get to act as a user to get the key signed!
650 0           while ($output = )
651             {
652 0           PGP::Pipe::Debug ("FOUT: $output");
653 0 0         last if ($output =~ /user ID/ );
654             };
655            
656 0           print KEYB "y\n"; # say yes it is the key we want
657 0           print "Sent a 'y' keystroke...";
658            
659 0           while ($output = )
660             {
661 0           PGP::Pipe::Debug ("FOUT: $output");
662 0 0         last if ($output =~ /Enter pass phrase:/);
663             };
664            
665 0           print KEYB "$args{Password}\n";
666            
667             # right now, we just hope that it signed it fine!
668 0           close (FIN);
669 0           close (FOUT);
670 0           close (FERR);
671             # Keyring has been modified.
672 0           $self->{Modified}++;
673            
674 0           $self->Extract_Key (Keyid => $args{Keyid});
675             }
676              
677              
678             =item * PGP::Keyring::Generate_Key
679              
680             Generate_Key $Keyring;
681              
682             Generate a new secret and public key set. This routine will not be
683             present in the first rev of code. It is also subject to change.
684              
685             =cut
686            
687              
688             sub Generate_Key
689             {
690 0     0     my ($self) = shift;
691              
692             # be sure to use +nomanual as an option
693 0           $self->{Modified}++;
694             }
695              
696              
697             =item * PGP::Keyring::Revoke_Key
698              
699             $certificate = Revoke_Key $Keyring $Keyobj;
700              
701             Produce a revocation certificate for the given key. Revocation is
702             actually a two step process. We must first mark the key as revoked.
703             This is the same as the C method. After flaging the key,
704             the key must be extracted to produce a revocation certificate.
705              
706             =cut
707              
708             sub Revoke_Key
709             {
710 0     0     my ($self, $key) = @_;
711            
712 0           $self->Remove_Key ($key);
713 0           return ($self->Extract_Key ($key));
714             }
715            
716            
717             =item * PGP::Keyring::List_Keys
718              
719             @{$keyobj} = List_Keys $Keyring;
720              
721             List the keys on a given keyring. This routine simply captures the output
722             of the command C and does a quick parse on it. It
723             takes the lines that it parses, and constructs L objects.
724             In the near future, this function will also pass the trust factors to the
725             PGP::Key object. We got it in the output, so why not use it.
726              
727             =cut
728            
729              
730             sub List_Keys
731             {
732 0     0     my ($self) = @_;
733 0           my ($keyid, $trust, $validity, $desc);
734            
735             # do not call PGP if the keys have not been modified
736 0 0         if (!$self->{Modified})
737             {
738 0 0         return (wantarray ? @{$self->{Keys}} : $self->{Keys});
  0            
739             };
740              
741             # clear the old array and get a list of all the keys again
742 0           $self->{Keys} = undef;
743 0           $self->Exec ("-kc", FIN, FOUT, FERR);
744            
745 0           while ()
746             {
747             # public key entry
748             /^pub/ && do
749 0 0         { push (@{$self->{Keys}}, PGP::Key->new ($_)) };
  0            
  0            
750             /^sig/ && do
751 0 0         { $self->{Keys}->[$#{$self->{Keys}}]->Add_Sig ($_) };
  0            
  0            
752             # more IDs to current key?
753             /^\s{30,32}(.+)$/ && do
754 0 0         { $self->{Keys}->[$#{$self->{Keys}}]->AddID ($1) };
  0            
  0            
755            
756             # public key trust entries follow
757 0 0         last if (/^\s+KeyID\s+Trust\s+Validity\s+User ID/);
758             };
759            
760 0           while ()
761             {
762             # valid entry?
763             /^..(\w+)\s+(\w+)\s+(\w+)\s+(.+)/ && do
764 0 0         {
765 0           $keyid = $1; $trust = $2; $validity = $3; $desc = $4;
  0            
  0            
  0            
766 0           $key = Find $self Keyid => $keyid;
767            
768 0           $key->Trust ($trust);
769 0           $key->Validity ($validity);
770             };
771             };
772              
773             # Now that we have the latest keyring data, reset the modified flag
774 0           undef $self->{Modified};
775            
776 0 0         return (wantarray ? @{$self->{Keys}} : $self->{Keys});
  0            
777             }
778              
779              
780             =item * PGP::Keyring::Find
781              
782             @keys = Find $keyring %criteria;
783             \@keys = Find $keyring %criteria;
784             $key = Find $keyring %criteria; (Single match)
785              
786             Function to locate a keys matching some criteria. This is not
787             implemented as nicely as it should be (read kludge). The
788             C<%criteria> array is used to specify what keys are to be selected.
789             The keys for the C<%criteria> array are as follows:
790              
791             Keyid Key with specifed keyid
792             Owner Name of the owner of the key
793             Email Email address of owner
794             Bits Size of the key in bits
795             Date Date that the key was generated
796             Desc Owner and Email keys combined
797              
798             The values for each specifed key (assocative array) are compared
799             using a case-insensitive regular expression. This means that
800             only a portion of the key data needs to be specified to have it
801             selected. This also means that specifing too little criteria
802             can cause several keys to be selected.
803              
804             =cut
805              
806              
807             sub Find
808             {
809 0     0     my ($self, %criteria) = @_;
810 0           my ($key, @match, $crit);
811              
812 0           NONMATCH:
813 0           foreach $key (@{$self->{Keys}})
814             {
815 0           foreach $crit (keys %criteria)
816             {
817 0 0         if ($crit eq 'Desc')
    0          
818             {
819 1     1   1353 for ($[ .. $#{$key->{Owner}})
  1         2016  
  1         385  
  0            
  0            
820             {
821 0           ($keydesc = "$key->{Owner}->[$_] $key->{Email}->[$_]") =~ tr/a-zA-Z0-9@.!\-//cd;
822 0           $keydesc =~ tr/ / /s;
823            
824 0           $desc = $criteria{$crit};
825 0           $desc =~ tr/a-zA-Z0-9@.!\-//cd; # update the tr/// above too!
826 0           $desc =~ tr/ / /s;
827            
828 0 0         next NONMATCH if ($keydesc !~ /$desc/i);
829             };
830             }
831             elsif (ref ($key->{$crit}) ne 'ARRAY')
832 0 0         { next NONMATCH if ($key->{$crit} !~ /$criteria{$crit}/i) }
833             else
834             {
835 0           for ($[ .. $#{$key->{$crit}})
  0            
836 0 0         { next NONMATCH if ($key->{$crit}->[$_] !~ /$criteria{$crit}/i) };
837             };
838             };
839 0           push (@match, $key);
840             };
841              
842             # return a scalar if there is only one match
843 0 0         return ($match[$[]) if ($#match == 0);
844 0 0         return (wantarray ? @match : \@match);
845             }
846            
847              
848              
849              
850             package PGP::Key;
851             @ISA = qw(PGP::Pipe);
852              
853 1     1   10 use Time::Local;
  1         2  
  1         137  
854 1     1   224825 use Dumper;
  0            
  0            
855              
856             =head2 PGP::Key
857              
858             The C object is used to store the individual key
859             information. It is primarily used by the C object and
860             for passing to the various methods that accept key parameters to
861             encrypt and sign documents.
862              
863             Future revisions will provide actual methods to do key comparison for
864             the trust and validity factors. These methods will provide a
865             standardized way to determine which keys can be trusted and which
866             keys should not be used at all.
867              
868             =cut
869              
870             =item * PGP::Key::new
871              
872             $key = new PGP::Key $keyline;
873              
874             This is the constructor for the C object. This is primarily
875             used by the C methods. The C methods keep
876             track of the keys and maintain the Trust and Validity components.
877             About the only useful method is the C, which
878             will return a string that is the finger print of the given key.
879              
880             =cut
881              
882             sub new
883             {
884             my ($class, $keyline) = @_;
885             my ($bits, $keyid, $date, $owner, $pgp);
886            
887             chomp $keyline;
888             ($bits, $keyid, $date, $owner) = PGP::Key->_keyparse ($keyline);
889            
890             $pgp = new PGP::Pipe; # inherit the PGP variables
891             $self = { %$pgp,
892             Bits => $bits,
893             Keyid => $keyid,
894             Date => $date,
895             Owner => [],
896             Email => []
897             };
898              
899             bless $self, $class;
900            
901             # Add on the ID information to the key object
902             $self->Add_ID ($owner);
903            
904             $self;
905             }
906              
907              
908             =item + PGP::Key::Add_ID
909              
910             Add_ID $key $desc;
911              
912             The C method will add identification information to the owner
913             and email portions of the given C object. This is to support
914             keys that multiple identification packets associated with them.
915              
916             =cut
917            
918             sub Add_ID
919             {
920             my ($self, $desc) = @_;
921            
922             # we have a total of three types of entries for the description
923             # full name /\<.+\>/
924             # email@domain /[\w\.\-\+]@[\w\.\-\+]/
925             # full name all other
926            
927             if ($desc =~ /\<.+\>/)
928             {
929             $desc =~ /([^\<]+)\s+\<(.+)\>/;
930             push (@{$self->{Owner}}, $1);
931             push (@{$self->{Email}}, $2);
932             }
933             elsif ($desc =~ /[\w\.\-\+]@[\w\.\-\+]/)
934             {
935             push (@{$self->{Owner}}, undef);
936             push (@{$self->{Email}}, $desc);
937             }
938             else
939             {
940             push (@{$self->{Owner}}, $desc);
941             push (@{$self->{Email}}, undef);
942             };
943             }
944              
945              
946             =item * PGP::Key::Add_Sig
947              
948              
949              
950             =cut
951              
952             sub Add_Sig
953             {
954             my ($self, $line) = @_;
955            
956            
957             }
958              
959              
960             =item * PGP::Key::Trust
961              
962             This will set and/or retrieve the trust factor. Currently, this routine
963             will just store what is sent to it. Need to define some "trust"
964             variables and provide useful routines to use them.
965              
966             =cut
967              
968              
969             sub Trust
970             {
971             my ($self, $trust) = @_;
972            
973             $self->{Trust} = $trust if ($trust);
974             $self->{Trust};
975             }
976              
977              
978             =item * PGP::Key::Validity
979              
980             This function will set and/or return the validity factor. This
981             subroutine is very much like PGP::Key::Trust. It also needs to be
982             worked on quite a bit.
983              
984             =cut
985            
986              
987             sub Validity
988             {
989             my ($self, $validity) = @_;
990            
991             $self->{Validity} = $validity if ($validity);
992             $self->{Validity};
993             }
994              
995              
996             =item * PGP::Key::Fingerprint
997              
998             $fingerprint = Fingerprint $key;
999              
1000              
1001             =cut
1002              
1003             # does the Fingerprint method belong in the key management stuff?
1004              
1005             sub Fingerprint
1006             {
1007             my ($self) = shift;
1008              
1009             $self->Exec ("-kvc", FIN, FOUT, FERR);
1010              
1011             while ()
1012             {
1013             /Key fingerprint = (.+)[\n\r]$/ && do
1014             { $fingerprint = $1 };
1015             };
1016            
1017             return $fingerprint;
1018             };
1019              
1020              
1021             =item * PGP::Key::Format
1022              
1023             $formatted_text = Format $key %args;
1024              
1025             This method will return a formatted text string for a key. It
1026             is essentially the same as do a 'pgp -kv' or 'pgp -kvv' for
1027             a key object. Currently the only argument that C will
1028             recognize is the C argument. The C parameter
1029             will list the signatures that have certified the current
1030             key object.
1031              
1032             =cut
1033              
1034             sub Format
1035             {
1036             my ($self, %args) = @_;
1037             my ($day, $month, $year) = $self->_date ($self->{Date});
1038              
1039             $text = sprintf ("pub %4d/%s %4d/%02d/%02d %s\n", $self->{Bits}, $self->{Keyid},
1040             $year, ($month+0), ($day+0),
1041             $self->_desc ($self->{Owner}->[0], $self->{Email}->[0]));
1042            
1043            
1044             my $index = 1;
1045             while ($self->{Owner}->[$index] || $self->{Email}->[$index])
1046             {
1047             $text .= sprintf ("%s%s\n", ' ' x 30, $self->_desc ($self->{Owner}->[$index],
1048             $self->{Email}->[$index]));
1049             if (exists $args{Verbose}) # produce a list of signatures
1050             {
1051            
1052            
1053             };
1054             $index++;
1055             };
1056            
1057             $text;
1058             }
1059              
1060              
1061            
1062             sub _keyparse
1063             {
1064             my ($self, $keyline) = @_;
1065             my ($bits, $keyid, $year, $mon, $day, $desc);
1066            
1067             ($bits, $keyid, $year, $mon, $day, $desc) =
1068             ($keyline =~ /^pub\s+(\d+)\/(\w+)\s+(\d+)\/(\d+)\/(\d+)\s+(.+)$/);
1069            
1070             $date = &Time::Local::timegm (0, 0, 0, $day, $mon, $year-1900);
1071            
1072             return ($bits, $keyid, $date, $desc);
1073             }
1074            
1075              
1076             sub _date
1077             {
1078             my $self = shift;
1079             my (@tm) = gmtime (shift);
1080             return ($tm[3], $tm[4], $tm[5]+1900);
1081             }
1082              
1083            
1084             sub _desc
1085             {
1086             my ($self, $owner, $email) = @_;
1087            
1088             return ("$owner <$email>") if ($owner && $email);
1089             return ("$owner") if (!$email);
1090             return ("$email") if (!$owner);
1091             return ("*** No ID on key ***");
1092             }
1093              
1094              
1095             =head2 Known Bugs and Limitations
1096              
1097             =item + Hopefully none, proabably many!
1098              
1099             =head2 Author
1100              
1101             Gerard Hickey
1102             RR 2 Box 409
1103             Lower Main St.
1104             North Berwick, ME 03906
1105             hickey@ctron.com
1106              
1107             =head2 Copyrights
1108              
1109             Copyleft (l) 1996, by Gerard Hickey
1110              
1111             What this means is that this program may be copied freely given that
1112             there is no payment in exchange for this program, and that all the
1113             source is left intact with all comments and documentation. If you
1114             wish to modify this program to correct bugs or to extend it's
1115             usefullness, please coordinate such actions with the author.
1116              
1117             =cut
1118