146 lines
3.6 KiB
Perl
146 lines
3.6 KiB
Perl
package Crypt::OpenPGP::KeyBlock;
|
|
use strict;
|
|
|
|
use Crypt::OpenPGP::PacketFactory;
|
|
|
|
sub primary_uid {
|
|
$_[0]->{pkt}{ 'Crypt::OpenPGP::UserID' } ?
|
|
$_[0]->{pkt}{ 'Crypt::OpenPGP::UserID' }->[0]->id : undef;
|
|
}
|
|
|
|
sub key { $_[0]->get('Crypt::OpenPGP::Certificate')->[0] }
|
|
sub subkey { $_[0]->get('Crypt::OpenPGP::Certificate')->[1] }
|
|
|
|
sub encrypting_key {
|
|
my $kb = shift;
|
|
my $keys = $kb->get('Crypt::OpenPGP::Certificate');
|
|
return unless $keys && @$keys;
|
|
for my $key (@$keys) {
|
|
return $key if $key->can_encrypt;
|
|
}
|
|
}
|
|
|
|
sub signing_key {
|
|
my $kb = shift;
|
|
my $keys = $kb->get('Crypt::OpenPGP::Certificate');
|
|
return unless $keys && @$keys;
|
|
for my $key (@$keys) {
|
|
return $key if $key->can_sign;
|
|
}
|
|
}
|
|
|
|
sub key_by_id { $_[0]->{keys_by_id}->{$_[1]} ||
|
|
$_[0]->{keys_by_short_id}->{$_[1]} }
|
|
|
|
sub new {
|
|
my $class = shift;
|
|
my $kb = bless { }, $class;
|
|
$kb->init(@_);
|
|
}
|
|
|
|
sub init {
|
|
my $kb = shift;
|
|
$kb->{pkt} = { };
|
|
$kb->{order} = [ ];
|
|
$kb->{keys_by_id} = { };
|
|
$kb;
|
|
}
|
|
|
|
sub add {
|
|
my $kb = shift;
|
|
my($pkt) = @_;
|
|
push @{ $kb->{pkt}->{ ref($pkt) } }, $pkt;
|
|
push @{ $kb->{order} }, $pkt;
|
|
if (ref($pkt) eq 'Crypt::OpenPGP::Certificate') {
|
|
my $kid = $pkt->key_id;
|
|
$kb->{keys_by_id}{ $kid } = $pkt;
|
|
$kb->{keys_by_short_id}{ substr $kid, -4, 4 } = $pkt;
|
|
}
|
|
}
|
|
|
|
sub get { $_[0]->{pkt}->{ $_[1] } }
|
|
|
|
sub save {
|
|
my $kb = shift;
|
|
Crypt::OpenPGP::PacketFactory->save( @{ $kb->{order} } );
|
|
}
|
|
|
|
sub save_armoured {
|
|
my $kb = shift;
|
|
require Crypt::OpenPGP::Armour;
|
|
Crypt::OpenPGP::Armour->armour(
|
|
Data => $kb->save,
|
|
Object => 'PUBLIC KEY BLOCK'
|
|
);
|
|
}
|
|
|
|
1;
|
|
__END__
|
|
|
|
=head1 NAME
|
|
|
|
Crypt::OpenPGP::KeyBlock - Key block object
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
use Crypt::OpenPGP::KeyBlock;
|
|
|
|
my $packet = Crypt::OpenPGP::UserID->new( Identity => 'foo' );
|
|
my $kb = Crypt::OpenPGP::KeyBlock->new;
|
|
$kb->add($packet);
|
|
|
|
my $serialized = $kb->save;
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
I<Crypt::OpenPGP::KeyBlock> represents a single keyblock in a keyring.
|
|
A key block is essentially just a set of associated keys containing
|
|
exactly one master key, zero or more subkeys, some user ID packets, some
|
|
signatures, etc. The key is that there is only one master key
|
|
associated with each keyblock.
|
|
|
|
=head1 USAGE
|
|
|
|
=head2 Crypt::OpenPGP::KeyBlock->new
|
|
|
|
Constructs a new key block object and returns that object.
|
|
|
|
=head2 $kb->encrypting_key
|
|
|
|
Returns the key that performs encryption in this key block. For example,
|
|
if a DSA key is the master key in a key block with an ElGamal subkey,
|
|
I<encrypting_key> returns the ElGamal subkey certificate, because DSA
|
|
keys do not perform encryption/decryption.
|
|
|
|
=head2 $kb->signing_key
|
|
|
|
Returns the key that performs signing in this key block. For example,
|
|
if a DSA key is the master key in a key block with an ElGamal subkey,
|
|
I<encrypting_key> returns the DSA master key certificate, because DSA
|
|
supports signing/verification.
|
|
|
|
=head2 $kb->add($packet)
|
|
|
|
Adds the packet I<$packet> to the key block. If the packet is a PGP
|
|
certificate (a I<Crypt::OpenPGP::Certificate> object), the certificate
|
|
is also added to the internal key-management mechanism.
|
|
|
|
=head2 $kb->save
|
|
|
|
Serializes each of the packets contained in the I<KeyBlock> object,
|
|
in order, and returns the serialized data. This output can then be
|
|
fed to I<Crypt::OpenPGP::Armour> for ASCII-armouring, for example,
|
|
or can be written out to a keyring file.
|
|
|
|
=head2 $kb->save_armoured
|
|
|
|
Saves an armoured version of the keyblock (this is useful for exporting
|
|
public keys).
|
|
|
|
=head1 AUTHOR & COPYRIGHTS
|
|
|
|
Please see the Crypt::OpenPGP manpage for author, copyright, and
|
|
license information.
|
|
|
|
=cut
|