Fp.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. #include "Fp.hpp"
  2. extern const double bn_v;
  3. Fp::Fp()
  4. {
  5. fpe_setzero(element);
  6. no_change = false;
  7. }
  8. Fp::Fp(const fpe_t & input)
  9. {
  10. set(input);
  11. no_change = false;
  12. }
  13. Fp::Fp(int input)
  14. {
  15. set(input);
  16. no_change = false;
  17. }
  18. void Fp::set(const fpe_t & fpe)
  19. {
  20. fpe_set(element, fpe);
  21. no_change = false;
  22. }
  23. void Fp::set(int input)
  24. {
  25. mydouble[12] coefficient_matrix;
  26. for (int i = 0; i < 12; i++)
  27. {
  28. switch (i)
  29. {
  30. case 0:
  31. coefficient_matrix[i] = ((mydouble) input);
  32. break;
  33. default:
  34. coefficient_matrix[i] = 0.;
  35. }
  36. }
  37. fpe_set_doublearray(element, coefficient_matrix);
  38. if (input > ((int) bn_v) * 3)
  39. {
  40. fpe_short_coeffred(element)
  41. }
  42. no_change = false;
  43. }
  44. void Fp::set_random()
  45. {
  46. // c.f. https://www.cryptojedi.org/papers/dclxvi-20100714.pdf for these maxes
  47. const int MAX_A = ((int) bn_v) * 3;
  48. const int MAX_B = ((int) bn_v) / 2 + 1;
  49. std::random_device generator;
  50. std::uniform_int_distribution<int> distribution_a(-MAX_A, MAX_A);
  51. std::uniform_int_distribution<int> distribution_b(-MAX_B, MAX_B);
  52. mydouble[12] coefficient_matrix;
  53. for (int i = 0; i < 12; i++)
  54. {
  55. switch (i)
  56. {
  57. case 0:
  58. case 6:
  59. coefficient_matrix[i] = ((mydouble) distribution_a(generator));
  60. break;
  61. default:
  62. coefficient_matrix[i] = ((mydouble) distribution_b(generator));
  63. }
  64. }
  65. fpe_set_doublearray(element, coefficient_matrix);
  66. no_change = false;
  67. }
  68. Fp Fp::operator-() const
  69. {
  70. fpe_t temp;
  71. fpe_neg(temp, element);
  72. return Fp(temp);
  73. }
  74. Fp Fp::operator+(const Fp & b) const
  75. {
  76. fpe_t temp;
  77. fpe_add(temp, element, b.element);
  78. return Fp(temp);
  79. }
  80. Fp Fp::operator-(const Fp & b) const
  81. {
  82. fpe_t temp;
  83. fpe_sub(temp, element, b.element);
  84. return Fp(temp);
  85. }
  86. Fp Fp::operator*(const Fp & b) const
  87. {
  88. fpe_t temp;
  89. fpe_mul(temp, element, b.element);
  90. return Fp(temp);
  91. }
  92. Fp Fp::operator/(const Fp & b) const
  93. {
  94. fpe_t temp;
  95. fpe_invert(temp, b.element);
  96. fpe_mul(temp, element, temp);
  97. return Fp(temp);
  98. }
  99. bool Fp::operator==(const Fp & b) const
  100. {
  101. return fpe_iseq(element, b.element) == 1;
  102. }
  103. bool Fp::operator!=(const Fp & b) const
  104. {
  105. return fpe_iseq(element, b.element) == 0;
  106. }
  107. bool Fp::is_zero() const
  108. {
  109. return fpe_iszero(element) == 1;
  110. }
  111. scalar_t& Fp::to_scalar() const
  112. {
  113. if (no_change)
  114. return scalar;
  115. mpz_class poly_at_one = 1.;
  116. mpz_class increment_factor = bn_v * 6;
  117. for (int i = 0; i < 12; i++)
  118. {
  119. switch (i)
  120. {
  121. case 0:
  122. poly_at_one = todouble(element->v[0]);
  123. break;
  124. case 1:
  125. case 2:
  126. case 3:
  127. case 4:
  128. case 5:
  129. case 6:
  130. poly_at_one += increment_factor * todouble(element->v[i]);
  131. increment_factor *= bn_v;
  132. break;
  133. case 7:
  134. increment_factor *= 6.;
  135. poly_at_one += increment_factor * todouble(element->v[i]);
  136. increment_factor *= bn_v;
  137. break;
  138. default:
  139. poly_at_one += increment_factor * todouble(element->v[i]);
  140. increment_factor *= bn_v;
  141. break;
  142. }
  143. }
  144. mpz_class bn_u = 1;
  145. for (int i = 0; i < 3; i++)
  146. bn_u *= bn_v;
  147. mpz_class bn_p;
  148. 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;
  149. mpz_class field_element = poly_at_one % bn_p;
  150. mpz_class mask = 0xffffffffffffffff; // 8 octets 64 bits
  151. scalar[0] = mpz2ull( field_element & mask);
  152. scalar[1] = mpz2ull((field_element >> 64) & mask);
  153. scalar[2] = mpz2ull((field_element >> 128) & mask);
  154. scalar[3] = mpz2ull((field_element >> 192) & mask);
  155. no_change = true;
  156. return scalar;
  157. }
  158. std::ostream& operator<<(std::ostream& os, const Fp& output)
  159. {
  160. if (!output.no_change)
  161. output.to_scalar();
  162. os << output.scalar[3] << output.scalar[2] << output.scalar[1] << output.scalar[0];
  163. return os;
  164. }
  165. unsigned long long Fp::mpz2ull(const mpz_class& n) const
  166. {
  167. stringstream str;
  168. unsigned long long retval;
  169. str << n;
  170. str >> retval;
  171. return retval;
  172. }