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
|
|
37
|
use strict; |
|
7
|
|
|
|
|
15
|
|
|
7
|
|
|
|
|
173
|
|
16
|
7
|
|
|
7
|
|
57
|
use warnings; |
|
7
|
|
|
|
|
20
|
|
|
7
|
|
|
|
|
171
|
|
17
|
|
|
|
|
|
|
|
18
|
7
|
|
|
7
|
|
35
|
use Try::Tiny; |
|
7
|
|
|
|
|
9
|
|
|
7
|
|
|
|
|
349
|
|
19
|
|
|
|
|
|
|
|
20
|
7
|
|
|
7
|
|
59
|
use Crypt::Perl::BigInt (); |
|
7
|
|
|
|
|
14
|
|
|
7
|
|
|
|
|
119
|
|
21
|
7
|
|
|
7
|
|
2526
|
use Crypt::Perl::ECDSA::EncodedPoint (); |
|
7
|
|
|
|
|
17
|
|
|
7
|
|
|
|
|
120
|
|
22
|
7
|
|
|
7
|
|
40
|
use Crypt::Perl::ECDSA::Utils (); |
|
7
|
|
|
|
|
12
|
|
|
7
|
|
|
|
|
77
|
|
23
|
7
|
|
|
7
|
|
27
|
use Crypt::Perl::X (); |
|
7
|
|
|
|
|
12
|
|
|
7
|
|
|
|
|
142
|
|
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
|
|
|
|
|
634
|
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
|
|
27
|
}; |
|
7
|
|
|
|
|
10
|
|
33
|
|
|
|
|
|
|
|
34
|
7
|
|
|
7
|
|
39
|
use constant EXPORTABLE => qw( p a b n h gx gy ); |
|
7
|
|
|
|
|
11
|
|
|
7
|
|
|
|
|
498
|
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
#cf. RFC 3279 |
37
|
7
|
|
|
|
|
2908
|
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
|
|
45
|
>; |
|
7
|
|
|
|
|
15
|
|
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
|
631
|
my ($parsed_or_der) = @_; |
101
|
|
|
|
|
|
|
|
102
|
258
|
|
|
|
|
416
|
my $params; |
103
|
258
|
50
|
|
|
|
979
|
if (ref $parsed_or_der) { |
104
|
258
|
|
|
|
|
739
|
$params = $parsed_or_der; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
else { |
107
|
0
|
|
|
|
|
0
|
die Crypt::Perl::X::create('Generic', 'TODO'); |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
258
|
|
|
|
|
787
|
my $field_type = $params->{'fieldID'}{'fieldType'}; |
111
|
258
|
100
|
|
|
|
900
|
if ($field_type ne OID_prime_field() ) { |
112
|
120
|
50
|
|
|
|
1029
|
if ($field_type eq OID_characteristic_two_field() ) { |
113
|
120
|
|
|
|
|
1085
|
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
|
|
|
|
|
1546
|
seed => $params->{'curve'}{'seed'}[0], |
127
|
|
|
|
|
|
|
); |
128
|
|
|
|
|
|
|
|
129
|
138
|
|
|
|
|
627
|
my @ints_to_upgrade = qw( p n ); |
130
|
138
|
50
|
|
|
|
423
|
if ( defined $curve{'h'} ) { |
131
|
138
|
|
|
|
|
294
|
push @ints_to_upgrade, 'h'; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
#Ensure that numbers like 0 and 1 are represented as BigInt, too. |
135
|
138
|
|
66
|
|
|
1037
|
ref || ($_ = Crypt::Perl::BigInt->new($_)) for @curve{@ints_to_upgrade}; |
136
|
|
|
|
|
|
|
|
137
|
138
|
|
|
|
|
5948
|
$_ = 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
|
|
|
|
|
95678
|
my $base = Crypt::Perl::ECDSA::EncodedPoint->new($params->{'base'})->get_uncompressed(\%curve); |
142
|
138
|
|
|
|
|
1505
|
@curve{'gx', 'gy'} = Crypt::Perl::ECDSA::Utils::split_G_or_public( $base ); |
143
|
|
|
|
|
|
|
|
144
|
138
|
|
|
|
|
597
|
my @strings_to_upgrade = qw( gx gy ); |
145
|
138
|
100
|
|
|
|
791
|
if ( defined $curve{'seed'} ) { |
146
|
67
|
|
|
|
|
211
|
push @strings_to_upgrade, 'seed'; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
138
|
|
|
|
|
912
|
$_ = Crypt::Perl::BigInt->from_bytes($_) for @curve{@strings_to_upgrade}; |
150
|
|
|
|
|
|
|
|
151
|
138
|
|
66
|
|
|
86516
|
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
|
|
|
|
|
993
|
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; |