JunkBox_Lib++ (for Windows) 1.10.1
Loading...
Searching...
No Matches
dh_tool.cpp
Go to the documentation of this file.
1
25#include "dh_tool.h"
26
27
28#ifdef ENABLE_SSL
29
30/*
31###############################################################################################
32for OpenSSL3
33see https://stackoverflow.com/questions/71551116/openssl-3-diffie-hellman-key-exchange-c
34see https://github.com/eugen15/diffie-hellman-cpp
35###############################################################################################
36*/
37
38
40// Diffie-Hellman 鍵交換法
41//
42
57int save_DHspki_with_private(Buffer pki, FILE* fp, DH* dhkey)
58{
59 unsigned int md;
60 Buffer pv;
61
62 if (fp==NULL || dhkey==NULL) return FALSE;
63
65 if (!save_tagged_Buffer(pki, fp, md, FALSE)) return FALSE;
66
67 pv = get_DHprivatekey(dhkey);
68 if (pv.buf==NULL) return FALSE;
69
71 if (!save_tagged_Buffer(pv, fp, md, FALSE)) return FALSE;
72 free_Buffer(&pv);
73
74 return TRUE;
75}
76
77
87Buffer read_DHspki_with_private(FILE* fp, DH** p_dhkey)
88{
89 int n = 0, code;
90 unsigned int md;
91 Buffer pp, pv, pk, gk, yk;
92
93 pp = init_Buffer();
94 if (fp==NULL) return pp;
95
97 pp = read_tagged_Buffer(fp, &md);
98 if (pp.buf==NULL) return pp;
99
100 if (*p_dhkey!=NULL) DH_free(*p_dhkey);
101 *p_dhkey = DH_new();
102 if (*p_dhkey==NULL) {
103 free_Buffer(&pp);
104 return pp;
105 }
106
107 pk = get_DHPkey(pp);
108 gk = get_DHGkey(pp);
109 yk = get_DHYkey(pp);
110
111#if OPENSSL_VERSION_NUMBER < 0x10101000L
112 // v1.1.0
113 (*p_dhkey)->p = BN_bin2bn((const unsigned char*)(pk.buf), pk.vldsz, NULL);
114 (*p_dhkey)->g = BN_bin2bn((const unsigned char*)(gk.buf), gk.vldsz, NULL);
115 (*p_dhkey)->pub_key = BN_bin2bn((const unsigned char*)(yk.buf), yk.vldsz, NULL);
116#else
117 // v1.1.1
118 BIGNUM* dhp_bn = BN_bin2bn((const unsigned char*)(pk.buf), pk.vldsz, NULL);
119 BIGNUM* dhg_bn = BN_bin2bn((const unsigned char*)(gk.buf), gk.vldsz, NULL);
120 BIGNUM* dhy_bn = BN_bin2bn((const unsigned char*)(gk.buf), gk.vldsz, NULL);
121
122 if (dhp_bn!=NULL && dhg_bn!=NULL && dhy_bn!=NULL) {
123 DH_set0_pqg(*p_dhkey, dhp_bn, NULL, dhg_bn);
124 DH_set0_key(*p_dhkey, dhy_bn, NULL);
125 }
126 else {
127 DH_free(*p_dhkey);
128 *p_dhkey = NULL;
129 }
130#endif
131
132 free_Buffer(&pk);
133 free_Buffer(&gk);
134 free_Buffer(&yk);
135
136 // 鍵のチェック
137 if (*p_dhkey!=NULL) n = DH_check(*p_dhkey, &code);
138 if (n!=1 || code!=0) {
139 if (*p_dhkey!=NULL) DH_free(*p_dhkey);
140 free_Buffer(&pp);
141 return pp;
142 }
143
144 // Private KEY の読み込み
146 pv = read_tagged_Buffer(fp, &md);
147 if (pv.buf==NULL) {
148 if (*p_dhkey!=NULL) DH_free(*p_dhkey);
149 free_Buffer(&pp);
150 return pp;
151 }
152
153#if OPENSSL_VERSION_NUMBER < 0x10101000L
154 (*p_dhkey)->priv_key = BN_bin2bn((const unsigned char*)(pv.buf), pv.vldsz, NULL);
155#else
156 BIGNUM* priv_key = BN_bin2bn((const unsigned char*)(pv.buf), pv.vldsz, NULL);
157 DH_set0_key(*p_dhkey, NULL, priv_key);
158#endif
159
160 free_Buffer(&pv);
161
162 return pp;
163}
164
165
186Buffer get_DHspki_ff(char* filename, int ks, DH** p_dhkey)
187{
188 Buffer pki;
189 FILE* fp;
190
191 pki = init_Buffer();
192 if (filename==NULL || p_dhkey==NULL) return pki;
193
194 if (file_exist(filename)) {
195 //DEBUG_MODE PRINT_MESG("Load DH public key. ");
196 fp = fopen(filename, "rb");
197 pki = read_DHspki_with_private(fp, p_dhkey);
198 fclose(fp);
199 //DEBUG_MODE PRINT_MESG("... done.\n");
200 if (pki.buf!=NULL) {
201#if OPENSSL_VERSION_NUMBER < 0x10101000L
202 if (DH_size(*p_dhkey)<(ks+7)/8 || (*p_dhkey)->priv_key==NULL) free_Buffer(&pki); // v1.1.0
203#else
204 const BIGNUM* priv_key = DH_get0_priv_key(*p_dhkey);
205 if (DH_size(*p_dhkey)<(ks+7)/8 || priv_key==NULL) free_Buffer(&pki); // v1.1.0
206#endif
207 }
208 }
209
210 if (pki.buf==NULL) {
211 //DEBUG_MODE PRINT_MESG("Generate DH public key.");
212 pki = gen_DHspki(ks, p_dhkey);
213 //DEBUG_MODE PRINT_MESG("... done.\n");
214
215 fp = file_chmod_open(filename, (char*)"w", S_IRUSR | S_IWUSR);
216 if (fp!=NULL) {
217 save_DHspki_with_private(pki, fp, *p_dhkey);
218 fclose(fp);
219 }
220 }
221
222 //DEBUG_MODE {
223 // Buffer enc;
224 // enc = encode_base64_Buffer(pki);
225 // DEBUG_MESG("SPKI = [%s]\n", enc.buf);
226 // free_Buffer(&enc);
227 //}
228 return pki;
229}
230
231
242Buffer gen_DHspki(int ks, DH** p_dhkey)
243{
244 int sz, n, code;
245 Buffer px, pp, pk;
246
247 pk = init_Buffer();
248 if (p_dhkey==NULL) return pk;
249
250 //if (!RAND_load_file("/dev/random", 1024)) return pk;
251 //DEBUG_MODE PRINT_MESG("Load /dev/urandom.\n");
252 if (!RAND_load_file("/dev/urandom", 1024)) return pk;
253
254 //DEBUG_MODE PRINT_MESG("Generate parameters.\n");
255 do {
256 if (*p_dhkey!=NULL) DH_free(*p_dhkey);
257 *p_dhkey = DH_new();
258
259#if OPENSSL_VERSION_NUMBER < 0x10101000L
260 *p_dhkey = DH_generate_parameters(ks, DH_GENERATOR_2, NULL, NULL);
261#else
262 n = DH_generate_parameters_ex(*p_dhkey, ks, DH_GENERATOR_2, NULL);
263#endif
264 n = DH_check(*p_dhkey, &code);
265 } while (n!=1 || code!=0);
266
267 //DEBUG_MODE PRINT_MESG("Generate key.\n");
268 sz = DH_generate_key(*p_dhkey); // 公開鍵(DH->pub_key)と秘密鍵(DH->priv_key)の生成
269 if (sz==0) {
270 DH_free(*p_dhkey);
271 *p_dhkey = NULL;
272 return pk;
273 }
274
275 //DEBUG_MODE PRINT_MESG("Check key size.\n");
276 sz = i2d_DHparams(*p_dhkey, NULL); // パラメタのサイズを検査
277 pp = px = make_Buffer(sz); // パラメタを入れるメモリを確保
278 if (pp.buf==NULL) {
279 DH_free(*p_dhkey);
280 *p_dhkey = NULL;
281 return pk;
282 }
283 pp.vldsz = i2d_DHparams(*p_dhkey, &(px.buf)); // パラメタ(P,G鍵)を DER形式へ.pp.bufに格納.
284 // px.bufは破壊される.
285
286#if OPENSSL_VERSION_NUMBER < 0x10101000L
287 sz = BN_num_bytes((*p_dhkey)->pub_key);
288#else
289 const BIGNUM* pub_key = DH_get0_pub_key(*p_dhkey);
290 sz = BN_num_bytes(pub_key);
291#endif
292
293 px = make_Buffer(sz);
294 if (px.buf==NULL) {
295 DH_free(*p_dhkey);
296 *p_dhkey = NULL;
297 free_Buffer(&pp);
298 return pk;
299 }
300
301#if OPENSSL_VERSION_NUMBER < 0x10101000L
302 px.vldsz = BN_bn2bin((*p_dhkey)->pub_key, px.buf);
303#else
304 px.vldsz = BN_bn2bin(pub_key, px.buf);
305#endif
306
307 pk = join_DHpubkey(pp, px); // pp -> DHパラメタ(P,G鍵), px-> Y鍵
308
309 free_Buffer(&pp);
310 free_Buffer(&px);
311
312 return pk;
313}
314
315
328Buffer gen_DHspki_fs(Buffer pki, DH** p_dhkey)
329{
330 int sz, n = 0, code;
331 Buffer px, pp, pk;
332 Buffer pkey, gkey;
333
334 //
335 pk = init_Buffer();
336 if (p_dhkey==NULL) return pk;
337 //
338 if (*p_dhkey!=NULL) DH_free(*p_dhkey);
339 *p_dhkey = DH_new();
340 if (*p_dhkey==NULL) return pk;
341
342 pkey = get_DHPkey(pki);
343 gkey = get_DHGkey(pki);
344 if (pkey.buf==NULL || gkey.buf==NULL) {
345 free_Buffer(&pkey);
346 free_Buffer(&gkey);
347 DH_free(*p_dhkey);
348 *p_dhkey = NULL;
349 return pk;
350 }
351
352#if OPENSSL_VERSION_NUMBER < 0x10101000L
353 (*p_dhkey)->p = BN_bin2bn((const unsigned char*)(pkey.buf), pkey.vldsz, NULL);
354 (*p_dhkey)->g = BN_bin2bn((const unsigned char*)(gkey.buf), gkey.vldsz, NULL);
355#else
356 BIGNUM* dhp_bn = BN_bin2bn((const unsigned char*)(pkey.buf), pkey.vldsz, NULL);
357 BIGNUM* dhg_bn = BN_bin2bn((const unsigned char*)(gkey.buf), gkey.vldsz, NULL);
358 //
359 if (dhp_bn!=NULL && dhg_bn!=NULL) {
360 DH_set0_pqg(*p_dhkey, dhp_bn, NULL, dhg_bn);
361 }
362 else {
363 DH_free(*p_dhkey);
364 *p_dhkey = NULL;
365 }
366 //BN_free(dhp_bn); // DHkeyの中身も消えてしまうので ここでは freeしない
367 //BN_free(dhg_bn);
368#endif
369
370 free_Buffer(&pkey);
371 free_Buffer(&gkey);
372
373 //
374 if (*p_dhkey!=NULL) n = DH_check(*p_dhkey, &code);
375 if (n!=1 || code!=0) {
376 if (*p_dhkey!=NULL) DH_free(*p_dhkey);
377 *p_dhkey = NULL;
378 return pk;
379 }
380
381 sz = DH_generate_key(*p_dhkey);
382 if (sz==0) {
383 DH_free(*p_dhkey);
384 *p_dhkey = NULL;
385 return pk;
386 }
387
388 //
389 sz = i2d_DHparams(*p_dhkey, NULL); // パラメタのサイズを検査
390 pp = px = make_Buffer(sz); // パラメタを入れるメモリを確保
391 if (pp.buf==NULL) {
392 DH_free(*p_dhkey);
393 *p_dhkey = NULL;
394 return pk;
395 }
396 pp.vldsz = i2d_DHparams(*p_dhkey, &(px.buf)); // パラメタ(P,G鍵)を DER形式へ.pp.bufに格納.
397 // px.bufは破壊される.
398#if OPENSSL_VERSION_NUMBER < 0x10101000L
399 sz = BN_num_bytes((*p_dhkey)->pub_key);
400#else
401 const BIGNUM* pub_key = DH_get0_pub_key(*p_dhkey);
402 sz = BN_num_bytes(pub_key);
403#endif
404
405 px = make_Buffer(sz);
406 if (px.buf==NULL) {
407 DH_free(*p_dhkey);
408 *p_dhkey = NULL;
409 free_Buffer(&pp);
410 return px;
411 }
412
413#if OPENSSL_VERSION_NUMBER < 0x10101000L
414 px.vldsz = BN_bn2bin((*p_dhkey)->pub_key, px.buf); // 公開鍵(Y鍵)の DER形式
415#else
416 px.vldsz = BN_bn2bin(pub_key, px.buf); // 公開鍵(Y鍵)の DER形式
417#endif
418
419 pk = join_DHpubkey(pp, px); // pp -> DHパラメタ(P,G鍵), px-> Y鍵
420
421 free_Buffer(&pp);
422 free_Buffer(&px);
423
424 return pk;
425}
426
427
442Buffer get_DHsharedkey(Buffer pki, DH* dhkey)
443{
444 Buffer ykey, skey;
445
446 skey = init_Buffer();
447 ykey = get_DHYkey(pki);
448 if (ykey.buf==NULL) return skey;
449
450 skey = get_DHsharedkey_fY(ykey, dhkey);
451
452 free_Buffer(&ykey);
453 return skey;
454}
455
456
471Buffer get_DHsharedkey_fY(Buffer ykey, DH* dhkey)
472{
473 int sz;
474 Buffer buf;
475
476 buf = init_Buffer();
477 if (dhkey==NULL) return buf;
478
479 BIGNUM* yk = BN_bin2bn((const unsigned char*)(ykey.buf), ykey.vldsz, NULL);
480
481 sz = DH_size(dhkey);
482 buf = make_Buffer(sz);
483 buf.vldsz = sz;
484
485 BN_free(yk);
486 return buf;
487}
488
489
510Buffer get_DHYkey(Buffer param)
511{
512 int i, lp, sz=0;
513 Buffer pp;
514 pp = init_Buffer();
515
516 sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
517 if (sz<0) return pp;
518
519 sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
520 if (sz<0) return pp;
521 sz = sz + lp;
522
523 sz = skip_DER_node(param, JBXL_ASN1_BIT, sz, &lp);
524 if (sz<0) return pp;
525 sz++; // for Seed(0x00)
526
527 sz = skip_DER_node(param, JBXL_ASN1_INT, sz, &lp);
528 if (sz<0) return pp;
529
530 pp = make_Buffer(lp);
531 if (pp.buf==NULL) return pp;
532 for (i=0; i<lp; i++) pp.buf[i] = param.buf[sz+i];
533 pp.vldsz = lp;
534 return pp;
535}
536
537
558Buffer get_DHPkey(Buffer param)
559{
560 int i, lp, sz=0;
561 Buffer pp;
562 pp = init_Buffer();
563
564 sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
565 if (sz<0) return pp;
566
567 sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
568 if (sz<0) return pp;
569
570 sz = skip_DER_node(param, JBXL_ASN1_OBJ, sz, &lp);
571 if (sz<0) return pp;
572 sz = sz + lp;
573
574 sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
575 if (sz<0) return pp;
576
577 sz = skip_DER_node(param, JBXL_ASN1_INT, sz, &lp);
578 if (sz<0) return pp;
579
580 pp = make_Buffer(lp);
581 if (pp.buf==NULL) return pp;
582 for (i=0; i<lp; i++) pp.buf[i] = param.buf[sz+i];
583 pp.vldsz = lp;
584 return pp;
585}
586
587
609Buffer get_DHGkey(Buffer param)
610{
611 int i, lp, sz=0;
612 Buffer pp;
613 pp = init_Buffer();
614
615 sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
616 if (sz<0) return pp;
617
618 sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
619 if (sz<0) return pp;
620
621 sz = skip_DER_node(param, JBXL_ASN1_OBJ, sz, &lp);
622 if (sz<0) return pp;
623 sz = sz + lp;
624
625 sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
626 if (sz<0) return pp;
627
628 sz = skip_DER_node(param, JBXL_ASN1_INT, sz, &lp);
629 if (sz<0) return pp;
630 sz = sz + lp;
631
632 sz = skip_DER_node(param, JBXL_ASN1_INT, sz, &lp);
633 if (sz<0) return pp;
634
635 pp = make_Buffer(lp);
636 if (pp.buf==NULL) return pp;
637 for (i=0; i<lp; i++) pp.buf[i] = param.buf[sz+i];
638 pp.vldsz = lp;
639 return pp;
640}
641
642
663Buffer get_DHalgorism(Buffer param)
664{
665 int i, lp, sz=0;
666 Buffer pp;
667 pp = init_Buffer();
668
669 sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
670 if (sz<0) return pp;
671
672 sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
673 if (sz<0) return pp;
674
675 sz = skip_DER_node(param, JBXL_ASN1_OBJ, sz, &lp);
676 if (sz<0) return pp;
677
678 pp = make_Buffer(lp);
679 if (pp.buf==NULL) return pp;
680 for (i=0; i<lp; i++) pp.buf[i] = param.buf[sz+i];
681 pp.vldsz = lp;
682 return pp;
683}
684
685
694Buffer get_DHprivatekey(DH* dhkey)
695{
696 int sz;
697 Buffer pv;
698
699#if OPENSSL_VERSION_NUMBER < 0x10101000L
700 sz = BN_num_bytes(dhkey->priv_key);
701//#elif OPENSSL_VERSION_NUMBER < 0x30000000L
702#else
703 const BIGNUM* priv_key = DH_get0_pub_key(dhkey);
704 sz = BN_num_bytes(priv_key);
705#endif
706
707 pv = make_Buffer(sz);
708 if (pv.buf==NULL) return pv;
709
710#if OPENSSL_VERSION_NUMBER < 0x10101000L
711 pv.vldsz = BN_bn2bin(dhkey->priv_key, pv.buf);
712//#elif OPENSSL_VERSION_NUMBER < 0xF0000000L
713#else
714 pv.vldsz = BN_bn2bin(priv_key, pv.buf);
715#endif
716
717 return pv;
718}
719
720
753Buffer join_DHpubkey(Buffer param, Buffer key)
754{
755// unsigned char dh_algor[]={0x06,0x07,0x2a,0x86,0x48,0xce,0x3e,0x02,0x01}; // DH ?
756 unsigned char dh_algor[]={0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x03,0x01}; // RSA ?
757 // ↑ RSAアルゴリズム?
758 int len_dh_algor = 11;
759
760 int ls, lp, la, sz;
761 Buffer px, pp, pm;
762
763 // [P鍵 + G鍵] → pp
764 pp = init_Buffer();
765 sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, 0, &lp);
766 if (sz<0) return pp;
767
768 pp.buf = param.buf + sz;
769 pp.bufsz = param.bufsz - sz;
770 pp.vldsz = param.vldsz - sz;
771
772 // [鍵サイズ] → pm
773 px = int2bin_DER(key.vldsz*8-1);
774 pm = node2DER(px, JBXL_ASN1_INT);
775 ls = pm.vldsz;
776 free_Buffer(&px);
777
778 // pp[P鍵 + G鍵] + pm[鍵サイズ] → pm
779 px = make_Buffer(lp+ls);
780 memcpy(px.buf, pp.buf, lp);
781 memcpy(px.buf+lp, pm.buf, ls);
782 px.vldsz = lp + ls;
783 free_Buffer(&pm); // ppを freeしてはいけない
785 ls = pm.vldsz;
786 free_Buffer(&px);
787
788 // dh_algor[アルゴリズム] + pm[P鍵 + G鍵 + 鍵サイズ] → px
789 la = len_dh_algor;
790 pp = make_Buffer(ls+la);
791 memcpy(pp.buf, dh_algor, la);
792 memcpy(pp.buf+la, pm.buf, ls);
793 pp.vldsz = ls + la;
794 free_Buffer(&pm);
796 ls = px.vldsz;
797 free_Buffer(&pp);
798
799 // px[アルゴリズム + P鍵 + G鍵 + 鍵サイズ] + pp[Y鍵] → pm
800 pm = node2DER(key, JBXL_ASN1_INT);
801 pp = node2DER(pm, JBXL_ASN1_BIT);
802 lp = pp.vldsz;
803 free_Buffer(&pm);
804 pm = make_Buffer(ls+lp);
805 memcpy(pm.buf, px.buf, ls);
806 memcpy(pm.buf+ls, pp.buf, lp);
807 pm.vldsz = ls + lp;
808 free_Buffer(&px);
809 free_Buffer(&pp);
810
812 free_Buffer(&pm);
813 return pp;
814}
815
816#endif
#define JBXL_ASN1_BIT
BIT_STRING.
Definition asn1_node.h:24
#define JBXL_ASN1_INT
INTEGER.
Definition asn1_node.h:23
#define JBXL_ASN1_OBJ
OBJECT_IDENTIFIER.
Definition asn1_node.h:27
#define JBXL_ASN1_SEQ_CNSTRCTD
SEQUENCE + CONSTRUCTED (構造化フラグ)
Definition asn1_node.h:52
Buffer int2bin_DER(long int n)
Buffer node2DER(Buffer pt, unsigned char node)
Definition asn1_tool.cpp:70
int skip_DER_node(Buffer param, unsigned char node, int ls, int *lp)
Definition asn1_tool.cpp:34
Buffer make_Buffer(int sz)
Buffer型変数のバッファ部をつくり出す.
Definition buffer.cpp:71
void free_Buffer(Buffer *buf)
Buffer型変数のバッファ部を解放する
Definition buffer.cpp:128
Buffer init_Buffer()
初期化したBuffer型変数を返す.
Definition buffer.cpp:47
#define TRUE
Definition common.h:226
#define FALSE
Definition common.h:223
int bufsz
確保してあるバッファの大きさ - 1.
Definition buffer.h:36
int vldsz
データの長さ.バイナリデータの場合も使用可能.文字列の場合は 0x00 を含まない.
Definition buffer.h:37
unsigned char * buf
バッファの先頭へのポインタ.str[bufsz]は必ず 0x00となる.
Definition buffer.h:39
int file_exist(const char *fn)
ファイルの存在を検査する.
Definition tools.cpp:2337
FILE * file_chmod_open(const char *fn, const char *fm, mode_t mode)
ファイルの許可属性をmode へ変更した後,ファイルを fmモードでオープン
Definition tools.cpp:2366
int save_tagged_Buffer(Buffer buf, FILE *fp, unsigned int mode, int prfm)
Bufferを指定された形式に従ってタグ付きでファイルに保存する.
Definition xtools.cpp:956
Buffer read_tagged_Buffer(FILE *fp, unsigned int *mode)
save_tagged_Buffer() で保存したファイルから,Buffer をタグに従って読み込む.
Definition xtools.cpp:1013
#define JBXL_FIO_ORIGINAL
Definition xtools.h:27
#define JBXL_FIO_PRIV_KEY
Definition xtools.h:23
#define JBXL_FIO_SPKI
Definition xtools.h:25