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   387222 use strict;
  10         19  
  10         376  
4 10     10   63 use warnings;
  10         17  
  10         1565  
5             our $VERSION = '0.089';
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   65 use Carp;
  10         29  
  10         874  
13             $Carp::Internal{(__PACKAGE__)}++;
14 10     10   1625 use CryptX;
  10         49  
  10         444  
15 10     10   1694 use Crypt::Digest qw(digest_data digest_data_b64u);
  10         28  
  10         719  
16 10     10   1718 use Crypt::Misc qw(read_rawfile encode_b64u decode_b64u encode_b64 decode_b64 pem_to_der der_to_pem);
  10         34  
  10         817  
17 10     10   1573 use Crypt::PK;
  10         18  
  10         33123  
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   2 my ($self, $x, $y, $k, $crv) = @_;
113 1 50       3 croak "FATAL: no curve" if !$crv;
114 1 50 33     6 if (defined $k && length($k) > 0) {
    0 0        
115 1 50       2 croak "FATAL: invalid length (k)" if length($k) % 2;
116 1         5606 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 1808034 my $self = shift->_new();
129 285 100       765405 return @_ > 0 ? $self->import_key(@_) : $self;
130             }
131              
132             sub export_key_pem {
133 9     9 1 2491 my ($self, $type, $password, $cipher) = @_;
134 9         59 local $SIG{__DIE__} = \&CryptX::_croak;
135 9   50     288 my $key = $self->export_key_der($type||'');
136 8 50       31 return unless $key;
137             # private, private_short, private_compressed all use the same PEM header
138 8 100       61 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       41 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 222004 my ($self, $key, $password) = @_;
190 122         826 local $SIG{__DIE__} = \&CryptX::_croak;
191 122 50       450 croak "FATAL: undefined key" unless $key;
192              
193             # special case
194 122 100       363 if (ref($key) eq 'HASH') {
195 1 50 33     9 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         212 my $data;
213 121 100       2618 if (ref($key) eq 'SCALAR') {
    50          
214 23         43 $data = $$key;
215             }
216             elsif (-f $key) {
217 98         557 $data = read_rawfile($key);
218             }
219             else {
220 0         0 croak "FATAL: non-existing file '$key'";
221             }
222 121 50       529 croak "FATAL: invalid key data" unless $data;
223              
224 121 100       1528 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         259 my $pem = $1;
226 65         147 my $rv = eval { $self->_import_pem($pem, $password) };
  65         503477  
227 65 100       403 if (!$rv) {
228 9         31 my $der = pem_to_der($pem, $password);
229 9 50       23 $rv = eval { $self->_import_old($der) } if defined $der;
  9         11216  
230             }
231 65 100       1130 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         787102 return $self->_import_openssh($data, $password);
238             }
239             elsif ($data =~ /---- BEGIN SSH2 PUBLIC KEY ----(.+?)---- END SSH2 PUBLIC KEY ----/s) {
240 3         32471 return $self->_import_openssh($data, undef);
241             }
242             elsif ($data =~ /(ecdsa-\S+)\s+(\S+)/) {
243 3         37 $data = decode_b64("$2");
244 3         20 my ($typ, $skip, $pubkey) = Crypt::PK::_ssh_parse($data);
245 3 50 33     33476 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     90 eval { $self->_import_x509($data) };
264 44 100       1951 return $rv if $rv;
265             }
266 6         365 croak "FATAL: invalid or unsupported EC key format";
267             }
268              
269             sub curve2hash {
270 3     3 1 6540 my $self = shift;
271 3         131 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         53 };
282             }
283              
284             ### FUNCTIONS
285              
286             sub ecc_encrypt { # legacy/obsolete
287 1     1 0 4791 my $key = shift;
288 1         9 local $SIG{__DIE__} = \&CryptX::_croak;
289 1 50       7 $key = __PACKAGE__->new($key) unless ref $key;
290 1 50       48 croak "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
291 1         11223 return $key->encrypt(@_);
292             }
293              
294             sub ecc_decrypt { # legacy/obsolete
295 1     1 0 442 my $key = shift;
296 1         8 local $SIG{__DIE__} = \&CryptX::_croak;
297 1 50       13 $key = __PACKAGE__->new($key) unless ref $key;
298 1 50       8 croak "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
299 1         12625 return $key->decrypt(@_);
300             }
301              
302             sub ecc_sign_message { # legacy/obsolete
303 1     1 0 707 my $key = shift;
304 1         8 local $SIG{__DIE__} = \&CryptX::_croak;
305 1 50       13 $key = __PACKAGE__->new($key) unless ref $key;
306 1 50       9 croak "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
307 1         6790 return $key->sign_message(@_);
308             }
309              
310             sub ecc_verify_message { # legacy/obsolete
311 1     1 0 524 my $key = shift;
312 1         8 local $SIG{__DIE__} = \&CryptX::_croak;
313 1 50       13 $key = __PACKAGE__->new($key) unless ref $key;
314 1 50       12 croak "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
315 1         3909 return $key->verify_message(@_);
316             }
317              
318             sub ecc_sign_hash { # legacy/obsolete
319 1     1 0 2 my $key = shift;
320 1         8 local $SIG{__DIE__} = \&CryptX::_croak;
321 1 50       11 $key = __PACKAGE__->new($key) unless ref $key;
322 1 50       7 croak "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
323 1         11929 return $key->sign_hash(@_);
324             }
325              
326             sub ecc_verify_hash { # legacy/obsolete
327 1     1 0 541 my $key = shift;
328 1         8 local $SIG{__DIE__} = \&CryptX::_croak;
329 1 50       12 $key = __PACKAGE__->new($key) unless ref $key;
330 1 50       10 croak "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
331 1         3698 return $key->verify_hash(@_);
332             }
333              
334             sub ecc_shared_secret { # legacy/obsolete
335 2     2 0 15 my ($privkey, $pubkey) = @_;
336 2         18 local $SIG{__DIE__} = \&CryptX::_croak;
337 2 50       27 $privkey = __PACKAGE__->new($privkey) unless ref $privkey;
338 2 50       25 $pubkey = __PACKAGE__->new($pubkey) unless ref $pubkey;
339 2 50 33     28 croak "FATAL: invalid 'privkey' param" unless ref($privkey) eq __PACKAGE__ && $privkey->is_private;
340 2 50       30 croak "FATAL: invalid 'pubkey' param" unless ref($pubkey) eq __PACKAGE__;
341 2         12123 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);
368             $alice_public->verify_message($signature, $message) 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), 'SHA256' or any other hash supported by Crypt::Digest
832              
833             For ECDSA with SHAKE per L
834             use C<'SHAKE128'> (output 32 bytes) or C<'SHAKE256'> (output 64 bytes); the
835             fixed output sizes match the ones required by the ecdsa-with-shake128 and
836             ecdsa-with-shake256 OIDs.
837              
838             my $sig = $pk->sign_message($message, 'SHAKE128'); # ecdsa-with-shake128
839             my $sig = $pk->sign_message($message, 'SHAKE256'); # ecdsa-with-shake256
840              
841             =head2 sign_message_rfc7518
842              
843             I
844              
845             Same as L only the signature format is as defined by L
846             (JWA - JSON Web Algorithms).
847              
848             B This creates signatures according to the structure that RFC 7518 describes but does not apply
849             the RFC logic for the hashing algorithm selection. You'll still need to specify, e.g., SHA256 for a P-256 key
850             to get a fully RFC-7518-compliant signature.
851              
852             =head2 verify_message
853              
854             Returns C<1> if the signature is valid, C<0> otherwise.
855              
856             my $pk = Crypt::PK::ECC->new($pub_key_filename);
857             my $valid = $pk->verify_message($signature, $message);
858             #or
859             my $valid = $pk->verify_message($signature, $message, $hash_name);
860              
861             # $hash_name .. [string] 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
862              
863             =head2 verify_message_rfc7518
864              
865             I
866              
867             Same as L only the signature format is as defined by L
868             (JWA - JSON Web Algorithms).
869              
870             B This verifies signatures according to the structure that RFC 7518 describes but does not apply
871             the RFC logic for the hashing algorithm selection. You'll still need to specify, e.g., SHA256 for a P-256 key
872             to get a fully RFC-7518-compliant signature.
873              
874             =head2 sign_hash
875              
876             Returns the signature as a binary string.
877              
878             my $pk = Crypt::PK::ECC->new($priv_key_filename);
879             my $signature = $pk->sign_hash($message_hash, $deterministic_hash_name);
880              
881             # $deterministic_hash_name .. [string] 'SHA1', 'SHA256' or any other hash supported by Crypt::Digest
882             # in most cases it will be the same as used to create $message_hash, if not provided non-deterministic
883             # signature will be created
884              
885             I
886              
887             =head2 sign_hash_eth
888              
889             Same as L but returns the signature in Ethereum format:
890             32-byte C value, 32-byte C value, 1-byte recovery ID (27 or 28). Total
891             output is always exactly 65 bytes.
892              
893             =head2 sign_hash_rfc7518
894              
895             I
896              
897             Same as L only the signature format is as defined by L
898             (JWA - JSON Web Algorithms).
899              
900             =head2 verify_hash
901              
902             Returns C<1> if the signature is valid, C<0> otherwise.
903              
904             my $pk = Crypt::PK::ECC->new($pub_key_filename);
905             my $valid = $pk->verify_hash($signature, $message_hash);
906              
907             =head2 verify_hash_rfc7518
908              
909             I
910              
911             Same as L only the signature format is as defined by L
912             (JWA - JSON Web Algorithms).
913              
914             =head2 verify_hash_eth
915              
916             Returns C<1> if the signature is valid, C<0> otherwise.
917             Same as L but expects the signature in Ethereum format
918             (65 bytes: r || s || recovery_id).
919             Compatible with signatures generated by L.
920              
921             =head2 recovery_pub_eth
922              
923             Alternative method to verify a signature with recovery of the public key.
924             Mainly used in Ethereum-like blockchain networks.
925             This method will recover public key from ECDSA signature in Ethereum format
926             (see L).
927              
928             my $pk = Crypt::PK::ECC->new($priv_key_filename);
929             my $signature = $pk->sign_hash_eth($message_hash);
930             my $pub_key = $pk->recovery_pub_eth($signature, $message_hash);
931              
932             =head2 recovery_pub
933              
934             Recovers the public key from an ECDSA signature produced by L.
935             Returns a new L object containing the recovered public key.
936              
937             Unlike L, the standard DER-encoded signature does not embed
938             the recovery identifier, so C<$recid> must be supplied explicitly.
939              
940             my $pk = Crypt::PK::ECC->new($priv_key_filename);
941             my $signature = $pk->sign_hash($message_hash);
942             my $pub_key = $pk->recovery_pub($signature, $message_hash, $recid);
943              
944             # $signature .... [binary string] binary DER-encoded ECDSA signature (from sign_hash)
945             # $message_hash . [binary string] the hash that was signed
946             # $recid ........ [integer] recovery identifier, 0 or 1 (selects which of the
947             # two possible public keys corresponds to the signature)
948              
949             =head2 recovery_pub_rfc7518
950              
951             I
952              
953             Same as L, but compatible with L
954             signatures. The main difference is that B<$recid> is required, because an RFC 7518 signature
955             does not contain the recovery bit, so you must specify it explicitly.
956              
957             my $pk = Crypt::PK::ECC->new($priv_key_filename);
958             my $signature = $pk->sign_hash_rfc7518($message_hash);
959             my $pub_key = $pk->recovery_pub_rfc7518($signature, $message_hash, $recid);
960              
961             =head2 shared_secret
962              
963             Returns the shared secret as a binary string (raw bytes).
964              
965             # Alice having her priv key $pk and Bob's public key $pkb
966             my $pk = Crypt::PK::ECC->new($priv_key_filename);
967             my $pkb = Crypt::PK::ECC->new($pub_key_filename);
968             my $shared_secret = $pk->shared_secret($pkb);
969              
970             # Bob having his priv key $pk and Alice's public key $pka
971             my $pk = Crypt::PK::ECC->new($priv_key_filename);
972             my $pka = Crypt::PK::ECC->new($pub_key_filename);
973             my $shared_secret = $pk->shared_secret($pka); # same value as computed by Alice
974              
975             =head2 is_private
976              
977             my $rv = $pk->is_private;
978             # 1 .. private key loaded
979             # 0 .. public key loaded
980             # undef .. no key loaded
981              
982             =head2 size
983              
984             my $size = $pk->size;
985             # returns key size in bytes or undef if no key loaded
986              
987             =head2 key2hash
988              
989             Returns a hashref with the key components, or C if no key is loaded.
990              
991             my $hash = $pk->key2hash;
992              
993             # returns hash like this (or undef if no key loaded):
994             {
995             size => 20, # integer: key (curve) size in bytes
996             type => 1, # integer: 1 .. private, 0 .. public
997             #curve parameters
998             curve_A => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
999             curve_B => "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
1000             curve_bits => 160,
1001             curve_bytes => 20,
1002             curve_cofactor => 1,
1003             curve_Gx => "4A96B5688EF573284664698968C38BB913CBFC82",
1004             curve_Gy => "23A628553168947D59DCC912042351377AC5FB32",
1005             curve_name => "secp160r1",
1006             curve_order => "0100000000000000000001F4C8F927AED3CA752257",
1007             curve_prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
1008             #private key
1009             k => "B0EE84A749FE95DF997E33B8F333E12101E824C3",
1010             #public key point coordinates
1011             pub_x => "5AE1ACE3ED0AEA9707CE5C0BCE014F6A2F15023A",
1012             pub_y => "895D57E992D0A15F88D6680B27B701F615FCDC0F",
1013             }
1014              
1015             =head2 curve2hash
1016              
1017             I
1018              
1019             my $crv = $pk->curve2hash;
1020              
1021             # returns a hash that can be passed to: $pk->generate_key($crv)
1022             {
1023             A => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
1024             B => "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
1025             cofactor => 1,
1026             Gx => "4A96B5688EF573284664698968C38BB913CBFC82",
1027             Gy => "23A628553168947D59DCC912042351377AC5FB32",
1028             order => "0100000000000000000001F4C8F927AED3CA752257",
1029             prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
1030             }
1031              
1032             =head1 OpenSSL interoperability
1033              
1034             ### let's have:
1035             # ECC private key in PEM format - eckey.priv.pem
1036             # ECC public key in PEM format - eckey.pub.pem
1037             # data file to be signed - input.data
1038              
1039             =head2 Sign by OpenSSL, verify by Crypt::PK::ECC
1040              
1041             Create signature (from commandline):
1042              
1043             openssl dgst -sha1 -sign eckey.priv.pem -out input.sha1-ec.sig input.data
1044              
1045             Verify signature (Perl code):
1046              
1047             use Crypt::PK::ECC;
1048             use Crypt::Digest 'digest_file';
1049             use Crypt::Misc 'read_rawfile';
1050              
1051             my $pkec = Crypt::PK::ECC->new("eckey.pub.pem");
1052             my $signature = read_rawfile("input.sha1-ec.sig");
1053             my $valid = $pkec->verify_hash($signature, digest_file("SHA1", "input.data"));
1054             print $valid ? "SUCCESS" : "FAILURE";
1055              
1056             =head2 Sign by Crypt::PK::ECC, verify by OpenSSL
1057              
1058             Create signature (Perl code):
1059              
1060             use Crypt::PK::ECC;
1061             use Crypt::Digest 'digest_file';
1062             use Crypt::Misc 'write_rawfile';
1063              
1064             my $pkec = Crypt::PK::ECC->new("eckey.priv.pem");
1065             my $signature = $pkec->sign_hash(digest_file("SHA1", "input.data"));
1066             write_rawfile("input.sha1-ec.sig", $signature);
1067              
1068             Verify signature (from commandline):
1069              
1070             openssl dgst -sha1 -verify eckey.pub.pem -signature input.sha1-ec.sig input.data
1071              
1072             =head2 Keys generated by Crypt::PK::ECC
1073              
1074             Generate keys (Perl code):
1075              
1076             use Crypt::PK::ECC;
1077             use Crypt::Misc 'write_rawfile';
1078              
1079             my $pkec = Crypt::PK::ECC->new;
1080             $pkec->generate_key('secp160k1');
1081             write_rawfile("eckey.pub.der", $pkec->export_key_der('public'));
1082             write_rawfile("eckey.priv.der", $pkec->export_key_der('private'));
1083             write_rawfile("eckey.pub.pem", $pkec->export_key_pem('public'));
1084             write_rawfile("eckey.priv.pem", $pkec->export_key_pem('private'));
1085             write_rawfile("eckey-passwd.priv.pem", $pkec->export_key_pem('private', 'secret'));
1086              
1087             Use keys by OpenSSL:
1088              
1089             openssl ec -in eckey.priv.der -text -inform der
1090             openssl ec -in eckey.priv.pem -text
1091             openssl ec -in eckey-passwd.priv.pem -text -inform pem -passin pass:secret
1092             openssl ec -in eckey.pub.der -pubin -text -inform der
1093             openssl ec -in eckey.pub.pem -pubin -text
1094              
1095             =head2 Keys generated by OpenSSL
1096              
1097             Generate keys:
1098              
1099             openssl ecparam -param_enc explicit -name prime192v3 -genkey -out eckey.priv.pem
1100             openssl ec -param_enc explicit -in eckey.priv.pem -out eckey.pub.pem -pubout
1101             openssl ec -param_enc explicit -in eckey.priv.pem -out eckey.priv.der -outform der
1102             openssl ec -param_enc explicit -in eckey.priv.pem -out eckey.pub.der -outform der -pubout
1103             openssl ec -param_enc explicit -in eckey.priv.pem -out eckey.privc.der -outform der -conv_form compressed
1104             openssl ec -param_enc explicit -in eckey.priv.pem -out eckey.pubc.der -outform der -pubout -conv_form compressed
1105             openssl ec -param_enc explicit -in eckey.priv.pem -passout pass:secret -des3 -out eckey-passwd.priv.pem
1106              
1107             Load keys (Perl code):
1108              
1109             use Crypt::PK::ECC;
1110              
1111             my $pkec = Crypt::PK::ECC->new;
1112             $pkec->import_key("eckey.pub.der");
1113             $pkec->import_key("eckey.pubc.der");
1114             $pkec->import_key("eckey.priv.der");
1115             $pkec->import_key("eckey.privc.der");
1116             $pkec->import_key("eckey.pub.pem");
1117             $pkec->import_key("eckey.priv.pem");
1118             $pkec->import_key("eckey-passwd.priv.pem", "secret");
1119              
1120             =head1 SEE ALSO
1121              
1122             =over
1123              
1124             =item * L
1125              
1126             =item * L
1127              
1128             =item * L
1129              
1130             =back
1131              
1132             =cut