| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Crypt::Perl::ECDSA::ECParameters; |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=encoding utf-8 |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 NAME |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
Crypt::Perl::ECDSA::ECParameters - Parse RFC 3279 explicit curves |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 DISCUSSION |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
This interface is undocumented for now. |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=cut |
|
14
|
|
|
|
|
|
|
|
|
15
|
7
|
|
|
7
|
|
40
|
use strict; |
|
|
7
|
|
|
|
|
13
|
|
|
|
7
|
|
|
|
|
166
|
|
|
16
|
7
|
|
|
7
|
|
30
|
use warnings; |
|
|
7
|
|
|
|
|
9
|
|
|
|
7
|
|
|
|
|
161
|
|
|
17
|
|
|
|
|
|
|
|
|
18
|
7
|
|
|
7
|
|
31
|
use Try::Tiny; |
|
|
7
|
|
|
|
|
18
|
|
|
|
7
|
|
|
|
|
357
|
|
|
19
|
|
|
|
|
|
|
|
|
20
|
7
|
|
|
7
|
|
39
|
use Crypt::Perl::BigInt (); |
|
|
7
|
|
|
|
|
10
|
|
|
|
7
|
|
|
|
|
108
|
|
|
21
|
7
|
|
|
7
|
|
2427
|
use Crypt::Perl::ECDSA::EncodedPoint (); |
|
|
7
|
|
|
|
|
16
|
|
|
|
7
|
|
|
|
|
124
|
|
|
22
|
7
|
|
|
7
|
|
38
|
use Crypt::Perl::ECDSA::Utils (); |
|
|
7
|
|
|
|
|
12
|
|
|
|
7
|
|
|
|
|
76
|
|
|
23
|
7
|
|
|
7
|
|
28
|
use Crypt::Perl::X (); |
|
|
7
|
|
|
|
|
13
|
|
|
|
7
|
|
|
|
|
149
|
|
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
#NOTE: This needs never to use Crypt::Perl::ECDSA::DB |
|
26
|
|
|
|
|
|
|
#so that extract_openssl_curves.pl will work. |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
use constant { |
|
29
|
7
|
|
|
|
|
607
|
OID_ecPublicKey => '1.2.840.10045.2.1', |
|
30
|
|
|
|
|
|
|
OID_prime_field => '1.2.840.10045.1.1', |
|
31
|
|
|
|
|
|
|
OID_characteristic_two_field => '1.2.840.10045.1.2', |
|
32
|
7
|
|
|
7
|
|
28
|
}; |
|
|
7
|
|
|
|
|
11
|
|
|
33
|
|
|
|
|
|
|
|
|
34
|
7
|
|
|
7
|
|
38
|
use constant EXPORTABLE => qw( p a b n h gx gy ); |
|
|
7
|
|
|
|
|
15
|
|
|
|
7
|
|
|
|
|
476
|
|
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
#cf. RFC 3279 |
|
37
|
7
|
|
|
|
|
6134
|
use constant ASN1_ECParameters => q< |
|
38
|
|
|
|
|
|
|
Trinomial ::= INTEGER |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
Pentanomial ::= SEQUENCE { |
|
41
|
|
|
|
|
|
|
k1 INTEGER, |
|
42
|
|
|
|
|
|
|
k2 INTEGER, |
|
43
|
|
|
|
|
|
|
k3 INTEGER |
|
44
|
|
|
|
|
|
|
} |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
FG_Basis_Parameters ::= CHOICE { |
|
47
|
|
|
|
|
|
|
gnBasis NULL, |
|
48
|
|
|
|
|
|
|
tpBasis Trinomial, |
|
49
|
|
|
|
|
|
|
ppBasis Pentanomial |
|
50
|
|
|
|
|
|
|
} |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
Characteristic-two ::= SEQUENCE { |
|
53
|
|
|
|
|
|
|
m INTEGER, |
|
54
|
|
|
|
|
|
|
basis OBJECT IDENTIFIER, |
|
55
|
|
|
|
|
|
|
parameters FG_Basis_Parameters |
|
56
|
|
|
|
|
|
|
} |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
FG_Field_Parameters ::= CHOICE { |
|
59
|
|
|
|
|
|
|
prime-field INTEGER, -- p |
|
60
|
|
|
|
|
|
|
characteristic-two Characteristic-two |
|
61
|
|
|
|
|
|
|
} |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
FieldID ::= SEQUENCE { |
|
64
|
|
|
|
|
|
|
fieldType OBJECT IDENTIFIER, |
|
65
|
|
|
|
|
|
|
parameters FG_Field_Parameters |
|
66
|
|
|
|
|
|
|
} |
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
FieldElement ::= OCTET STRING |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
Curve ::= SEQUENCE { |
|
71
|
|
|
|
|
|
|
a FieldElement, |
|
72
|
|
|
|
|
|
|
b FieldElement, |
|
73
|
|
|
|
|
|
|
seed BIT STRING OPTIONAL |
|
74
|
|
|
|
|
|
|
} |
|
75
|
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
ECPoint ::= OCTET STRING |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
ECPVer ::= INTEGER |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
-- Look for this. |
|
81
|
|
|
|
|
|
|
ECParameters ::= SEQUENCE { |
|
82
|
|
|
|
|
|
|
version ECPVer, -- always 1 |
|
83
|
|
|
|
|
|
|
fieldID FieldID, |
|
84
|
|
|
|
|
|
|
curve Curve, |
|
85
|
|
|
|
|
|
|
base ECPoint, -- generator |
|
86
|
|
|
|
|
|
|
order INTEGER, -- n |
|
87
|
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
-- ECDH needs it; ECDSA doesn’t (RFC 3279, p14) |
|
89
|
|
|
|
|
|
|
cofactor INTEGER OPTIONAL -- h |
|
90
|
|
|
|
|
|
|
} |
|
91
|
7
|
|
|
7
|
|
43
|
>; |
|
|
7
|
|
|
|
|
10
|
|
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
#This must return the same information as |
|
94
|
|
|
|
|
|
|
#Crypt::Perl::ECDSA::EC::DB::get_curve_data_by_oid(). |
|
95
|
|
|
|
|
|
|
# |
|
96
|
|
|
|
|
|
|
#It also expects the same structure that Convert::ASN1 parses, |
|
97
|
|
|
|
|
|
|
#including array references for BIT STRINGs. |
|
98
|
|
|
|
|
|
|
# |
|
99
|
|
|
|
|
|
|
sub normalize { |
|
100
|
258
|
|
|
258
|
0
|
695
|
my ($parsed_or_der) = @_; |
|
101
|
|
|
|
|
|
|
|
|
102
|
258
|
|
|
|
|
720
|
my $params; |
|
103
|
258
|
50
|
|
|
|
743
|
if (ref $parsed_or_der) { |
|
104
|
258
|
|
|
|
|
715
|
$params = $parsed_or_der; |
|
105
|
|
|
|
|
|
|
} |
|
106
|
|
|
|
|
|
|
else { |
|
107
|
0
|
|
|
|
|
0
|
die Crypt::Perl::X::create('Generic', 'TODO'); |
|
108
|
|
|
|
|
|
|
} |
|
109
|
|
|
|
|
|
|
|
|
110
|
258
|
|
|
|
|
697
|
my $field_type = $params->{'fieldID'}{'fieldType'}; |
|
111
|
258
|
100
|
|
|
|
1220
|
if ($field_type ne OID_prime_field() ) { |
|
112
|
120
|
50
|
|
|
|
643
|
if ($field_type eq OID_characteristic_two_field() ) { |
|
113
|
120
|
|
|
|
|
940
|
die Crypt::Perl::X::create('ECDSA::CharacteristicTwoUnsupported'); |
|
114
|
|
|
|
|
|
|
} |
|
115
|
|
|
|
|
|
|
|
|
116
|
0
|
|
|
|
|
0
|
die Crypt::Perl::X::create('Generic', "Unknown field type OID: “$field_type”"); |
|
117
|
|
|
|
|
|
|
} |
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
#“seed” isn’t necessary here for calculations (… right??) |
|
120
|
|
|
|
|
|
|
my %curve = ( |
|
121
|
|
|
|
|
|
|
p => $params->{'fieldID'}{'parameters'}{'prime-field'}, |
|
122
|
|
|
|
|
|
|
a => $params->{'curve'}{'a'}, |
|
123
|
|
|
|
|
|
|
b => $params->{'curve'}{'b'}, |
|
124
|
|
|
|
|
|
|
n => $params->{'order'}, |
|
125
|
|
|
|
|
|
|
h => $params->{'cofactor'}, |
|
126
|
138
|
|
|
|
|
1402
|
seed => $params->{'curve'}{'seed'}[0], |
|
127
|
|
|
|
|
|
|
); |
|
128
|
|
|
|
|
|
|
|
|
129
|
138
|
|
|
|
|
840
|
my @ints_to_upgrade = qw( p n ); |
|
130
|
138
|
50
|
|
|
|
609
|
if ( defined $curve{'h'} ) { |
|
131
|
138
|
|
|
|
|
335
|
push @ints_to_upgrade, 'h'; |
|
132
|
|
|
|
|
|
|
} |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
#Ensure that numbers like 0 and 1 are represented as BigInt, too. |
|
135
|
138
|
|
66
|
|
|
1121
|
ref || ($_ = Crypt::Perl::BigInt->new($_)) for @curve{@ints_to_upgrade}; |
|
136
|
|
|
|
|
|
|
|
|
137
|
138
|
|
|
|
|
5905
|
$_ = Crypt::Perl::BigInt->from_bytes($_) for @curve{'a', 'b'}; |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
#We might receive the base point as compressed, uncompressed, or hybrid. |
|
140
|
|
|
|
|
|
|
#Support all of those formats. |
|
141
|
138
|
|
|
|
|
99578
|
my $base = Crypt::Perl::ECDSA::EncodedPoint->new($params->{'base'})->get_uncompressed(\%curve); |
|
142
|
138
|
|
|
|
|
1659
|
@curve{'gx', 'gy'} = Crypt::Perl::ECDSA::Utils::split_G_or_public( $base ); |
|
143
|
|
|
|
|
|
|
|
|
144
|
138
|
|
|
|
|
945
|
my @strings_to_upgrade = qw( gx gy ); |
|
145
|
138
|
100
|
|
|
|
923
|
if ( defined $curve{'seed'} ) { |
|
146
|
67
|
|
|
|
|
198
|
push @strings_to_upgrade, 'seed'; |
|
147
|
|
|
|
|
|
|
} |
|
148
|
|
|
|
|
|
|
|
|
149
|
138
|
|
|
|
|
1031
|
$_ = Crypt::Perl::BigInt->from_bytes($_) for @curve{@strings_to_upgrade}; |
|
150
|
|
|
|
|
|
|
|
|
151
|
138
|
|
66
|
|
|
86370
|
defined($curve{$_}) || delete($curve{$_}) for qw( h seed ); |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
#---------------------------------------------------------------------- |
|
154
|
|
|
|
|
|
|
# my $db_params; |
|
155
|
|
|
|
|
|
|
# |
|
156
|
|
|
|
|
|
|
# try { |
|
157
|
|
|
|
|
|
|
# $db_params = Crypt::Perl::ECDSA::EC::DB::get_curve_name_by_data(\%curve); |
|
158
|
|
|
|
|
|
|
# } |
|
159
|
|
|
|
|
|
|
# catch { |
|
160
|
|
|
|
|
|
|
# if ( !try { $_->isa('Crypt::Perl::X::ECDSA::NoCurveForParameters') } ) { |
|
161
|
|
|
|
|
|
|
# local $@ = $_; |
|
162
|
|
|
|
|
|
|
# die; |
|
163
|
|
|
|
|
|
|
# } |
|
164
|
|
|
|
|
|
|
# }; |
|
165
|
|
|
|
|
|
|
# |
|
166
|
|
|
|
|
|
|
# #We only get here if there’s no cofactor |
|
167
|
|
|
|
|
|
|
# #or if the one given is correct. |
|
168
|
|
|
|
|
|
|
# if (!$curve{'h'} && !$db_params) { |
|
169
|
|
|
|
|
|
|
# die Crypt::Perl::X::create('Generic', 'This library currently requires a cofactor (“h”) for custom curves.'); |
|
170
|
|
|
|
|
|
|
# } |
|
171
|
|
|
|
|
|
|
#---------------------------------------------------------------------- |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
# if ( $params->{'curve'}{'seed'} ) { |
|
174
|
|
|
|
|
|
|
# $curve{'seed'} = Crypt::Perl::BigInt->from_bytes($params->{'curve'}{'seed'}); |
|
175
|
|
|
|
|
|
|
# |
|
176
|
|
|
|
|
|
|
# #Make sure that the given seed is either for an unknown curve |
|
177
|
|
|
|
|
|
|
# #or is correct for the given curve. |
|
178
|
|
|
|
|
|
|
# |
|
179
|
|
|
|
|
|
|
# |
|
180
|
|
|
|
|
|
|
# #_get_db_params_or_undef(\%curve); |
|
181
|
|
|
|
|
|
|
# |
|
182
|
|
|
|
|
|
|
# #If it’s a known curve, verify that the seed matches. |
|
183
|
|
|
|
|
|
|
# #if ($db_params) { |
|
184
|
|
|
|
|
|
|
# # my $seed_hex = unpack 'H*', $params->{'curve'}{'seed'}; |
|
185
|
|
|
|
|
|
|
# # |
|
186
|
|
|
|
|
|
|
# # if ($seed_hex ne $db_params->{'seed'}) { |
|
187
|
|
|
|
|
|
|
# # Crypt::Perl::X::create('Generic', "Curve parameters match “$curve_name”, but the seed ($seed_hex) does not match expected value ($db_params->{'seed'})"); |
|
188
|
|
|
|
|
|
|
# # } |
|
189
|
|
|
|
|
|
|
# #} |
|
190
|
|
|
|
|
|
|
# } |
|
191
|
|
|
|
|
|
|
# |
|
192
|
|
|
|
|
|
|
# if (grep { !defined $curve{$_} } 'h', 'seed') { |
|
193
|
|
|
|
|
|
|
# Module::Load::load('Crypt::Perl::ECDSA::EC::DB'); |
|
194
|
|
|
|
|
|
|
# |
|
195
|
|
|
|
|
|
|
# #TODO: Would it be worthwhile to support arbitrary curves that don’t |
|
196
|
|
|
|
|
|
|
# #give a cofactor? I’d need to figure out how to determine the |
|
197
|
|
|
|
|
|
|
# #cofactor from the other parameters. |
|
198
|
|
|
|
|
|
|
# my $curve_name = Crypt::Perl::ECDSA::EC::DB::get_curve_name_by_data(\%curve); |
|
199
|
|
|
|
|
|
|
# my $params_hr = Crypt::Perl::ECDSA::EC::DB::get_curve_data_by_name($curve_name); |
|
200
|
|
|
|
|
|
|
# |
|
201
|
|
|
|
|
|
|
# @curve{'h', 'seed'} = @{$params}{'h', 'seed'}; |
|
202
|
|
|
|
|
|
|
# } |
|
203
|
|
|
|
|
|
|
|
|
204
|
138
|
|
|
|
|
1026
|
return \%curve; |
|
205
|
|
|
|
|
|
|
} |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
#sub _get_db_params_or_undef { |
|
208
|
|
|
|
|
|
|
# my ($curve_hr) = @_; |
|
209
|
|
|
|
|
|
|
# |
|
210
|
|
|
|
|
|
|
# my ($curve_name, $params_hr); |
|
211
|
|
|
|
|
|
|
# try { |
|
212
|
|
|
|
|
|
|
# $curve_name = Crypt::Perl::ECDSA::EC::DB::get_curve_name_by_data(\%curve); |
|
213
|
|
|
|
|
|
|
# $params_hr = Crypt::Perl::ECDSA::EC::DB::get_curve_data_by_name($curve_name); |
|
214
|
|
|
|
|
|
|
# } |
|
215
|
|
|
|
|
|
|
# catch { |
|
216
|
|
|
|
|
|
|
# if ( !try { $_->isa('Crypt::Perl::X::ECDSA::NoCurveForParameters') } ) { |
|
217
|
|
|
|
|
|
|
# local $@ = $_; |
|
218
|
|
|
|
|
|
|
# die; |
|
219
|
|
|
|
|
|
|
# } |
|
220
|
|
|
|
|
|
|
# }; |
|
221
|
|
|
|
|
|
|
# |
|
222
|
|
|
|
|
|
|
# return $params_hr; |
|
223
|
|
|
|
|
|
|
#} |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
#---------------------------------------------------------------------- |
|
226
|
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
sub _asn1 { |
|
228
|
0
|
|
|
0
|
|
|
my ($class) = @_; |
|
229
|
|
|
|
|
|
|
|
|
230
|
0
|
|
|
|
|
|
return Crypt::Perl::ASN1->new()->prepare($class->ASN1_ECParameters())->find('ECParameters'); |
|
231
|
|
|
|
|
|
|
} |
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
1; |