fpe2scalar.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. #include "fpe2scalar.hpp"
  2. unsigned long long mpz2ull (mpz_class n)
  3. {
  4. stringstream str;
  5. str << n;
  6. unsigned long long ull;
  7. str >> ull;
  8. return ull;
  9. }
  10. mpz_class ull2mpz (unsigned long long n)
  11. {
  12. stringstream str;
  13. str << n;
  14. mpz_class ull;
  15. str >> ull;
  16. return ull;
  17. }
  18. mpz_class fpe2mpz(const fpe_t op)
  19. {
  20. //fpe_print(stdout,op);
  21. //jump;
  22. extern const double bn_v;
  23. //zout(bn_v);
  24. //for (int i=0;i<12;i++)
  25. //{
  26. //cout << todouble(op->v[i]) << " " ;
  27. //}
  28. //cout << endl;
  29. mpz_class poly_at_one=1., increment_factor=6* bn_v;
  30. for (int i=0;i<12;i++)
  31. {
  32. if (i==0)
  33. {
  34. poly_at_one=todouble(op->v[0]);
  35. cout.precision ( 15 ); //NB
  36. ////zout(std::numeric_limits<double>::digits10);
  37. }
  38. if (i>=1 && i<=6) {poly_at_one+=increment_factor*todouble(op->v[i]); increment_factor*=bn_v;}
  39. if (i==7) {increment_factor*=6.; poly_at_one+=increment_factor*todouble(op->v[i]); increment_factor*=bn_v;}
  40. if (i>=8 && i<=11) {poly_at_one+=increment_factor*todouble(op->v[i]); increment_factor*=bn_v;}
  41. //if (i<11) {zout(increment_factor);}
  42. }
  43. //zout(poly_at_one);
  44. ///** Méthode fausse 0: division ceil mpz_t, increment_factor=6*bn_v=11208198 l'incrément final est ok avec ce type de division mais on ne part pas du bon incrément au départ. Il faut multiplier, additionner des mpz_class pas des doubles pour le calculer correctement. **/
  45. //mpz_t v;
  46. //mpz_init_set_str (v, "1868033", 0);
  47. //mpz_t six;
  48. //mpz_init_set_str (six, "6", 0);
  49. //mpz_class poly_at_one=1;
  50. //mpz_class increment_factor=36 * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v; // l'erreur est ici, on peut pas définir un grand nombre en faisant des opérations sur les doubles
  51. //zout(increment_factor);
  52. //for (int i=11;i>=0;i--)
  53. //{
  54. //if (i>=8 && i<=11) {poly_at_one+=increment_factor*todouble(op->v[i]); mpz_cdiv_q(increment_factor.get_mpz_t(), increment_factor.get_mpz_t(), v);}
  55. //if (i==7) {mpz_cdiv_q(increment_factor.get_mpz_t(), increment_factor.get_mpz_t(), six); poly_at_one+=increment_factor*todouble(op->v[i]); mpz_cdiv_q(increment_factor.get_mpz_t(), increment_factor.get_mpz_t(), v);}
  56. //if (i>=2 && i<=6) {poly_at_one+=increment_factor*todouble(op->v[i]); mpz_cdiv_q(increment_factor.get_mpz_t(), increment_factor.get_mpz_t(), v);}
  57. //if (i==1) {poly_at_one+=increment_factor*todouble(op->v[i]);}
  58. //if (i==0) {poly_at_one+=todouble(op->v[0]); }
  59. //if (i>1) {zout(increment_factor);}
  60. //}
  61. //zout(poly_at_one);
  62. //mpz_clear(v);
  63. //mpz_clear(six);
  64. /** Méthode fausse 1 Ca marche presque avec / la division tronquée, mpz_class. increment_factor=11208197 **/
  65. //mpz_class poly_at_one=1;
  66. //mpz_class increment_factor=36 * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v;
  67. //for (int i=11;i>=0;i--)
  68. //{
  69. //if (i>=8 && i<=11) {poly_at_one+=increment_factor*todouble(op->v[i]); increment_factor/=bn_v;}
  70. //if (i==7) {increment_factor/=6; poly_at_one+=increment_factor*todouble(op->v[i]); increment_factor/=bn_v;}
  71. //if (i>=2 && i<=6) {poly_at_one+=increment_factor*todouble(op->v[i]); increment_factor/=bn_v;}
  72. //if (i==1) {poly_at_one+=increment_factor*todouble(op->v[i]);}
  73. //if (i==0) {poly_at_one+=todouble(op->v[0]); }
  74. //zout(poly_at_one,increment_factor);
  75. //}
  76. //zout(poly_at_one);
  77. ///** Méthode fausse numéro 2 pour calculer poly_at_one. Tous les opérandes sont des doubles, le résultat est incorrect, la précision est inférieur à 1 sur des doubles de plus de 53 bits. Il faut additionner des mpz_class. **/
  78. //mpz_class poly_at_one =
  79. //todouble(op->v[0]) +
  80. //todouble(op->v[1]) * 6 * bn_v +
  81. //todouble(op->v[2]) * 6 * bn_v * bn_v +
  82. //todouble(op->v[3]) * 6 * bn_v * bn_v * bn_v +
  83. //todouble(op->v[4]) * 6 * bn_v * bn_v * bn_v * bn_v +
  84. //todouble(op->v[5]) * 6 * bn_v * bn_v * bn_v * bn_v * bn_v +
  85. //todouble(op->v[6]) * 6 * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v +
  86. //todouble(op->v[7]) * 36 * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v +
  87. //todouble(op->v[8]) * 36 * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v +
  88. //todouble(op->v[9]) * 36 * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v +
  89. //todouble(op->v[10]) * 36 * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v +
  90. //todouble(op->v[11]) * 36 * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v;
  91. //zout(poly_at_one);
  92. mpz_class bn_u, bn_p;
  93. bn_u=1;//attention pow(bn_v,3); ne marche pas ni bn_v*bn_v*bn_v
  94. for (int i =0;i<3;i++)
  95. {
  96. bn_u*=bn_v;
  97. }
  98. bn_p=36 * bn_u * bn_u * bn_u * bn_u+36 * bn_u * bn_u * bn_u+24 * bn_u * bn_u+6 * bn_u + 1;
  99. //zout(bn_p);
  100. mpz_class field_element = poly_at_one % bn_p; //32 octets 256 bits le reste n'est pas forcément positif, il est obtenu avec une division dite tronquée, i.e. le reste a le même signe que le divisé, poly_at_one dans ce cas.
  101. //field_element = (sgn(field_element)>=0)? field_element :field_element+bn_p;
  102. //if (sgn(field_element)<0)
  103. //{
  104. //field_element+=bn_p;
  105. //}
  106. //zout(field_element);
  107. return field_element;
  108. }
  109. void fpe2scalar(scalar_t rop, const fpe_t op)
  110. {
  111. mpz_class field_element=fpe2mpz(op);
  112. ///** Technique du modulo **/
  113. ///** Calcul d'une puissance entière **/
  114. //mpz_class base=1;
  115. //for (int i=0; i<64; i++)
  116. //{
  117. //base=base*2;
  118. //}
  119. ////zout(base); // base 2^64
  120. //rop[0] = mpz2ull( field_element % base); //décomposition en base 2^64
  121. //rop[1] = mpz2ull((field_element >> 64) % base);
  122. //rop[2] = mpz2ull((field_element >> 128) % base);
  123. //rop[3] = mpz2ull((field_element >> 192) % base);
  124. //mpz_class test_modulo =ull2mpz(rop[0])+ull2mpz(rop[1])*base +ull2mpz(rop[2])*base*base+ull2mpz(rop[3])*base*base*base;
  125. //zout(test_modulo);
  126. /** Technique du masque en C++**/
  127. mpz_class mask = 0xffffffffffffffff; // 8 octets 64 bits
  128. rop[0] = mpz2ull (field_element & mask);
  129. rop[1] = mpz2ull((field_element >> 64) & mask);
  130. rop[2] = mpz2ull((field_element >> 128) & mask);
  131. rop[3] = mpz2ull((field_element >> 192) & mask);
  132. //mpz_class test_mask =ull2mpz(rop[0])+(ull2mpz(rop[1])<<64) +(ull2mpz(rop[2])<<128)+(ull2mpz(rop[3])<<192); //il faut mettre les parenthèses
  133. //zout(test_mask); //le test consiste à bien recomposer field_element à partir des rop[]
  134. /** Technique du masque en C**/
  135. //mpz_t c;
  136. //mpz_and(c,field_element.get_mpz_t() ,mask.get_mpz_t());
  137. // pour continuer avec la méthode C, il faut définir une fonction de conversion entre mpz_t et ull
  138. //zout(rop[0],rop[1],rop[2],rop[3]);
  139. }
  140. mpz_class scalar2mpz( const scalar_t op)
  141. {
  142. mpz_class r,rop;
  143. rop = ull2mpz(op[0]);
  144. mpz_ui_pow_ui (r.get_mpz_t(), 2, 64); //on doit repasser par l'interface C de GMP
  145. rop += ull2mpz(op[1])*r;
  146. mpz_ui_pow_ui (r.get_mpz_t(), 2, 128);
  147. rop += ull2mpz(op[2])*r;
  148. mpz_ui_pow_ui (r.get_mpz_t(), 2, 192);
  149. rop += ull2mpz(op[3])*r;
  150. //zout(mpz_sizeinbase(rop.get_mpz_t(),2));
  151. if (mpz_sizeinbase(rop.get_mpz_t(),2) == 256) //si le mpz fait 256 bits, le bit de poids fort est pour le signe
  152. {
  153. mpz_ui_pow_ui (r.get_mpz_t(), 2, 256);
  154. rop=rop-r;
  155. }
  156. return rop;
  157. }
  158. void mpz2scalar1024(scalar1024 rop, mpz_class field_element)
  159. {
  160. mpz_class mask = 0xffffffffffffffff; // 8 octets 64 bits
  161. rop[0] = mpz2ull (field_element & mask);
  162. rop[1] = mpz2ull((field_element >> 64) & mask);
  163. rop[2] = mpz2ull((field_element >> 128) & mask);
  164. rop[3] = mpz2ull((field_element >> 192) & mask);
  165. rop[4] = mpz2ull((field_element >> 256) & mask);
  166. rop[5] = mpz2ull((field_element >> 320) & mask);
  167. rop[6] = mpz2ull((field_element >> 384) & mask);
  168. rop[7] = mpz2ull((field_element >> 448) & mask);
  169. rop[8] = mpz2ull((field_element >> 512) & mask);
  170. rop[9] = mpz2ull((field_element >> 576) & mask);
  171. rop[10] = mpz2ull((field_element >> 640) & mask);
  172. rop[11] = mpz2ull((field_element >> 704) & mask);
  173. rop[12] = mpz2ull((field_element >> 768) & mask);
  174. rop[13] = mpz2ull((field_element >> 832) & mask);
  175. rop[14] = mpz2ull((field_element >> 896) & mask);
  176. rop[15] = mpz2ull((field_element >> 960) & mask);
  177. }
  178. mpz_class scalar1024_2mpz( const scalar1024 op)
  179. {
  180. mpz_class r,rop;
  181. rop = ull2mpz(op[0]);
  182. mpz_ui_pow_ui (r.get_mpz_t(), 2, 64); //on doit repasser par l'interface C de GMP
  183. rop += ull2mpz(op[1])*r;
  184. mpz_ui_pow_ui (r.get_mpz_t(), 2, 128);
  185. rop += ull2mpz(op[2])*r;
  186. mpz_ui_pow_ui (r.get_mpz_t(), 2, 192);
  187. rop += ull2mpz(op[3])*r;
  188. mpz_ui_pow_ui (r.get_mpz_t(), 2, 256);
  189. rop += ull2mpz(op[4])*r;
  190. mpz_ui_pow_ui (r.get_mpz_t(), 2, 320);
  191. rop += ull2mpz(op[5])*r;
  192. mpz_ui_pow_ui (r.get_mpz_t(), 2, 384);
  193. rop += ull2mpz(op[6])*r;
  194. mpz_ui_pow_ui (r.get_mpz_t(), 2, 448);
  195. rop += ull2mpz(op[7])*r;
  196. mpz_ui_pow_ui (r.get_mpz_t(), 2, 512);
  197. rop += ull2mpz(op[8])*r;
  198. mpz_ui_pow_ui (r.get_mpz_t(), 2, 576);
  199. rop += ull2mpz(op[9])*r;
  200. mpz_ui_pow_ui (r.get_mpz_t(), 2, 640);
  201. rop += ull2mpz(op[10])*r;
  202. mpz_ui_pow_ui (r.get_mpz_t(), 2, 704);
  203. rop += ull2mpz(op[11])*r;
  204. mpz_ui_pow_ui (r.get_mpz_t(), 2, 768);
  205. rop += ull2mpz(op[12])*r;
  206. mpz_ui_pow_ui (r.get_mpz_t(), 2, 832);
  207. rop += ull2mpz(op[13])*r;
  208. mpz_ui_pow_ui (r.get_mpz_t(), 2, 896);
  209. rop += ull2mpz(op[14])*r;
  210. mpz_ui_pow_ui (r.get_mpz_t(), 2, 960);
  211. rop += ull2mpz(op[15])*r;
  212. //zout(mpz_sizeinbase(rop.get_mpz_t(),2));
  213. if (mpz_sizeinbase(rop.get_mpz_t(),2) == 1024) //si le mpz fait 256 bits, le bit de poids fort est pour le signe
  214. {
  215. mpz_ui_pow_ui (r.get_mpz_t(), 2, 1024);
  216. rop=rop-r;
  217. }
  218. return rop;
  219. }