File Coverage

blib/lib/Crypt/DSA/Key/PEM.pm
Criterion Covered Total %
statement 61 61 100.0
branch 12 18 66.6
condition n/a
subroutine 13 13 100.0
pod 0 2 0.0
total 86 94 91.4


line stmt bran cond sub pod time code
1             package Crypt::DSA::Key::PEM;
2              
3 2     2   26 use strict;
  2         11  
  2         124  
4 2     2   18 use Carp qw( croak );
  2         4  
  2         191  
5 2     2   18 use Convert::PEM;
  2         3  
  2         97  
6 2     2   22 use Crypt::DSA::Key;
  2         11  
  2         135  
7              
8             our $VERSION = '1.19'; #VERSION
9              
10 2     2   11 use vars qw{$VERSION @ISA};
  2         3  
  2         292  
11             BEGIN {
12 2     2   1780 @ISA = 'Crypt::DSA::Key';
13             }
14              
15             sub deserialize {
16 4     4 0 11 my $key = shift;
17 4         18 my %param = @_;
18 4 100       101 $param{Content} =~ /DSA PRIVATE KEY/ ?
19             $key->_deserialize_privkey(%param) :
20             $key->_deserialize_pubkey(%param);
21             }
22              
23             sub _deserialize_privkey {
24 2     2   7 my $key = shift;
25 2         7 my %param = @_;
26              
27 2         11 my $pem = $key->_pem;
28             my $pkey = $pem->decode( Content => $param{Content},
29             Password => $param{Password},
30 2         45 Macro => 'DSAPrivateKey' );
31 2 50       206142 return unless $pkey;
32              
33 2         8 for my $m (qw( p q g pub_key priv_key )) {
34 10         94 $key->$m( $pkey->{$m} );
35             }
36 2         111 $key;
37             }
38              
39             sub _deserialize_pubkey {
40 2     2   5 my $key = shift;
41 2         7 my %param = @_;
42              
43 2         9 my $pem = $key->_pem;
44             my $pkey = $pem->decode( Content => $param{Content},
45             Password => $param{Password},
46 2         24 Macro => 'DSAPublicKey',
47             Name => 'PUBLIC KEY' );
48 2 50       226724 return unless $pkey;
49              
50 2         34 my $asn = $pem->asn->find('DSAPubKeyInner');
51 2 50       90 my $num = $asn->decode($pkey->{pub_key}[0]) or croak $asn->{error};
52              
53 2         98805 for my $m (qw( p q g )) {
54 6         119 $key->$m( $pkey->{inner}{DSAParams}{$m} );
55             }
56 2         64 $key->pub_key($num);
57              
58 2         146 $key;
59             }
60              
61             sub serialize {
62 3     3 0 5 my $key = shift;
63             ## If this is a private key (has the private key portion), serialize
64             ## it as a private key; otherwise use a public key ASN.1 object.
65 3 100       22 $key->priv_key ? $key->_serialize_privkey(@_) : $key->_serialize_pubkey(@_);
66             }
67              
68             sub _serialize_privkey {
69 2     2   82 my $key = shift;
70 2         9 my %param = @_;
71              
72 2         7 my $pkey = { version => 0 };
73 2         4 for my $m (qw( p q g pub_key priv_key )) {
74 10         42 $pkey->{$m} = $key->$m();
75             }
76              
77 2         16 my $pem = $key->_pem;
78             my $buf = $pem->encode(
79             Content => $pkey,
80             Password => $param{Password},
81 2 50       41 Name => 'DSA PRIVATE KEY',
82             Macro => 'DSAPrivateKey',
83             ) or croak $pem->errstr;
84 2         353727 $buf;
85             }
86              
87             sub _serialize_pubkey {
88 1     1   3 my $key = shift;
89 1         6 my %param = @_;
90 1         5 my $pem = $key->_pem;
91 1         9 my $asn = $pem->asn->find('DSAPubKeyInner');
92             ## Force stringification.
93 1 50       40 my $str = $asn->encode($key->pub_key . '') or croak $asn->{error};
94 1         56305 my $pkey = {
95             inner => {
96             objId => '1.2.840.10040.4.1',
97             DSAParams => {
98             p => $key->p,
99             q => $key->q,
100             g => $key->g
101             },
102             },
103             pub_key => $str
104             };
105             my $buf = $pem->encode(
106             Content => $pkey,
107             Password => $param{Password},
108 1 50       15 Name => 'PUBLIC KEY',
109             Macro => 'DSAPublicKey',
110             ) or return $key->error($pem->errstr);
111 1         131339 $buf;
112             }
113              
114             sub _pem {
115 7     7   13 my $key = shift;
116 7 100       30 unless (defined $key->{__pem}) {
117 5         85 my $pem = Convert::PEM->new(
118             Name => "DSA PRIVATE KEY",
119             ASN => qq(
120             DSAPrivateKey ::= SEQUENCE {
121             version INTEGER,
122             p INTEGER,
123             q INTEGER,
124             g INTEGER,
125             pub_key INTEGER,
126             priv_key INTEGER
127             }
128              
129             DSAPublicKey ::= SEQUENCE {
130             inner SEQUENCE {
131             objId OBJECT IDENTIFIER,
132             DSAParams SEQUENCE {
133             p INTEGER,
134             q INTEGER,
135             g INTEGER
136             }
137             }
138             pub_key BIT STRING
139             }
140              
141             DSAPubKeyInner ::= INTEGER
142             ));
143 5         36689 $key->{__pem} = $pem;
144             }
145 7         72 $key->{__pem};
146             }
147              
148             1;
149             __END__