Crypt-OpenPGP
view release on metacpan or search on metacpan
lib/Crypt/OpenPGP/KeyServer.pm view on Meta::CPAN
package Crypt::OpenPGP::KeyServer;
use strict;
use warnings;
our $VERSION = '1.21'; # VERSION
use Crypt::OpenPGP;
use Crypt::OpenPGP::KeyRing;
use LWP::UserAgent;
use URI::Escape;
use parent qw( Crypt::OpenPGP::ErrorHandler );
sub new {
my $class = shift;
my $server = bless { }, $class;
$server->init(@_)
or return $class->error($server->errstr);
$server;
}
sub init {
my $server = shift;
my %param = @_;
$server->{keyserver} = $param{Server}
or return $server->error("Need a keyserver ('Server')");
$server->{keyserver} = 'http://' . $server->{keyserver} . ':11371' .
'/pks/lookup';
$server->{include_revoked} = $param{IncludeRevoked} || 0;
$server;
}
sub find_keyblock_by_uid {
my $server = shift;
my($address) = @_;
my $ua = LWP::UserAgent->new;
$ua->agent('Crypt::OpenPGP/' . Crypt::OpenPGP->VERSION);
my $url = $server->{keyserver} . '?op=index&search=' .
uri_escape($address);
my $req = HTTP::Request->new(GET => $url);
my $res = $ua->request($req);
return $server->error("HTTP error: " . $res->status_line)
unless $res->is_success;
my $page = $res->content;
my @kb;
while ($page =~ m!(pub.*?>)!gs) {
my $line = $1;
next if index($line, "*** KEY REVOKED ***") != -1 &&
!$server->{include_revoked};
my($key_id) = $line =~ m!<a.*?>(.{8})</a>!g;
my $kb = $server->find_keyblock_by_keyid(pack 'H*', $key_id) or next;
push @kb, $kb;
}
@kb;
}
sub find_keyblock_by_keyid {
my $server = shift;
my($key_id) = @_;
$key_id = unpack 'H*', $key_id;
my $ua = LWP::UserAgent->new;
$ua->agent('Crypt::OpenPGP/' . Crypt::OpenPGP->VERSION);
$key_id = substr($key_id, -8, 8);
my $url = $server->{keyserver} . '?op=get&search=0x' . $key_id;
my $req = HTTP::Request->new(GET => $url);
my $res = $ua->request($req);
return $server->error("HTTP error: " . $res->status_line)
unless $res->is_success;
my $page = $res->content;
my($key) = $page =~ /(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----)/s;
return $server->error("No matching keys") unless $key;
my $ring = Crypt::OpenPGP::KeyRing->new( Data => $key )
or return Crypt::OpenPGP::KeyRing->errstr;
$ring->find_keyblock_by_index(0);
}
1;
__END__
=head1 NAME
Crypt::OpenPGP::KeyServer - Interface to HKP keyservers
=head1 SYNOPSIS
use Crypt::OpenPGP::KeyServer;
my $key_id = '...';
my $server = Crypt::OpenPGP::KeyServer->new(
Server => 'keyserver.ubuntu.com'
);
my $kb = $server->find_keyblock_by_keyid($key_id);
print $kb->primary_uid, "\n";
my $cert = $kb->key;
my @kbs = $server->find_keyblock_by_uid( 'foo@bar.com' );
=head1 DESCRIPTION
I<Crypt::OpenPGP::KeyServer> is an interface to HKP keyservers; it provides
lookup by UID and by key ID. At the moment only HKP keyservers are
supported; future releases will likely support the NAI LDAP servers and
the email keyservers.
=head1 USAGE
=head2 Crypt::OpenPGP::KeyServer->new( %arg )
Constructs a new I<Crypt::OpenPGP::KeyServer> object and returns that
object.
I<%arg> can contain:
=over 4
=item * Server
The hostname of the HKP keyserver. This is a required argument. There are a
number of keyservers including:
keyserver.ubuntu.com
keys.openpgp.org
=item * IncludeRevoked
( run in 2.001 seconds using v1.01-cache-2.11-cpan-140bd7fdf52 )