15 | 15 |
use Crypt::Misc qw(read_rawfile encode_b64u decode_b64u encode_b64 decode_b64 pem_to_der der_to_pem);
|
16 | 16 |
use Crypt::PK;
|
17 | 17 |
|
18 | |
our %curve = (
|
19 | |
# extra curves not recognized by libtomcrypt
|
20 | |
'wap-wsg-idm-ecid-wtls8' => {
|
21 | |
prime => "FFFFFFFFFFFFFFFFFFFFFFFFFDE7",
|
22 | |
A => "0000000000000000000000000000",
|
23 | |
B => "0000000000000000000000000003",
|
24 | |
order => "0100000000000001ECEA551AD837E9",
|
25 | |
Gx => "0000000000000000000000000001",
|
26 | |
Gy => "0000000000000000000000000002",
|
27 | |
cofactor => 1,
|
28 | |
oid => '2.23.43.1.4.8',
|
29 | |
},
|
30 | |
'wap-wsg-idm-ecid-wtls9' => {
|
31 | |
prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC808F",
|
32 | |
A => "0000000000000000000000000000000000000000",
|
33 | |
B => "0000000000000000000000000000000000000003",
|
34 | |
order => "0100000000000000000001CDC98AE0E2DE574ABF33",
|
35 | |
Gx => "0000000000000000000000000000000000000001",
|
36 | |
Gy => "0000000000000000000000000000000000000002",
|
37 | |
cofactor => 1,
|
38 | |
oid => '2.23.43.1.4.9',
|
39 | |
},
|
|
18 |
our %curve = ( # must be "our" as we use it from XS code
|
|
19 |
# extra curves not recognized by libtomcrypt
|
|
20 |
'wap-wsg-idm-ecid-wtls8' => {
|
|
21 |
prime => "FFFFFFFFFFFFFFFFFFFFFFFFFDE7",
|
|
22 |
A => "0000000000000000000000000000",
|
|
23 |
B => "0000000000000000000000000003",
|
|
24 |
order => "0100000000000001ECEA551AD837E9",
|
|
25 |
Gx => "0000000000000000000000000001",
|
|
26 |
Gy => "0000000000000000000000000002",
|
|
27 |
cofactor => 1,
|
|
28 |
oid => '2.23.43.1.4.8',
|
|
29 |
},
|
|
30 |
'wap-wsg-idm-ecid-wtls9' => {
|
|
31 |
prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC808F",
|
|
32 |
A => "0000000000000000000000000000000000000000",
|
|
33 |
B => "0000000000000000000000000000000000000003",
|
|
34 |
order => "0100000000000000000001CDC98AE0E2DE574ABF33",
|
|
35 |
Gx => "0000000000000000000000000000000000000001",
|
|
36 |
Gy => "0000000000000000000000000000000000000002",
|
|
37 |
cofactor => 1,
|
|
38 |
oid => '2.23.43.1.4.9',
|
|
39 |
},
|
|
40 |
# some unusual openssl names
|
|
41 |
"wap-wsg-idm-ecid-wtls6" => 'secp112r1',
|
|
42 |
"wap-wsg-idm-ecid-wtls7" => 'secp160r2',
|
|
43 |
"wap-wsg-idm-ecid-wtls12" => 'secp224r1',
|
40 | 44 |
);
|
41 | 45 |
|
42 | |
my %jwk2curve = (
|
43 | |
'P-192' => 'secp192r1',
|
44 | |
'P-224' => 'secp224r1',
|
45 | |
'P-256' => 'secp256r1',
|
46 | |
'P-384' => 'secp384r1',
|
47 | |
'P-521' => 'secp521r1',
|
|
46 |
our %curve_oid2name = ( # must be "our" as we use it from XS code
|
|
47 |
# the following are used to derive curve_name from OID in key2hash()
|
|
48 |
"1.2.840.10045.3.1.1" => "secp192r1",
|
|
49 |
"1.2.840.10045.3.1.2" => "prime192v2",
|
|
50 |
"1.2.840.10045.3.1.3" => "prime192v3",
|
|
51 |
"1.2.840.10045.3.1.4" => "prime239v1",
|
|
52 |
"1.2.840.10045.3.1.5" => "prime239v2",
|
|
53 |
"1.2.840.10045.3.1.6" => "prime239v3",
|
|
54 |
"1.2.840.10045.3.1.7" => "secp256r1",
|
|
55 |
"1.3.132.0.6" => "secp112r1",
|
|
56 |
"1.3.132.0.7" => "secp112r2",
|
|
57 |
"1.3.132.0.8" => "secp160r1",
|
|
58 |
"1.3.132.0.9" => "secp160k1",
|
|
59 |
"1.3.132.0.10" => "secp256k1",
|
|
60 |
"1.3.132.0.28" => "secp128r1",
|
|
61 |
"1.3.132.0.29" => "secp128r2",
|
|
62 |
"1.3.132.0.30" => "secp160r2",
|
|
63 |
"1.3.132.0.31" => "secp192k1",
|
|
64 |
"1.3.132.0.32" => "secp224k1",
|
|
65 |
"1.3.132.0.33" => "secp224r1",
|
|
66 |
"1.3.132.0.34" => "secp384r1",
|
|
67 |
"1.3.132.0.35" => "secp521r1",
|
|
68 |
"1.3.36.3.3.2.8.1.1.1" => "brainpoolp160r1",
|
|
69 |
"1.3.36.3.3.2.8.1.1.2" => "brainpoolp160t1",
|
|
70 |
"1.3.36.3.3.2.8.1.1.3" => "brainpoolp192r1",
|
|
71 |
"1.3.36.3.3.2.8.1.1.4" => "brainpoolp192t1",
|
|
72 |
"1.3.36.3.3.2.8.1.1.5" => "brainpoolp224r1",
|
|
73 |
"1.3.36.3.3.2.8.1.1.6" => "brainpoolp224t1",
|
|
74 |
"1.3.36.3.3.2.8.1.1.7" => "brainpoolp256r1",
|
|
75 |
"1.3.36.3.3.2.8.1.1.8" => "brainpoolp256t1",
|
|
76 |
"1.3.36.3.3.2.8.1.1.9" => "brainpoolp320r1",
|
|
77 |
"1.3.36.3.3.2.8.1.1.10" => "brainpoolp320t1",
|
|
78 |
"1.3.36.3.3.2.8.1.1.11" => "brainpoolp384r1",
|
|
79 |
"1.3.36.3.3.2.8.1.1.12" => "brainpoolp384t1",
|
|
80 |
"1.3.36.3.3.2.8.1.1.13" => "brainpoolp512r1",
|
|
81 |
"1.3.36.3.3.2.8.1.1.14" => "brainpoolp512t1",
|
48 | 82 |
);
|
49 | 83 |
|
50 | 84 |
my %curve2jwk = (
|
|
85 |
# necessary for conversion of curve_name_or_OID >> P-NNN
|
51 | 86 |
'1.2.840.10045.3.1.1' => 'P-192', # secp192r1
|
52 | 87 |
'1.3.132.0.33' => 'P-224', # secp224r1
|
53 | 88 |
'1.2.840.10045.3.1.7' => 'P-256', # secp256r1
|
|
65 | 100 |
'secp256r1' => 'P-256',
|
66 | 101 |
'secp384r1' => 'P-384',
|
67 | 102 |
'secp521r1' => 'P-521',
|
68 | |
);
|
69 | |
|
70 | |
our %curve2ltc = ( # must be "our" as we use it from XS code
|
71 | |
# OIDs
|
72 | |
"1.2.840.10045.3.1.1" => "SECP192R1",
|
73 | |
"1.2.840.10045.3.1.2" => "PRIME192V2",
|
74 | |
"1.2.840.10045.3.1.3" => "PRIME192V3",
|
75 | |
"1.2.840.10045.3.1.4" => "PRIME239V1",
|
76 | |
"1.2.840.10045.3.1.5" => "PRIME239V2",
|
77 | |
"1.2.840.10045.3.1.6" => "PRIME239V3",
|
78 | |
"1.2.840.10045.3.1.7" => "SECP256R1",
|
79 | |
"1.3.132.0.10" => "SECP256K1",
|
80 | |
"1.3.132.0.28" => "SECP128R1",
|
81 | |
"1.3.132.0.29" => "SECP128R2",
|
82 | |
"1.3.132.0.30" => "SECP160R2",
|
83 | |
"1.3.132.0.31" => "SECP192K1",
|
84 | |
"1.3.132.0.32" => "SECP224K1",
|
85 | |
"1.3.132.0.33" => "SECP224R1",
|
86 | |
"1.3.132.0.34" => "SECP384R1",
|
87 | |
"1.3.132.0.35" => "SECP521R1",
|
88 | |
"1.3.132.0.6" => "SECP112R1",
|
89 | |
"1.3.132.0.7" => "SECP112R2",
|
90 | |
"1.3.132.0.8" => "SECP160R1",
|
91 | |
"1.3.132.0.9" => "SECP160K1",
|
92 | |
"1.3.36.3.3.2.8.1.1.1" => "BRAINPOOLP160R1",
|
93 | |
"1.3.36.3.3.2.8.1.1.11" => "BRAINPOOLP384R1",
|
94 | |
"1.3.36.3.3.2.8.1.1.13" => "BRAINPOOLP512R1",
|
95 | |
"1.3.36.3.3.2.8.1.1.3" => "BRAINPOOLP192R1",
|
96 | |
"1.3.36.3.3.2.8.1.1.5" => "BRAINPOOLP224R1",
|
97 | |
"1.3.36.3.3.2.8.1.1.7" => "BRAINPOOLP256R1",
|
98 | |
"1.3.36.3.3.2.8.1.1.9" => "BRAINPOOLP320R1",
|
99 | |
"1.3.36.3.3.2.8.1.1.10" => "BRAINPOOLP320T1",
|
100 | |
"1.3.36.3.3.2.8.1.1.12" => "BRAINPOOLP384T1",
|
101 | |
"1.3.36.3.3.2.8.1.1.14" => "BRAINPOOLP512T1",
|
102 | |
"1.3.36.3.3.2.8.1.1.2" => "BRAINPOOLP160T1",
|
103 | |
"1.3.36.3.3.2.8.1.1.4" => "BRAINPOOLP192T1",
|
104 | |
"1.3.36.3.3.2.8.1.1.6" => "BRAINPOOLP224T1",
|
105 | |
"1.3.36.3.3.2.8.1.1.8" => "BRAINPOOLP256T1",
|
106 | |
# JWT names
|
107 | |
"P-192" => "SECP192R1",
|
108 | |
"P-224" => "SECP224R1",
|
109 | |
"P-256" => "SECP256R1",
|
110 | |
"P-384" => "SECP384R1",
|
111 | |
"P-521" => "SECP521R1",
|
112 | |
# openssl names
|
113 | |
"brainpoolp160r1" => "BRAINPOOLP160R1",
|
114 | |
"brainpoolp192r1" => "BRAINPOOLP192R1",
|
115 | |
"brainpoolp224r1" => "BRAINPOOLP224R1",
|
116 | |
"brainpoolp256r1" => "BRAINPOOLP256R1",
|
117 | |
"brainpoolp320r1" => "BRAINPOOLP320R1",
|
118 | |
"brainpoolp384r1" => "BRAINPOOLP384R1",
|
119 | |
"brainpoolp512r1" => "BRAINPOOLP512R1",
|
120 | |
"brainpoolp160t1" => "BRAINPOOLP160T1",
|
121 | |
"brainpoolp192t1" => "BRAINPOOLP192T1",
|
122 | |
"brainpoolp224t1" => "BRAINPOOLP224T1",
|
123 | |
"brainpoolp256t1" => "BRAINPOOLP256T1",
|
124 | |
"brainpoolp320t1" => "BRAINPOOLP320T1",
|
125 | |
"brainpoolp384t1" => "BRAINPOOLP384T1",
|
126 | |
"brainpoolp512t1" => "BRAINPOOLP512T1",
|
127 | |
"nistp192" => "SECP192R1",
|
128 | |
"nistp224" => "SECP224R1",
|
129 | |
"nistp256" => "SECP256R1",
|
130 | |
"nistp384" => "SECP384R1",
|
131 | |
"nistp521" => "SECP521R1",
|
132 | |
"prime192v1" => "SECP192R1",
|
133 | |
"prime192v2" => "PRIME192V2",
|
134 | |
"prime192v3" => "PRIME192V3",
|
135 | |
"prime239v1" => "PRIME239V1",
|
136 | |
"prime239v2" => "PRIME239V2",
|
137 | |
"prime239v3" => "PRIME239V3",
|
138 | |
"prime256v1" => "SECP256R1",
|
139 | |
"secp112r1" => "SECP112R1",
|
140 | |
"secp112r2" => "SECP112R2",
|
141 | |
"secp128r1" => "SECP128R1",
|
142 | |
"secp128r2" => "SECP128R2",
|
143 | |
"secp160k1" => "SECP160K1",
|
144 | |
"secp160r1" => "SECP160R1",
|
145 | |
"secp160r2" => "SECP160R2",
|
146 | |
"secp192k1" => "SECP192K1",
|
147 | |
"secp192r1" => "SECP192R1",
|
148 | |
"secp224k1" => "SECP224K1",
|
149 | |
"secp224r1" => "SECP224R1",
|
150 | |
"secp256k1" => "SECP256K1",
|
151 | |
"secp256r1" => "SECP256R1",
|
152 | |
"secp384r1" => "SECP384R1",
|
153 | |
"secp521r1" => "SECP521R1",
|
154 | |
"wap-wsg-idm-ecid-wtls6" => 'SECP112R1',
|
155 | |
"wap-wsg-idm-ecid-wtls7" => 'SECP160R2',
|
156 | |
"wap-wsg-idm-ecid-wtls12" => 'SECP224R1',
|
157 | 103 |
);
|
158 | 104 |
|
159 | 105 |
sub _import_hex {
|
|
249 | 195 |
for (qw/x y d/) {
|
250 | 196 |
$key->{$_} = eval { unpack("H*", decode_b64u($key->{$_})) } if exists $key->{$_};
|
251 | 197 |
}
|
252 | |
if (my $curve_name = $jwk2curve{$key->{crv}}) {
|
253 | |
return $self->_import_hex($key->{x}, $key->{y}, $key->{d}, $curve_name);
|
254 | |
}
|
255 | |
# curve is not JWK compliant e.g. P-192 P-224 P-256 P-384 P-521 (we'll try to import anyway)
|
|
198 |
# names P-192 P-224 P-256 P-384 P-521 are recognized by libtomcrypt
|
256 | 199 |
return $self->_import_hex($key->{x}, $key->{y}, $key->{d}, $key->{crv});
|
257 | 200 |
}
|
258 | 201 |
croak "FATAL: unexpected ECC key hash";
|
|
290 | 233 |
for (qw/x y d/) {
|
291 | 234 |
$h->{$_} = eval { unpack("H*", decode_b64u($h->{$_})) } if exists $h->{$_};
|
292 | 235 |
}
|
293 | |
if (my $curve_name = $jwk2curve{$h->{crv}}) {
|
294 | |
return $self->_import_hex($h->{x}, $h->{y}, $h->{d}, $curve_name);
|
295 | |
}
|
296 | |
# curve is not JWK compliant e.g. P-192 P-224 P-256 P-384 P-521 (we'll try to import anyway)
|
|
236 |
# names P-192 P-224 P-256 P-384 P-521 are recognized by libtomcrypt
|
297 | 237 |
return $self->_import_hex($h->{x}, $h->{y}, $h->{d}, $h->{crv});
|
298 | 238 |
}
|
299 | 239 |
}
|