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 13 13 100.0
total 188 360 52.2


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