File Coverage

blib/lib/Crypt/PK/ECC.pm
Criterion Covered Total %
statement 98 146 67.1
branch 47 116 40.5
condition 11 63 17.4
subroutine 19 22 86.3
pod 6 13 46.1
total 181 360 50.2


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