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 4     4   269445 use strict;
  4         39  
  4         107  
42 4     4   28 use warnings;
  4         6  
  4         127  
43              
44 4     4   628 use Crypt::Perl::BigInt ();
  4         9  
  4         63  
45 4     4   1141 use Crypt::Perl::Math ();
  4         8  
  4         65  
46 4     4   18 use Crypt::Perl::RNG ();
  4         6  
  4         41  
47 4     4   689 use Crypt::Perl::ECDSA::EC::DB ();
  4         7  
  4         47  
48 4     4   1252 use Crypt::Perl::ECDSA::EC::Curve ();
  4         7  
  4         63  
49 4     4   1309 use Crypt::Perl::ECDSA::PrivateKey ();
  4         11  
  4         1044  
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 191017 my ($curve_name) = @_;
55              
56 49         646 my $key_parts = _generate(
57             Crypt::Perl::ECDSA::EC::DB::get_curve_data_by_name($curve_name),
58             );
59              
60 49         1425 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   159 my ($curve_hr) = @_;
76              
77 49         134 my $biN = $curve_hr->{'n'};
78              
79 49         369 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         127 my $curve = Crypt::Perl::ECDSA::EC::Curve->new( @{$curve_hr}{'p', 'a', 'b'} );
  49         443  
85              
86 49         110 my $G = $curve->decode_point( @{$curve_hr}{'gx','gy'});
  49         275  
87              
88 49         287 my $epPub = $G->multiply($biPrv);
89 49         204 my $biX = $epPub->get_x()->to_bigint();
90 49         239 my $biY = $epPub->get_y()->to_bigint();
91              
92 49         276 my $key_hex_len = 2 * Crypt::Perl::Math::ceil( $curve->keylen() / 8 );
93              
94 49         151 my ($hx, $hy) = map { substr( $_->as_hex(), 2 ) } $biX, $biY;
  98         44010  
95              
96 49         41395 $_ = sprintf "%0${key_hex_len}s", $_ for ($hx, $hy);
97              
98 49         440 my $biPub = Crypt::Perl::BigInt->from_hex("04$hx$hy");
99              
100             return {
101 49         106763 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;