Enhance Crypt::PK::DH (#10)
Crypt::PK::DH - accept base/prime values
Lance Kinley authored 7 years ago
karel-m committed 7 years ago
16 | 16 | RETVAL |
17 | 17 | |
18 | 18 | void |
19 | generate_key(Crypt::PK::DH self, int key_size=256) | |
19 | _generate_key(Crypt::PK::DH self, int key_size=256) | |
20 | 20 | PPCODE: |
21 | 21 | { |
22 | 22 | int rv; |
30 | 30 | } |
31 | 31 | |
32 | 32 | void |
33 | _generate_key_ex(Crypt::PK::DH self, SV * g, SV * p) | |
34 | PPCODE: | |
35 | { | |
36 | int rv; | |
37 | STRLEN p_len = 0; | |
38 | STRLEN g_len = 0; | |
39 | unsigned char *p_ptr=NULL; | |
40 | unsigned char *g_ptr=NULL; | |
41 | ||
42 | p_ptr = (unsigned char *)SvPVbyte(p, p_len); | |
43 | g_ptr = (unsigned char *)SvPVbyte(g, g_len); | |
44 | ||
45 | /* add a small random entropy before generating key - not necessary as we have initialized prng with 256bit entropy in _new() */ | |
46 | rv = rng_make_prng(64, self->yarrow_prng_index, &self->yarrow_prng_state, NULL); | |
47 | if (rv != CRYPT_OK) croak("FATAL: rng_make_prng failed: %s", error_to_string(rv)); | |
48 | /* gen the key */ | |
49 | rv = dh_make_key_ex(&self->yarrow_prng_state, self->yarrow_prng_index, (const char *) g_ptr, (const char *) p_ptr, &self->key); | |
50 | if (rv != CRYPT_OK) croak("FATAL: dh_make_key_ex failed: %s", error_to_string(rv)); | |
51 | XPUSHs(ST(0)); /* return self */ | |
52 | } | |
53 | ||
54 | void | |
33 | 55 | _import(Crypt::PK::DH self, SV * key_data) |
34 | 56 | PPCODE: |
35 | 57 | { |
41 | 63 | if (self->key.type != -1) { dh_free(&self->key); self->key.type = -1; } |
42 | 64 | rv = dh_import(data, (unsigned long)data_len, &self->key); |
43 | 65 | if (rv != CRYPT_OK) croak("FATAL: dh_import failed: %s", error_to_string(rv)); |
66 | XPUSHs(ST(0)); /* return self */ | |
67 | } | |
68 | ||
69 | void | |
70 | _import_raw(Crypt::PK::DH self, SV * raw_key, int type, char * g, char * p) | |
71 | PPCODE: | |
72 | { | |
73 | int rv; | |
74 | unsigned char *data=NULL; | |
75 | STRLEN data_len=0; | |
76 | ||
77 | data = (unsigned char *)SvPVbyte(raw_key, data_len); | |
78 | if (self->key.type != -1) { dh_free(&self->key); self->key.type = -1; } | |
79 | /* public */ | |
80 | if (type == 0) { | |
81 | rv = dh_import_raw(data, (unsigned long)data_len, PK_PUBLIC, g, p, &self->key); | |
82 | if (rv != CRYPT_OK) croak("FATAL: dh_import_raw failed: %s", error_to_string(rv)); | |
83 | } | |
84 | /* private */ | |
85 | else if (type == 1) { | |
86 | rv = dh_import_raw(data, (unsigned long)data_len, PK_PRIVATE, g, p, &self->key); | |
87 | if (rv != CRYPT_OK) croak("FATAL: dh_import_raw failed: %s", error_to_string(rv)); | |
88 | } | |
89 | else { | |
90 | croak("FATAL: import_raw invalid type '%d'", type); | |
91 | } | |
92 | ||
44 | 93 | XPUSHs(ST(0)); /* return self */ |
45 | 94 | } |
46 | 95 | |
94 | 143 | else{ |
95 | 144 | not_used = hv_store(rv_hash, "y", 1, newSVpv("", 0), 0); |
96 | 145 | } |
97 | /* =====> name */ | |
98 | snprintf(buf, sizeof(buf), "DH-%d", dh_get_size(&self->key)*8); | |
99 | not_used = hv_store(rv_hash, "name", 4, newSVpv(buf, strlen(buf)), 0); | |
146 | /* =====> p */ | |
147 | siz = (self->key.prime) ? mp_unsigned_bin_size(self->key.prime) : 0; | |
148 | if (siz>10000) { | |
149 | croak("FATAL: key2hash failed - 'p' too big number"); | |
150 | } | |
151 | if (siz>0) { | |
152 | mp_tohex(self->key.prime, buf); | |
153 | not_used = hv_store(rv_hash, "p", 1, newSVpv(buf, strlen(buf)), 0); | |
154 | } | |
155 | else { | |
156 | not_used = hv_store(rv_hash, "p", 1, newSVpv("", 0), 0); | |
157 | } | |
158 | ||
159 | /* =====> g */ | |
160 | siz = (self->key.base) ? mp_unsigned_bin_size(self->key.base) : 0; | |
161 | if (siz>10000) { | |
162 | croak("FATAL: key2hash failed - 'g' too big number"); | |
163 | } | |
164 | if (siz>0) { | |
165 | mp_tohex(self->key.base, buf); | |
166 | not_used = hv_store(rv_hash, "g", 1, newSVpv(buf, strlen(buf)), 0); | |
167 | } | |
168 | else { | |
169 | not_used = hv_store(rv_hash, "g", 1, newSVpv("", 0), 0); | |
170 | } | |
100 | 171 | /* =====> size */ |
101 | 172 | not_used = hv_store(rv_hash, "size", 4, newSViv(dh_get_size(&self->key)), 0); |
102 | 173 | /* =====> type */ |
106 | 177 | OUTPUT: |
107 | 178 | RETVAL |
108 | 179 | |
180 | SV* | |
181 | params2hash(Crypt::PK::DH self) | |
182 | PREINIT: | |
183 | HV *rv_hash; | |
184 | long siz; | |
185 | char buf[20001]; | |
186 | SV **not_used; | |
187 | CODE: | |
188 | if (self->key.type == -1) XSRETURN_UNDEF; | |
189 | rv_hash = newHV(); | |
190 | /* =====> p */ | |
191 | siz = (self->key.prime) ? mp_unsigned_bin_size(self->key.prime) : 0; | |
192 | if (siz>10000) { | |
193 | croak("FATAL: key2hash failed - 'p' too big number"); | |
194 | } | |
195 | if (siz>0) { | |
196 | mp_tohex(self->key.prime, buf); | |
197 | not_used = hv_store(rv_hash, "p", 1, newSVpv(buf, strlen(buf)), 0); | |
198 | } | |
199 | else { | |
200 | not_used = hv_store(rv_hash, "p", 1, newSVpv("", 0), 0); | |
201 | } | |
202 | ||
203 | /* =====> g */ | |
204 | siz = (self->key.base) ? mp_unsigned_bin_size(self->key.base) : 0; | |
205 | if (siz>10000) { | |
206 | croak("FATAL: key2hash failed - 'g' too big number"); | |
207 | } | |
208 | if (siz>0) { | |
209 | mp_tohex(self->key.base, buf); | |
210 | not_used = hv_store(rv_hash, "g", 1, newSVpv(buf, strlen(buf)), 0); | |
211 | } | |
212 | else { | |
213 | not_used = hv_store(rv_hash, "g", 1, newSVpv("", 0), 0); | |
214 | } | |
215 | if (not_used) not_used = NULL; /* just silence the warning: variable 'not_used' set but not used */ | |
216 | RETVAL = newRV_noinc((SV*)rv_hash); | |
217 | OUTPUT: | |
218 | RETVAL | |
219 | ||
109 | 220 | SV * |
110 | 221 | export_key(Crypt::PK::DH self, char * type) |
111 | 222 | CODE: |
112 | 223 | { |
113 | 224 | int rv; |
114 | unsigned char out[4096]; | |
115 | 225 | unsigned long int out_len = 4096; |
226 | unsigned char out[out_len]; | |
116 | 227 | |
117 | 228 | RETVAL = newSVpvn(NULL, 0); /* undef */ |
118 | 229 | if (strnEQ(type, "private", 7)) { |
139 | 250 | int rv, hash_id; |
140 | 251 | unsigned char *data_ptr=NULL; |
141 | 252 | STRLEN data_len=0; |
142 | unsigned char buffer[1024]; | |
143 | 253 | unsigned long buffer_len = 1024; |
254 | unsigned char buffer[buffer_len]; | |
144 | 255 | |
145 | 256 | data_ptr = (unsigned char *)SvPVbyte(data, data_len); |
146 | 257 | |
162 | 273 | int rv; |
163 | 274 | unsigned char *data_ptr=NULL; |
164 | 275 | STRLEN data_len=0; |
165 | unsigned char buffer[1024]; | |
166 | 276 | unsigned long buffer_len = 1024; |
277 | unsigned char buffer[buffer_len]; | |
167 | 278 | |
168 | 279 | data_ptr = (unsigned char *)SvPVbyte(data, data_len); |
169 | 280 | |
170 | 281 | rv = dh_decrypt_key(data_ptr, (unsigned long)data_len, buffer, &buffer_len, &self->key); |
171 | if (rv != CRYPT_OK) croak("FATAL: dh_decrypt_key_ex failed: %s", error_to_string(rv)); | |
282 | if (rv != CRYPT_OK) croak("FATAL: dh_decrypt_key failed: %s", error_to_string(rv)); | |
172 | 283 | RETVAL = newSVpvn((char*)buffer, buffer_len); |
173 | 284 | } |
174 | 285 | OUTPUT: |
181 | 292 | int rv; |
182 | 293 | unsigned char *data_ptr=NULL; |
183 | 294 | STRLEN data_len=0; |
184 | unsigned char buffer[1024]; | |
185 | 295 | unsigned long buffer_len = 1024; |
296 | unsigned char buffer[buffer_len]; | |
186 | 297 | |
187 | 298 | data_ptr = (unsigned char *)SvPVbyte(data, data_len); |
188 | 299 | |
189 | 300 | rv = dh_sign_hash(data_ptr, (unsigned long)data_len, buffer, &buffer_len, |
190 | 301 | &self->yarrow_prng_state, self->yarrow_prng_index, |
191 | 302 | &self->key); |
192 | if (rv != CRYPT_OK) croak("FATAL: dh_sign_hash_ex failed: %s", error_to_string(rv)); | |
303 | if (rv != CRYPT_OK) croak("FATAL: dh_sign_hash failed: %s", error_to_string(rv)); | |
193 | 304 | RETVAL = newSVpvn((char*)buffer, buffer_len); |
194 | 305 | } |
195 | 306 | OUTPUT: |
220 | 331 | CODE: |
221 | 332 | { |
222 | 333 | int rv; |
223 | unsigned char buffer[1024]; | |
224 | 334 | unsigned long buffer_len = 1024; |
335 | unsigned char buffer[buffer_len]; | |
225 | 336 | |
226 | 337 | rv = dh_shared_secret(&self->key, &pubkey->key, buffer, &buffer_len); |
227 | 338 | if (rv != CRYPT_OK) croak("FATAL: dh_shared_secret failed: %s", error_to_string(rv)); |
230 | 341 | OUTPUT: |
231 | 342 | RETVAL |
232 | 343 | |
344 | SV * | |
345 | export_key_raw(Crypt::PK::DH self, char * type) | |
346 | CODE: | |
347 | { | |
348 | int rv, len; | |
349 | unsigned long buffer_len = 1024; | |
350 | unsigned char buffer[buffer_len]; | |
351 | void *key; | |
352 | ||
353 | RETVAL = newSVpvn(NULL, 0); /* undef */ | |
354 | if (strnEQ(type, "private", 7)) { | |
355 | key = self->key.x; | |
356 | } | |
357 | else if (strnEQ(type, "public", 6)) { | |
358 | key = self->key.y; | |
359 | } | |
360 | else { | |
361 | croak("FATAL: export_key_raw: invalid type '%s'", type); | |
362 | } | |
363 | ||
364 | len = (unsigned long)mp_unsigned_bin_size(key); | |
365 | if (buffer_len < len) { | |
366 | croak("FATAL: %s", error_to_string(CRYPT_BUFFER_OVERFLOW)); | |
367 | } | |
368 | rv = mp_to_unsigned_bin(key, buffer); | |
369 | if (rv != CRYPT_OK) croak("FATAL: %s", error_to_string(rv)); | |
370 | RETVAL = newSVpvn((char*)buffer, len); | |
371 | } | |
372 | OUTPUT: | |
373 | RETVAL | |
374 | ||
375 | int | |
376 | _is_pubkey_valid(Crypt::PK::DH self); | |
377 | CODE: | |
378 | { | |
379 | int rv, i, bits_set = 0; | |
380 | mp_int one, two, p1, *y; | |
381 | mp_digit digit; | |
382 | ||
383 | if ((rv = mp_init_multi(&one, &two, &p1, NULL)) != MP_OKAY) { | |
384 | croak("FATAL: %s", error_to_string(rv)); | |
385 | } | |
386 | ||
387 | y = self->key.y; | |
388 | mp_set(&one, 1); | |
389 | mp_set(&two, 2); | |
390 | ||
391 | /* p1 = p-1 */ | |
392 | if ((rv = mp_sub(self->key.prime, &one, &p1)) != MP_OKAY) { | |
393 | croak("FATAL: %s", error_to_string(rv)); | |
394 | } | |
395 | /* valid public key cannot be negative */ | |
396 | if (y->sign == MP_NEG) { | |
397 | RETVAL = 0; | |
398 | } | |
399 | /* valid public key != 1 */ | |
400 | else if (mp_cmp(y, &one) == MP_EQ) { | |
401 | RETVAL = 0; | |
402 | } | |
403 | /* public key cannot be > p-1 */ | |
404 | else if (mp_cmp(y, &p1) == MP_GT) { | |
405 | RETVAL = 0; | |
406 | } | |
407 | /* if base == 2, public must have more than one bit set */ | |
408 | else if (mp_cmp(self->key.base, &two) == MP_EQ) { | |
409 | for (i = 0; i < y->used; i++) { | |
410 | digit = y->dp[i]; | |
411 | while (digit > ((mp_digit) 0)) { | |
412 | if (digit & ((mp_digit) 1)) | |
413 | bits_set++; | |
414 | digit >>= ((mp_digit) 1); | |
415 | } | |
416 | } | |
417 | if (bits_set > 1) | |
418 | RETVAL = 1; | |
419 | else RETVAL = 0; | |
420 | } | |
421 | else RETVAL = 1; | |
422 | } | |
423 | OUTPUT: | |
424 | RETVAL | |
425 | ||
233 | 426 | void |
234 | 427 | DESTROY(Crypt::PK::DH self) |
235 | 428 | CODE: |
10 | 10 | use Carp; |
11 | 11 | use CryptX; |
12 | 12 | use Crypt::Digest 'digest_data'; |
13 | use Crypt::Misc qw(read_rawfile encode_b64u decode_b64u encode_b64 decode_b64); | |
13 | use Crypt::Misc qw(read_rawfile); | |
14 | ||
15 | my %DH_PARAMS = ( | |
16 | ike768 => { g => 2, p => 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1'. | |
17 | '29024E088A67CC74020BBEA63B139B22514A08798E3404DD'. | |
18 | 'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245'. | |
19 | 'E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF' | |
20 | }, | |
21 | ike1024 => { g => 2, p => 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1'. | |
22 | '29024E088A67CC74020BBEA63B139B22514A08798E3404DD'. | |
23 | 'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245'. | |
24 | 'E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED'. | |
25 | 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381'. | |
26 | 'FFFFFFFFFFFFFFFF' | |
27 | }, | |
28 | ike1536 => { g => 2, p => 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1'. | |
29 | '29024E088A67CC74020BBEA63B139B22514A08798E3404DD'. | |
30 | 'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245'. | |
31 | 'E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED'. | |
32 | 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D'. | |
33 | 'C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F'. | |
34 | '83655D23DCA3AD961C62F356208552BB9ED529077096966D'. | |
35 | '670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF' | |
36 | }, | |
37 | ike2048 => { g => 2, p => 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1'. | |
38 | '29024E088A67CC74020BBEA63B139B22514A08798E3404DD'. | |
39 | 'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245'. | |
40 | 'E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED'. | |
41 | 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D'. | |
42 | 'C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F'. | |
43 | '83655D23DCA3AD961C62F356208552BB9ED529077096966D'. | |
44 | '670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B'. | |
45 | 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9'. | |
46 | 'DE2BCBF6955817183995497CEA956AE515D2261898FA0510'. | |
47 | '15728E5A8AACAA68FFFFFFFFFFFFFFFF' | |
48 | }, | |
49 | ike3072 => { g => 2, p => 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1'. | |
50 | '29024E088A67CC74020BBEA63B139B22514A08798E3404DD'. | |
51 | 'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245'. | |
52 | 'E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED'. | |
53 | 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D'. | |
54 | 'C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F'. | |
55 | '83655D23DCA3AD961C62F356208552BB9ED529077096966D'. | |
56 | '670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B'. | |
57 | 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9'. | |
58 | 'DE2BCBF6955817183995497CEA956AE515D2261898FA0510'. | |
59 | '15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64'. | |
60 | 'ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7'. | |
61 | 'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B'. | |
62 | 'F12FFA06D98A0864D87602733EC86A64521F2B18177B200C'. | |
63 | 'BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31'. | |
64 | '43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF' | |
65 | }, | |
66 | ike4096 => { g => 2, p => 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1'. | |
67 | '29024E088A67CC74020BBEA63B139B22514A08798E3404DD'. | |
68 | 'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245'. | |
69 | 'E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED'. | |
70 | 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D'. | |
71 | 'C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F'. | |
72 | '83655D23DCA3AD961C62F356208552BB9ED529077096966D'. | |
73 | '670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B'. | |
74 | 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9'. | |
75 | 'DE2BCBF6955817183995497CEA956AE515D2261898FA0510'. | |
76 | '15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64'. | |
77 | 'ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7'. | |
78 | 'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B'. | |
79 | 'F12FFA06D98A0864D87602733EC86A64521F2B18177B200C'. | |
80 | 'BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31'. | |
81 | '43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7'. | |
82 | '88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA'. | |
83 | '2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6'. | |
84 | '287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED'. | |
85 | '1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9'. | |
86 | '93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199'. | |
87 | 'FFFFFFFFFFFFFFFF' | |
88 | }, | |
89 | ike6144 => { g => 2, p => 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1'. | |
90 | '29024E088A67CC74020BBEA63B139B22514A08798E3404DD'. | |
91 | 'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245'. | |
92 | 'E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED'. | |
93 | 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D'. | |
94 | 'C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F'. | |
95 | '83655D23DCA3AD961C62F356208552BB9ED529077096966D'. | |
96 | '670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B'. | |
97 | 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9'. | |
98 | 'DE2BCBF6955817183995497CEA956AE515D2261898FA0510'. | |
99 | '15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64'. | |
100 | 'ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7'. | |
101 | 'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B'. | |
102 | 'F12FFA06D98A0864D87602733EC86A64521F2B18177B200C'. | |
103 | 'BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31'. | |
104 | '43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7'. | |
105 | '88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA'. | |
106 | '2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6'. | |
107 | '287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED'. | |
108 | '1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9'. | |
109 | '93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492'. | |
110 | '36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD'. | |
111 | 'F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831'. | |
112 | '179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B'. | |
113 | 'DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF'. | |
114 | '5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6'. | |
115 | 'D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3'. | |
116 | '23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA'. | |
117 | 'CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328'. | |
118 | '06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C'. | |
119 | 'DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE'. | |
120 | '12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF' | |
121 | }, | |
122 | ike8192 => { g => 2, p => 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1'. | |
123 | '29024E088A67CC74020BBEA63B139B22514A08798E3404DD'. | |
124 | 'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245'. | |
125 | 'E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED'. | |
126 | 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D'. | |
127 | 'C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F'. | |
128 | '83655D23DCA3AD961C62F356208552BB9ED529077096966D'. | |
129 | '670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B'. | |
130 | 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9'. | |
131 | 'DE2BCBF6955817183995497CEA956AE515D2261898FA0510'. | |
132 | '15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64'. | |
133 | 'ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7'. | |
134 | 'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B'. | |
135 | 'F12FFA06D98A0864D87602733EC86A64521F2B18177B200C'. | |
136 | 'BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31'. | |
137 | '43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7'. | |
138 | '88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA'. | |
139 | '2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6'. | |
140 | '287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED'. | |
141 | '1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9'. | |
142 | '93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492'. | |
143 | '36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD'. | |
144 | 'F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831'. | |
145 | '179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B'. | |
146 | 'DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF'. | |
147 | '5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6'. | |
148 | 'D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3'. | |
149 | '23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA'. | |
150 | 'CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328'. | |
151 | '06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C'. | |
152 | 'DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE'. | |
153 | '12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4'. | |
154 | '38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300'. | |
155 | '741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568'. | |
156 | '3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9'. | |
157 | '22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B'. | |
158 | '4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A'. | |
159 | '062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36'. | |
160 | '4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1'. | |
161 | 'B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92'. | |
162 | '4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47'. | |
163 | '9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71'. | |
164 | '60C980DD98EDD3DFFFFFFFFFFFFFFFFF' | |
165 | } | |
166 | ); | |
14 | 167 | |
15 | 168 | sub new { |
16 | 169 | my ($class, $f) = @_; |
36 | 189 | return $self->_import($data); |
37 | 190 | } |
38 | 191 | |
192 | sub import_key_raw { | |
193 | my ($self, $raw_bytes, $type, $param) = @_; | |
194 | my ($g, $p, $x, $y); | |
195 | ||
196 | if (ref $param eq 'HASH') { | |
197 | $g = $param->{g} or croak "FATAL: 'g' param not specified"; | |
198 | $p = $param->{p} or croak "FATAL: 'p' param not specified"; | |
199 | $g =~ s/^0x//; | |
200 | $p =~ s/^0x//; | |
201 | } elsif (my $dhparam = $DH_PARAMS{$param}) { | |
202 | $g = $dhparam->{g}; | |
203 | $p = $dhparam->{p}; | |
204 | } else { | |
205 | croak "FATAL: invalid parameter"; | |
206 | } | |
207 | ||
208 | if ($type eq 'private') { | |
209 | $type = 1; | |
210 | } elsif ($type eq 'public') { | |
211 | $type = 0; | |
212 | } else { | |
213 | croak "FATAL: invalid key type '$type'"; | |
214 | } | |
215 | my $rv = $self->_import_raw($raw_bytes, $type, $g, $p); | |
216 | croak "FATAL: invalid public key" unless $self->_is_pubkey_valid; | |
217 | return $rv; | |
218 | } | |
219 | ||
39 | 220 | sub encrypt { |
40 | 221 | my ($self, $data, $hash_name) = @_; |
41 | 222 | $hash_name = Crypt::Digest::_trans_digest_name($hash_name||'SHA1'); |
69 | 250 | sub verify_hash { |
70 | 251 | my ($self, $sig, $data_hash) = @_; |
71 | 252 | return $self->_verify($sig, $data_hash); |
253 | } | |
254 | ||
255 | sub generate_key { | |
256 | my ($key,$param) = @_; | |
257 | ||
258 | if (!ref $param) { | |
259 | if (my $dhparam = $DH_PARAMS{$param}) { | |
260 | $param = $dhparam; | |
261 | } else { | |
262 | croak "FATAL: invalid key length" unless ($param >= 96 || $param <= 512); | |
263 | return $key->_generate_key($param); | |
264 | } | |
265 | } | |
266 | my $g = $param->{g} or croak "FATAL: 'g' param not specified"; | |
267 | my $p = $param->{p} or croak "FATAL: 'p' param not specified"; | |
268 | $g =~ s/^0x//; | |
269 | $p =~ s/^0x//; | |
270 | return $key->_generate_key_ex($g, $p); | |
72 | 271 | } |
73 | 272 | |
74 | 273 | ### FUNCTIONS |
162 | 361 | #Key generation |
163 | 362 | my $pk = Crypt::PK::DH->new(); |
164 | 363 | $pk->generate_key(128); |
364 | my $private = $pk->export_key('private'); | |
365 | my $public = $pk->export_key('public'); | |
366 | ||
367 | or | |
368 | ||
369 | my $pk = Crypt::PK::DH->new(); | |
370 | $pk->generate_key('ike2048'); | |
371 | my $private = $pk->export_key('private'); | |
372 | my $public = $pk->export_key('public'); | |
373 | ||
374 | or | |
375 | ||
376 | my $pk = Crypt::PK::DH->new(); | |
377 | $pk->generate_key({ p => $p, g => $g }); | |
165 | 378 | my $private = $pk->export_key('private'); |
166 | 379 | my $public = $pk->export_key('public'); |
167 | 380 | |
207 | 420 | # 384 => DH-3072 |
208 | 421 | # 512 => DH-4096 |
209 | 422 | |
423 | $pk->generate_key($name) | |
424 | ### $name corresponds to values defined in RFC7296 and RFC3526 | |
425 | # ike768 => 768-bit MODP (Group 1) | |
426 | # ike1024 => 1024-bit MODP (Group 2) | |
427 | # ike1536 => 1536-bit MODP (Group 5) | |
428 | # ike2048 => 2048-bit MODP (Group 14) | |
429 | # ike3072 => 3072-bit MODP (Group 15) | |
430 | # ike4096 => 4096-bit MODP (Group 16) | |
431 | # ike6144 => 6144-bit MODP (Group 17) | |
432 | # ike8192 => 8192-bit MODP (Group 18) | |
433 | ||
434 | $pk->generate_key($param_hash) | |
435 | ## $param_hash is { g => $g, p => $p } | |
436 | ## where $g is the generator (base) in a hex string and $p is the prime in a hex string | |
437 | ||
210 | 438 | =head2 import_key |
211 | 439 | |
212 | 440 | Loads private or public key (exported by L</export_key>). |
215 | 443 | #or |
216 | 444 | $pk->import_key(\$buffer_containing_key); |
217 | 445 | |
446 | =head2 import_key_raw | |
447 | ||
448 | $pk->import_key_raw($raw_bytes, $type, $params) | |
449 | ### $raw_bytes is a binary string containing the key | |
450 | ### $type is either 'private' or 'public' | |
451 | ### $param is either a name ('ike2038') or hash containing the p,g values { g=>$g, p=>$p } | |
452 | ### in hex strings | |
453 | ||
218 | 454 | =head2 export_key |
219 | 455 | |
220 | 456 | my $private = $pk->export_key('private'); |
221 | 457 | #or |
222 | 458 | my $public = $pk->export_key('public'); |
459 | ||
460 | =head2 export_key_raw | |
461 | ||
462 | $raw_bytes = $dh->export_key_raw('public') | |
463 | #or | |
464 | $raw_bytes = $dh->export_key_raw('private') | |
223 | 465 | |
224 | 466 | =head2 encrypt |
225 | 467 | |
295 | 537 | { |
296 | 538 | type => 0, # integer: 1 .. private, 0 .. public |
297 | 539 | size => 256, # integer: key size in bytes |
298 | name => "DH-2048", # internal libtomcrypt name | |
299 | 540 | x => "FBC1062F73B9A17BB8473A2F5A074911FA7F20D28FB...", #private key |
300 | 541 | y => "AB9AAA40774D3CD476B52F82E7EE2D8A8D40CD88BF4...", #public key |
542 | g => "2", # generator/base | |
543 | p => "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80D...", # prime | |
544 | } | |
545 | ||
546 | =head2 params2hash | |
547 | ||
548 | my $params = $pk->params2hash; | |
549 | ||
550 | # returns hash like this (or undef if no key loaded): | |
551 | { | |
552 | g => "2", # generator/base | |
553 | p => "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80D...", # prime | |
301 | 554 | } |
302 | 555 | |
303 | 556 | =head1 FUNCTIONS |
175 | 175 | int idx, type; |
176 | 176 | void *x; |
177 | 177 | void *y; |
178 | void *base; | |
179 | void *prime; | |
178 | 180 | } dh_key; |
179 | 181 | |
180 | 182 | int dh_compat_test(void); |
182 | 184 | int dh_get_size(dh_key *key); |
183 | 185 | |
184 | 186 | int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key); |
187 | int dh_make_key_ex(prng_state *prng, int wprng, const char *g, const char *p, dh_key *key); | |
188 | int dh_make_key_ex_main(prng_state *prng, int wprng, dh_key *key); | |
185 | 189 | void dh_free(dh_key *key); |
186 | 190 | |
187 | 191 | int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key); |
188 | 192 | int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key); |
193 | int dh_import_raw(unsigned char *in, unsigned long inlen, int type, | |
194 | const char *base, const char *prime, dh_key *key); | |
189 | 195 | |
190 | 196 | int dh_shared_secret(dh_key *private_key, dh_key *public_key, |
191 | 197 | unsigned char *out, unsigned long *outlen); |
94 | 94 | int dh_get_size(dh_key *key) |
95 | 95 | { |
96 | 96 | LTC_ARGCHK(key != NULL); |
97 | if (key->idx == SUPPLIED_PRIME) { | |
98 | return mp_unsigned_bin_size(key->prime); | |
99 | } | |
97 | 100 | if (dh_is_valid_idx(key->idx) == 1) { |
98 | 101 | return sets[key->idx].size; |
99 | 102 | } else { |
111 | 114 | */ |
112 | 115 | int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key) |
113 | 116 | { |
114 | unsigned char *buf; | |
115 | 117 | unsigned long x; |
116 | void *p, *g; | |
117 | 118 | int err; |
118 | ||
119 | LTC_ARGCHK(key != NULL); | |
120 | ||
121 | /* good prng? */ | |
122 | if ((err = prng_is_valid(wprng)) != CRYPT_OK) { | |
123 | return err; | |
124 | } | |
125 | 119 | |
126 | 120 | /* find key size */ |
127 | 121 | for (x = 0; (keysize > sets[x].size) && (sets[x].size != 0); x++); |
135 | 129 | } |
136 | 130 | key->idx = x; |
137 | 131 | |
132 | if ((err = mp_init_multi(&key->base, &key->prime, NULL)) != CRYPT_OK) { | |
133 | goto error; | |
134 | } | |
135 | if ((err = mp_read_radix(key->base, sets[key->idx].base, 64)) != CRYPT_OK) { goto error; } | |
136 | if ((err = mp_read_radix(key->prime, sets[key->idx].prime, 64)) != CRYPT_OK) { goto error; } | |
137 | return dh_make_key_ex_main(prng, wprng, key); | |
138 | error: | |
139 | mp_clear_multi(key->base, key->prime, NULL); | |
140 | return err; | |
141 | } | |
142 | ||
143 | /** | |
144 | Make a DH key [private key pair] from provided base and prime | |
145 | @param prng An active PRNG state | |
146 | @param wprng The index for the PRNG you desire to use | |
147 | @param keysize The key size (octets) desired | |
148 | @param base The base (generator) to create the key from | |
149 | @param prime The prime to create the key from | |
150 | @param key [out] Where the newly created DH key will be stored | |
151 | @return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically. | |
152 | */ | |
153 | int dh_make_key_ex(prng_state *prng, int wprng, const char *base, const char *prime, dh_key *key) | |
154 | { | |
155 | int err; | |
156 | ||
157 | LTC_ARGCHK(base != NULL); | |
158 | LTC_ARGCHK(prime != NULL); | |
159 | LTC_ARGCHK(key != NULL); | |
160 | ||
161 | /* good prng? */ | |
162 | if ((err = prng_is_valid(wprng)) != CRYPT_OK) { | |
163 | return err; | |
164 | } | |
165 | ||
166 | if ((err = mp_init_multi(&key->base, &key->prime, NULL)) != CRYPT_OK) { | |
167 | goto error; | |
168 | } | |
169 | if ((err = mp_read_radix(key->base, base, 16)) != CRYPT_OK) { goto error; } | |
170 | if ((err = mp_read_radix(key->prime, prime, 16)) != CRYPT_OK) { goto error; } | |
171 | key->idx = SUPPLIED_PRIME; | |
172 | return dh_make_key_ex_main(prng, wprng, key); | |
173 | error: | |
174 | mp_clear_multi(key->base, key->prime, NULL); | |
175 | return err; | |
176 | } | |
177 | ||
178 | ||
179 | int dh_make_key_ex_main(prng_state *prng, int wprng, dh_key *key) | |
180 | { | |
181 | unsigned char *buf; | |
182 | int err, keysize; | |
183 | ||
184 | LTC_ARGCHK(key != NULL); | |
185 | LTC_ARGCHK(key->prime != NULL); | |
186 | LTC_ARGCHK(key->base != NULL); | |
187 | ||
188 | /* init parameters */ | |
189 | if ((err = mp_init_multi(&key->x, &key->y, NULL)) != CRYPT_OK) { | |
190 | goto error; | |
191 | } | |
192 | ||
193 | keysize = dh_get_size(key); | |
194 | if (keysize < 96) { | |
195 | return CRYPT_INVALID_KEYSIZE; | |
196 | } | |
197 | ||
138 | 198 | /* allocate buffer */ |
139 | 199 | buf = XMALLOC(keysize); |
140 | 200 | if (buf == NULL) { |
142 | 202 | } |
143 | 203 | |
144 | 204 | /* make up random string */ |
145 | if ( rng_make_prng( keysize, wprng, prng, NULL) != CRYPT_OK) { | |
146 | err = CRYPT_ERROR_READPRNG; | |
205 | if ( (err = rng_make_prng( keysize, wprng, prng, NULL)) != CRYPT_OK) { | |
206 | /*err = CRYPT_ERROR_READPRNG;*/ | |
147 | 207 | goto error2; |
148 | 208 | } |
149 | 209 | |
152 | 212 | goto error2; |
153 | 213 | } |
154 | 214 | |
155 | /* init parameters */ | |
156 | if ((err = mp_init_multi(&g, &p, &key->x, &key->y, NULL)) != CRYPT_OK) { | |
157 | goto error; | |
158 | } | |
159 | ||
160 | if ((err = mp_read_radix(g, sets[key->idx].base, 64)) != CRYPT_OK) { goto error; } | |
161 | if ((err = mp_read_radix(p, sets[key->idx].prime, 64)) != CRYPT_OK) { goto error; } | |
162 | ||
163 | 215 | /* load the x value */ |
164 | if ((err = mp_read_unsigned_bin(key->x, buf, keysize)) != CRYPT_OK) { goto error; } | |
165 | if ((err = mp_exptmod(g, key->x, p, key->y)) != CRYPT_OK) { goto error; } | |
216 | if ((err = mp_read_unsigned_bin(key->x, buf, keysize)) != CRYPT_OK) { goto error; } | |
217 | if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { goto error; } | |
166 | 218 | key->type = PK_PRIVATE; |
167 | 219 | |
168 | 220 | /* free up ram */ |
169 | 221 | err = CRYPT_OK; |
170 | 222 | goto done; |
171 | 223 | error: |
172 | mp_clear_multi(key->x, key->y, NULL); | |
224 | mp_clear_multi(key->base, key->prime, key->x, key->y, NULL); | |
173 | 225 | done: |
174 | mp_clear_multi(p, g, NULL); | |
175 | 226 | error2: |
176 | 227 | #ifdef LTC_CLEAN_STACK |
177 | 228 | zeromem(buf, keysize); |
187 | 238 | void dh_free(dh_key *key) |
188 | 239 | { |
189 | 240 | LTC_ARGCHKVD(key != NULL); |
241 | if ( key->base ) { | |
242 | mp_clear( key->base ); | |
243 | key->base = NULL; | |
244 | } | |
245 | if ( key->prime ) { | |
246 | mp_clear( key->prime ); | |
247 | key->prime = NULL; | |
248 | } | |
190 | 249 | if ( key->x ) { |
191 | mp_clear( key->x ); | |
192 | key->x = NULL; | |
250 | mp_clear( key->x ); | |
251 | key->x = NULL; | |
193 | 252 | } |
194 | 253 | if ( key->y ) { |
195 | mp_clear( key->y ); | |
196 | key->y = NULL; | |
254 | mp_clear( key->y ); | |
255 | key->y = NULL; | |
197 | 256 | } |
198 | 257 | } |
199 | 258 | |
228 | 287 | |
229 | 288 | /* header */ |
230 | 289 | out[y++] = type; |
231 | out[y++] = (unsigned char)(sets[key->idx].size / 8); | |
290 | out[y++] = key->idx == SUPPLIED_PRIME ? | |
291 | SUPPLIED_PRIME : | |
292 | (unsigned char)(sets[key->idx].size / 8); | |
232 | 293 | |
233 | 294 | /* export y */ |
234 | 295 | OUTPUT_BIGNUM(key->y, out, y, z); |
237 | 298 | /* export x */ |
238 | 299 | OUTPUT_BIGNUM(key->x, out, y, z); |
239 | 300 | } |
301 | /* export g and p */ | |
302 | if (key->idx == SUPPLIED_PRIME) { | |
303 | OUTPUT_BIGNUM(key->base, out, y, z); | |
304 | OUTPUT_BIGNUM(key->prime, out, y, z); | |
305 | } | |
240 | 306 | |
241 | 307 | /* store header */ |
242 | 308 | packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_KEY); |
244 | 310 | /* store len */ |
245 | 311 | *outlen = y; |
246 | 312 | return CRYPT_OK; |
313 | } | |
314 | ||
315 | /** | |
316 | Import a DH key from a binary string | |
317 | @param in The string to read | |
318 | @param inlen The length of the input packet | |
319 | @param type The type of key. PK_PRIVATE or PK_PUBLIC | |
320 | @param base The base (generator) in hex string | |
321 | @param prime The prime in hex string | |
322 | @param key [out] Where to import the key to | |
323 | @return CRYPT_OK if successful, on error all allocated memory is freed automatically | |
324 | */ | |
325 | int dh_import_raw(unsigned char *in, unsigned long inlen, int type, | |
326 | const char *base, const char *prime, dh_key *key) | |
327 | { | |
328 | int err; | |
329 | ||
330 | LTC_ARGCHK(in != NULL); | |
331 | LTC_ARGCHK(base != NULL); | |
332 | LTC_ARGCHK(prime != NULL); | |
333 | LTC_ARGCHK(key != NULL); | |
334 | ||
335 | if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, NULL)) != CRYPT_OK) { | |
336 | goto error; | |
337 | } | |
338 | if ((err = mp_read_radix(key->base, base, 16)) != CRYPT_OK) { goto error; } | |
339 | if ((err = mp_read_radix(key->prime, prime, 16)) != CRYPT_OK) { goto error; } | |
340 | key->idx = SUPPLIED_PRIME; | |
341 | ||
342 | if (type == PK_PRIVATE) { | |
343 | /* load the x value */ | |
344 | if ((err = mp_read_unsigned_bin(key->x, in, inlen)) != CRYPT_OK) { goto error; } | |
345 | if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { goto error; } | |
346 | key->type = PK_PRIVATE; | |
347 | } else { | |
348 | /* load the y value */ | |
349 | if ((err = mp_read_unsigned_bin(key->y, in, inlen)) != CRYPT_OK) { goto error; } | |
350 | key->type = PK_PUBLIC; | |
351 | mp_clear(key->x); | |
352 | key->x = NULL; | |
353 | } | |
354 | key->idx = SUPPLIED_PRIME; | |
355 | return CRYPT_OK; | |
356 | error: | |
357 | mp_clear_multi(key->y, key->x, key->base, key->prime, NULL); | |
358 | return err; | |
247 | 359 | } |
248 | 360 | |
249 | 361 | /** |
255 | 367 | */ |
256 | 368 | int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key) |
257 | 369 | { |
258 | unsigned long x, y, s; | |
370 | long x, y, s; | |
259 | 371 | int err; |
260 | 372 | |
261 | 373 | LTC_ARGCHK(in != NULL); |
272 | 384 | } |
273 | 385 | |
274 | 386 | /* init */ |
275 | if ((err = mp_init_multi(&key->x, &key->y, NULL)) != CRYPT_OK) { | |
387 | if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, NULL)) != CRYPT_OK) { | |
276 | 388 | return err; |
277 | 389 | } |
278 | 390 | |
283 | 395 | key->type = (int)in[y++]; |
284 | 396 | |
285 | 397 | /* key size in bytes */ |
286 | s = (unsigned long)in[y++] * 8; | |
287 | ||
288 | for (x = 0; (s > (unsigned long)sets[x].size) && (sets[x].size != 0); x++); | |
289 | if (sets[x].size == 0) { | |
290 | err = CRYPT_INVALID_KEYSIZE; | |
291 | goto error; | |
292 | } | |
293 | key->idx = (int)x; | |
398 | s = (int)in[y++]; | |
399 | ||
400 | if (s == SUPPLIED_PRIME) { | |
401 | /* key from provided p,g values */ | |
402 | key->idx = SUPPLIED_PRIME; | |
403 | } else { | |
404 | s *= 8; | |
405 | for (x = 0; (s > sets[x].size) && (sets[x].size != 0); x++); | |
406 | if (sets[x].size == 0) { | |
407 | err = CRYPT_INVALID_KEYSIZE; | |
408 | goto error; | |
409 | } | |
410 | key->idx = (int)x; | |
411 | if ((err = mp_read_radix(key->base, (char *)sets[x].base, 64)) != CRYPT_OK) { goto error; } | |
412 | if ((err = mp_read_radix(key->prime, (char *)sets[x].prime, 64)) != CRYPT_OK) { goto error; } | |
413 | } | |
294 | 414 | |
295 | 415 | /* type check both values */ |
296 | 416 | if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE)) { |
309 | 429 | |
310 | 430 | if (key->type == PK_PRIVATE) { |
311 | 431 | INPUT_BIGNUM(key->x, in, x, y, inlen); |
432 | /* if idx = SUPPLIED_PRIME then prime is not from static table */ | |
433 | } | |
434 | if (key->idx == SUPPLIED_PRIME) { | |
435 | INPUT_BIGNUM(key->base, in, x, y, inlen); | |
436 | INPUT_BIGNUM(key->prime, in, x, y, inlen); | |
312 | 437 | } |
313 | 438 | |
314 | 439 | /* eliminate private key if public */ |
319 | 444 | |
320 | 445 | return CRYPT_OK; |
321 | 446 | error: |
322 | mp_clear_multi(key->y, key->x, NULL); | |
447 | mp_clear_multi(key->y, key->x, key->base, key->prime, NULL); | |
323 | 448 | return err; |
324 | 449 | } |
325 | 450 | |
334 | 459 | int dh_shared_secret(dh_key *private_key, dh_key *public_key, |
335 | 460 | unsigned char *out, unsigned long *outlen) |
336 | 461 | { |
337 | void *tmp, *p; | |
462 | void *tmp; | |
338 | 463 | unsigned long x; |
339 | 464 | int err; |
340 | 465 | |
354 | 479 | } |
355 | 480 | |
356 | 481 | /* compute y^x mod p */ |
357 | if ((err = mp_init_multi(&tmp, &p, NULL)) != CRYPT_OK) { | |
482 | if ((err = mp_init(&tmp)) != CRYPT_OK) { | |
358 | 483 | return err; |
359 | 484 | } |
360 | 485 | |
361 | if ((err = mp_read_radix(p, (char *)sets[private_key->idx].prime, 64)) != CRYPT_OK) { goto error; } | |
362 | if ((err = mp_exptmod(public_key->y, private_key->x, p, tmp)) != CRYPT_OK) { goto error; } | |
486 | if ((err = mp_exptmod(public_key->y, private_key->x, private_key->prime, tmp)) != CRYPT_OK) { goto error; } | |
363 | 487 | |
364 | 488 | /* enough space for output? */ |
365 | 489 | x = (unsigned long)mp_unsigned_bin_size(tmp); |
373 | 497 | goto done; |
374 | 498 | error: |
375 | 499 | done: |
376 | mp_clear_multi(p, tmp, NULL); | |
500 | mp_clear(tmp); | |
377 | 501 | return err; |
378 | 502 | } |
379 | 503 |
151 | 151 | { |
152 | 152 | int x; |
153 | 153 | |
154 | if (n == SUPPLIED_PRIME) | |
155 | return 1; | |
154 | 156 | for (x = 0; sets[x].size; x++); |
155 | 157 | if ((n < 0) || (n >= x)) { |
156 | 158 | return 0; |
68 | 68 | y += x; \ |
69 | 69 | } |
70 | 70 | |
71 | #define SUPPLIED_PRIME 255 | |
72 | ||
71 | 73 | static void packet_store_header (unsigned char *dst, int section, int subsection) |
72 | 74 | { |
73 | 75 | LTC_ARGCHKVD(dst != NULL); |
77 | 77 | } |
78 | 78 | |
79 | 79 | /* make a random key and export the public copy */ |
80 | if ((err = dh_make_key(prng, wprng, dh_get_size(key), &pubkey)) != CRYPT_OK) { | |
80 | pubkey.idx = key->idx; | |
81 | if ((err = mp_init_multi(&pubkey.base, &pubkey.prime, NULL)) != CRYPT_OK) { | |
82 | goto LBL_ERR; | |
83 | } | |
84 | if ((err = mp_copy(key->base, pubkey.base)) != CRYPT_OK) { goto LBL_ERR; } | |
85 | if ((err = mp_copy(key->prime, pubkey.prime)) != CRYPT_OK) { goto LBL_ERR; } | |
86 | if ((err = dh_make_key_ex_main(prng, wprng, &pubkey)) != CRYPT_OK) { | |
81 | 87 | goto LBL_ERR; |
82 | 88 | } |
83 | 89 | |
306 | 312 | unsigned char *out, unsigned long *outlen, |
307 | 313 | prng_state *prng, int wprng, dh_key *key) |
308 | 314 | { |
309 | void *a, *b, *k, *m, *g, *p, *p1, *tmp; | |
315 | void *a, *b, *k, *m, *p1, *tmp; | |
310 | 316 | unsigned char *buf; |
311 | 317 | unsigned long x, y; |
312 | 318 | int err; |
337 | 343 | * since the order of the group is prime |
338 | 344 | * we need not check if gcd(k, r) is 1 |
339 | 345 | */ |
340 | if (prng_descriptor[wprng].read(buf, sets[key->idx].size, prng) != | |
341 | (unsigned long)(sets[key->idx].size)) { | |
346 | if (prng_descriptor[wprng].read(buf, dh_get_size(key), prng) != | |
347 | (unsigned long)(dh_get_size(key))) { | |
342 | 348 | err = CRYPT_ERROR_READPRNG; |
343 | 349 | goto LBL_ERR_1; |
344 | 350 | } |
345 | 351 | |
346 | 352 | /* init bignums */ |
347 | if ((err = mp_init_multi(&a, &b, &k, &m, &p, &g, &p1, &tmp, NULL)) != CRYPT_OK) { | |
348 | goto LBL_ERR; | |
349 | } | |
350 | ||
351 | /* load k and m */ | |
352 | if ((err = mp_read_unsigned_bin(m, (unsigned char *)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } | |
353 | if ((err = mp_read_unsigned_bin(k, buf, sets[key->idx].size)) != CRYPT_OK) { goto LBL_ERR; } | |
354 | ||
355 | /* load g, p and p1 */ | |
356 | if ((err = mp_read_radix(g, sets[key->idx].base, 64)) != CRYPT_OK) { goto LBL_ERR; } | |
357 | if ((err = mp_read_radix(p, sets[key->idx].prime, 64)) != CRYPT_OK) { goto LBL_ERR; } | |
358 | if ((err = mp_sub_d(p, 1, p1)) != CRYPT_OK) { goto LBL_ERR; } | |
359 | if ((err = mp_div_2(p1, p1)) != CRYPT_OK) { goto LBL_ERR; } /* p1 = (p-1)/2 */ | |
360 | ||
353 | if ((err = mp_init_multi(&a, &b, &k, &m, &p1, &tmp, NULL)) != CRYPT_OK) { | |
354 | goto LBL_ERR; | |
355 | } | |
356 | ||
357 | /* load k, m and p1 */ | |
358 | if ((err = mp_read_unsigned_bin(m, (unsigned char *)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } | |
359 | if ((err = mp_read_unsigned_bin(k, buf, dh_get_size(key))) != CRYPT_OK) { goto LBL_ERR; } | |
360 | if ((err = mp_sub_d(key->prime, 1, p1)) != CRYPT_OK) { goto LBL_ERR; } | |
361 | if ((err = mp_div_2(p1, p1)) != CRYPT_OK) { goto LBL_ERR; } /* p1 = (p-1)/2 */ | |
361 | 362 | /* now get a = g^k mod p */ |
362 | if ((err = mp_exptmod(g, k, p, a)) != CRYPT_OK) { goto LBL_ERR; } | |
363 | if ((err = mp_exptmod(key->base, k, key->prime, a)) != CRYPT_OK) { goto LBL_ERR; } | |
363 | 364 | |
364 | 365 | /* now find M = xa + kb mod p1 or just b = (M - xa)/k mod p1 */ |
365 | if ((err = mp_invmod(k, p1, k)) != CRYPT_OK) { goto LBL_ERR; } /* k = 1/k mod p1 */ | |
366 | if ((err = mp_invmod(k, p1, k)) != CRYPT_OK) { goto LBL_ERR; } /* k = 1/k mod p1 */ | |
366 | 367 | if ((err = mp_mulmod(a, key->x, p1, tmp)) != CRYPT_OK) { goto LBL_ERR; } /* tmp = xa */ |
367 | 368 | if ((err = mp_submod(m, tmp, p1, tmp)) != CRYPT_OK) { goto LBL_ERR; } /* tmp = M - xa */ |
368 | 369 | if ((err = mp_mulmod(k, tmp, p1, b)) != CRYPT_OK) { goto LBL_ERR; } /* b = (M - xa)/k */ |
399 | 400 | |
400 | 401 | err = CRYPT_OK; |
401 | 402 | LBL_ERR: |
402 | mp_clear_multi(tmp, p1, g, p, m, k, b, a, NULL); | |
403 | mp_clear_multi(tmp, p1, m, k, b, a, NULL); | |
403 | 404 | LBL_ERR_1: |
404 | 405 | |
405 | 406 | XFREE(buf); |
448 | 449 | y = PACKET_SIZE; |
449 | 450 | |
450 | 451 | /* init all bignums */ |
451 | if ((err = mp_init_multi(&a, &p, &b, &g, &m, &tmp, NULL)) != CRYPT_OK) { | |
452 | if ((err = mp_init_multi(&a, &b, &m, &tmp, NULL)) != CRYPT_OK) { | |
452 | 453 | return err; |
453 | 454 | } |
454 | 455 | |
456 | 457 | INPUT_BIGNUM(a, sig, x, y, siglen); |
457 | 458 | INPUT_BIGNUM(b, sig, x, y, siglen); |
458 | 459 | |
459 | /* load p and g */ | |
460 | if ((err = mp_read_radix(p, sets[key->idx].prime, 64)) != CRYPT_OK) { goto error1; } | |
461 | if ((err = mp_read_radix(g, sets[key->idx].base, 64)) != CRYPT_OK) { goto error1; } | |
462 | ||
463 | 460 | /* load m */ |
464 | 461 | if ((err = mp_read_unsigned_bin(m, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error1; } |
465 | 462 | |
466 | 463 | /* find g^m mod p */ |
467 | if ((err = mp_exptmod(g, m, p, m)) != CRYPT_OK) { goto error1; } /* m = g^m mod p */ | |
464 | if ((err = mp_exptmod(key->base, m, key->prime, m)) != CRYPT_OK) { goto error1; } /* m = g^m mod p */ | |
468 | 465 | |
469 | 466 | /* find y^a * a^b */ |
470 | if ((err = mp_exptmod(key->y, a, p, tmp)) != CRYPT_OK) { goto error1; } /* tmp = y^a mod p */ | |
471 | if ((err = mp_exptmod(a, b, p, a)) != CRYPT_OK) { goto error1; } /* a = a^b mod p */ | |
472 | if ((err = mp_mulmod(a, tmp, p, a)) != CRYPT_OK) { goto error1; } /* a = y^a * a^b mod p */ | |
467 | if ((err = mp_exptmod(key->y, a, key->prime, tmp)) != CRYPT_OK) { goto error1; } /* tmp = y^a mod p */ | |
468 | if ((err = mp_exptmod(a, b, key->prime, a)) != CRYPT_OK) { goto error1; } /* a = a^b mod p */ | |
469 | if ((err = mp_mulmod(a, tmp, key->prime, a)) != CRYPT_OK) { goto error1; } /* a = y^a * a^b mod p */ | |
473 | 470 | |
474 | 471 | /* y^a * a^b == g^m ??? */ |
475 | 472 | if (mp_cmp(a, m) == 0) { |
482 | 479 | error1: |
483 | 480 | error: |
484 | 481 | done: |
485 | mp_clear_multi(tmp, m, g, p, b, a, NULL); | |
482 | mp_clear_multi(tmp, m, b, a, NULL); | |
486 | 483 | return err; |
487 | 484 | } |
488 | 485 |
Binary diff not shown
Binary diff not shown
Binary diff not shown
Binary diff not shown
0 | 0 | use strict; |
1 | 1 | use warnings; |
2 | use Test::More tests => 28; | |
2 | use Test::More tests => 74; | |
3 | 3 | |
4 | 4 | use Crypt::PK::DH qw(dh_encrypt dh_decrypt dh_sign_message dh_verify_message dh_sign_hash dh_verify_hash dh_shared_secret); |
5 | 5 | |
26 | 26 | } |
27 | 27 | |
28 | 28 | { |
29 | my $k; | |
30 | ||
31 | $k = Crypt::PK::DH->new('t/data/cryptx_priv_dh_pg1.bin'); | |
32 | ok($k, 'load cryptx_priv_dh_pg1.bin'); | |
33 | ok($k->is_private, 'is_private cryptx_priv_dh_pg1.bin'); | |
34 | is($k->size, 256, 'size'); | |
35 | is(uc($k->key2hash->{x}), '29BB37065071D1C23AE0D8C555E24E5E546954B985260ECC6A1A21252FCFD2D633B0580F6A00B80ED75123EC37A3E784F888EE026C1034CD930CA58464EB6A59A090D1113855AFA48C9A79631E2534D7F33FAD4DC8FF48E88C865E517B67DAD4B40D64BD67CBFE52F56FBC6764D0629E5EFF63351AF19FF398375BDCE22FBDF3A044DAB2B6EAAA44D1A78F4FF74088175E6B5F184222F116F4C6188547F90B0ADCA3255EA7148CB57E5E852E79F438F995CFC3AC79A01D2C329C0750D55FDADCC6FAF6D6850892EEC073FD77CC7F98D8D317D402E2A89E4161001DAEF43DAC0F386E48870D457FB12CC5B70E6F5719609631CB8B439DB6D2F04CF8A774678F68', 'key2hash'); | |
36 | ||
37 | $k = Crypt::PK::DH->new('t/data/cryptx_priv_dh_pg2.bin'); | |
38 | ok($k, 'load cryptx_priv_dh_pg2.bin'); | |
39 | ok($k->is_private, 'is_private cryptx_priv_dh_pg2.bin'); | |
40 | ||
41 | $k = Crypt::PK::DH->new('t/data/cryptx_pub_dh_pg1.bin'); | |
42 | ok($k, 'load cryptx_pub_dh_pg1.bin'); | |
43 | ok(!$k->is_private, 'is_private cryptx_pub_dh_pg1.bin'); | |
44 | ||
45 | $k = Crypt::PK::DH->new('t/data/cryptx_pub_dh_pg2.bin'); | |
46 | ok($k, 'load cryptx_pub_dh_pg2.bin'); | |
47 | ok(!$k->is_private, 'is_private cryptx_pub_dh_pg2.bin'); | |
48 | } | |
49 | ||
50 | { | |
29 | 51 | my $pr1 = Crypt::PK::DH->new; |
30 | 52 | $pr1->import_key('t/data/cryptx_priv_dh1.bin'); |
31 | 53 | my $pu1 = Crypt::PK::DH->new; |
50 | 72 | my $pu2 = Crypt::PK::DH->new; |
51 | 73 | $pu2->import_key('t/data/cryptx_pub_dh2.bin'); |
52 | 74 | |
75 | my $ss1 = $pr1->shared_secret($pu2); | |
76 | my $ss2 = $pr2->shared_secret($pu1); | |
77 | is(unpack("H*",$ss1), unpack("H*",$ss2), 'shared_secret'); | |
78 | } | |
79 | ||
80 | { | |
81 | my $pr1 = Crypt::PK::DH->new; | |
82 | $pr1->import_key('t/data/cryptx_priv_dh_pg1.bin'); | |
83 | my $pu1 = Crypt::PK::DH->new; | |
84 | $pu1->import_key('t/data/cryptx_pub_dh_pg1.bin'); | |
85 | ||
86 | my $ct = $pu1->encrypt("secret message"); | |
87 | my $pt = $pr1->decrypt($ct); | |
88 | ok(length $ct > 100, 'encrypt ' . length($ct)); | |
89 | is($pt, "secret message", 'decrypt'); | |
90 | ||
91 | my $sig = $pr1->sign_message("message"); | |
92 | ok(length $sig > 60, 'sign_message ' . length($sig)); | |
93 | ok($pu1->verify_message($sig, "message"), 'verify_message'); | |
94 | ||
95 | my $hash = pack("H*","04624fae618e9ad0c5e479f62e1420c71fff34dd"); | |
96 | $sig = $pr1->sign_hash($hash, 'SHA1'); | |
97 | ok(length $sig > 60, 'sign_hash ' . length($sig)); | |
98 | ok($pu1->verify_hash($sig, $hash, 'SHA1'), 'verify_hash'); | |
99 | ||
100 | my $pr2 = Crypt::PK::DH->new; | |
101 | $pr2->import_key('t/data/cryptx_priv_dh_pg2.bin'); | |
102 | my $pu2 = Crypt::PK::DH->new; | |
103 | $pu2->import_key('t/data/cryptx_pub_dh_pg2.bin'); | |
104 | ||
105 | my $ss1 = $pr1->shared_secret($pu2); | |
106 | my $ss2 = $pr2->shared_secret($pu1); | |
107 | is(unpack("H*",$ss1), unpack("H*",$ss2), 'shared_secret'); | |
108 | } | |
109 | ||
110 | { | |
111 | my $pr1 = Crypt::PK::DH->new; | |
112 | $pr1->import_key_raw(pack('H*','5F7EF8D4F7D80C2D88ADADDFE57F4F4DC578259E3B5F42D82838D5905FF6D2BECDC489452D3F5807EF4E2361821089DDC9B27198D79E9C22EE249318688FE250CCC69E49C5F985777405A76264C5EF0D83AEA1C368B1E1A48DC0E04D6E0C884F0C95A3949B29A05437A6179E7AADCC4D095A55C03046296C02AA9991EFD17745615726D52B8B8A12DAC7218265DBB4B760176C27E644AD2EC15B238980326BE1B27D5AC28EA2B2DC5F24FD6A315CA2193A23370B130B541D54C470AD91BE20ECD697B01C2DAEE00E0027A9EBD2D87404E20ADE1DE3B92798928B837AC5EFB305C168823D362A1162C7A709A70E6619F01AF113E316376B3561F88AC2B6F647B2'),'private','ike2048'); | |
113 | my $pu1 = Crypt::PK::DH->new; | |
114 | $pu1->import_key_raw(pack('H*','4B9ECB56202EDBC6578072A4519EBE625DE8972877462240F62393C59A6C04AA159E56505156E7DF645FF6EC588E0778A96B78B26A0793D90A4B5C5EC4C61EA69D21C630843ACC2BFD3864CD9DA9600BA8F1B7D8542B01F7251AA3AC257C7AC65A1D2BCF51A8E3E67D9544599B0956710E2B052CDA9B565CDD121CC123364B480E9E7E2237D3D6B5B1E200C7BF858C54CCD3175736DB28336210A16F8F0ACEC08847EF7905FAB7E97E626CFD13CBDF167441FEEB72CB6E7407DFC59F03249F79312A94DA89B1D61196B41E90C08D2C801FD7BEA02A47A1CDA1581F57BA700C1BCDDE6338718E19079055194CAF176D85464957D405B04CC3DD9756C211E11BF2'),'public','ike2048'); | |
115 | ok($pr1, 'import_key_raw private1'); | |
116 | ok($pu1, 'import_key_raw public1'); | |
117 | ok($pr1->is_private, 'is_private private1'); | |
118 | ok(!$pu1->is_private, 'is_private public1'); | |
119 | is(uc(unpack('H*',$pr1->export_key_raw('private'))),'5F7EF8D4F7D80C2D88ADADDFE57F4F4DC578259E3B5F42D82838D5905FF6D2BECDC489452D3F5807EF4E2361821089DDC9B27198D79E9C22EE249318688FE250CCC69E49C5F985777405A76264C5EF0D83AEA1C368B1E1A48DC0E04D6E0C884F0C95A3949B29A05437A6179E7AADCC4D095A55C03046296C02AA9991EFD17745615726D52B8B8A12DAC7218265DBB4B760176C27E644AD2EC15B238980326BE1B27D5AC28EA2B2DC5F24FD6A315CA2193A23370B130B541D54C470AD91BE20ECD697B01C2DAEE00E0027A9EBD2D87404E20ADE1DE3B92798928B837AC5EFB305C168823D362A1162C7A709A70E6619F01AF113E316376B3561F88AC2B6F647B2'); | |
120 | is(uc(unpack('H*',$pr1->export_key_raw('public'))),'4B9ECB56202EDBC6578072A4519EBE625DE8972877462240F62393C59A6C04AA159E56505156E7DF645FF6EC588E0778A96B78B26A0793D90A4B5C5EC4C61EA69D21C630843ACC2BFD3864CD9DA9600BA8F1B7D8542B01F7251AA3AC257C7AC65A1D2BCF51A8E3E67D9544599B0956710E2B052CDA9B565CDD121CC123364B480E9E7E2237D3D6B5B1E200C7BF858C54CCD3175736DB28336210A16F8F0ACEC08847EF7905FAB7E97E626CFD13CBDF167441FEEB72CB6E7407DFC59F03249F79312A94DA89B1D61196B41E90C08D2C801FD7BEA02A47A1CDA1581F57BA700C1BCDDE6338718E19079055194CAF176D85464957D405B04CC3DD9756C211E11BF2'); | |
121 | is(uc(unpack('H*',$pu1->export_key_raw('public'))),'4B9ECB56202EDBC6578072A4519EBE625DE8972877462240F62393C59A6C04AA159E56505156E7DF645FF6EC588E0778A96B78B26A0793D90A4B5C5EC4C61EA69D21C630843ACC2BFD3864CD9DA9600BA8F1B7D8542B01F7251AA3AC257C7AC65A1D2BCF51A8E3E67D9544599B0956710E2B052CDA9B565CDD121CC123364B480E9E7E2237D3D6B5B1E200C7BF858C54CCD3175736DB28336210A16F8F0ACEC08847EF7905FAB7E97E626CFD13CBDF167441FEEB72CB6E7407DFC59F03249F79312A94DA89B1D61196B41E90C08D2C801FD7BEA02A47A1CDA1581F57BA700C1BCDDE6338718E19079055194CAF176D85464957D405B04CC3DD9756C211E11BF2'); | |
122 | ||
123 | my $ct = $pu1->encrypt("secret message"); | |
124 | my $pt = $pr1->decrypt($ct); | |
125 | ok(length $ct > 100, 'encrypt ' . length($ct)); | |
126 | is($pt, "secret message", 'decrypt'); | |
127 | ||
128 | my $sig = $pr1->sign_message("message"); | |
129 | ok(length $sig > 60, 'sign_message ' . length($sig)); | |
130 | ok($pu1->verify_message($sig, "message"), 'verify_message'); | |
131 | ||
132 | my $hash = pack("H*","04624fae618e9ad0c5e479f62e1420c71fff34dd"); | |
133 | $sig = $pr1->sign_hash($hash, 'SHA1'); | |
134 | ok(length $sig > 60, 'sign_hash ' . length($sig)); | |
135 | ok($pu1->verify_hash($sig, $hash, 'SHA1'), 'verify_hash'); | |
136 | ||
137 | my $pr2 = Crypt::PK::DH->new; | |
138 | $pr2->import_key_raw(pack('H*','473156C909EBB0A6F61F707CDDD7E6401BFDE22BC57B8D3CCC30C4CD3FF7678CCD9B022167AA774786F367FE5B5924A3C1E09AA71264F94E7ABA87FFA888913BB9592613F8AD87FBE82E99064B00CE3294CFD410BCFB4C88A46F5F8532633458C317DF40F395C2F08A822D84BF4291A1A63DE1F6D0F460DB81C685ADD0F26262307823227C17B4671BCF74A6337738BB4596337644656A060F1BB109640878D23F56E493719D6EF60FEA7AC85123CFB6E476392789AC1FE4F4CA371DB2863192ADE424F3EFDEE52D4CB445B99B10566A4B6F6DC813C265DC0052D710AEAA0969392BD478A46AB9C7A0E2FA27964A759938904FCEFAC4CE061C9927764AAB57DC'),'private','ike2048'); | |
139 | my $pu2 = Crypt::PK::DH->new; | |
140 | $pu2->import_key_raw(pack('H*','774A01FF19C1603040DFBB5C8A44F11CE8719F757C2AF6B2921EDDDEF27F77D5F2DAF9539BCBCB30F80D76E054C489C9E6533051767E6220539C871F23D3B6F80D84037A6FBAB3AE6AF8F214A60A816D6F0F6C3F31801DCD6EA771F41A2A5618BC333D650F46F22FEA81A94F4E00CD05B83F8FE257A2607E62519D9BF8B8C96D0587FB2BCEC8D18DDCF66EBBB8A56623953531EE27C68C8C37E6413FD2C98339F491A0472E5D4DFADC7BF30E89A2CE2081EE3CF9F9B0FFCD902A3021CAC14A4AD7E00F6202C8A9AB93BF96E33838FB9178DC8A8F995ABD81F28F5A137A78E813ABD185498A3A50CB3021CF58BE9D0200C19928AA097D306ABAD9874E0F217482'),'public','ike2048'); | |
141 | ||
53 | 142 | my $ss1 = $pr1->shared_secret($pu2); |
54 | 143 | my $ss2 = $pr2->shared_secret($pu1); |
55 | 144 | is(unpack("H*",$ss1), unpack("H*",$ss2), 'shared_secret'); |
62 | 151 | ok($k->is_private, 'is_private'); |
63 | 152 | ok($k->export_key('private'), 'export_key_pem pri'); |
64 | 153 | ok($k->export_key('public'), 'export_key_pem pub'); |
154 | } | |
155 | ||
156 | { | |
157 | my $k = Crypt::PK::DH->new; | |
158 | $k->generate_key({g => 2, p => 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF'}); | |
159 | ok($k, 'generate_key'); | |
160 | ok($k->is_private, 'is_private'); | |
161 | ok($k->export_key('private'), 'export_key_pem pri gp'); | |
162 | ok($k->export_key('public'), 'export_key_pem pub gp'); | |
163 | } | |
164 | ||
165 | { | |
166 | my $k = Crypt::PK::DH->new; | |
167 | $k->generate_key('ike2048'); | |
168 | ok($k, 'generate_key'); | |
169 | ok($k->is_private, 'is_private'); | |
170 | ok($k->export_key('private'), 'export_key_pem pri ike2048'); | |
171 | ok($k->export_key('public'), 'export_key_pem pub ike2048'); | |
65 | 172 | } |
66 | 173 | |
67 | 174 | { |
81 | 188 | my $ss2 = dh_shared_secret('t/data/cryptx_priv_dh2.bin', 't/data/cryptx_pub_dh1.bin'); |
82 | 189 | is(unpack("H*",$ss1), unpack("H*",$ss2), 'shared_secret'); |
83 | 190 | } |
191 | ||
192 | { | |
193 | my $ct = dh_encrypt('t/data/cryptx_pub_dh_pg1.bin', 'test string'); | |
194 | ok($ct, 'dh_encrypt'); | |
195 | my $pt = dh_decrypt('t/data/cryptx_priv_dh_pg1.bin', $ct); | |
196 | ok($pt, 'dh_decrypt'); | |
197 | my $sig = dh_sign_message('t/data/cryptx_priv_dh_pg1.bin', 'test string'); | |
198 | ok($sig, 'dh_sign_message'); | |
199 | ok(dh_verify_message('t/data/cryptx_pub_dh_pg1.bin', $sig, 'test string'), 'dh_verify_message'); | |
200 | my $hash = pack("H*","04624fae618e9ad0c5e479f62e1420c71fff34dd"); | |
201 | $sig = dh_sign_hash('t/data/cryptx_priv_dh_pg1.bin', $hash, 'SHA1'); | |
202 | ok($sig, 'dh_sign_hash'); | |
203 | ok(dh_verify_hash('t/data/cryptx_pub_dh_pg1.bin', $sig, $hash, 'SHA1'), 'dh_verify_hash'); | |
204 | ||
205 | my $ss1 = dh_shared_secret('t/data/cryptx_priv_dh_pg1.bin', 't/data/cryptx_pub_dh_pg2.bin'); | |
206 | my $ss2 = dh_shared_secret('t/data/cryptx_priv_dh_pg2.bin', 't/data/cryptx_pub_dh_pg1.bin'); | |
207 | is(unpack("H*",$ss1), unpack("H*",$ss2), 'shared_secret'); | |
208 | } |