dgk.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. /**
  2. \file dgk.cpp
  3. \author Daniel Demmler
  4. \copyright Copyright (C) 2019 ENCRYPTO Group, TU Darmstadt
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU Lesser General Public License as published
  7. by the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. ABY is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. \brief libdgk - v0.9
  16. A library implementing the DGK crypto system with full decryption
  17. Thanks to Marina Blanton for sharing her Miracl DGK implementation from
  18. M. Blanton and P. Gasti, "Secure and efficient protocols for iris and fingerprint identification" (ESORICS’11)
  19. with us. We used it as a template for this GMP version.
  20. The implementation structure was inspired by
  21. libpailler - A library implementing the Paillier crypto system. (http://hms.isi.jhu.edu/acsc/libpaillier/)
  22. */
  23. #include "dgk.h"
  24. #include "../powmod.h"
  25. #include "../utils.h"
  26. #include <cstdlib>
  27. #include <cstring>
  28. #define DGK_CHECKSIZE 0
  29. // number of test encryptions and decryptions that are performed to verify a generated key. This will take time, but more are better.
  30. #define KEYTEST_ITERATIONS 1000
  31. //array holding the powers of two
  32. mpz_t* powtwo;
  33. //array for holding temporary values
  34. mpz_t* gvpvqp;
  35. void dgk_complete_pubkey(unsigned int modulusbits, unsigned int lbits, dgk_pubkey_t** pub, mpz_t n, mpz_t g, mpz_t h) {
  36. *pub = (dgk_pubkey_t*) malloc(sizeof(dgk_pubkey_t));
  37. mpz_init((*pub)->n);
  38. mpz_init((*pub)->u);
  39. mpz_init((*pub)->h);
  40. mpz_init((*pub)->g);
  41. mpz_set((*pub)->n, n);
  42. mpz_setbit((*pub)->u, 2 * lbits + 2);
  43. mpz_set((*pub)->g, g);
  44. mpz_set((*pub)->h, h);
  45. (*pub)->bits = modulusbits;
  46. (*pub)->lbits = 2 * lbits + 2;
  47. }
  48. void dgk_keygen(unsigned int modulusbits, unsigned int lbits, dgk_pubkey_t** pub, dgk_prvkey_t** prv) {
  49. mpz_t tmp, tmp2, f1, f2, exp1, exp2, exp3, xp, xq;
  50. unsigned int found = 0, i;
  51. //printf("Keygen %u %u\n", modulusbits, lbits);
  52. /* allocate the new key structures */
  53. *pub = (dgk_pubkey_t*) malloc(sizeof(dgk_pubkey_t));
  54. *prv = (dgk_prvkey_t*) malloc(sizeof(dgk_prvkey_t));
  55. /* initialize our integers */
  56. mpz_init((*pub)->n);
  57. mpz_init((*pub)->u);
  58. mpz_init((*pub)->h);
  59. mpz_init((*pub)->g);
  60. mpz_init((*prv)->vp);
  61. mpz_init((*prv)->vq);
  62. mpz_init((*prv)->p);
  63. mpz_init((*prv)->q);
  64. mpz_init((*prv)->p_minusone);
  65. mpz_init((*prv)->q_minusone);
  66. mpz_init((*prv)->pinv);
  67. mpz_init((*prv)->qinv);
  68. mpz_inits(tmp, tmp2, f1, f2, exp1, exp2, exp3, xp, xq, NULL);
  69. lbits = lbits * 2 + 2; // plaintext space needs to 2l+2 in our use case. probably not needed for general use, but four our MT generation.
  70. (*pub)->bits = modulusbits;
  71. (*pub)->lbits = lbits;
  72. // vp and vq are primes
  73. aby_prng((*prv)->vp, 160);
  74. mpz_nextprime((*prv)->vp, (*prv)->vp);
  75. aby_prng((*prv)->vq, 160);
  76. do {
  77. mpz_nextprime((*prv)->vq, (*prv)->vq);
  78. } while (mpz_cmp((*prv)->vp, (*prv)->vq) == 0);
  79. // u = 2^lbits. u is NOT a prime (different from original DGK to allow full and easy decryption. See Blanton/Gasti Paper for details).
  80. mpz_setbit((*pub)->u, lbits);
  81. // p
  82. while (!found) {
  83. aby_prng(f1, modulusbits / 2 - 160 - lbits);
  84. mpz_nextprime(f1, f1);
  85. mpz_mul((*prv)->p, (*pub)->u, (*prv)->vp);
  86. mpz_mul((*prv)->p, f1, (*prv)->p);
  87. mpz_add_ui((*prv)->p, (*prv)->p, 1);
  88. found = mpz_probab_prime_p((*prv)->p, 50);
  89. }
  90. found = 0;
  91. // q
  92. while (!found) {
  93. aby_prng(f2, modulusbits / 2 - 159 - lbits);
  94. mpz_nextprime(f2, f2);
  95. mpz_mul((*prv)->q, (*pub)->u, (*prv)->vq);
  96. mpz_mul((*prv)->q, f2, (*prv)->q);
  97. mpz_add_ui((*prv)->q, (*prv)->q, 1);
  98. found = mpz_probab_prime_p((*prv)->q, 50);
  99. }
  100. found = 0;
  101. // p-1, q-1 - this is currently not used
  102. mpz_sub_ui((*prv)->p_minusone, (*prv)->p, 1);
  103. mpz_sub_ui((*prv)->q_minusone, (*prv)->q, 1);
  104. // n = pq
  105. mpz_mul((*pub)->n, (*prv)->p, (*prv)->q);
  106. mpz_setbit(exp1, lbits - 1);
  107. mpz_mul(exp1, (*prv)->vp, exp1);
  108. mpz_mul(exp1, f1, exp1);
  109. mpz_mul(exp2, (*prv)->vp, (*pub)->u);
  110. mpz_mul(exp3, f1, (*pub)->u);
  111. // xp
  112. while (!found) {
  113. aby_prng(xp, mpz_sizeinbase((*prv)->p, 2) + 128);
  114. mpz_mod(xp, xp, (*prv)->p);
  115. mpz_powm(tmp, xp, exp1, (*prv)->p);
  116. if (mpz_cmp_ui(tmp, 1) != 0) {
  117. mpz_powm(tmp, xp, exp2, (*prv)->p);
  118. if (mpz_cmp_ui(tmp, 1) != 0) {
  119. mpz_powm(tmp, xp, exp3, (*prv)->p);
  120. if (mpz_cmp_ui(tmp, 1) != 0) {
  121. found = 1;
  122. }
  123. }
  124. }
  125. }
  126. found = 0;
  127. mpz_setbit(exp1, lbits - 1);
  128. mpz_mul(exp1, (*prv)->vq, exp1);
  129. mpz_mul(exp1, f2, exp1);
  130. mpz_mul(exp2, (*prv)->vq, (*pub)->u);
  131. mpz_mul(exp3, f2, (*pub)->u);
  132. // xq
  133. while (!found) {
  134. aby_prng(xq, mpz_sizeinbase((*prv)->q, 2) + 128);
  135. mpz_mod(xq, xq, (*prv)->q);
  136. mpz_powm(tmp, xq, exp1, (*prv)->q);
  137. if (mpz_cmp_ui(tmp, 1) != 0) {
  138. mpz_powm(tmp, xq, exp2, (*prv)->q);
  139. if (mpz_cmp_ui(tmp, 1) != 0) {
  140. mpz_powm(tmp, xq, exp3, (*prv)->q);
  141. if (mpz_cmp_ui(tmp, 1) != 0) {
  142. found = 1;
  143. }
  144. }
  145. }
  146. }
  147. // compute CRT: g = xp*q*(q^{-1} mod p) + xq*p*(p^{-1} mod q) mod n
  148. mpz_invert(tmp, (*prv)->q, (*prv)->p); // tmp = 1/q % p
  149. mpz_set((*prv)->qinv, tmp);
  150. mpz_mul(tmp, tmp, (*prv)->q); // tmp = tmp * q
  151. // tmp = xp*tmp % n
  152. mpz_mul(tmp, xp, tmp);
  153. mpz_mod(tmp, tmp, (*pub)->n);
  154. mpz_invert(tmp2, (*prv)->p, (*prv)->q); // tmp1 = 1/p % q
  155. mpz_set((*prv)->pinv, tmp2);
  156. mpz_mul(tmp2, tmp2, (*prv)->p); // tmp1 = tmp1*p
  157. // tmp1 = xq*tmp1 % n
  158. mpz_mul(tmp2, xq, tmp2);
  159. mpz_mod(tmp2, tmp2, (*pub)->n);
  160. // g = xp + xq % n
  161. mpz_add((*pub)->g, xq, xp);
  162. mpz_mod((*pub)->g, (*pub)->g, (*pub)->n);
  163. mpz_mul(tmp, f1, f2); // tmp = f1*f2
  164. mpz_powm((*pub)->g, (*pub)->g, tmp, (*pub)->n); // g = g^tmp % n
  165. aby_prng((*pub)->h, mpz_sizeinbase((*pub)->n, 2) + 128);
  166. mpz_mod((*pub)->h, (*pub)->h, (*pub)->n);
  167. mpz_mul(tmp, tmp, (*pub)->u);
  168. mpz_powm((*pub)->h, (*pub)->h, tmp, (*pub)->n); // h = h^tmp % n
  169. powtwo = (mpz_t*) malloc(sizeof(mpz_t) * lbits);
  170. gvpvqp = (mpz_t*) malloc(sizeof(mpz_t) * lbits);
  171. // array holding powers of two
  172. for (i = 0; i < lbits; i++) {
  173. mpz_init(powtwo[i]);
  174. mpz_setbit(powtwo[i], i);
  175. }
  176. mpz_powm(f1, (*pub)->g, (*prv)->vp, (*prv)->p); // gvpvq
  177. mpz_sub_ui(tmp2, (*pub)->u, 1); // tmp1 = u - 1
  178. for (i = 0; i < lbits; i++) {
  179. mpz_init(gvpvqp[i]);
  180. mpz_powm(gvpvqp[i], f1, powtwo[i], (*prv)->p);
  181. mpz_powm(gvpvqp[i], gvpvqp[i], tmp2, (*prv)->p);
  182. }
  183. /* clear temporary integers */
  184. mpz_clears(tmp, tmp2, f1, f2, exp1, exp2, exp3, xp, xq, NULL);
  185. }
  186. void dgk_encrypt_db(mpz_t res, dgk_pubkey_t* pub, mpz_t plaintext) {
  187. mpz_t r;
  188. mpz_init(r);
  189. #if DGK_CHECKSIZE
  190. mpz_setbit(r, (pub->lbits-2)/2);
  191. if (mpz_cmp(plaintext, r) >= 0) {
  192. gmp_printf("m: %Zd\nmax:%Zd\n", plaintext, r);
  193. printf("DGK WARNING: m too big!\n");
  194. }
  195. #endif
  196. /* pick random blinding factor r */
  197. aby_prng(r, 400); // 2.5 * 160 = 400 bit
  198. dbpowmod(res, pub->h, r, pub->g, plaintext, pub->n);
  199. mpz_clear(r);
  200. }
  201. void dgk_encrypt_fb(mpz_t res, dgk_pubkey_t* pub, mpz_t plaintext) {
  202. mpz_t r;
  203. mpz_init(r);
  204. #if DGK_CHECKSIZE
  205. mpz_setbit(r, (pub->lbits-2)/2);
  206. if (mpz_cmp(plaintext, r) >= 0) {
  207. gmp_printf("m: %Zd\nmax:%Zd\n", plaintext, r);
  208. printf("DGK WARNING: m too big!\n");
  209. }
  210. #endif
  211. /* pick random blinding factor r */
  212. aby_prng(r, 400); // 2.5 * 160 = 400 bit
  213. fbpowmod_h(r, r); //r = h^r
  214. fbpowmod_g(res, plaintext); //res = g^plaintext
  215. mpz_mul(res, res, r);
  216. mpz_mod(res, res, pub->n);
  217. mpz_clear(r);
  218. }
  219. void dgk_encrypt_plain(mpz_t res, dgk_pubkey_t* pub, mpz_t plaintext) {
  220. mpz_t r;
  221. mpz_init(r);
  222. #if DGK_CHECKSIZE
  223. mpz_setbit(r, (pub->lbits-2)/2);
  224. if (mpz_cmp(plaintext, r) >= 0) {
  225. gmp_printf("m: %Zd\nmax:%Zd\n", plaintext, r);
  226. printf("DGK WARNING: m too big!\n");
  227. }
  228. #endif
  229. /* pick random blinding factor r */
  230. aby_prng(r, 400); // 2.5 * 160 = 400 bit
  231. mpz_powm(r, pub->h, r, pub->n);
  232. mpz_powm(res, pub->g, plaintext, pub->n);
  233. mpz_mul(res, res, r);
  234. mpz_mod(res, res, pub->n);
  235. mpz_clear(r);
  236. }
  237. void dgk_encrypt_crt_db(mpz_t res, dgk_pubkey_t * pub, dgk_prvkey_t * prv, mpz_t plaintext) {
  238. mpz_t r, ep;
  239. mpz_inits(r, ep, NULL);
  240. #if DGK_CHECKSIZE
  241. mpz_setbit(r, (pub->lbits-2)/2);
  242. if (mpz_cmp(plaintext, r) >= 0) {
  243. gmp_printf("m: %Zd\nmax:%Zd\n", plaintext, r);
  244. printf("DGK WARNING: m too big!\n");
  245. }
  246. #endif
  247. /* pick random blinding factor r */
  248. //mpz_urandomb(r, rnd, 400); // 2.5 * 160 = 400 bit
  249. aby_prng(r, 400);
  250. dbpowmod(ep, pub->h, r, pub->g, plaintext, prv->p);
  251. mpz_mul(res, ep, prv->q);
  252. mpz_mul(res, res, prv->qinv);
  253. mpz_mod(res, res, pub->n);
  254. dbpowmod(ep, pub->h, r, pub->g, plaintext, prv->q);
  255. mpz_mul(ep, ep, prv->p);
  256. mpz_mul(ep, ep, prv->pinv);
  257. mpz_mod(ep, ep, pub->n);
  258. mpz_add(res, res, ep);
  259. mpz_mod(res, res, pub->n);
  260. mpz_clears(r, ep, NULL);
  261. }
  262. void dgk_encrypt_crt(mpz_t res, dgk_pubkey_t * pub, dgk_prvkey_t * prv, mpz_t plaintext) {
  263. mpz_t r, ep, eq;
  264. mpz_inits(r, ep, eq, NULL);
  265. #if DGK_CHECKSIZE
  266. mpz_setbit(r, (pub->lbits-2)/2);
  267. if (mpz_cmp(plaintext, r) >= 0) {
  268. gmp_printf("m: %Zd\nmax:%Zd\n", plaintext, r);
  269. printf("DGK WARNING: m too big!\n");
  270. }
  271. #endif
  272. /* pick random blinding factor r */
  273. aby_prng(r, 400); // 2.5 * 160 = 400 bit
  274. // ep = h^r * g^plaintext % p
  275. mpz_powm(ep, pub->h, r, prv->p);
  276. mpz_powm(res, pub->g, plaintext, prv->p);
  277. mpz_mul(ep, ep, res);
  278. mpz_mod(ep, ep, prv->p);
  279. mpz_mul(res, ep, prv->q);
  280. mpz_mul(res, res, prv->qinv);
  281. mpz_mod(res, res, pub->n);
  282. // ep = h^r*g^plaintext % q
  283. mpz_powm(ep, pub->h, r, prv->q);
  284. mpz_powm(eq, pub->g, plaintext, prv->q);
  285. mpz_mul(ep, ep, eq);
  286. mpz_mod(ep, ep, prv->q);
  287. mpz_mul(ep, ep, prv->p);
  288. mpz_mul(ep, ep, prv->pinv);
  289. mpz_mod(ep, ep, pub->n);
  290. mpz_add(res, res, ep);
  291. mpz_mod(res, res, pub->n);
  292. mpz_clears(r, ep, eq, NULL);
  293. }
  294. void dgk_decrypt(mpz_t res, dgk_pubkey_t* pub, dgk_prvkey_t* prv, mpz_t ciphertext) {
  295. mpz_t y, yi;
  296. mpz_inits(y, yi, NULL);
  297. unsigned int i, xi[pub->lbits];
  298. mpz_powm(y, ciphertext, prv->vp, prv->p);
  299. mpz_set_ui(res, 0);
  300. for (i = 0; i < pub->lbits; i++) {
  301. mpz_powm(yi, y, powtwo[pub->lbits - 1 - i], prv->p);
  302. if (mpz_cmp_ui(yi, 1) == 0) {
  303. xi[i] = 0;
  304. } else {
  305. xi[i] = 1;
  306. mpz_mul(y, y, gvpvqp[i]);
  307. mpz_mod(y, y, prv->p);
  308. }
  309. }
  310. for (i = 0; i < pub->lbits; i++) {
  311. if (xi[i] == 1) {
  312. mpz_add(res, powtwo[i], res);
  313. }
  314. }
  315. mpz_clears(y, yi, NULL);
  316. }
  317. void dgk_freepubkey(dgk_pubkey_t* pub) {
  318. mpz_clears(pub->n, pub->u, pub->g, pub->h, NULL);
  319. free(pub);
  320. }
  321. void dgk_freeprvkey(dgk_prvkey_t* prv) {
  322. mpz_clears(prv->p, prv->q, prv->vp, prv->vq, prv->qinv, prv->pinv, prv->p_minusone, prv->q_minusone, NULL);
  323. free(prv);
  324. }
  325. void dgk_storekey(unsigned int modulusbits, unsigned int lbits, dgk_pubkey_t* pub, dgk_prvkey_t* prv) {
  326. FILE *fp;
  327. char smod[5];
  328. char slbit[4];
  329. char name[40] = "dgk_key_";
  330. const char* div = "_";
  331. const char* ext = ".bin";
  332. sprintf(smod, "%d", modulusbits);
  333. sprintf(slbit, "%d", lbits);
  334. strcat(name, smod);
  335. strcat(name, div);
  336. strcat(name, slbit);
  337. strcat(name, ext);
  338. printf("writing dgk key to %s\n", name);
  339. fp = fopen(name, "w");
  340. mpz_out_raw(fp, prv->p);
  341. mpz_out_raw(fp, prv->q);
  342. mpz_out_raw(fp, prv->vp);
  343. mpz_out_raw(fp, prv->vq);
  344. mpz_out_raw(fp, prv->pinv);
  345. mpz_out_raw(fp, prv->qinv);
  346. mpz_out_raw(fp, pub->n);
  347. mpz_out_raw(fp, pub->u);
  348. mpz_out_raw(fp, pub->g);
  349. mpz_out_raw(fp, pub->h);
  350. fclose(fp);
  351. }
  352. void dgk_readkey(unsigned int modulusbits, unsigned int lbits, dgk_pubkey_t** pub, dgk_prvkey_t** prv) {
  353. unsigned int i;
  354. mpz_t f1, tmp;
  355. mpz_inits(f1, tmp, NULL);
  356. char smod[5];
  357. char slbit[4];
  358. char name[40] = "dgk_key_";
  359. const char* div = "_";
  360. const char* ext = ".bin";
  361. sprintf(smod, "%d", modulusbits);
  362. sprintf(slbit, "%d", lbits);
  363. strcat(name, smod);
  364. strcat(name, div);
  365. strcat(name, slbit);
  366. strcat(name, ext);
  367. // printf("reading dgk key from %s\n", name);
  368. /* allocate the new key structures */
  369. *pub = (dgk_pubkey_t*) malloc(sizeof(dgk_pubkey_t));
  370. *prv = (dgk_prvkey_t*) malloc(sizeof(dgk_prvkey_t));
  371. FILE *fp;
  372. fp = fopen(name, "r");
  373. /* initialize our integers */
  374. mpz_init((*pub)->n);
  375. mpz_init((*pub)->u);
  376. mpz_init((*pub)->h);
  377. mpz_init((*pub)->g);
  378. mpz_init((*prv)->vp);
  379. mpz_init((*prv)->vq);
  380. mpz_init((*prv)->p);
  381. mpz_init((*prv)->q);
  382. mpz_init((*prv)->pinv);
  383. mpz_init((*prv)->qinv);
  384. mpz_init((*prv)->p_minusone);
  385. mpz_init((*prv)->q_minusone);
  386. mpz_inp_raw((*prv)->p, fp);
  387. mpz_inp_raw((*prv)->q, fp);
  388. mpz_inp_raw((*prv)->vp, fp);
  389. mpz_inp_raw((*prv)->vq, fp);
  390. mpz_inp_raw((*prv)->pinv, fp);
  391. mpz_inp_raw((*prv)->qinv, fp);
  392. mpz_inp_raw((*pub)->n, fp);
  393. mpz_inp_raw((*pub)->u, fp);
  394. mpz_inp_raw((*pub)->g, fp);
  395. mpz_inp_raw((*pub)->h, fp);
  396. fclose(fp);
  397. mpz_sub_ui((*prv)->p_minusone, (*prv)->p, 1);
  398. mpz_sub_ui((*prv)->q_minusone, (*prv)->q, 1);
  399. lbits = lbits * 2 + 2;
  400. (*pub)->bits = modulusbits;
  401. (*pub)->lbits = lbits;
  402. powtwo = (mpz_t*) malloc(sizeof(mpz_t) * lbits);
  403. gvpvqp = (mpz_t*) malloc(sizeof(mpz_t) * lbits);
  404. // array holding powers of two
  405. for (i = 0; i < lbits; i++) {
  406. mpz_init(powtwo[i]);
  407. mpz_setbit(powtwo[i], i);
  408. }
  409. mpz_powm(f1, (*pub)->g, (*prv)->vp, (*prv)->p); //gvpvq
  410. mpz_sub_ui(tmp, (*pub)->u, 1); // tmp1 = u - 1
  411. for (i = 0; i < lbits; i++) {
  412. mpz_init(gvpvqp[i]);
  413. mpz_powm(gvpvqp[i], f1, powtwo[i], (*prv)->p);
  414. mpz_powm(gvpvqp[i], gvpvqp[i], tmp, (*prv)->p);
  415. }
  416. /*
  417. // debug output
  418. gmp_printf("n %Zd\n", (*pub)->n);
  419. gmp_printf("u %Zd\n", (*pub)->u);
  420. gmp_printf("g %Zd\n", (*pub)->g);
  421. gmp_printf("h %Zd\n", (*pub)->h);
  422. gmp_printf("p %Zd\n", (*prv)->p);
  423. gmp_printf("q %Zd\n", (*prv)->q);
  424. gmp_printf("vp %Zd\n", (*prv)->vp);
  425. gmp_printf("vq %Zd\n", (*prv)->vq);
  426. gmp_printf("vpinv %Zd\n", (*prv)->pinv);
  427. gmp_printf("vqinv %Zd\n", (*prv)->qinv);
  428. */
  429. }
  430. void createKeys() {
  431. dgk_pubkey_t * pub;
  432. dgk_prvkey_t * prv;
  433. mpz_t msg, ct, msg2;
  434. mpz_inits(msg, ct, msg2, NULL);
  435. for (unsigned int n = 1024; n <= 3072; n += 1024) {
  436. for (unsigned int l = 8; l <= 64; l *= 2) {
  437. // choose either keygen or readkey
  438. // dgk_keygen(n, l, &pub, &prv); //uncomment to acutally create keys
  439. dgk_readkey(n, l, &pub, &prv); //only read from file
  440. int no_error = 1;
  441. if (l < 16) {
  442. int maxit = 1 << l;
  443. for (int i = 0; i < maxit; i++) {
  444. mpz_set_ui(msg, i);
  445. dgk_encrypt_plain(ct, pub, msg);
  446. dgk_decrypt(msg2, pub, prv, ct);
  447. if (mpz_cmp(msg, msg2)) {
  448. // printf("ERROR: \n");
  449. //
  450. // gmp_printf("msg %Zd\n", msg);
  451. // gmp_printf("ct %Zd\n", ct);
  452. // gmp_printf("msg2 %Zd\n", msg2);
  453. //
  454. // gmp_printf("n %Zd\n", pub->n);
  455. // gmp_printf("u %Zd\n", pub->u);
  456. // gmp_printf("g %Zd\n", pub->g);
  457. // gmp_printf("h %Zd\n", pub->h);
  458. // gmp_printf("p %Zd\n", prv->p);
  459. // gmp_printf("q %Zd\n", prv->q);
  460. // gmp_printf("vp %Zd\n", prv->vp);
  461. // gmp_printf("vq %Zd\n", prv->vq);
  462. printf(".");
  463. i = maxit;
  464. no_error = 0;
  465. }
  466. }
  467. } else {
  468. for (int i = 0; i < KEYTEST_ITERATIONS; i++) {
  469. if (i > 3) {
  470. aby_prng(msg, l);
  471. }
  472. // test some corner cases first: 0, 1, 2^l-1, 2^l-2. After that random numbers.
  473. else if (i == 0)
  474. mpz_set_ui(msg, 0);
  475. else if (i == 1)
  476. mpz_set_ui(msg, 1);
  477. else if (i == 2) {
  478. mpz_set_ui(msg, 0);
  479. mpz_setbit(msg, l);
  480. mpz_sub_ui(msg, msg, 1);
  481. } else if (i == 3) {
  482. mpz_sub_ui(msg, msg, 1);
  483. }
  484. dgk_encrypt_plain(ct, pub, msg);
  485. dgk_decrypt(msg2, pub, prv, ct);
  486. if (mpz_cmp(msg, msg2)) {
  487. // Error: decrypted message is different from encrypted message. We have to start again.
  488. // printf("ERROR: \n");
  489. //
  490. // gmp_printf("msg %Zd\n", msg);
  491. // gmp_printf("ct %Zd\n", ct);
  492. // gmp_printf("msg2 %Zd\n", msg2);
  493. //
  494. // gmp_printf("n %Zd\n", pub->n);
  495. // gmp_printf("u %Zd\n", pub->u);
  496. // gmp_printf("g %Zd\n", pub->g);
  497. // gmp_printf("h %Zd\n", pub->h);
  498. // gmp_printf("p %Zd\n", prv->p);
  499. // gmp_printf("q %Zd\n", prv->q);
  500. // gmp_printf("vp %Zd\n", prv->vp);
  501. // gmp_printf("vq %Zd\n", prv->vq);
  502. printf(".");
  503. no_error = 0;
  504. break;
  505. }
  506. }
  507. }
  508. if (no_error) {
  509. // dgk_storekey(n, l, pub, prv);
  510. } else {
  511. if (l > 4) { // re-do last iteration
  512. l /= 2;
  513. }
  514. }
  515. }
  516. }
  517. }
  518. void test_encdec() {
  519. dgk_pubkey_t * pub;
  520. dgk_prvkey_t * prv;
  521. mpz_t a0, a1, b0, b1, c0, c1, r, d, a0c, b0c, rc, tmp0, tmp1;
  522. mpz_inits(a0, a1, b0, b1, c0, c1, r, d, a0c, b0c, rc, tmp0, tmp1, NULL);
  523. unsigned int l = 32;
  524. unsigned int nbit = 3072;
  525. //choose either keygen or readkey
  526. //dgk_keygen(nbit, l, &pub, &prv);
  527. dgk_readkey(nbit, l, &pub, &prv);
  528. aby_prng(a0, l);
  529. dgk_encrypt_crt(a0c, pub, prv, a0); //encrypt a0
  530. dgk_decrypt(b0, pub, prv, a0c);
  531. if (mpz_cmp(a0, b0) == 0) {
  532. printf("fine\n");
  533. } else {
  534. printf("ERR :(\n");
  535. gmp_printf("%Zd, %Zd", a0, b0);
  536. }
  537. dgk_encrypt_plain(a0c, pub, a0);
  538. dgk_decrypt(b0, pub, prv, a0c);
  539. if (mpz_cmp(a0, b0) == 0) {
  540. printf("fine\n");
  541. } else {
  542. printf("ERR :(\n");
  543. gmp_printf("%Zd, %Zd", a0, b0);
  544. }
  545. }
  546. void test_sharing() {
  547. dgk_pubkey_t * pub;
  548. dgk_prvkey_t * prv;
  549. mpz_t a0, a1, b0, b1, c0, c1, r, d, a0c, b0c, rc, tmp0, tmp1;
  550. mpz_inits(a0, a1, b0, b1, c0, c1, r, d, a0c, b0c, rc, tmp0, tmp1, NULL);
  551. unsigned int l = 32;
  552. unsigned int nbit = 3072;
  553. //choose either keygen or readkey
  554. // dgk_keygen(nbit, l, &pub, &prv);
  555. dgk_readkey(nbit, l, &pub, &prv);
  556. // choose random a and b shares, l bits long
  557. aby_prng(a0, l);
  558. aby_prng(b0, l);
  559. aby_prng(a1, l);
  560. aby_prng(b1, l);
  561. gmp_printf("a0,b0: %Zd %Zd \n", a0, b0);
  562. gmp_printf("a1,b1: %Zd %Zd \n", a1, b1);
  563. // choose random r for masking
  564. aby_prng(r, 2 * l + 2);
  565. dgk_encrypt_plain(a0c, pub, a0); //encrypt a0
  566. dgk_encrypt_plain(b0c, pub, b0); //encrypt b0
  567. dgk_encrypt_plain(rc, pub, r); //encrypt r
  568. mpz_mul(c1, a1, b1);
  569. mpz_mod_2exp(c1, c1, l);
  570. mpz_sub(c1, c1, r); // c1 = a1*b1 - r
  571. mpz_mod_2exp(c1, c1, l); // % l (stay within plaintext space)
  572. // homomorphic multiplication
  573. mpz_powm(a0c, a0c, b1, pub->n);
  574. mpz_powm(b0c, b0c, a1, pub->n);
  575. // test from here
  576. dgk_decrypt(d, pub, prv, a0c);
  577. gmp_printf("---test shares---\ndec a0*b1= %Zd\n", d);
  578. mpz_mul(tmp0, b1, a0);
  579. gmp_printf("a0*b1= %Zd\n", tmp0);
  580. dgk_decrypt(d, pub, prv, b0c);
  581. gmp_printf("dec a1*b0= %Zd\n", d);
  582. mpz_mul(tmp1, b0, a1);
  583. gmp_printf("a1*b0= %Zd\n---test shares---\n", tmp1);
  584. // test till here
  585. mpz_mul(a0c, a0c, b0c); // multiply [a0]^b1 and [b0]^a1 (homomorphic addition)
  586. mpz_mod(a0c, a0c, pub->n); // product % n (stay within ciphertext space)
  587. // test from here
  588. dgk_decrypt(d, pub, prv, a0c); // decrypt ciphertext (sum of products a0c, yet no r)
  589. gmp_printf("dec 4x= %Zd\n", d);
  590. mpz_add(tmp0, tmp0, tmp1); // add plaintext products, should be equal to d
  591. gmp_printf("4x= %Zd\n", tmp0);
  592. mpz_add(tmp0, tmp0, r); // plaintext add r
  593. mpz_mod_2exp(tmp1, tmp0, l); // mod l
  594. gmp_printf("4x + r= %Zd = %Zd (mod l)\n", tmp0, tmp1);
  595. // test till here
  596. mpz_mul(a0c, a0c, rc); // homomorphic addition of r
  597. mpz_mod(a0c, a0c, pub->n); // product % n
  598. dgk_decrypt(d, pub, prv, a0c); // decrypt masked sum+r
  599. mpz_mul(c0, a0, b0); // c0 = a0 * b0
  600. mpz_mod_2exp(c0, c0, l); // c0 = c0 % 2^l
  601. mpz_add(c0, c0, d); // c0 = c0 + d
  602. mpz_mod_2exp(c0, c0, l); // c0 = c0 % 2^l
  603. gmp_printf("%Zd %Zd %Zd\n", a0, b0, c0);
  604. gmp_printf("%Zd %Zd %Zd\n", a1, b1, c1);
  605. gmp_printf("%Zd %Zd\n", r, d);
  606. // test if MT is valid: (a0+a1) * (b0+b1) = c0+c1 [mod l]
  607. mpz_add(a0, a0, a1);
  608. mpz_add(b0, b0, b1);
  609. mpz_mul(a0, a0, b0);
  610. mpz_add(c0, c0, c1);
  611. mpz_mod_2exp(c0, c0, l);
  612. mpz_mod_2exp(a0, a0, l);
  613. if (mpz_cmp(a0, c0) == 0) {
  614. printf("fine\n");
  615. } else {
  616. printf("ERR :(\n");
  617. }
  618. }
  619. /**
  620. * uncomment the following main for direct testing
  621. * g++ dgk.cpp ../utils.cpp ../powmod.cpp -lgmp -O3 -g0 -o dgk
  622. */
  623. // #include <time.h>
  624. // int main(){
  625. // srand (time(NULL)^clock());
  626. // // createKeys();
  627. // test_encdec();
  628. // test_sharing();
  629. // printf("DGK END.\n");
  630. // return 0;
  631. // }