File Coverage

blib/lib/Crypt/PK/DH.pm
Criterion Covered Total %
statement 58 69 84.0
branch 34 58 58.6
condition 2 3 66.6
subroutine 10 11 90.9
pod 4 5 80.0
total 108 146 73.9


line stmt bran cond sub pod time code
1             package Crypt::PK::DH;
2              
3 5     5   142343 use strict;
  5         14  
  5         224  
4 5     5   27 use warnings;
  5         12  
  5         705  
5             our $VERSION = '0.089';
6              
7             require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import';
8             our %EXPORT_TAGS = ( all => [qw( dh_shared_secret )] );
9             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
10             our @EXPORT = qw();
11              
12 5     5   57 use Carp;
  5         16  
  5         333  
13 5     5   567 use CryptX;
  5         12  
  5         198  
14 5     5   676 use Crypt::Misc qw(read_rawfile pem_to_der);
  5         9  
  5         7941  
15              
16             my %DH_PARAMS = (
17             ike768 => { g => 2, p => 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1'.
18             '29024E088A67CC74020BBEA63B139B22514A08798E3404DD'.
19             'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245'.
20             'E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF'
21             },
22             ike1024 => { g => 2, p => 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1'.
23             '29024E088A67CC74020BBEA63B139B22514A08798E3404DD'.
24             'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245'.
25             'E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED'.
26             'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381'.
27             'FFFFFFFFFFFFFFFF'
28             },
29             ike1536 => { g => 2, p => 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1'.
30             '29024E088A67CC74020BBEA63B139B22514A08798E3404DD'.
31             'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245'.
32             'E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED'.
33             'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D'.
34             'C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F'.
35             '83655D23DCA3AD961C62F356208552BB9ED529077096966D'.
36             '670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF'
37             },
38             ike2048 => { g => 2, p => 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1'.
39             '29024E088A67CC74020BBEA63B139B22514A08798E3404DD'.
40             'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245'.
41             'E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED'.
42             'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D'.
43             'C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F'.
44             '83655D23DCA3AD961C62F356208552BB9ED529077096966D'.
45             '670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B'.
46             'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9'.
47             'DE2BCBF6955817183995497CEA956AE515D2261898FA0510'.
48             '15728E5A8AACAA68FFFFFFFFFFFFFFFF'
49             },
50             ike3072 => { g => 2, p => 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1'.
51             '29024E088A67CC74020BBEA63B139B22514A08798E3404DD'.
52             'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245'.
53             'E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED'.
54             'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D'.
55             'C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F'.
56             '83655D23DCA3AD961C62F356208552BB9ED529077096966D'.
57             '670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B'.
58             'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9'.
59             'DE2BCBF6955817183995497CEA956AE515D2261898FA0510'.
60             '15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64'.
61             'ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7'.
62             'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B'.
63             'F12FFA06D98A0864D87602733EC86A64521F2B18177B200C'.
64             'BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31'.
65             '43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF'
66             },
67             ike4096 => { g => 2, p => 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1'.
68             '29024E088A67CC74020BBEA63B139B22514A08798E3404DD'.
69             'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245'.
70             'E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED'.
71             'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D'.
72             'C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F'.
73             '83655D23DCA3AD961C62F356208552BB9ED529077096966D'.
74             '670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B'.
75             'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9'.
76             'DE2BCBF6955817183995497CEA956AE515D2261898FA0510'.
77             '15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64'.
78             'ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7'.
79             'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B'.
80             'F12FFA06D98A0864D87602733EC86A64521F2B18177B200C'.
81             'BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31'.
82             '43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7'.
83             '88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA'.
84             '2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6'.
85             '287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED'.
86             '1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9'.
87             '93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199'.
88             'FFFFFFFFFFFFFFFF'
89             },
90             ike6144 => { g => 2, p => 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1'.
91             '29024E088A67CC74020BBEA63B139B22514A08798E3404DD'.
92             'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245'.
93             'E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED'.
94             'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D'.
95             'C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F'.
96             '83655D23DCA3AD961C62F356208552BB9ED529077096966D'.
97             '670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B'.
98             'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9'.
99             'DE2BCBF6955817183995497CEA956AE515D2261898FA0510'.
100             '15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64'.
101             'ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7'.
102             'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B'.
103             'F12FFA06D98A0864D87602733EC86A64521F2B18177B200C'.
104             'BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31'.
105             '43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7'.
106             '88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA'.
107             '2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6'.
108             '287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED'.
109             '1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9'.
110             '93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492'.
111             '36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD'.
112             'F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831'.
113             '179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B'.
114             'DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF'.
115             '5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6'.
116             'D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3'.
117             '23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA'.
118             'CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328'.
119             '06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C'.
120             'DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE'.
121             '12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF'
122             },
123             ike8192 => { g => 2, p => 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1'.
124             '29024E088A67CC74020BBEA63B139B22514A08798E3404DD'.
125             'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245'.
126             'E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED'.
127             'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D'.
128             'C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F'.
129             '83655D23DCA3AD961C62F356208552BB9ED529077096966D'.
130             '670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B'.
131             'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9'.
132             'DE2BCBF6955817183995497CEA956AE515D2261898FA0510'.
133             '15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64'.
134             'ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7'.
135             'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B'.
136             'F12FFA06D98A0864D87602733EC86A64521F2B18177B200C'.
137             'BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31'.
138             '43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7'.
139             '88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA'.
140             '2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6'.
141             '287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED'.
142             '1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9'.
143             '93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492'.
144             '36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD'.
145             'F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831'.
146             '179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B'.
147             'DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF'.
148             '5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6'.
149             'D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3'.
150             '23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA'.
151             'CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328'.
152             '06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C'.
153             'DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE'.
154             '12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4'.
155             '38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300'.
156             '741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568'.
157             '3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9'.
158             '22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B'.
159             '4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A'.
160             '062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36'.
161             '4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1'.
162             'B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92'.
163             '4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47'.
164             '9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71'.
165             '60C980DD98EDD3DFFFFFFFFFFFFFFFFF'
166             }
167             );
168              
169             sub new {
170 46     46 1 268686 my $self = shift->_new();
171 46 100       387 return @_ > 0 ? $self->import_key(@_) : $self;
172             }
173              
174             sub import_key {
175 27     27 1 129 my ($self, $key) = @_;
176 27 50       92 croak "FATAL: undefined key" unless $key;
177 27         41 my $data;
178 27 50       655 if (ref($key) eq 'SCALAR') {
    50          
179 0         0 $data = $$key;
180             }
181             elsif (-f $key) {
182 27         119 $data = read_rawfile($key);
183             }
184             else {
185 0         0 croak "FATAL: non-existing file '$key'";
186             }
187 27 50       115 croak "FATAL: invalid key format" unless $data;
188 27         41681 return $self->_import($data);
189             }
190              
191             sub import_key_raw {
192 4     4 1 38 my ($self, $raw_bytes, $type, $param) = @_;
193 4         11 my ($g, $p, $x, $y);
194              
195 4 50       28 if (ref $param eq 'HASH') {
    50          
196 0 0       0 $g = $param->{g} or croak "FATAL: 'g' param not specified";
197 0 0       0 $p = $param->{p} or croak "FATAL: 'p' param not specified";
198 0         0 $g =~ s/^0x//;
199 0         0 $p =~ s/^0x//;
200 0 0       0 croak "FATAL: 'g' param is empty after stripping '0x' prefix" unless length $g;
201 0 0       0 croak "FATAL: 'p' param is empty after stripping '0x' prefix" unless length $p;
202             } elsif (my $dhparam = $DH_PARAMS{$param}) {
203 4         12 $g = $dhparam->{g};
204 4         11 $p = $dhparam->{p};
205             } else {
206 0         0 croak "FATAL: invalid parameter";
207             }
208              
209 4 100       19 if ($type eq 'private') {
    50          
210 2         5 $type = 1;
211             } elsif ($type eq 'public') {
212 2         5 $type = 0;
213             } else {
214 0         0 croak "FATAL: invalid key type '$type'";
215             }
216 4         44514 my $rv = $self->_import_raw($raw_bytes, $type, $g, $p);
217 4         33 return $rv;
218             }
219              
220             sub generate_key {
221 16     16 1 2790 my ($self, $param) = @_;
222              
223 16 100       118 if (!defined $param) {
224 1         100 croak "FATAL: DH generate_key - invalid args";
225             }
226 15 100       90 if (!ref $param) {
    100          
    50          
227             # group name
228 10 100       18872 return $self->_generate_key_gp($DH_PARAMS{$param}{g}, $DH_PARAMS{$param}{p}) if exists $DH_PARAMS{$param};
229             # size
230 5 100       4225 return $self->_generate_key_size($param) if $param =~ /^[0-9]+\z/;
231             }
232             elsif (ref $param eq 'SCALAR') {
233 2         5 my $data = $$param;
234 2 100       22 if ($data =~ /-----BEGIN DH PARAMETERS-----\s*(.+)\s*-----END DH PARAMETERS-----/s) {
235 1 50       8 $data = pem_to_der($data) or croak "FATAL: PEM/params decode failed";
236             }
237 2         7593 return $self->_generate_key_dhparam($data);
238             }
239             elsif (ref $param eq 'HASH') {
240 3 50       13 my $g = $param->{g} or croak "FATAL: 'g' param not specified";
241 3 50       13 my $p = $param->{p} or croak "FATAL: 'p' param not specified";
242 3         11 $g =~ s/^0x//;
243 3         10 $p =~ s/^0x//;
244 3 50       11 croak "FATAL: 'g' param is empty after stripping '0x' prefix" unless length $g;
245 3 50       7 croak "FATAL: 'p' param is empty after stripping '0x' prefix" unless length $p;
246 3         12948 return $self->_generate_key_gp($g, $p);
247             }
248 3         471 croak "FATAL: DH generate_key - invalid args";
249             }
250              
251             ### FUNCTIONS
252              
253             sub dh_shared_secret { # legacy/obsolete
254 5     5 0 2713 my ($privkey, $pubkey) = @_;
255 5 50       34 $privkey = __PACKAGE__->new($privkey) unless ref $privkey;
256 5 50       47 $pubkey = __PACKAGE__->new($pubkey) unless ref $pubkey;
257 5 100 66     173 croak "FATAL: invalid 'privkey' param" unless ref($privkey) eq __PACKAGE__ && $privkey->is_private;
258 4 50       8 croak "FATAL: invalid 'pubkey' param" unless ref($pubkey) eq __PACKAGE__;
259 4         9289 return $privkey->shared_secret($pubkey);
260             }
261              
262 0     0     sub CLONE_SKIP { 1 } # prevent cloning
263              
264             1;
265              
266             =pod
267              
268             =head1 NAME
269              
270             Crypt::PK::DH - Public key cryptography based on Diffie-Hellman
271              
272             =head1 SYNOPSIS
273              
274             ### OO interface
275              
276             #Shared secret
277             my $alice = Crypt::PK::DH->new();
278             $alice->generate_key('ike2048');
279             my $bob = Crypt::PK::DH->new();
280             $bob->generate_key($alice->params2hash);
281              
282             my $alice_public = $alice->export_key('public');
283             my $bob_public = $bob->export_key('public');
284              
285             my $alice_shared = $alice->shared_secret(Crypt::PK::DH->new(\$bob_public));
286             my $bob_shared = $bob->shared_secret(Crypt::PK::DH->new(\$alice_public));
287              
288             #Key generation
289             my $pk = Crypt::PK::DH->new();
290             $pk->generate_key(256);
291             my $private = $pk->export_key('private');
292             my $public = $pk->export_key('public');
293              
294             #or use a named IKE group
295              
296             my $pk = Crypt::PK::DH->new();
297             $pk->generate_key('ike2048');
298             my $private = $pk->export_key('private');
299             my $public = $pk->export_key('public');
300              
301             #or provide explicit parameters
302              
303             my $pk = Crypt::PK::DH->new();
304             $pk->generate_key({ p => $p, g => $g });
305             my $private = $pk->export_key('private');
306             my $public = $pk->export_key('public');
307              
308             =head1 DESCRIPTION
309              
310             Provides Diffie-Hellman key agreement. Use it to generate a DH private/public
311             key pair and to derive a shared secret from your private key and the peer's
312             public key.
313              
314             Parameters can come from libtomcrypt's built-in groups, the named IKE groups,
315             an explicit C<{ p =E ..., g =E ... }> hash, or a PEM/DER buffer that
316             contains DH parameters.
317              
318             Legacy function-style wrappers still exist in code for backwards compatibility,
319             but they are intentionally undocumented.
320              
321             =head1 METHODS
322              
323             =head2 new
324              
325             my $pk = Crypt::PK::DH->new();
326             $pk->generate_key('ike2048');
327              
328             my $public_blob = $pk->export_key('public');
329             my $pub = Crypt::PK::DH->new(\$public_blob);
330              
331             Passing C<$filename> or C<\$buffer> to C is equivalent: both forms
332             immediately import the key material into the new object.
333              
334             =head2 generate_key
335              
336             Uses the bundled C PRNG via libtomcrypt's C.
337             Returns the object itself (for chaining).
338              
339             $pk->generate_key($groupsize);
340             ### $groupsize (in bytes) corresponds to DH parameters (p, g) predefined by libtomcrypt
341             # 96 => DH-768
342             # 128 => DH-1024
343             # 192 => DH-1536
344             # 256 => DH-2048
345             # 384 => DH-3072
346             # 512 => DH-4096
347             # 768 => DH-6144
348             # 1024 => DH-8192
349              
350             The following variants are available since CryptX-0.032
351              
352             $pk->generate_key($groupname)
353             ### $groupname selects a named IKE/MODP group from RFC 7296 and RFC 3526.
354             ### The number suffix is the bit size of the prime (p).
355             # 'ike768' => 768-bit MODP (IKE Group 1 - RFC 2409) -- NOT recommended
356             # 'ike1024' => 1024-bit MODP (IKE Group 2 - RFC 2409) -- NOT recommended
357             # 'ike1536' => 1536-bit MODP (IKE Group 5 - RFC 3526)
358             # 'ike2048' => 2048-bit MODP (IKE Group 14 - RFC 3526) -- minimum recommended
359             # 'ike3072' => 3072-bit MODP (IKE Group 15 - RFC 3526)
360             # 'ike4096' => 4096-bit MODP (IKE Group 16 - RFC 3526)
361             # 'ike6144' => 6144-bit MODP (IKE Group 17 - RFC 3526)
362             # 'ike8192' => 8192-bit MODP (IKE Group 18 - RFC 3526)
363              
364             $pk->generate_key($param_hash)
365             # $param_hash is { g => $g, p => $p }
366             # where $g is the generator (base) in a hex string and $p is the prime in a hex string
367             # practical current limit: custom p/g values must fit into the current XS buffers
368             # (roughly up to the built-in 8192-bit group sizes)
369              
370             $pk->generate_key(\$dh_param)
371             # $dh_param is the content of DER or PEM file with DH parameters
372             # e.g. openssl dhparam 2048
373              
374             =head2 import_key
375              
376             Loads private or public key (exported by L).
377              
378             my $source = Crypt::PK::DH->new();
379             $source->generate_key('ike2048');
380              
381             my $public_blob = $source->export_key('public');
382             my $pub = Crypt::PK::DH->new();
383             $pub->import_key(\$public_blob);
384              
385             The same method also accepts a filename instead of C<\$public_blob>.
386              
387             =head2 import_key_raw
388              
389             I
390              
391             $pk->import_key_raw($raw_bytes, $type, $params)
392             # $raw_bytes .. [binary string] raw key data
393             # $type ....... [string] 'private' or 'public'
394             # $params ..... [string | hashref] group name (e.g. 'ike2048') or { g => $g, p => $p } with hex strings
395              
396             =head2 export_key
397              
398             B DH key format change - since v0.049 it is compatible with libtomcrypt 1.18.
399              
400             my $private = $pk->export_key('private');
401             #or
402             my $public = $pk->export_key('public');
403              
404             =head2 export_key_raw
405              
406             I
407              
408             Returns the raw key as a binary string.
409              
410             $raw_bytes = $dh->export_key_raw('public')
411             #or
412             $raw_bytes = $dh->export_key_raw('private')
413              
414             =head2 shared_secret
415              
416             Returns the shared secret as a binary string (raw bytes).
417              
418             my $alice = Crypt::PK::DH->new();
419             $alice->generate_key('ike2048');
420             my $bob = Crypt::PK::DH->new();
421             $bob->generate_key($alice->params2hash);
422              
423             my $alice_public = $alice->export_key('public');
424             my $bob_public = $bob->export_key('public');
425              
426             my $alice_shared = $alice->shared_secret(Crypt::PK::DH->new(\$bob_public));
427             my $bob_shared = $bob->shared_secret(Crypt::PK::DH->new(\$alice_public));
428              
429             =head2 is_private
430              
431             my $rv = $pk->is_private;
432             # 1 .. private key loaded
433             # 0 .. public key loaded
434             # undef .. no key loaded
435              
436             =head2 size
437              
438             my $size = $pk->size;
439             # returns key size in bytes or undef if no key loaded
440              
441             =head2 key2hash
442              
443             Returns a hashref with the key components, or C if no key is loaded.
444              
445             my $hash = $pk->key2hash;
446              
447             # returns hash like this (or undef if no key loaded):
448             {
449             type => 0, # integer: 1 .. private, 0 .. public
450             size => 256, # integer: key size in bytes
451             x => "FBC1062F73B9A17BB8473A2F5A074911FA7F20D28FB...", #private key
452             y => "AB9AAA40774D3CD476B52F82E7EE2D8A8D40CD88BF4...", #public key
453             g => "2", # generator/base
454             p => "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80D...", # prime
455             }
456              
457             =head2 params2hash
458              
459             I
460              
461             my $params = $pk->params2hash;
462              
463             # returns hash like this (or undef if no key loaded):
464             {
465             g => "2", # generator/base
466             p => "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80D...", # prime
467             }
468              
469             =head1 SEE ALSO
470              
471             =over
472              
473             =item * L
474              
475             =item * L
476              
477             =item * L
478              
479             =back
480              
481             =cut