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   181521 use strict;
  7         11  
  7         217  
4 7     7   29 use warnings;
  7         19  
  7         800  
5             our $VERSION = '0.087_002';
6              
7             require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import';
8             our %EXPORT_TAGS = ( all => [qw( ecc_encrypt ecc_decrypt ecc_sign_message ecc_verify_message ecc_sign_hash ecc_verify_hash ecc_shared_secret )] );
9             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
10             our @EXPORT = qw();
11              
12 7     7   33 use Carp;
  7         9  
  7         473  
13             $Carp::Internal{(__PACKAGE__)}++;
14 7     7   715 use CryptX;
  7         10  
  7         191  
15 7     7   762 use Crypt::Digest qw(digest_data digest_data_b64u);
  7         9  
  7         337  
16 7     7   816 use Crypt::Misc qw(read_rawfile encode_b64u decode_b64u encode_b64 decode_b64 pem_to_der der_to_pem);
  7         10  
  7         463  
17 7     7   668 use Crypt::PK;
  7         10  
  7         15373  
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   3 my ($self, $x, $y, $k, $crv) = @_;
112 1 50       3 croak "FATAL: no curve" if !$crv;
113 1 50 33     6 if (defined $k && length($k) > 0) {
    0 0        
114 1 50       4 croak "FATAL: invalid length (k)" if length($k) % 2;
115 1         5786 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 271     271 1 1102307 my $self = shift->_new();
128 271 100       577520 return @_ > 0 ? $self->import_key(@_) : $self;
129             }
130              
131             sub export_key_pem {
132 9     9 1 2126 my ($self, $type, $password, $cipher) = @_;
133 9         38 local $SIG{__DIE__} = \&CryptX::_croak;
134 9   50     192 my $key = $self->export_key_der($type||'');
135 8 50       18 return unless $key;
136 8 100       39 return der_to_pem($key, "EC PRIVATE KEY", $password, $cipher) if substr($type, 0, 7) eq 'private';
137 4 50       23 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 192691 my ($self, $key, $password) = @_;
187 113         620 local $SIG{__DIE__} = \&CryptX::_croak;
188 113 50       346 croak "FATAL: undefined key" unless $key;
189              
190             # special case
191 113 100       329 if (ref($key) eq 'HASH') {
192 1 50 33     9 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 112         266 my $data;
210 112 100       3206 if (ref($key) eq 'SCALAR') {
    50          
211 16         23 $data = $$key;
212             }
213             elsif (-f $key) {
214 96         462 $data = read_rawfile($key);
215             }
216             else {
217 0         0 croak "FATAL: non-existing file '$key'";
218             }
219 112 50       418 croak "FATAL: invalid key data" unless $data;
220              
221 112 100       1290 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         209 my $pem = $1;
223 61   100     96 my $rv = eval { $self->_import_pem($pem, $password) } || eval { $self->_import_old(pem_to_der($pem, $password)) };
224 61 100       672 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         711690 return $self->_import_openssh($data, $password);
231             }
232             elsif ($data =~ /---- BEGIN SSH2 PUBLIC KEY ----(.+?)---- END SSH2 PUBLIC KEY ----/s) {
233 3         18388 return $self->_import_openssh($data, undef);
234             }
235             elsif ($data =~ /(ecdsa-\S+)\s+(\S+)/) {
236 3         39 $data = decode_b64("$2");
237 3         18 my ($typ, $skip, $pubkey) = Crypt::PK::_ssh_parse($data);
238 3 50 33     17132 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     76 eval { $self->_import_x509($data) };
257 39 50       369 return $rv if $rv;
258             }
259 5         310 croak "FATAL: invalid or unsupported EC key format";
260             }
261              
262             sub curve2hash {
263 3     3 1 5271 my $self = shift;
264 3         106 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         41 };
275             }
276              
277             ### FUNCTIONS
278              
279             sub ecc_encrypt {
280 1     1 1 3376 my $key = shift;
281 1         5 local $SIG{__DIE__} = \&CryptX::_croak;
282 1 50       6 $key = __PACKAGE__->new($key) unless ref $key;
283 1 50       6 carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
284 1         5698 return $key->encrypt(@_);
285             }
286              
287             sub ecc_decrypt {
288 1     1 1 309 my $key = shift;
289 1         6 local $SIG{__DIE__} = \&CryptX::_croak;
290 1 50       9 $key = __PACKAGE__->new($key) unless ref $key;
291 1 50       36 carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
292 1         5922 return $key->decrypt(@_);
293             }
294              
295             sub ecc_sign_message {
296 1     1 1 345 my $key = shift;
297 1         5 local $SIG{__DIE__} = \&CryptX::_croak;
298 1 50       9 $key = __PACKAGE__->new($key) unless ref $key;
299 1 50       12 carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
300 1         2893 return $key->sign_message(@_);
301             }
302              
303             sub ecc_verify_message {
304 1     1 1 320 my $key = shift;
305 1         4 local $SIG{__DIE__} = \&CryptX::_croak;
306 1 50       10 $key = __PACKAGE__->new($key) unless ref $key;
307 1 50       7 carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
308 1         1840 return $key->verify_message(@_);
309             }
310              
311             sub ecc_sign_hash {
312 1     1 1 2 my $key = shift;
313 1         4 local $SIG{__DIE__} = \&CryptX::_croak;
314 1 50       7 $key = __PACKAGE__->new($key) unless ref $key;
315 1 50       5 carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
316 1         5651 return $key->sign_hash(@_);
317             }
318              
319             sub ecc_verify_hash {
320 1     1 1 387 my $key = shift;
321 1         5 local $SIG{__DIE__} = \&CryptX::_croak;
322 1 50       10 $key = __PACKAGE__->new($key) unless ref $key;
323 1 50       6 carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
324 1         1818 return $key->verify_hash(@_);
325             }
326              
327             sub ecc_shared_secret {
328 2     2 1 8 my ($privkey, $pubkey) = @_;
329 2         31 local $SIG{__DIE__} = \&CryptX::_croak;
330 2 50       14 $privkey = __PACKAGE__->new($privkey) unless ref $privkey;
331 2 50       14 $pubkey = __PACKAGE__->new($pubkey) unless ref $pubkey;
332 2 50 33     18 carp "FATAL: invalid 'privkey' param" unless ref($privkey) eq __PACKAGE__ && $privkey->is_private;
333 2 50       7 carp "FATAL: invalid 'pubkey' param" unless ref($pubkey) eq __PACKAGE__;
334 2         5633 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, $deterministic_hash_name);
855              
856             #NOTE: $deterministic_hash_name can be 'SHA1', 'SHA256' or any other hash supported by Crypt::Digest
857             # in most cases it will be the same as used to create $message_hash, if not provided non-deterministic
858             # signature will be created
859              
860             I
861              
862             =head2 sign_hash_eth
863              
864             Same as L only the signature format is as defined by Ethereum.
865             32 byte r value, 32 byte s value, 1 recovery byte (27 or 28)
866              
867             =head2 sign_hash_rfc7518
868              
869             I
870              
871             Same as L only the signature format is as defined by L
872             (JWA - JSON Web Algorithms).
873              
874             =head2 verify_hash
875              
876             my $pk = Crypt::PK::ECC->new($pub_key_filename);
877             my $valid = $pub->verify_hash($signature, $message_hash);
878              
879             =head2 verify_hash_rfc7518
880              
881             I
882              
883             =head2 verify_hash_eth
884              
885             Same as L only the signature format is as defined by Ethereum.
886             Compatible with signatures generated by L.
887              
888             =head2 recovery_pub_eth
889              
890             Alternative method to verify a signature with recovery of the public key.
891             Mainly used for in Ethereum-like blockchain networks.
892             This method will recover public key from ECDSA signature in Ethereum format
893             (see L).
894              
895             my $pk = Crypt::PK::ECC->new($priv_key_filename);
896             my $signature = $pk->sign_hash_eth($message_hash);
897             my $pub_key = $pk->recovery_pub_eth($sig, $hash)
898              
899             =head2 recovery_pub
900              
901             Same logic as recovery_pub_eth except, but compatible with L
902             signature. The main difference that B<$recid> is required, because B signature
903             doesn't contain parity bit, so you need to specify it explicitly.
904              
905             my $pk = Crypt::PK::ECC->new($priv_key_filename);
906             my $signature = $pk->sign_hash($message_hash);
907             my $pub_key = $pk->recovery_pub($signature, $message_hash, $recid)
908              
909             =head2 recovery_pub_rfc7518
910              
911             Same logic as recovery_pub_eth except, but compatible with L
912             signature. The main difference that B<$recid> is required, because rfc7518 signature
913             doesn't contain parity bit, so you need to specify it explicitly.
914              
915             my $pk = Crypt::PK::ECC->new($priv_key_filename);
916             my $signature = $pk->sign_hash_rfc7518($message_hash);
917             my $pub_key = $pk->recovery_pub_rfc7518($signature, $message_hash, $recid)
918              
919             I
920              
921             Same as L only the signature format is as defined by L
922             (JWA - JSON Web Algorithms).
923              
924             =head2 shared_secret
925              
926             # Alice having her priv key $pk and Bob's public key $pkb
927             my $pk = Crypt::PK::ECC->new($priv_key_filename);
928             my $pkb = Crypt::PK::ECC->new($pub_key_filename);
929             my $shared_secret = $pk->shared_secret($pkb);
930              
931             # Bob having his priv key $pk and Alice's public key $pka
932             my $pk = Crypt::PK::ECC->new($priv_key_filename);
933             my $pka = Crypt::PK::ECC->new($pub_key_filename);
934             my $shared_secret = $pk->shared_secret($pka); # same value as computed by Alice
935              
936             =head2 is_private
937              
938             my $rv = $pk->is_private;
939             # 1 .. private key loaded
940             # 0 .. public key loaded
941             # undef .. no key loaded
942              
943             =head2 size
944              
945             my $size = $pk->size;
946             # returns key size in bytes or undef if no key loaded
947              
948             =head2 key2hash
949              
950             my $hash = $pk->key2hash;
951              
952             # returns hash like this (or undef if no key loaded):
953             {
954             size => 20, # integer: key (curve) size in bytes
955             type => 1, # integer: 1 .. private, 0 .. public
956             #curve parameters
957             curve_A => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
958             curve_B => "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
959             curve_bits => 160,
960             curve_bytes => 20,
961             curve_cofactor => 1,
962             curve_Gx => "4A96B5688EF573284664698968C38BB913CBFC82",
963             curve_Gy => "23A628553168947D59DCC912042351377AC5FB32",
964             curve_name => "secp160r1",
965             curve_order => "0100000000000000000001F4C8F927AED3CA752257",
966             curve_prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
967             #private key
968             k => "B0EE84A749FE95DF997E33B8F333E12101E824C3",
969             #public key point coordinates
970             pub_x => "5AE1ACE3ED0AEA9707CE5C0BCE014F6A2F15023A",
971             pub_y => "895D57E992D0A15F88D6680B27B701F615FCDC0F",
972             }
973              
974             =head2 curve2hash
975              
976             I
977              
978             my $crv = $pk->curve2hash;
979              
980             # returns a hash that can be passed to: $pk->generate_key($crv)
981             {
982             A => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
983             B => "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
984             cofactor => 1,
985             Gx => "4A96B5688EF573284664698968C38BB913CBFC82",
986             Gy => "23A628553168947D59DCC912042351377AC5FB32",
987             order => "0100000000000000000001F4C8F927AED3CA752257",
988             prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
989             }
990              
991             =head1 FUNCTIONS
992              
993             =head2 ecc_encrypt
994              
995             Elliptic Curve Diffie-Hellman (ECDH) encryption as implemented by libtomcrypt. See method L below.
996              
997             my $ct = ecc_encrypt($pub_key_filename, $message);
998             #or
999             my $ct = ecc_encrypt(\$buffer_containing_pub_key, $message);
1000             #or
1001             my $ct = ecc_encrypt($pub_key_filename, $message, $hash_name);
1002              
1003             #NOTE: $hash_name can be 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
1004              
1005             ECCDH Encryption is performed by producing a random key, hashing it, and XOR'ing the digest against the plaintext.
1006              
1007             =head2 ecc_decrypt
1008              
1009             Elliptic Curve Diffie-Hellman (ECDH) decryption as implemented by libtomcrypt. See method L below.
1010              
1011             my $pt = ecc_decrypt($priv_key_filename, $ciphertext);
1012             #or
1013             my $pt = ecc_decrypt(\$buffer_containing_priv_key, $ciphertext);
1014              
1015             =head2 ecc_sign_message
1016              
1017             Elliptic Curve Digital Signature Algorithm (ECDSA) - signature generation. See method L below.
1018              
1019             my $sig = ecc_sign_message($priv_key_filename, $message);
1020             #or
1021             my $sig = ecc_sign_message(\$buffer_containing_priv_key, $message);
1022             #or
1023             my $sig = ecc_sign_message($priv_key, $message, $hash_name);
1024              
1025             =head2 ecc_verify_message
1026              
1027             Elliptic Curve Digital Signature Algorithm (ECDSA) - signature verification. See method L below.
1028              
1029             ecc_verify_message($pub_key_filename, $signature, $message) or die "ERROR";
1030             #or
1031             ecc_verify_message(\$buffer_containing_pub_key, $signature, $message) or die "ERROR";
1032             #or
1033             ecc_verify_message($pub_key, $signature, $message, $hash_name) or die "ERROR";
1034              
1035             =head2 ecc_sign_hash
1036              
1037             Elliptic Curve Digital Signature Algorithm (ECDSA) - signature generation. See method L below.
1038              
1039             my $sig = ecc_sign_hash($priv_key_filename, $message_hash);
1040             #or
1041             my $sig = ecc_sign_hash(\$buffer_containing_priv_key, $message_hash);
1042              
1043             =head2 ecc_verify_hash
1044              
1045             Elliptic Curve Digital Signature Algorithm (ECDSA) - signature verification. See method L below.
1046              
1047             ecc_verify_hash($pub_key_filename, $signature, $message_hash) or die "ERROR";
1048             #or
1049             ecc_verify_hash(\$buffer_containing_pub_key, $signature, $message_hash) or die "ERROR";
1050              
1051             =head2 ecc_shared_secret
1052              
1053             Elliptic curve Diffie-Hellman (ECDH) - construct a Diffie-Hellman shared secret with a private and public ECC key. See method L below.
1054              
1055             #on Alice side
1056             my $shared_secret = ecc_shared_secret('Alice_priv_ecc1.der', 'Bob_pub_ecc1.der');
1057              
1058             #on Bob side
1059             my $shared_secret = ecc_shared_secret('Bob_priv_ecc1.der', 'Alice_pub_ecc1.der');
1060              
1061             =head1 OpenSSL interoperability
1062              
1063             ### let's have:
1064             # ECC private key in PEM format - eckey.priv.pem
1065             # ECC public key in PEM format - eckey.pub.pem
1066             # data file to be signed - input.data
1067              
1068             =head2 Sign by OpenSSL, verify by Crypt::PK::ECC
1069              
1070             Create signature (from commandline):
1071              
1072             openssl dgst -sha1 -sign eckey.priv.pem -out input.sha1-ec.sig input.data
1073              
1074             Verify signature (Perl code):
1075              
1076             use Crypt::PK::ECC;
1077             use Crypt::Digest 'digest_file';
1078             use Crypt::Misc 'read_rawfile';
1079              
1080             my $pkec = Crypt::PK::ECC->new("eckey.pub.pem");
1081             my $signature = read_rawfile("input.sha1-ec.sig");
1082             my $valid = $pkec->verify_hash($signature, digest_file("SHA1", "input.data"), "SHA1", "v1.5");
1083             print $valid ? "SUCCESS" : "FAILURE";
1084              
1085             =head2 Sign by Crypt::PK::ECC, verify by OpenSSL
1086              
1087             Create signature (Perl code):
1088              
1089             use Crypt::PK::ECC;
1090             use Crypt::Digest 'digest_file';
1091             use Crypt::Misc 'write_rawfile';
1092              
1093             my $pkec = Crypt::PK::ECC->new("eckey.priv.pem");
1094             my $signature = $pkec->sign_hash(digest_file("SHA1", "input.data"), "SHA1", "v1.5");
1095             write_rawfile("input.sha1-ec.sig", $signature);
1096              
1097             Verify signature (from commandline):
1098              
1099             openssl dgst -sha1 -verify eckey.pub.pem -signature input.sha1-ec.sig input.data
1100              
1101             =head2 Keys generated by Crypt::PK::ECC
1102              
1103             Generate keys (Perl code):
1104              
1105             use Crypt::PK::ECC;
1106             use Crypt::Misc 'write_rawfile';
1107              
1108             my $pkec = Crypt::PK::ECC->new;
1109             $pkec->generate_key('secp160k1');
1110             write_rawfile("eckey.pub.der", $pkec->export_key_der('public'));
1111             write_rawfile("eckey.priv.der", $pkec->export_key_der('private'));
1112             write_rawfile("eckey.pub.pem", $pkec->export_key_pem('public'));
1113             write_rawfile("eckey.priv.pem", $pkec->export_key_pem('private'));
1114             write_rawfile("eckey-passwd.priv.pem", $pkec->export_key_pem('private', 'secret'));
1115              
1116             Use keys by OpenSSL:
1117              
1118             openssl ec -in eckey.priv.der -text -inform der
1119             openssl ec -in eckey.priv.pem -text
1120             openssl ec -in eckey-passwd.priv.pem -text -inform pem -passin pass:secret
1121             openssl ec -in eckey.pub.der -pubin -text -inform der
1122             openssl ec -in eckey.pub.pem -pubin -text
1123              
1124             =head2 Keys generated by OpenSSL
1125              
1126             Generate keys:
1127              
1128             openssl ecparam -param_enc explicit -name prime192v3 -genkey -out eckey.priv.pem
1129             openssl ec -param_enc explicit -in eckey.priv.pem -out eckey.pub.pem -pubout
1130             openssl ec -param_enc explicit -in eckey.priv.pem -out eckey.priv.der -outform der
1131             openssl ec -param_enc explicit -in eckey.priv.pem -out eckey.pub.der -outform der -pubout
1132             openssl ec -param_enc explicit -in eckey.priv.pem -out eckey.privc.der -outform der -conv_form compressed
1133             openssl ec -param_enc explicit -in eckey.priv.pem -out eckey.pubc.der -outform der -pubout -conv_form compressed
1134             openssl ec -param_enc explicit -in eckey.priv.pem -passout pass:secret -des3 -out eckey-passwd.priv.pem
1135              
1136             Load keys (Perl code):
1137              
1138             use Crypt::PK::ECC;
1139              
1140             my $pkec = Crypt::PK::ECC->new;
1141             $pkec->import_key("eckey.pub.der");
1142             $pkec->import_key("eckey.pubc.der");
1143             $pkec->import_key("eckey.priv.der");
1144             $pkec->import_key("eckey.privc.der");
1145             $pkec->import_key("eckey.pub.pem");
1146             $pkec->import_key("eckey.priv.pem");
1147             $pkec->import_key("eckey-passwd.priv.pem", "secret");
1148              
1149             =head1 SEE ALSO
1150              
1151             =over
1152              
1153             =item * L
1154              
1155             =item * L
1156              
1157             =item * L
1158              
1159             =back
1160              
1161             =cut