File Coverage

blib/lib/Crypt/PK/ECC.pm
Criterion Covered Total %
statement 103 151 68.2
branch 51 120 42.5
condition 9 60 15.0
subroutine 19 22 86.3
pod 6 13 46.1
total 188 366 51.3


line stmt bran cond sub pod time code
1             package Crypt::PK::ECC;
2              
3 10     10   253116 use strict;
  10         17  
  10         288  
4 10     10   47 use warnings;
  10         13  
  10         1267  
5             our $VERSION = '0.089_002';
6              
7             require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import';
8             our %EXPORT_TAGS = ( all => [qw( ecc_encrypt ecc_decrypt ecc_sign_message ecc_verify_message ecc_sign_hash ecc_verify_hash ecc_shared_secret )] );
9             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
10             our @EXPORT = qw();
11              
12 10     10   66 use Carp;
  10         13  
  10         626  
13             $Carp::Internal{(__PACKAGE__)}++;
14 10     10   1207 use CryptX;
  10         14  
  10         362  
15 10     10   1178 use Crypt::Digest qw(digest_data digest_data_b64u);
  10         17  
  10         547  
16 10     10   1319 use Crypt::Misc qw(read_rawfile encode_b64u decode_b64u encode_b64 decode_b64 pem_to_der der_to_pem);
  10         23  
  10         676  
17 10     10   988 use Crypt::PK;
  10         21  
  10         23864  
18              
19             our %curve = ( # must be "our" as we use it from XS code
20             # extra curves not recognized by libtomcrypt
21             'wap-wsg-idm-ecid-wtls8' => {
22             prime => "FFFFFFFFFFFFFFFFFFFFFFFFFDE7",
23             A => "0000000000000000000000000000",
24             B => "0000000000000000000000000003",
25             order => "0100000000000001ECEA551AD837E9",
26             Gx => "0000000000000000000000000001",
27             Gy => "0000000000000000000000000002",
28             cofactor => 1,
29             oid => '2.23.43.1.4.8',
30             },
31             'wap-wsg-idm-ecid-wtls9' => {
32             prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC808F",
33             A => "0000000000000000000000000000000000000000",
34             B => "0000000000000000000000000000000000000003",
35             order => "0100000000000000000001CDC98AE0E2DE574ABF33",
36             Gx => "0000000000000000000000000000000000000001",
37             Gy => "0000000000000000000000000000000000000002",
38             cofactor => 1,
39             oid => '2.23.43.1.4.9',
40             },
41             # some unusual openssl names
42             "wap-wsg-idm-ecid-wtls6" => 'secp112r1',
43             "wap-wsg-idm-ecid-wtls7" => 'secp160r2',
44             "wap-wsg-idm-ecid-wtls12" => 'secp224r1',
45             # extra aliases
46             'P-256K' => 'secp256k1',
47             );
48              
49             our %curve_oid2name = ( # must be "our" as we use it from XS code
50             # the following are used to derive curve_name from OID in key2hash()
51             "1.2.840.10045.3.1.1" => "secp192r1",
52             "1.2.840.10045.3.1.2" => "prime192v2",
53             "1.2.840.10045.3.1.3" => "prime192v3",
54             "1.2.840.10045.3.1.4" => "prime239v1",
55             "1.2.840.10045.3.1.5" => "prime239v2",
56             "1.2.840.10045.3.1.6" => "prime239v3",
57             "1.2.840.10045.3.1.7" => "secp256r1",
58             "1.3.132.0.6" => "secp112r1",
59             "1.3.132.0.7" => "secp112r2",
60             "1.3.132.0.8" => "secp160r1",
61             "1.3.132.0.9" => "secp160k1",
62             "1.3.132.0.10" => "secp256k1",
63             "1.3.132.0.28" => "secp128r1",
64             "1.3.132.0.29" => "secp128r2",
65             "1.3.132.0.30" => "secp160r2",
66             "1.3.132.0.31" => "secp192k1",
67             "1.3.132.0.32" => "secp224k1",
68             "1.3.132.0.33" => "secp224r1",
69             "1.3.132.0.34" => "secp384r1",
70             "1.3.132.0.35" => "secp521r1",
71             "1.3.36.3.3.2.8.1.1.1" => "brainpoolp160r1",
72             "1.3.36.3.3.2.8.1.1.2" => "brainpoolp160t1",
73             "1.3.36.3.3.2.8.1.1.3" => "brainpoolp192r1",
74             "1.3.36.3.3.2.8.1.1.4" => "brainpoolp192t1",
75             "1.3.36.3.3.2.8.1.1.5" => "brainpoolp224r1",
76             "1.3.36.3.3.2.8.1.1.6" => "brainpoolp224t1",
77             "1.3.36.3.3.2.8.1.1.7" => "brainpoolp256r1",
78             "1.3.36.3.3.2.8.1.1.8" => "brainpoolp256t1",
79             "1.3.36.3.3.2.8.1.1.9" => "brainpoolp320r1",
80             "1.3.36.3.3.2.8.1.1.10" => "brainpoolp320t1",
81             "1.3.36.3.3.2.8.1.1.11" => "brainpoolp384r1",
82             "1.3.36.3.3.2.8.1.1.12" => "brainpoolp384t1",
83             "1.3.36.3.3.2.8.1.1.13" => "brainpoolp512r1",
84             "1.3.36.3.3.2.8.1.1.14" => "brainpoolp512t1",
85             "1.2.250.1.223.101.256.1" => "frp256v1",
86             );
87              
88             my %curve2jwk = (
89             # necessary for conversion of curve_name_or_OID >> P-NNN
90             '1.2.840.10045.3.1.1' => 'P-192', # secp192r1
91             '1.3.132.0.33' => 'P-224', # secp224r1
92             '1.2.840.10045.3.1.7' => 'P-256', # secp256r1
93             '1.3.132.0.10' => 'P-256K',# secp256k1
94             '1.3.132.0.34' => 'P-384', # secp384r1
95             '1.3.132.0.35' => 'P-521', # secp521r1
96             'nistp192' => 'P-192',
97             'nistp224' => 'P-224',
98             'nistp256' => 'P-256',
99             'nistp384' => 'P-384',
100             'nistp521' => 'P-521',
101             'prime192v1' => 'P-192',
102             'prime256v1' => 'P-256',
103             'secp192r1' => 'P-192',
104             'secp224r1' => 'P-224',
105             'secp256r1' => 'P-256',
106             'secp256k1' => 'P-256K',
107             'secp384r1' => 'P-384',
108             'secp521r1' => 'P-521',
109             );
110              
111             sub _import_hex {
112 1     1   3 my ($self, $x, $y, $k, $crv) = @_;
113 1 50       3 croak "FATAL: no curve" if !$crv;
114 1 50 33     4 if (defined $k && length($k) > 0) {
    0 0        
115 1 50       24 croak "FATAL: invalid length (k)" if length($k) % 2;
116 1         5720 return $self->import_key_raw(pack("H*", $k), $crv);
117             }
118             elsif (defined $x && defined $y) {
119 0 0       0 croak "FATAL: invalid length (x)" if length($x) % 2;
120 0 0       0 croak "FATAL: invalid length (y)" if length($y) % 2;
121 0 0       0 croak "FATAL: invalid length (x,y)" if length($y) != length($x);
122 0         0 my $pub_hex = "04" . $x . $y;
123 0         0 return $self->import_key_raw(pack("H*", $pub_hex), $crv);
124             }
125             }
126              
127             sub new {
128 285     285 1 1436921 my $self = shift->_new();
129 285 100       608673 return @_ > 0 ? $self->import_key(@_) : $self;
130             }
131              
132             sub export_key_pem {
133 9     9 1 2262 my ($self, $type, $password, $cipher) = @_;
134 9         47 local $SIG{__DIE__} = \&CryptX::_croak;
135 9   50     208 my $key = $self->export_key_der($type||'');
136 8 50       19 return unless $key;
137             # private, private_short, private_compressed all use the same PEM header
138 8 100       42 return der_to_pem($key, "EC PRIVATE KEY", $password, $cipher) if $type =~ /\Aprivate(?:_short|_compressed)?\z/;
139             # public, public_short, public_compressed all use the same PEM header
140 4 50       33 return der_to_pem($key, "PUBLIC KEY") if $type =~ /\Apublic(?:_short|_compressed)?\z/;
141             }
142              
143             sub export_key_jwk {
144 0     0 1 0 my ($self, $type, $wanthash) = @_;
145 0         0 local $SIG{__DIE__} = \&CryptX::_croak;
146 0         0 my $kh = $self->key2hash;
147 0 0       0 $kh->{curve_oid} = '' if !defined $kh->{curve_oid};
148 0 0       0 $kh->{curve_name} = '' if !defined $kh->{curve_name};
149 0   0     0 my $curve_jwt = $curve2jwk{$kh->{curve_oid}} || $curve2jwk{lc $kh->{curve_name}} || $kh->{curve_name};
150 0 0 0     0 if ($type && $type eq 'private') {
    0 0        
151 0 0 0     0 return unless $kh->{pub_x} && $kh->{pub_y} && $kh->{k};
      0        
152 0         0 for (qw/pub_x pub_y k/) {
153 0 0       0 $kh->{$_} = "0$kh->{$_}" if length($kh->{$_}) % 2;
154             }
155             # NOTE: x + y are not necessary in privkey
156             # but they are used in https://www.rfc-editor.org/rfc/rfc7517#appendix-A.2
157             my $hash = {
158             kty => "EC", crv => $curve_jwt,
159             x => encode_b64u(pack("H*", $kh->{pub_x})),
160             y => encode_b64u(pack("H*", $kh->{pub_y})),
161 0         0 d => encode_b64u(pack("H*", $kh->{k})),
162             };
163 0 0       0 return $wanthash ? $hash : CryptX::_encode_json($hash);
164             }
165             elsif ($type && $type eq 'public') {
166 0 0 0     0 return unless $kh->{pub_x} && $kh->{pub_y};
167 0         0 for (qw/pub_x pub_y/) {
168 0 0       0 $kh->{$_} = "0$kh->{$_}" if length($kh->{$_}) % 2;
169             }
170             my $hash = {
171             kty => "EC", crv => $curve_jwt,
172             x => encode_b64u(pack("H*", $kh->{pub_x})),
173 0         0 y => encode_b64u(pack("H*", $kh->{pub_y})),
174             };
175 0 0       0 return $wanthash ? $hash : CryptX::_encode_json($hash);
176             }
177             }
178              
179             sub export_key_jwk_thumbprint {
180 0     0 1 0 my ($self, $hash_name) = @_;
181 0         0 local $SIG{__DIE__} = \&CryptX::_croak;
182 0   0     0 $hash_name ||= 'SHA256';
183 0         0 my $h = $self->export_key_jwk('public', 1);
184 0         0 my $json = CryptX::_encode_json({crv=>$h->{crv}, kty=>$h->{kty}, x=>$h->{x}, y=>$h->{y}});
185 0         0 return digest_data_b64u($hash_name, $json);
186             }
187              
188             sub import_key {
189 122     122 1 151605 my ($self, $key, $password) = @_;
190 122         615 local $SIG{__DIE__} = \&CryptX::_croak;
191 122 50       331 croak "FATAL: undefined key" unless $key;
192              
193             # special case
194 122 100       301 if (ref($key) eq 'HASH') {
195 1 50 33     7 if (($key->{pub_x} && $key->{pub_y}) || $key->{k}) {
      33        
196             # hash exported via key2hash
197 1   33     4 my $curve_name = $key->{curve_name} || $key->{curve_oid};
198 1         5 return $self->_import_hex($key->{pub_x}, $key->{pub_y}, $key->{k}, $curve_name);
199             }
200 0 0 0     0 if ($key->{crv} && $key->{kty} && $key->{kty} eq "EC" && ($key->{d} || ($key->{x} && $key->{y}))) {
      0        
      0        
      0        
201             # hash with items corresponding to JSON Web Key (JWK)
202 0         0 $key = {%$key}; # make a copy as we will modify it
203 0         0 for (qw/x y d/) {
204 0 0       0 $key->{$_} = eval { unpack("H*", decode_b64u($key->{$_})) } if exists $key->{$_};
  0         0  
205             }
206             # names P-192 P-224 P-256 P-384 P-521 are recognized by libtomcrypt
207 0         0 return $self->_import_hex($key->{x}, $key->{y}, $key->{d}, $key->{crv});
208             }
209 0         0 croak "FATAL: unexpected ECC key hash";
210             }
211              
212 121         146 my $data;
213 121 100       2428 if (ref($key) eq 'SCALAR') {
    50          
214 23         48 $data = $$key;
215             }
216             elsif (-f $key) {
217 98         394 $data = read_rawfile($key);
218             }
219             else {
220 0         0 croak "FATAL: non-existing file '$key'";
221             }
222 121 50       423 croak "FATAL: invalid key data" unless $data;
223              
224 121 100       1206 if ($data =~ /(-----BEGIN (PUBLIC|EC PRIVATE|PRIVATE|ENCRYPTED PRIVATE) KEY-----(.+?)-----END (PUBLIC|EC PRIVATE|PRIVATE|ENCRYPTED PRIVATE) KEY-----)/s) {
    50          
    100          
    100          
    100          
    50          
225 65         201 my $pem = $1;
226 65         96 my $rv = eval { $self->_import_pem($pem, $password) };
  65         369359  
227 65 100       289 if (!$rv) {
228 9         33 my $der = pem_to_der($pem, $password);
229 9 50       22 $rv = eval { $self->_import_old($der) } if defined $der;
  9         11215  
230             }
231 65 100       880 return $rv if $rv;
232             }
233             elsif ($data =~ /-----BEGIN CERTIFICATE-----(.+?)-----END CERTIFICATE-----/s) {
234 0         0 return $self->_import_pem($data, undef);
235             }
236             elsif ($data =~ /-----BEGIN OPENSSH PRIVATE KEY-----(.+?)-----END OPENSSH PRIVATE KEY-----/s) {
237 6         695202 return $self->_import_openssh($data, $password);
238             }
239             elsif ($data =~ /---- BEGIN SSH2 PUBLIC KEY ----(.+?)---- END SSH2 PUBLIC KEY ----/s) {
240 3         16575 return $self->_import_openssh($data, undef);
241             }
242             elsif ($data =~ /(ecdsa-\S+)\s+(\S+)/) {
243 3         28 $data = decode_b64("$2");
244 3         20 my ($typ, $skip, $pubkey) = Crypt::PK::_ssh_parse($data);
245 3 50 33     16555 return $self->import_key_raw($pubkey, "$2") if $pubkey && $typ =~ /^ecdsa-(.+?)-(.*)$/;
246             }
247             elsif ($data =~ /^\s*(\{.*?\})\s*$/s) {
248             # JSON Web Key (JWK) - https://www.rfc-editor.org/rfc/rfc7517
249 0         0 my $json = "$1";
250 0   0     0 my $h = CryptX::_decode_json($json) || {};
251 0 0       0 if ($h->{kty} eq "EC") {
252 0 0       0 $h->{x} = eval { unpack("H*", decode_b64u($h->{x})) } if exists $h->{x};
  0         0  
253 0 0       0 $h->{y} = eval { unpack("H*", decode_b64u($h->{y})) } if exists $h->{y};
  0         0  
254 0 0       0 $h->{d} = eval { unpack("H*", decode_b64u($h->{d})) } if exists $h->{d};
  0         0  
255             # names P-192 P-224 P-256 P-384 P-521 are recognized by libtomcrypt
256 0         0 return $self->_import_hex($h->{x}, $h->{y}, $h->{d}, $h->{crv});
257             }
258             }
259             else {
260             my $rv = eval { $self->_import($data) } ||
261             eval { $self->_import_old($data) } ||
262             eval { $self->_import_pkcs8($data, $password) } ||
263 44   66     76 eval { $self->_import_x509($data) };
264 44 100       788 return $rv if $rv;
265             }
266 6         370 croak "FATAL: invalid or unsupported EC key format";
267             }
268              
269             sub curve2hash {
270 3     3 1 5106 my $self = shift;
271 3         140 my $kh = $self->key2hash;
272             return {
273             prime => $kh->{curve_prime},
274             A => $kh->{curve_A},
275             B => $kh->{curve_B},
276             Gx => $kh->{curve_Gx},
277             Gy => $kh->{curve_Gy},
278             cofactor => $kh->{curve_cofactor},
279             order => $kh->{curve_order},
280             oid => $kh->{curve_oid},
281 3         39 };
282             }
283              
284             ### FUNCTIONS
285              
286             sub ecc_encrypt { # legacy/obsolete
287 1     1 0 3444 my $key = shift;
288 1         8 local $SIG{__DIE__} = \&CryptX::_croak;
289 1 50       7 $key = __PACKAGE__->new($key) unless ref $key;
290 1 50       67 croak "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
291 1         5635 return $key->encrypt(@_);
292             }
293              
294             sub ecc_decrypt { # legacy/obsolete
295 1     1 0 294 my $key = shift;
296 1         4 local $SIG{__DIE__} = \&CryptX::_croak;
297 1 50       9 $key = __PACKAGE__->new($key) unless ref $key;
298 1 50       5 croak "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
299 1         5944 return $key->decrypt(@_);
300             }
301              
302             sub ecc_sign_message { # legacy/obsolete
303 1     1 0 302 my $key = shift;
304 1         5 local $SIG{__DIE__} = \&CryptX::_croak;
305 1 50       8 $key = __PACKAGE__->new($key) unless ref $key;
306 1 50       6 croak "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
307 1         2908 return $key->sign_message(@_);
308             }
309              
310             sub ecc_verify_message { # legacy/obsolete
311 1     1 0 289 my $key = shift;
312 1         4 local $SIG{__DIE__} = \&CryptX::_croak;
313 1 50       8 $key = __PACKAGE__->new($key) unless ref $key;
314 1 50       5 croak "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
315 1         2021 return $key->verify_message(@_);
316             }
317              
318             sub ecc_sign_hash { # legacy/obsolete
319 1     1 0 3 my $key = shift;
320 1         5 local $SIG{__DIE__} = \&CryptX::_croak;
321 1 50       7 $key = __PACKAGE__->new($key) unless ref $key;
322 1 50       5 croak "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
323 1         5976 return $key->sign_hash(@_);
324             }
325              
326             sub ecc_verify_hash { # legacy/obsolete
327 1     1 0 380 my $key = shift;
328 1         6 local $SIG{__DIE__} = \&CryptX::_croak;
329 1 50       10 $key = __PACKAGE__->new($key) unless ref $key;
330 1 50       6 croak "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
331 1         1828 return $key->verify_hash(@_);
332             }
333              
334             sub ecc_shared_secret { # legacy/obsolete
335 2     2 0 10 my ($privkey, $pubkey) = @_;
336 2         10 local $SIG{__DIE__} = \&CryptX::_croak;
337 2 50       15 $privkey = __PACKAGE__->new($privkey) unless ref $privkey;
338 2 50       15 $pubkey = __PACKAGE__->new($pubkey) unless ref $pubkey;
339 2 50 33     18 croak "FATAL: invalid 'privkey' param" unless ref($privkey) eq __PACKAGE__ && $privkey->is_private;
340 2 50       5 croak "FATAL: invalid 'pubkey' param" unless ref($pubkey) eq __PACKAGE__;
341 2         5838 return $privkey->shared_secret($pubkey);
342             }
343              
344 0     0     sub CLONE_SKIP { 1 } # prevent cloning
345              
346             1;
347              
348             =pod
349              
350             =head1 NAME
351              
352             Crypt::PK::ECC - Public key cryptography based on EC
353              
354             =head1 SYNOPSIS
355              
356             ### OO interface
357              
358             my $message = 'hello world';
359             my $alice = Crypt::PK::ECC->new();
360             $alice->generate_key('secp256r1');
361             my $alice_public_der = $alice->export_key_der('public');
362             my $alice_public = Crypt::PK::ECC->new(\$alice_public_der);
363              
364             my $ciphertext = $alice_public->encrypt($message);
365             my $plaintext = $alice->decrypt($ciphertext);
366              
367             my $signature = $alice->sign_message($message, 'SHA256');
368             $alice_public->verify_message($signature, $message, 'SHA256') or die "ERROR";
369              
370             my $bob = Crypt::PK::ECC->new();
371             $bob->generate_key('secp256r1');
372             my $bob_public_der = $bob->export_key_der('public');
373             my $bob_public = Crypt::PK::ECC->new(\$bob_public_der);
374              
375             my $alice_secret = $alice->shared_secret($bob_public);
376             my $bob_secret = $bob->shared_secret($alice_public);
377              
378             my $private_der = $alice->export_key_der('private');
379             my $public_pem = $alice_public->export_key_pem('public');
380             my $public_raw = $alice_public->export_key_raw('public');
381              
382             =head1 DESCRIPTION
383              
384             The module provides a set of core ECC functions as well as implementation of ECDSA and ECDH.
385              
386             Supports elliptic curves C over prime fields C (binary fields not supported).
387              
388             Legacy function-style wrappers still exist in code for backwards compatibility,
389             but they are intentionally undocumented.
390              
391             =head1 METHODS
392              
393             =head2 new
394              
395             my $pk = Crypt::PK::ECC->new();
396             #or
397             my $source = Crypt::PK::ECC->new();
398             $source->generate_key('secp256r1');
399              
400             my $public_der = $source->export_key_der('public');
401             my $pub = Crypt::PK::ECC->new(\$public_der);
402              
403             my $private_pem = $source->export_key_pem('private', 'secret', 'AES-256-CBC');
404             my $priv = Crypt::PK::ECC->new(\$private_pem, 'secret');
405              
406             Passing C<$filename> or C<\$buffer> to C is equivalent: both forms
407             immediately import the key material into the new object.
408              
409             =head2 generate_key
410              
411             Uses Yarrow-based cryptographically strong random number generator seeded with
412             random data taken from C (UNIX) or C (Win32).
413             Returns the object itself (for chaining).
414              
415             $pk->generate_key($curve_name);
416             #or
417             $pk->generate_key($hashref_with_curve_params);
418              
419             The following predefined C<$curve_name> values are supported:
420              
421             # curves from https://www.rfc-editor.org/rfc/rfc5639
422             'brainpoolp160r1'
423             'brainpoolp192r1'
424             'brainpoolp224r1'
425             'brainpoolp256r1'
426             'brainpoolp320r1'
427             'brainpoolp384r1'
428             'brainpoolp512r1'
429             # curve from https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000024668816
430             'frp256v1'
431             # curves from https://www.secg.org/sec2-v2.pdf
432             'secp112r1'
433             'secp112r2'
434             'secp128r1'
435             'secp128r2'
436             'secp160k1'
437             'secp160r1'
438             'secp160r2'
439             'secp192k1'
440             'secp192r1' ... same as nistp192, prime192v1
441             'secp224k1'
442             'secp224r1' ... same as nistp224
443             'secp256k1' ... used by Bitcoin
444             'secp256r1' ... same as nistp256, prime256v1
445             'secp384r1' ... same as nistp384
446             'secp521r1' ... same as nistp521
447             #curves from https://csrc.nist.gov/pubs/fips/186-4/final
448             'nistp192' ... same as secp192r1, prime192v1
449             'nistp224' ... same as secp224r1
450             'nistp256' ... same as secp256r1, prime256v1
451             'nistp384' ... same as secp384r1
452             'nistp521' ... same as secp521r1
453             # curves from ANS X9.62
454             'prime192v1' ... same as nistp192, secp192r1
455             'prime192v2'
456             'prime192v3'
457             'prime239v1'
458             'prime239v2'
459             'prime239v3'
460             'prime256v1' ... same as nistp256, secp256r1
461              
462             Using custom curve parameters:
463              
464             $pk->generate_key({ prime => 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF',
465             A => 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC',
466             B => '22123DC2395A05CAA7423DAECCC94760A7D462256BD56916',
467             Gx => '7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896',
468             Gy => '38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0',
469             order => 'FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13',
470             cofactor => 1 });
471              
472             See L,
473             L,
474             L
475              
476             =head2 import_key
477              
478             Loads private or public key in DER or PEM format.
479              
480             my $source = Crypt::PK::ECC->new();
481             $source->generate_key('secp256r1');
482              
483             my $public_der = $source->export_key_der('public');
484             my $pub = Crypt::PK::ECC->new();
485             $pub->import_key(\$public_der);
486              
487             my $private_pem = $source->export_key_pem('private', 'secret', 'AES-256-CBC');
488             my $priv = Crypt::PK::ECC->new();
489             $priv->import_key(\$private_pem, 'secret');
490              
491             The same method also accepts filenames instead of buffers.
492              
493             Loading private or public keys from a Perl HASH:
494              
495             $pk->import_key($hashref);
496              
497             # the $hashref is either a key exported via key2hash
498             $pk->import_key({
499             curve_A => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
500             curve_B => "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
501             curve_bits => 160,
502             curve_bytes => 20,
503             curve_cofactor => 1,
504             curve_Gx => "4A96B5688EF573284664698968C38BB913CBFC82",
505             curve_Gy => "23A628553168947D59DCC912042351377AC5FB32",
506             curve_order => "0100000000000000000001F4C8F927AED3CA752257",
507             curve_prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
508             k => "B0EE84A749FE95DF997E33B8F333E12101E824C3",
509             pub_x => "5AE1ACE3ED0AEA9707CE5C0BCE014F6A2F15023A",
510             pub_y => "895D57E992D0A15F88D6680B27B701F615FCDC0F",
511             });
512              
513             # or with the curve defined just by name
514             $pk->import_key({
515             curve_name => "secp160r1",
516             k => "B0EE84A749FE95DF997E33B8F333E12101E824C3",
517             pub_x => "5AE1ACE3ED0AEA9707CE5C0BCE014F6A2F15023A",
518             pub_y => "895D57E992D0A15F88D6680B27B701F615FCDC0F",
519             });
520              
521             # or a hash with items corresponding to JWK (JSON Web Key)
522             $pk->import_key({
523             kty => "EC",
524             crv => "P-256",
525             x => "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
526             y => "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
527             d => "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE",
528             });
529              
530             Supported key formats:
531              
532             # all formats can be loaded from a file
533             my $pk = Crypt::PK::ECC->new($filename);
534              
535             # or from a buffer containing the key
536             my $pk = Crypt::PK::ECC->new(\$buffer_with_key);
537              
538             =over
539              
540             =item * EC private keys with with all curve parameters
541              
542             -----BEGIN EC PRIVATE KEY-----
543             MIIB+gIBAQQwCKEAcA6cIt6CGfyLKm57LyXWv2PgTjydrHSbvhDJTOl+7bzUW8DS
544             rgSdtSPONPq1oIIBWzCCAVcCAQEwPAYHKoZIzj0BAQIxAP//////////////////
545             ///////////////////////+/////wAAAAAAAAAA/////zB7BDD/////////////
546             /////////////////////////////v////8AAAAAAAAAAP////wEMLMxL6fiPufk
547             mI4Fa+P4LRkYHZxu/oFBEgMUCI9QE4daxlY5jYou0Z0qhcjt0+wq7wMVAKM1kmqj
548             GaJ6HQCJamdzpIJ6zaxzBGEEqofKIr6LBTeOscce8yCtdG4dO2KLp5uYWfdB4IJU
549             KjhVAvJdv1UpbDpUXjhydgq3NhfeSpYmLG9dnpi/kpLcKfj0Hb0omhR86doxE7Xw
550             uMAKYLHOHX6BnXpDHXyQ6g5fAjEA////////////////////////////////x2NN
551             gfQ3Ld9YGg2ySLCneuzsGWrMxSlzAgEBoWQDYgAEeGyHPLmHcszPQ9MIIYnznpzi
552             QbvuJtYSjCqtIGxDfzgcLcc3nCc5tBxo+qX6OJEzcWdDAC0bwplY+9Z9jHR3ylNy
553             ovlHoK4ItdWkVO8NH89SLSRyVuOF8N5t3CHIo93B
554             -----END EC PRIVATE KEY-----
555              
556             =item * EC private keys with curve defined by OID (short form)
557              
558             -----BEGIN EC PRIVATE KEY-----
559             MHcCAQEEIBG1c3z52T8XwMsahGVdOZWgKCQJfv+l7djuJjgetdbDoAoGCCqGSM49
560             AwEHoUQDQgAEoBUyo8CQAFPeYPvv78ylh5MwFZjTCLQeb042TjiMJxG+9DLFmRSM
561             lBQ9T/RsLLc+PmpB1+7yPAR+oR5gZn3kJQ==
562             -----END EC PRIVATE KEY-----
563              
564             =item * EC private keys with curve defined by OID + compressed form (supported since: CryptX-0.059)
565              
566             -----BEGIN EC PRIVATE KEY-----
567             MFcCAQEEIBG1c3z52T8XwMsahGVdOZWgKCQJfv+l7djuJjgetdbDoAoGCCqGSM49
568             AwEHoSQDIgADoBUyo8CQAFPeYPvv78ylh5MwFZjTCLQeb042TjiMJxE=
569             -----END EC PRIVATE KEY-----
570              
571             =item * EC private keys in password protected PEM format
572              
573             -----BEGIN EC PRIVATE KEY-----
574             Proc-Type: 4,ENCRYPTED
575             DEK-Info: AES-128-CBC,98245C830C9282F7937E13D1D5BA11EC
576              
577             0Y85oZ2+BKXYwrkBjsZdj6gnhOAfS5yDVmEsxFCDug+R3+Kw3QvyIfO4MVo9iWoA
578             D7wtoRfbt2OlBaLVl553+6QrUoa2DyKf8kLHQs1x1/J7tJOMM4SCXjlrOaToQ0dT
579             o7fOnjQjHne16pjgBVqGilY/I79Ab85AnE4uw7vgEucBEiU0d3nrhwuS2Opnhzyx
580             009q9VLDPwY2+q7tXjTqnk9mCmQgsiaDJqY09wlauSukYPgVuOJFmi1VdkRSDKYZ
581             rUUsQvz6Q6Q+QirSlfHna+NhUgQ2eyhGszwcP6NU8iqIxI+NCwfFVuAzw539yYwS
582             8SICczoC/YRlaclayXuomQ==
583             -----END EC PRIVATE KEY-----
584              
585             =item * EC public keys with all curve parameters
586              
587             -----BEGIN PUBLIC KEY-----
588             MIH1MIGuBgcqhkjOPQIBMIGiAgEBMCwGByqGSM49AQECIQD/////////////////
589             ///////////////////+///8LzAGBAEABAEHBEEEeb5mfvncu6xVoGKVzocLBwKb
590             /NstzijZWfKBWxb4F5hIOtp3JqPEZV2k+/wOEQio/Re0SKaFVBmcR9CP+xDUuAIh
591             AP////////////////////66rtzmr0igO7/SXozQNkFBAgEBA0IABITjF/nKK3jg
592             pjmBRXKWAv7ekR1Ko/Nb5FFPHXjH0sDrpS7qRxFALwJHv7ylGnekgfKU3vzcewNs
593             lvjpBYt0Yg4=
594             -----END PUBLIC KEY-----
595              
596             =item * EC public keys with curve defined by OID (short form)
597              
598             -----BEGIN PUBLIC KEY-----
599             MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoBUyo8CQAFPeYPvv78ylh5MwFZjT
600             CLQeb042TjiMJxG+9DLFmRSMlBQ9T/RsLLc+PmpB1+7yPAR+oR5gZn3kJQ==
601             -----END PUBLIC KEY-----
602              
603             =item * EC public keys with curve defined by OID + public point in compressed form (supported since: CryptX-0.059)
604              
605             -----BEGIN PUBLIC KEY-----
606             MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADoBUyo8CQAFPeYPvv78ylh5MwFZjT
607             CLQeb042TjiMJxE=
608             -----END PUBLIC KEY-----
609              
610             =item * PKCS#8 private keys with all curve parameters
611              
612             -----BEGIN PRIVATE KEY-----
613             MIIBMAIBADCB0wYHKoZIzj0CATCBxwIBATAkBgcqhkjOPQEBAhkA////////////
614             /////////v//////////MEsEGP////////////////////7//////////AQYIhI9
615             wjlaBcqnQj2uzMlHYKfUYiVr1WkWAxUAxGloRDXes3jEtlypWR4qV2MFmi4EMQR9
616             KXeBAMZaHaF4NxZYjc4ri0rujiKPGJY4qQ8iY3M3M0tJ3LZqbcj5l4rKdkipQ7AC
617             GQD///////////////96YtAxyD9ClPZA7BMCAQEEVTBTAgEBBBiKolTGIsTgOCtl
618             6dpdos0LvuaExCDFyT6hNAMyAAREwaCX0VY1LZxLW3G75tmft4p9uhc0J7/+NGaP
619             DN3Tr7SXkT9+co2a+8KPJhQy10k=
620             -----END PRIVATE KEY-----
621              
622             =item * PKCS#8 private keys with curve defined by OID (short form)
623              
624             -----BEGIN PRIVATE KEY-----
625             MG8CAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQMEVTBTAgEBBBjFP/caeQV4WO3fnWWS
626             f917PGzwtypd/t+hNAMyAATSg6pBT7RO6l/p+aKcrFsGuthUdfwJWS5V3NGcVt1b
627             lEHQYjWya2YnHaPq/iMFa7A=
628             -----END PRIVATE KEY-----
629              
630             =item * PKCS#8 encrypted private keys - password protected keys (supported since: CryptX-0.059)
631              
632             -----BEGIN ENCRYPTED PRIVATE KEY-----
633             MIGYMBwGCiqGSIb3DQEMAQMwDgQINApjTa6oFl0CAggABHi+59l4d4e6KtG9yci2
634             BSC65LEsQSnrnFAExfKptNU1zMFsDLCRvDeDQDbxc6HlfoxyqFL4SmH1g3RvC/Vv
635             NfckdL5O2L8MRnM+ljkFtV2Te4fszWcJFdd7KiNOkPpn+7sWLfzQdvhHChLKUzmz
636             4INKZyMv/G7VpZ0=
637             -----END ENCRYPTED PRIVATE KEY-----
638              
639             =item * EC public key from X509 certificate
640              
641             -----BEGIN CERTIFICATE-----
642             MIIBdDCCARqgAwIBAgIJAL2BBClDEnnOMAoGCCqGSM49BAMEMBcxFTATBgNVBAMM
643             DFRlc3QgQ2VydCBFQzAgFw0xNzEyMzAyMDMzNDFaGA8zMDE3MDUwMjIwMzM0MVow
644             FzEVMBMGA1UEAwwMVGVzdCBDZXJ0IEVDMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE
645             KvkL2r5xZp7RzxLQJK+6tn/7lic+L70e1fmNbHOdxRaRvbK5G0AQWrdsbjJb92Ni
646             lCQk2+w/i+VuS2Q3MSR5TaNQME4wHQYDVR0OBBYEFGbJkDyKgaMcIGHS8/WuqIVw
647             +R8sMB8GA1UdIwQYMBaAFGbJkDyKgaMcIGHS8/WuqIVw+R8sMAwGA1UdEwQFMAMB
648             Af8wCgYIKoZIzj0EAwQDSAAwRQIhAJtOsmrM+gJpImoynAyqTN+7myL71uxd+YeC
649             6ze4MnzWAiBQi5/BqEr/SQ1+BC2TPtswvJPRFh2ZvT/6Km3gKoNVXQ==
650             -----END CERTIFICATE-----
651              
652             =item * SSH public EC keys
653              
654             ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNT...T3xYfJIs=
655              
656             =item * SSH public EC keys (RFC-4716 format)
657              
658             ---- BEGIN SSH2 PUBLIC KEY ----
659             Comment: "521-bit ECDSA, converted from OpenSSH"
660             AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAFk35srteP9twCwYK
661             vU9ovMBi77Dd6lEBPrFaMEb0CZdZ5MC3nSqflGHRWkSbUpjdPdO7cYQNpK9YXHbNSO5hbU
662             1gFZgyiGFxwJYYz8NAjedBXMgyH4JWplK5FQm5P5cvaglItC9qkKioUXhCc67YMYBtivXl
663             Ue0PgIq6kbHTqbX6+5Nw==
664             ---- END SSH2 PUBLIC KEY ----
665              
666             =item * EC private keys in JSON Web Key (JWK) format
667              
668             See L
669              
670             {
671             "kty":"EC",
672             "crv":"P-256",
673             "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
674             "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
675             "d":"870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE",
676             }
677              
678             B For JWK support you need to have L module installed.
679              
680             =item * EC public keys in JSON Web Key (JWK) format
681              
682             {
683             "kty":"EC",
684             "crv":"P-256",
685             "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
686             "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
687             }
688              
689             B For JWK support you need to have L module installed.
690              
691             =back
692              
693             =head2 import_key_raw
694              
695             Import raw public/private key - can load data exported by L.
696              
697             $pk->import_key_raw($key, $curve);
698             # $key .... [binary string] data exported by export_key_raw()
699             # $curve .. [string | hashref] curve name or hashref with curve parameters - same as by generate_key()
700              
701             =head2 export_key_der
702              
703             Returns the key as a binary DER-encoded string.
704              
705             my $private_der = $pk->export_key_der('private');
706             #or
707             my $public_der = $pk->export_key_der('public');
708              
709             Since CryptX-0.36 C can also export keys in a format
710             that does not explicitly contain curve parameters but only curve OID.
711              
712             my $private_der = $pk->export_key_der('private_short');
713             #or
714             my $public_der = $pk->export_key_der('public_short');
715              
716             Since CryptX-0.59 C can also export keys in "compressed" format
717             that defines curve by OID + stores public point in compressed form.
718              
719             my $private_pem = $pk->export_key_der('private_compressed');
720             #or
721             my $public_pem = $pk->export_key_der('public_compressed');
722              
723             =head2 export_key_pem
724              
725             Returns the key as a PEM-encoded string (ASCII).
726              
727             my $private_pem = $pk->export_key_pem('private');
728             #or
729             my $public_pem = $pk->export_key_pem('public');
730              
731             Since CryptX-0.36 C can also export keys in a format
732             that does not explicitly contain curve parameters but only curve OID.
733              
734             my $private_pem = $pk->export_key_pem('private_short');
735             #or
736             my $public_pem = $pk->export_key_pem('public_short');
737              
738             Since CryptX-0.59 C can also export keys in "compressed" format
739             that defines curve by OID + stores public point in compressed form.
740              
741             my $private_pem = $pk->export_key_pem('private_compressed');
742             #or
743             my $public_pem = $pk->export_key_pem('public_compressed');
744              
745             Support for password protected PEM keys
746              
747             my $private_pem = $pk->export_key_pem('private', $password);
748             #or
749             my $private_pem = $pk->export_key_pem('private', $password, $cipher);
750              
751             # supported ciphers: 'DES-CBC'
752             # 'DES-EDE3-CBC'
753             # 'SEED-CBC'
754             # 'CAMELLIA-128-CBC'
755             # 'CAMELLIA-192-CBC'
756             # 'CAMELLIA-256-CBC'
757             # 'AES-128-CBC'
758             # 'AES-192-CBC'
759             # 'AES-256-CBC' (DEFAULT)
760              
761             =head2 export_key_jwk
762              
763             I
764              
765             Returns a JSON string, or a hashref if the optional second argument is true.
766              
767             Exports public/private keys as a JSON Web Key (JWK).
768              
769             my $private_json_text = $pk->export_key_jwk('private');
770             #or
771             my $public_json_text = $pk->export_key_jwk('public');
772              
773             Also exports public/private keys as a Perl HASH with JWK structure.
774              
775             my $jwk_hash = $pk->export_key_jwk('private', 1);
776             #or
777             my $jwk_hash = $pk->export_key_jwk('public', 1);
778              
779             B For JWK support you need to have L module installed.
780              
781             =head2 export_key_jwk_thumbprint
782              
783             I
784              
785             Exports the key's JSON Web Key Thumbprint as a string.
786              
787             If you don't know what this is, see RFC 7638 L.
788              
789             my $thumbprint = $pk->export_key_jwk_thumbprint('SHA256');
790              
791             =head2 export_key_raw
792              
793             Returns the raw key as a binary string.
794              
795             Export raw public/private key. Public key is exported in ASN X9.62 format (compressed or uncompressed),
796             private key is exported as raw bytes (padded with leading zeros to have the same size as the ECC curve).
797              
798             my $pubkey_octets = $pk->export_key_raw('public');
799             #or
800             my $pubckey_octets = $pk->export_key_raw('public_compressed');
801             #or
802             my $privkey_octets = $pk->export_key_raw('private');
803              
804             =head2 encrypt
805              
806             Returns the ciphertext as a binary string.
807              
808             my $pk = Crypt::PK::ECC->new($pub_key_filename);
809             my $ct = $pk->encrypt($message);
810             #or
811             my $ct = $pk->encrypt($message, $hash_name);
812              
813             # $hash_name .. [string] 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
814              
815             =head2 decrypt
816              
817             Returns the plaintext as a binary string.
818              
819             my $pk = Crypt::PK::ECC->new($priv_key_filename);
820             my $pt = $pk->decrypt($ciphertext);
821              
822             =head2 sign_message
823              
824             Returns the signature as a binary string.
825              
826             my $pk = Crypt::PK::ECC->new($priv_key_filename);
827             my $signature = $pk->sign_message($message);
828             #or
829             my $signature = $pk->sign_message($message, $hash_name);
830              
831             # $hash_name .. [string] 'SHA1' (DEFAULT, INSECURE), 'SHA256' or any other hash supported by Crypt::Digest
832              
833             B The C<$hash_name> default is C<'SHA1'> only for backward compatibility.
834             SHA-1 is vulnerable to practical collision attacks and is not safe for signing
835             messages whose content may be influenced by an attacker. Always pass an explicit
836             hash name such as C<'SHA256'>. The same applies to L.
837              
838             For ECDSA with SHAKE per L
839             use C<'SHAKE128'> (output 32 bytes) or C<'SHAKE256'> (output 64 bytes); the
840             fixed output sizes match the ones required by the ecdsa-with-shake128 and
841             ecdsa-with-shake256 OIDs.
842              
843             my $sig = $pk->sign_message($message, 'SHAKE128'); # ecdsa-with-shake128
844             my $sig = $pk->sign_message($message, 'SHAKE256'); # ecdsa-with-shake256
845              
846             =head2 sign_message_rfc7518
847              
848             I
849              
850             Same as L only the signature format is as defined by L
851             (JWA - JSON Web Algorithms).
852              
853             B This creates signatures according to the structure that RFC 7518 describes but does not apply
854             the RFC logic for the hashing algorithm selection. You'll still need to specify, e.g., SHA256 for a P-256 key
855             to get a fully RFC-7518-compliant signature.
856              
857             =head2 verify_message
858              
859             Returns C<1> if the signature is valid, C<0> otherwise.
860              
861             my $pk = Crypt::PK::ECC->new($pub_key_filename);
862             my $valid = $pk->verify_message($signature, $message);
863             #or
864             my $valid = $pk->verify_message($signature, $message, $hash_name);
865              
866             # $hash_name .. [string] 'SHA1' (DEFAULT, INSECURE), 'SHA256' or any other hash supported by Crypt::Digest
867              
868             =head2 verify_message_rfc7518
869              
870             I
871              
872             Same as L only the signature format is as defined by L
873             (JWA - JSON Web Algorithms).
874              
875             B This verifies signatures according to the structure that RFC 7518 describes but does not apply
876             the RFC logic for the hashing algorithm selection. You'll still need to specify, e.g., SHA256 for a P-256 key
877             to get a fully RFC-7518-compliant signature.
878              
879             =head2 sign_hash
880              
881             Returns the signature as a binary string.
882              
883             my $pk = Crypt::PK::ECC->new($priv_key_filename);
884             my $signature = $pk->sign_hash($message_hash, $deterministic_hash_name);
885              
886             # $deterministic_hash_name .. [string] 'SHA1', 'SHA256' or any other hash supported by Crypt::Digest
887             # in most cases it will be the same as used to create $message_hash, if not provided non-deterministic
888             # signature will be created
889              
890             I - the optional C<$deterministic_hash_name> argument enabling RFC 6979 deterministic signatures.
891              
892             =head2 sign_hash_eth
893              
894             Same as L but returns the signature in Ethereum format:
895             32-byte C value, 32-byte C value, 1-byte recovery ID (27 or 28). Total
896             output is always exactly 65 bytes.
897              
898             =head2 sign_hash_rfc7518
899              
900             I
901              
902             Same as L only the signature format is as defined by L
903             (JWA - JSON Web Algorithms).
904              
905             =head2 verify_hash
906              
907             Returns C<1> if the signature is valid, C<0> otherwise.
908              
909             my $pk = Crypt::PK::ECC->new($pub_key_filename);
910             my $valid = $pk->verify_hash($signature, $message_hash);
911              
912             =head2 verify_hash_rfc7518
913              
914             I
915              
916             Same as L only the signature format is as defined by L
917             (JWA - JSON Web Algorithms).
918              
919             =head2 verify_hash_eth
920              
921             Returns C<1> if the signature is valid, C<0> otherwise.
922             Same as L but expects the signature in Ethereum format
923             (65 bytes: r || s || recovery_id).
924             Compatible with signatures generated by L.
925              
926             =head2 recovery_pub_eth
927              
928             Alternative method to verify a signature with recovery of the public key.
929             Mainly used in Ethereum-like blockchain networks.
930             This method will recover public key from ECDSA signature in Ethereum format
931             (see L).
932              
933             my $pk = Crypt::PK::ECC->new($priv_key_filename);
934             my $signature = $pk->sign_hash_eth($message_hash);
935             my $pub_key = $pk->recovery_pub_eth($signature, $message_hash);
936              
937             =head2 recovery_pub
938              
939             Recovers the public key from an ECDSA signature produced by L.
940             Returns a new L object containing the recovered public key.
941              
942             Unlike L, the standard DER-encoded signature does not embed
943             the recovery identifier, so C<$recid> must be supplied explicitly.
944              
945             my $pk = Crypt::PK::ECC->new($priv_key_filename);
946             my $signature = $pk->sign_hash($message_hash);
947             my $pub_key = $pk->recovery_pub($signature, $message_hash, $recid);
948              
949             # $signature .... [binary string] binary DER-encoded ECDSA signature (from sign_hash)
950             # $message_hash . [binary string] the hash that was signed
951             # $recid ........ [integer] recovery identifier, 0 or 1 (selects which of the
952             # two possible public keys corresponds to the signature)
953              
954             =head2 recovery_pub_rfc7518
955              
956             I
957              
958             Same as L, but compatible with L
959             signatures. The main difference is that B<$recid> is required, because an RFC 7518 signature
960             does not contain the recovery bit, so you must specify it explicitly.
961              
962             my $pk = Crypt::PK::ECC->new($priv_key_filename);
963             my $signature = $pk->sign_hash_rfc7518($message_hash);
964             my $pub_key = $pk->recovery_pub_rfc7518($signature, $message_hash, $recid);
965              
966             =head2 shared_secret
967              
968             Returns the shared secret as a binary string (raw bytes).
969              
970             # Alice having her priv key $pk and Bob's public key $pkb
971             my $pk = Crypt::PK::ECC->new($priv_key_filename);
972             my $pkb = Crypt::PK::ECC->new($pub_key_filename);
973             my $shared_secret = $pk->shared_secret($pkb);
974              
975             # Bob having his priv key $pk and Alice's public key $pka
976             my $pk = Crypt::PK::ECC->new($priv_key_filename);
977             my $pka = Crypt::PK::ECC->new($pub_key_filename);
978             my $shared_secret = $pk->shared_secret($pka); # same value as computed by Alice
979              
980             =head2 is_private
981              
982             my $rv = $pk->is_private;
983             # 1 .. private key loaded
984             # 0 .. public key loaded
985             # undef .. no key loaded
986              
987             =head2 size
988              
989             my $size = $pk->size;
990             # returns key size in bytes or undef if no key loaded
991              
992             =head2 key2hash
993              
994             Returns a hashref with the key components, or C if no key is loaded.
995              
996             my $hash = $pk->key2hash;
997              
998             # returns hash like this (or undef if no key loaded):
999             {
1000             size => 20, # integer: key (curve) size in bytes
1001             type => 1, # integer: 1 .. private, 0 .. public
1002             #curve parameters
1003             curve_A => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
1004             curve_B => "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
1005             curve_bits => 160,
1006             curve_bytes => 20,
1007             curve_cofactor => 1,
1008             curve_Gx => "4A96B5688EF573284664698968C38BB913CBFC82",
1009             curve_Gy => "23A628553168947D59DCC912042351377AC5FB32",
1010             curve_name => "secp160r1",
1011             curve_order => "0100000000000000000001F4C8F927AED3CA752257",
1012             curve_prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
1013             #private key
1014             k => "B0EE84A749FE95DF997E33B8F333E12101E824C3",
1015             #public key point coordinates
1016             pub_x => "5AE1ACE3ED0AEA9707CE5C0BCE014F6A2F15023A",
1017             pub_y => "895D57E992D0A15F88D6680B27B701F615FCDC0F",
1018             }
1019              
1020             =head2 curve2hash
1021              
1022             I
1023              
1024             my $crv = $pk->curve2hash;
1025              
1026             # returns a hash that can be passed to: $pk->generate_key($crv)
1027             {
1028             A => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
1029             B => "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
1030             cofactor => 1,
1031             Gx => "4A96B5688EF573284664698968C38BB913CBFC82",
1032             Gy => "23A628553168947D59DCC912042351377AC5FB32",
1033             order => "0100000000000000000001F4C8F927AED3CA752257",
1034             prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
1035             }
1036              
1037             =head1 OpenSSL interoperability
1038              
1039             ### let's have:
1040             # ECC private key in PEM format - eckey.priv.pem
1041             # ECC public key in PEM format - eckey.pub.pem
1042             # data file to be signed - input.data
1043              
1044             =head2 Sign by OpenSSL, verify by Crypt::PK::ECC
1045              
1046             Create signature (from commandline):
1047              
1048             openssl dgst -sha256 -sign eckey.priv.pem -out input.sha256-ec.sig input.data
1049              
1050             Verify signature (Perl code):
1051              
1052             use Crypt::PK::ECC;
1053             use Crypt::Digest 'digest_file';
1054             use Crypt::Misc 'read_rawfile';
1055              
1056             my $pkec = Crypt::PK::ECC->new("eckey.pub.pem");
1057             my $signature = read_rawfile("input.sha256-ec.sig");
1058             my $valid = $pkec->verify_hash($signature, digest_file("SHA256", "input.data"));
1059             print $valid ? "SUCCESS" : "FAILURE";
1060              
1061             =head2 Sign by Crypt::PK::ECC, verify by OpenSSL
1062              
1063             Create signature (Perl code):
1064              
1065             use Crypt::PK::ECC;
1066             use Crypt::Digest 'digest_file';
1067             use Crypt::Misc 'write_rawfile';
1068              
1069             my $pkec = Crypt::PK::ECC->new("eckey.priv.pem");
1070             my $signature = $pkec->sign_hash(digest_file("SHA256", "input.data"));
1071             write_rawfile("input.sha256-ec.sig", $signature);
1072              
1073             Verify signature (from commandline):
1074              
1075             openssl dgst -sha256 -verify eckey.pub.pem -signature input.sha256-ec.sig input.data
1076              
1077             =head2 Keys generated by Crypt::PK::ECC
1078              
1079             Generate keys (Perl code):
1080              
1081             use Crypt::PK::ECC;
1082             use Crypt::Misc 'write_rawfile';
1083              
1084             my $pkec = Crypt::PK::ECC->new;
1085             $pkec->generate_key('secp160k1');
1086             write_rawfile("eckey.pub.der", $pkec->export_key_der('public'));
1087             write_rawfile("eckey.priv.der", $pkec->export_key_der('private'));
1088             write_rawfile("eckey.pub.pem", $pkec->export_key_pem('public'));
1089             write_rawfile("eckey.priv.pem", $pkec->export_key_pem('private'));
1090             write_rawfile("eckey-passwd.priv.pem", $pkec->export_key_pem('private', 'secret'));
1091              
1092             Use keys by OpenSSL:
1093              
1094             openssl ec -in eckey.priv.der -text -inform der
1095             openssl ec -in eckey.priv.pem -text
1096             openssl ec -in eckey-passwd.priv.pem -text -inform pem -passin pass:secret
1097             openssl ec -in eckey.pub.der -pubin -text -inform der
1098             openssl ec -in eckey.pub.pem -pubin -text
1099              
1100             =head2 Keys generated by OpenSSL
1101              
1102             Generate keys:
1103              
1104             openssl ecparam -param_enc explicit -name prime192v3 -genkey -out eckey.priv.pem
1105             openssl ec -param_enc explicit -in eckey.priv.pem -out eckey.pub.pem -pubout
1106             openssl ec -param_enc explicit -in eckey.priv.pem -out eckey.priv.der -outform der
1107             openssl ec -param_enc explicit -in eckey.priv.pem -out eckey.pub.der -outform der -pubout
1108             openssl ec -param_enc explicit -in eckey.priv.pem -out eckey.privc.der -outform der -conv_form compressed
1109             openssl ec -param_enc explicit -in eckey.priv.pem -out eckey.pubc.der -outform der -pubout -conv_form compressed
1110             openssl ec -param_enc explicit -in eckey.priv.pem -passout pass:secret -des3 -out eckey-passwd.priv.pem
1111              
1112             Load keys (Perl code):
1113              
1114             use Crypt::PK::ECC;
1115              
1116             my $pkec = Crypt::PK::ECC->new;
1117             $pkec->import_key("eckey.pub.der");
1118             $pkec->import_key("eckey.pubc.der");
1119             $pkec->import_key("eckey.priv.der");
1120             $pkec->import_key("eckey.privc.der");
1121             $pkec->import_key("eckey.pub.pem");
1122             $pkec->import_key("eckey.priv.pem");
1123             $pkec->import_key("eckey-passwd.priv.pem", "secret");
1124              
1125             =head1 SEE ALSO
1126              
1127             =over
1128              
1129             =item * L
1130              
1131             =item * L
1132              
1133             =item * L
1134              
1135             =back
1136              
1137             =cut