File Coverage

blib/lib/Crypt/PK/ECC.pm
Criterion Covered Total %
statement 102 149 68.4
branch 53 126 42.0
condition 11 67 16.4
subroutine 19 22 86.3
pod 13 13 100.0
total 198 377 52.5


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