#!/usr/bin/perl use strict; use warnings; my ($keyserver, $getEmails); BEGIN { $keyserver = shift || 'subkeys.pgp.net:11371'; # the keyserver to use $getEmails = undef; # wether to get emails or not } $, = $\ = $/; # ;-) use LWP::Simple; use URI::Find; use if $getEmails => 'Email::Find'; use if $getEmails => 'PGP::FindKey'; # mainly compile time death BEGIN { unless (eval { require Crypt::OpenPGP::KeyServer }){ # getting ugly ## the following emulates Crypt::OpenPGP::Keyserver, in a not so pretty way. *Crypt::OpenPGP::KeyServer::new = sub { # create a new object my $pkg = shift; my %conf = @_; bless \$conf{Server}, $pkg; # fill it only with the keyserver setting }; *Crypt::OpenPGP::KeyServer::find_keyblock_by_uid = sub { # fetch a key via uid - wraps around PGP::FindKey - not much fun. my $self = shift; my $str = shift; my $id = PGP::FindKey->new( keyserver => $keyserver, address => $str, )->result; $self->find_keyblock_by_keyid(pack("H*",$id)); # "find" they key ID. PGP::FindKey only gives back one key }; *Crypt::OpenPGP::KeyServer::find_keyblock_by_keyid = sub { # fetch a key via it's id - constructs a simple URL my $self = shift; my $id = unpack("H*", shift); my $url = "http://" . $$self . '/pks/lookup?op=get&search=0x' . $id; # the URL we'll be fetching filter_key_blocks(LWP::Simple::get($url)); # give back an array or string of key blocks, made from the return value of the HTTP get }; } } my $kbs = Crypt::OpenPGP::KeyServer->new( Server => $keyserver, ); my @finders = ( # the general interface is the same, so we've grouped them URI::Find->new(sub { # to find URLS print filter_key_blocks(get(shift)); # get the URL using LWP::Simple, and filter key blocks out of it return shift; }), ($getEmails ? Email::Find->new(sub { # to find emails, if at all my $emails = shift; foreach my $email (@$emails){ print $kbs->find_keyblock_by_uid($email) || '' }; # run the list of emails through the key server object, and print the results out return shift; }) : () ), ); sub get_id { # a shortcut to print a key by it's ID print $kbs->find_keyblock_by_keyid(pack 'H*', shift) || ''; } sub filter_key_blocks { my $str = shift; my @blocks = $str =~ /(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----)/sg; # get all the blocks, nothing more return wantarray ? @blocks : join($/, @blocks); # join if scalar context } while (<>){ #study; foreach my $uid (/\b(?:0x)((?:[a-fA-F0-9]{8}){1,2})\b/g){ get_id($uid) }; # matches ID foreach my $finder (@finders) { $finder->find(\$_) }; # run the canned matches on the input }