File Coverage

lib/Crypt/Perl/ECDSA/Generate.pm
Criterion Covered Total %
statement 43 46 93.4
branch n/a
condition n/a
subroutine 10 11 90.9
pod 0 2 0.0
total 53 59 89.8


line stmt bran cond sub pod time code
1             package Crypt::Perl::ECDSA::Generate;
2              
3             =encoding utf-8
4              
5             =head1 NAME
6              
7             Crypt::Perl::ECDSA::Generate - ECDSA key generation
8              
9             =head1 SYNOPSIS
10              
11             use Crypt::Perl::ECDSA::Generate ();
12              
13             #$prkey is a C::P::E::PrivateKey instance.
14             my $prkey = Crypt::Perl::ECDSA::Generate::by_curve_name('secp521r1');
15              
16             my $signature = $prkey->sign('Hello!');
17              
18             die 'Wut' if $prkey->verify('Hello!', $signature);
19              
20             #You can also, in case it’s useful, do this. It’s probably
21             #only useful if you’re developing a new curve or something … ??
22             my $prkey2 = Crypt::Perl::ECDSA::Generate::by_explicit_curve(
23             {
24             p => Crypt::Perl::BigInt->new(...),
25             a => ...,
26             b => ...,
27             n => ...,
28             h => ...,
29             gx => ...,
30             gy => ...,
31             },
32             );
33              
34             =head1 DISCUSSION
35              
36             Thankfully, this is easy enough on processors that it’s feasible
37             in pure Perl!
38              
39             =cut
40              
41 5     5   26128 use strict;
  5         19  
  5         166  
42 5     5   26 use warnings;
  5         18  
  5         123  
43              
44 5     5   438 use Crypt::Perl::BigInt ();
  5         11  
  5         115  
45 5     5   2348 use Crypt::Perl::Math ();
  5         17  
  5         110  
46 5     5   36 use Crypt::Perl::RNG ();
  5         10  
  5         82  
47 5     5   1459 use Crypt::Perl::ECDSA::EC::DB ();
  5         11  
  5         103  
48 5     5   2268 use Crypt::Perl::ECDSA::EC::Curve ();
  5         15  
  5         116  
49 5     5   2478 use Crypt::Perl::ECDSA::PrivateKey ();
  5         22  
  5         1784  
50              
51             #The curve name is optional; if given, only the name will be encoded
52             #into the key rather than the explicit curve parameters.
53             sub by_curve_name {
54 49     49 0 299491 my ($curve_name) = @_;
55              
56 49         554 my $key_parts = _generate(
57             Crypt::Perl::ECDSA::EC::DB::get_curve_data_by_name($curve_name),
58             );
59              
60 49         1656 return Crypt::Perl::ECDSA::PrivateKey->new_by_curve_name($key_parts, $curve_name);
61             }
62              
63             *by_name = *by_curve_name; #legacy
64              
65             sub by_explicit_curve {
66 0     0 0 0 my ($curve_hr) = @_;
67              
68 0         0 my $key_parts = _generate($curve_hr);
69              
70 0         0 return Crypt::Perl::ECDSA::PrivateKey->new($key_parts, $curve_hr);
71             }
72              
73             #from generateKeyPairHex() in jsrsasign
74             sub _generate {
75 49     49   276 my ($curve_hr) = @_;
76              
77 49         226 my $biN = $curve_hr->{'n'};
78              
79 49         434 my $biPrv = Crypt::Perl::Math::randint( $biN );
80              
81             #my $G = '04' . join(q<>, map { substr( $_->as_hex(), 2 ) } @{$curve}{'gx','gy'});
82             #$G = Crypt::Perl::BigInt->from_hex($full_g);
83              
84 49         312 my $curve = Crypt::Perl::ECDSA::EC::Curve->new( @{$curve_hr}{'p', 'a', 'b'} );
  49         482  
85              
86 49         208 my $G = $curve->decode_point( @{$curve_hr}{'gx','gy'});
  49         309  
87              
88 49         474 my $epPub = $G->multiply($biPrv);
89 49         383 my $biX = $epPub->get_x()->to_bigint();
90 49         352 my $biY = $epPub->get_y()->to_bigint();
91              
92 49         492 my $key_hex_len = 2 * Crypt::Perl::Math::ceil( $curve->keylen() / 8 );
93              
94 49         194 my ($hx, $hy) = map { substr( $_->as_hex(), 2 ) } $biX, $biY;
  98         2475  
95              
96 49         1884 $_ = sprintf "%0${key_hex_len}s", $_ for ($hx, $hy);
97              
98 49         419 my $biPub = Crypt::Perl::BigInt->from_hex("04$hx$hy");
99              
100             return {
101 49         19196 version => 0,
102             private => $biPrv,
103             public => $biPub,
104             };
105             }
106              
107             #sub generate {
108             # my ($curve_name) = @_
109             #
110             # my $curve_hr = Crypt::Perl::ECDSA::EC::DB::get_curve_data_by_name($curve_name);
111             #
112             # my $bytes = $curve_hr->{'n'}->as_hex() / 2 - 1;
113             # my $ns2 = $curve_hr->{'n'} - 2;
114             #
115             # do {
116             # my $priv = _gen_bignum($bytes);
117             # next if $priv > $ns2;
118             #
119             # $priv += 1;
120             #
121             # return _key_from_private($curve_hr, $priv);
122             # } while 1;
123             #}
124             #
125             #sub _key_from_private {
126             # return _keypair( $curve_hr, $priv );
127             #}
128             #
129             #sub _keypair {
130             # my ($curve_hr, $priv) = @_;
131             #
132             # $priv %= $curve_hr->{'n'};
133             #
134             # my $full_g = '04' . join(q<>, map { substr( $_->as_hex(), 2 ) } @{$curve}{'gx','gy'});
135             # $full_g = Crypt::Perl::BigInt->from_hex($full_g);
136             #
137             # return {
138             # priv => $priv,
139             # pub => $full_g * $priv,
140             # };
141             #}
142             #
143             #sub _gen_bignum {
144             # my ($bits) = @_;
145             #
146             # return Crypt::Perl::BigInt->from_bin( Crypt::Perl::RNG::bit_string($bits) );
147             #}
148              
149             1;