package Crypt::OpenPGP::Signature::SubPacket; use strict; use Crypt::OpenPGP::ErrorHandler; use base qw( Crypt::OpenPGP::ErrorHandler ); use vars qw( %SUBPACKET_TYPES ); %SUBPACKET_TYPES = ( 2 => { name => 'Signature creation time', r => sub { $_[0]->get_int32 }, w => sub { $_[0]->put_int32($_[1]) } }, 3 => { name => 'Signature expiration time', r => sub { $_[0]->get_int32 }, w => sub { $_[0]->put_int32($_[1]) } }, 4 => { name => 'Exportable certification', r => sub { $_[0]->get_int8 }, w => sub { $_[0]->put_int8($_[1]) } }, 5 => { name => 'Trust signature', r => sub { $_[0]->get_int8 }, w => sub { $_[0]->put_int8($_[1]) } }, 6 => { name => 'Regular expression', r => sub { $_[0]->bytes }, w => sub { $_[0]->append($_[1]) } }, 7 => { name => 'Revocable', r => sub { $_[0]->get_int8 }, w => sub { $_[0]->put_int8($_[1]) } }, 9 => { name => 'Key expiration time', r => sub { $_[0]->get_int32 }, w => sub { $_[0]->put_int32($_[1]) } }, 10 => { name => '(Unsupported placeholder', r => sub { }, w => sub { } }, 11 => { name => 'Preferred symmetric algorithms', r => sub { [ unpack 'C*', $_[0]->bytes ] }, w => sub { $_[0]->append(pack 'C*', @{ $_[1] }) } }, 12 => { name => 'Revocation key', r => sub { { class => $_[0]->get_int8, alg_id => $_[0]->get_int8, fingerprint => $_[0]->get_bytes(20) } }, w => sub { $_[0]->put_int8($_[1]->{class}); $_[0]->put_int8($_[1]->{alg_id}); $_[0]->put_bytes($_[1]->{fingerprint}, 20) } }, 16 => { name => 'Issuer key ID', r => sub { $_[0]->get_bytes(8) }, w => sub { $_[0]->put_bytes($_[1], 8) } }, 20 => { name => 'Notation data', r => sub { { flags => $_[0]->get_int32, name => $_[0]->get_bytes($_[0]->get_int16), value => $_[0]->get_bytes($_[0]->get_int16) } }, w => sub { $_[0]->put_int32($_[1]->{flags}); $_[0]->put_int16(length $_[1]->{name}); $_[0]->put_bytes($_[1]->{name}); $_[0]->put_int16(length $_[1]->{value}); $_[0]->put_bytes($_[1]->{value}) } }, 21 => { name => 'Preferred hash algorithms', r => sub { [ unpack 'C', $_[0]->bytes ] }, w => sub { $_[0]->put_bytes(pack 'C*', @{ $_[1] }) } }, 22 => { name => 'Preferred compression algorithms', r => sub { [ unpack 'C', $_[0]->bytes ] }, w => sub { $_[0]->put_bytes(pack 'C*', @{ $_[1] }) } }, 23 => { name => 'Key server preferences', r => sub { $_[0]->bytes }, w => sub { $_[0]->append($_[1]) } }, 24 => { name => 'Preferred key server', r => sub { $_[0]->bytes }, w => sub { $_[0]->append($_[1]) } }, 25 => { name => 'Primary user ID', r => sub { $_[0]->get_int8 }, w => sub { $_[0]->put_int8($_[1]) } }, 26 => { name => 'Policy URL', r => sub { $_[0]->bytes }, w => sub { $_[0]->append($_[1]) } }, 27 => { name => 'Key flags', r => sub { $_[0]->bytes }, w => sub { $_[0]->append($_[1]) } }, 28 => { name => 'Signer\'s user ID', r => sub { $_[0]->bytes }, w => sub { $_[0]->append($_[1]) } }, 29 => { name => 'Reason for revocation', r => sub { { code => $_[0]->get_int8, reason => $_[0]->get_bytes($_[0]->length - $_[0]->offset) } }, w => sub { $_[0]->put_int8($_[1]->{code}); $_[0]->put_bytes($_[1]->{reason}) } }, ); sub new { bless { }, $_[0] } sub parse { my $class = shift; my($buf) = @_; my $sp = $class->new; my $tag = $buf->get_int8; $sp->{critical} = $tag & 0x80; $sp->{type} = $tag & 0x7f; $buf->bytes(0, 1, ''); ## Cut off tag byte $buf->{offset} = 0; my $ref = $SUBPACKET_TYPES{$sp->{type}}; $sp->{data} = $ref->{r}->($buf) if $ref && $ref->{r}; $sp; } sub save { my $sp = shift; my $buf = Crypt::OpenPGP::Buffer->new; my $tag = $sp->{type}; $tag |= 0x80 if $sp->{critical}; $buf->put_int8($tag); my $ref = $SUBPACKET_TYPES{$sp->{type}}; $ref->{w}->($buf, $sp->{data}) if $ref && $ref->{w}; $buf->bytes; } 1;