gmp-pk-crypto.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /**
  2. \file gmp-pk-crypto.cpp
  3. \author michael.zohner@ec-spride.de
  4. \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation
  5. Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt
  6. This program is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU Lesser General Public License as published
  8. by the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. ABY is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU Lesser General Public License for more details.
  14. You should have received a copy of the GNU Lesser General Public License
  15. along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. \brief Implementation of finite-field-cryptography operations (using the GMP library)
  17. */
  18. #include "gmp-pk-crypto.h"
  19. #include <iostream>
  20. //Parameters for different security levels
  21. const char* ifcp1024 =
  22. "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371";
  23. const char* ifcg1024 =
  24. "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507FD6406CFF14266D31266FEA1E5C41564B777E690F5504F213160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28AD662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24855E6EEB22B3B2E5";
  25. const char* ifcq1024 = "F518AA8781A8DF278ABA4E7D64B7CB9D49462353";
  26. const char* ifcp2048 =
  27. "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC2129037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708B3BF8A317091883681286130BC8985DB1602E714415D9330278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486DCDF93ACC44328387315D75E198C641A480CD86A1B9E587E8BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71CF9DE5384E71B81C0AC4DFFE0C10E64F";
  28. const char* ifcg2048 =
  29. "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFAAB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7C17669101999024AF4D027275AC1348BB8A762D0521BC98AE247150422EA1ED409939D54DA7460CDB5F6C6B250717CBEF180EB34118E98D119529A45D6F834566E3025E316A330EFBB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC017981BC087F2A7065B384B890D3191F2BFA";
  30. const char* ifcq2048 = "801C0D34C58D93FE997177101F80535A4738CEBCBF389A99B36371EB";
  31. const char* ifcp3072 =
  32. "4660194093823565506151007332698542081380390944320667936220310340292682538415201463451360005469701273992420569531194415296871671272562243754789577412471203509686259933515539120145538889500684305065682267020422897056483203401642088590732633756278140548667640739272073464322452643609409839498807131787408915921523565001045685221279165409792825261753615641493423723165471868882028678262386826730035778207616806238910696112513243832793252430036079010833108716296401084350809152423357477416465451376967706115065572717893335336664895800189754170750266169252030669114411476002012410621336179123441424048589750501111541393610787337793314723136089502117079738181113934544472215273637670210480814609550715859453809706797176331069587697357167970759889883398852942449568449890603652456531060380065260476714266615239827983706919432589669744367350756821903843388105282430635020233707272521317674908786962912228887786913664926989228941514639";
  33. const char* ifcg3072 =
  34. "326984479748743614358878489890111032378521682641889472728164592588245254735528952815040417677135099463681521117067228131302984716932197927691804537047698386112034189358693637764887258325546424576668654933254773228919028116187485325776123548207630122958160311311825230114818910264101591293903307807790394765896174615027850669640300925521032111542648598127663424462192520490917608209583615366128345913820058976254028107968965281721876376153097516948596625654797921929621363755081263164203185942482227411046415127689226121648774535224687708280963930985498313715804706762069594298539593719253724193098201932449349224692341850008449711165375995101343314201170357859203662648251088921851885444086613889195257606710405156897225917687758015354941738963422772322756212536951044725465040734436163477969317027796051497934165333064621979305683254912099909723895352817468375097484456065145582788954244042708099846989842764657922387568064";
  35. const char* ifcq3072 = "95729504467608377623766753562217147614989054519467474668915026082895293552781";
  36. gmp_num::gmp_num(prime_field* fld) {
  37. field = fld;
  38. mpz_init(val);
  39. }
  40. gmp_num::gmp_num(prime_field* fld, mpz_t src) {
  41. field = fld;
  42. mpz_init(val);
  43. mpz_set(val, src);
  44. }
  45. gmp_num::~gmp_num() {
  46. mpz_clear(val);
  47. }
  48. mpz_t* gmp_num::get_val() {
  49. return &val;
  50. }
  51. void gmp_num::set(num* src) {
  52. mpz_set(val, *num2mpz(src));
  53. }
  54. void gmp_num::set_si(int32_t src) {
  55. mpz_set_si(val, src);
  56. }
  57. void gmp_num::set_add(num* a, num* b) {
  58. mpz_add(val, *num2mpz(a), *num2mpz(b));
  59. }
  60. //a-b
  61. void gmp_num::set_sub(num* a, num* b) {
  62. mpz_sub(val, *num2mpz(a), *num2mpz(b));
  63. }
  64. void gmp_num::set_mul(num* a, num* b) {
  65. mpz_mul(val, *num2mpz(a), *num2mpz(b));
  66. }
  67. void gmp_num::mod(num* modulus) {
  68. mpz_mod(val, val, *num2mpz(modulus));
  69. }
  70. void gmp_num::set_mul_mod(num* a, num* b, num* modulus) {
  71. set_mul(a, b);
  72. mod(modulus);
  73. }
  74. void gmp_num::import_from_bytes(uint8_t* buf, uint32_t field_size_bytes) {
  75. mpz_import(val, field_size_bytes, 1, sizeof((buf)[0]), 0, 0, (buf));
  76. }
  77. void gmp_num::print() {
  78. std::cout << val << std::endl;
  79. }
  80. //export and pad all leading zeros
  81. void gmp_num::export_to_bytes(uint8_t* buf, uint32_t field_size_bytes) {
  82. mpz_export_padded(buf, field_size_bytes, val);
  83. }
  84. num* prime_field::get_rnd_num(uint32_t bitlen) {
  85. mpz_t val;
  86. if (bitlen == 0)
  87. bitlen = secparam.ifcbits;
  88. mpz_init(val);
  89. aby_prng(val, (mp_bitcnt_t) mpz_sizeinbase(q, 2) + secparam.ifcbits);
  90. mpz_mod(val, val, q);
  91. num* ret = new gmp_num(this, val);
  92. mpz_clear(val);
  93. return ret;
  94. }
  95. fe* prime_field::get_rnd_fe() {
  96. mpz_t val;
  97. mpz_init(val);
  98. aby_prng(val, mpz_sizeinbase(q, 2) + secparam.ifcbits);
  99. mpz_mod(val, val, q);
  100. fe* ret = new gmp_fe(this, val);
  101. mpz_clear(val);
  102. return ret;
  103. }
  104. gmp_fe::gmp_fe(prime_field* fld) {
  105. field = fld;
  106. init();
  107. }
  108. gmp_fe::gmp_fe(prime_field* fld, mpz_t src) {
  109. field = fld;
  110. init();
  111. mpz_set(val, src);
  112. }
  113. gmp_fe::~gmp_fe() {
  114. mpz_clear(val);
  115. }
  116. void gmp_fe::set(fe* src) {
  117. mpz_set(val, *fe2mpz(src));
  118. }
  119. mpz_t* gmp_fe::get_val() {
  120. return &val;
  121. }
  122. void gmp_fe::set_mul(fe* a, fe* b) {
  123. mpz_mul(val, *fe2mpz(a), *fe2mpz(b));
  124. mpz_mod(val, val, *field->get_p());
  125. }
  126. void gmp_fe::set_pow(fe* b, num* e) {
  127. mpz_powm(val, *fe2mpz(b), *num2mpz(e), *field->get_p());
  128. }
  129. void gmp_fe::set_div(fe* a, fe* b) {
  130. mpz_invert(val, *fe2mpz(b), *field->get_p());
  131. mpz_mul(val, *fe2mpz(a), val);
  132. mpz_mod(val, val, *field->get_p());
  133. }
  134. void gmp_fe::set_double_pow_mul(fe* b1, num* e1, fe* b2, num* e2) {
  135. gmp_fe tmpa(field), tmpb(field);
  136. tmpa.set_pow(b1, e1);
  137. tmpb.set_pow(b2, e2);
  138. set_mul(&tmpa, &tmpb);
  139. }
  140. void gmp_fe::import_from_bytes(uint8_t* buf) {
  141. mpz_import(val, field->fe_byte_size(), 1, sizeof((buf)[0]), 0, 0, (buf));
  142. }
  143. //export and pad all leading zeros
  144. void gmp_fe::export_to_bytes(uint8_t* buf) {
  145. mpz_export_padded(buf, field->fe_byte_size(), val);
  146. }
  147. void gmp_fe::sample_fe_from_bytes(uint8_t* buf, uint32_t bytelen) {
  148. mpz_import(val, bytelen, 1, sizeof((buf)[0]), 0, 0, (buf));
  149. mpz_mod(val, val, *field->get_p());
  150. }
  151. bool gmp_fe::eq(fe* a) {
  152. return mpz_cmp(val, *fe2mpz(a)) == 0;
  153. }
  154. void gmp_fe::print() {
  155. std::cout << val << std::endl;
  156. }
  157. num* prime_field::get_num() {
  158. return new gmp_num(this);
  159. }
  160. fe* prime_field::get_fe() {
  161. return new gmp_fe(this);
  162. }
  163. mpz_t* prime_field::get_p() {
  164. return &p;
  165. }
  166. fe* prime_field::get_generator() {
  167. return new gmp_fe(this, g);
  168. }
  169. num* prime_field::get_order() {
  170. num* val = get_num();
  171. val->set(order);
  172. return val;
  173. }
  174. fe* prime_field::get_rnd_generator() {
  175. mpz_t tmp;
  176. mpz_init(tmp);
  177. //sample random element x in Zp, and then compute x^{(p-1)/q} mod p
  178. do {
  179. aby_prng(tmp, secparam.ifcbits);
  180. mpz_mod(tmp, tmp, p);
  181. mpz_powm(tmp, tmp, q, p);
  182. } while (!(mpz_cmp_ui(tmp, (uint32_t ) 1)));
  183. fe* ret = new gmp_fe(this, tmp);
  184. mpz_clear(tmp);
  185. return ret;
  186. }
  187. brickexp* prime_field::get_brick(fe* gen) {
  188. return new gmp_brickexp(gen, this);
  189. }
  190. uint32_t prime_field::get_size() {
  191. return secparam.ifcbits;
  192. }
  193. void prime_field::init(seclvl sp, uint8_t* seed) {
  194. mpz_t rnd_seed;
  195. mpz_inits(p, q, g, rnd_seed, NULL);
  196. secparam = sp;
  197. mpz_import(rnd_seed, ceil_divide(secparam.symbits, 8), 1, sizeof((seed)[0]), 0, 0, seed);
  198. if (secparam.ifcbits == ST.ifcbits) {
  199. mpz_set_str(p, ifcp1024, 16);
  200. mpz_set_str(g, ifcg1024, 16);
  201. mpz_set_str(q, ifcq1024, 16);
  202. } else if (secparam.ifcbits == MT.ifcbits) {
  203. mpz_set_str(p, ifcp2048, 16);
  204. mpz_set_str(g, ifcg2048, 16);
  205. mpz_set_str(q, ifcq2048, 16);
  206. } else if (secparam.ifcbits == LT.ifcbits) {
  207. mpz_set_str(p, ifcp3072, 10);
  208. mpz_set_str(g, ifcg3072, 10);
  209. mpz_set_str(q, ifcq3072, 10);
  210. } else //Long term security
  211. {
  212. mpz_set_str(p, ifcp3072, 10);
  213. mpz_set_str(g, ifcg3072, 10);
  214. mpz_set_str(q, ifcq3072, 10);
  215. }
  216. order = new gmp_num(this, q);
  217. fe_bytelen = ceil_divide(secparam.ifcbits, 8);
  218. mpz_clear(rnd_seed);
  219. }
  220. prime_field::~prime_field() {
  221. mpz_clear(p);
  222. mpz_clear(g);
  223. mpz_clear(q);
  224. delete order;
  225. }
  226. gmp_brickexp::~gmp_brickexp() {
  227. for (uint32_t i = 0; i < m_numberOfElements; i++)
  228. mpz_clear(m_table[i]);
  229. free(m_table);
  230. }
  231. ;
  232. void gmp_brickexp::init(fe* g, prime_field* pfield) {
  233. field = pfield;
  234. m_numberOfElements = field->get_field_size();
  235. m_table = (mpz_t*) malloc(sizeof(mpz_t) * m_numberOfElements);
  236. for (uint32_t i = 0; i < m_numberOfElements; i++) {
  237. mpz_init(m_table[i]);
  238. }
  239. mpz_set(m_table[0], *((gmp_fe*) g)->get_val());
  240. for (unsigned u = 1; u < m_numberOfElements; ++u) {
  241. mpz_mul(m_table[u], m_table[u - 1], m_table[u - 1]);
  242. mpz_mod(m_table[u], m_table[u], *field->get_p());
  243. }
  244. }
  245. void gmp_brickexp::pow(fe* result, num* e) {
  246. mpz_t* res = ((gmp_fe*) result)->get_val();
  247. mpz_t* exp = ((gmp_num*) e)->get_val();
  248. uint32_t u;
  249. mpz_set_ui(*res, 1);
  250. for (u = 0; u < m_numberOfElements; u++) {
  251. if (mpz_tstbit(*exp, u)) {
  252. mpz_mul(*res, *res, m_table[u]);
  253. mpz_mod(*res, *res, *field->get_p());
  254. }
  255. }
  256. }
  257. // mpz_export does not fill leading zeros, thus a prepending of leading 0s is required
  258. void mpz_export_padded(uint8_t* pBufIdx, uint32_t field_size_bytes, mpz_t to_export) {
  259. size_t size = 0;
  260. mpz_export(pBufIdx, &size, 1, sizeof(pBufIdx[0]), 0, 0, to_export);
  261. if (size < field_size_bytes) {
  262. for (int i = 0; i + size < field_size_bytes; i++) {
  263. pBufIdx[i] = 0;
  264. }
  265. pBufIdx += (field_size_bytes - size);
  266. mpz_export(pBufIdx, &size, 1, sizeof(pBufIdx[0]), 0, 0, to_export);
  267. }
  268. }