ecp_test.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. *******************************************************************************
  3. \file ecp_test.c
  4. \brief Tests for elliptic curves over prime fields
  5. \project bee2/test
  6. \created 2017.05.29
  7. \version 2023.03.30
  8. \copyright The Bee2 authors
  9. \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt).
  10. *******************************************************************************
  11. */
  12. #include <bee2/core/hex.h>
  13. #include <bee2/core/mem.h>
  14. #include <bee2/core/obj.h>
  15. #include <bee2/core/util.h>
  16. #include <bee2/math/gfp.h>
  17. #include <bee2/math/ecp.h>
  18. #include <bee2/math/ww.h>
  19. /*
  20. *******************************************************************************
  21. Проверочная кривая
  22. *******************************************************************************
  23. */
  24. static const size_t no = 32;
  25. static char p[] =
  26. "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF43";
  27. static char a[] =
  28. "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40";
  29. static char b[] =
  30. "00000000000000000000000000000000000000000000000000000000000014B8";
  31. static char q[] =
  32. "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D1229165911507C328526818EC4E11D";
  33. static char xbase[] =
  34. "0000000000000000000000000000000000000000000000000000000000000000";
  35. static char ybase[] =
  36. "B0E9804939D7C2E931D4CE052CCC6B6B692514CCADBA44940484EEA5F52D9268";
  37. static u32 cofactor = 1;
  38. /*
  39. *******************************************************************************
  40. Тестирование
  41. *******************************************************************************
  42. */
  43. bool_t ecpTest()
  44. {
  45. // размерности
  46. const size_t n = W_OF_O(no);
  47. const size_t f_keep = gfpCreate_keep(no);
  48. const size_t ec_keep = ecpCreateJ_keep(n);
  49. const size_t f_deep = gfpCreate_deep(no);
  50. // состояние и стек
  51. octet state[2048];
  52. octet stack[2048];
  53. octet t[32 * 5];
  54. // поле и эк
  55. qr_o* f;
  56. ec_o* ec;
  57. // подготовить память
  58. if (sizeof(state) < f_keep + ec_keep ||
  59. sizeof(stack) < f_deep ||
  60. sizeof(t) < 3 * no)
  61. return FALSE;
  62. // создать f = GF(p)
  63. hexToRev(t, p);
  64. f = (qr_o*)(state + ec_keep);
  65. if (!gfpCreate(f, t, no, stack))
  66. return FALSE;
  67. // создать ec = EC_{ab}(f)
  68. hexToRev(t, a), hexToRev(t + no, b);
  69. ec = (ec_o*)state;
  70. if (sizeof(stack) < ecpCreateJ_deep(n, f_deep) ||
  71. !ecpCreateJ(ec, f, t, t + no, stack))
  72. return FALSE;
  73. // создать группу точек ec
  74. hexToRev(t, xbase), hexToRev(t + no, ybase), hexToRev(t + 2 * no, q);
  75. if (sizeof(stack) < ecCreateGroup_deep(f_deep) ||
  76. !ecCreateGroup(ec, t, t + no, t + 2 * no, no, cofactor, stack))
  77. return FALSE;
  78. // присоединить f к ec
  79. objAppend(ec, f, 0);
  80. // корректная кривая?
  81. if (sizeof(stack) < ecpIsValid_deep(n, f_deep) ||
  82. !ecpIsValid(ec, stack))
  83. return FALSE;
  84. // корректная группа?
  85. if (sizeof(stack) < ecpSeemsValidGroup_deep(n, f_deep) ||
  86. !ecpSeemsValidGroup(ec, stack))
  87. return FALSE;
  88. // надежная группа?
  89. if (sizeof(stack) < ecpIsSafeGroup_deep(n) ||
  90. !ecpIsSafeGroup(ec, 40, stack))
  91. return FALSE;
  92. // базовая точка имеет порядок q?
  93. if (sizeof(stack) < ecHasOrderA_deep(n, ec->d, ec->deep, n) ||
  94. !ecHasOrderA(ec->base, ec, ec->order, n, stack))
  95. return FALSE;
  96. // утроить базовую точку разными способами
  97. if (sizeof(t) < (2 + ec->d) * no ||
  98. sizeof(stack) < utilMax(5,
  99. ec->deep,
  100. ecpIsOnA_deep(n, f_deep),
  101. ecpAddAA_deep(n, f_deep),
  102. ecpSubAA_deep(n, f_deep),
  103. ecMulA_deep(n, ec->d, ec->deep, 1)))
  104. return FALSE;
  105. {
  106. word* pts = (word*)t;
  107. word d = 3;
  108. // удвоить и сложить
  109. if (!ecpIsOnA(ec->base, ec, stack) ||
  110. !ecpAddAA(pts, ec->base, ec->base, ec, stack) ||
  111. !ecpAddAA(pts, pts, ec->base, ec, stack))
  112. return FALSE;
  113. // дважды удвоить и вычесть
  114. if (!ecpAddAA(pts + 2 * n, ec->base, ec->base, ec, stack) ||
  115. !ecpAddAA(pts + 2 * n, pts + 2 * n, pts + 2 * n, ec, stack) ||
  116. !ecpSubAA(pts + 2 * n, pts + 2 * n, ec->base, ec, stack) ||
  117. !memEq(pts, pts + 2 * n, 2 * n))
  118. return FALSE;
  119. ecpNegA(pts + 2 * n, pts + 2 * n, ec);
  120. if (ecpAddAA(pts + 2 * n, pts, pts + 2 * n, ec, stack))
  121. return FALSE;
  122. // вычислить кратную точку
  123. if (!ecMulA(pts + 2 * n, ec->base, ec, &d, 1, stack) ||
  124. !memEq(pts, pts + 2 * n, 2 * n))
  125. return FALSE;
  126. // утроить напрямую
  127. if (!ec->froma || !ec->tpl || !ec->toa)
  128. return FALSE;
  129. ec->froma(pts + 2 * n, ec->base, ec, stack);
  130. ec->tpl(pts + 2 * n, pts + 2 * n, ec, stack);
  131. ec->toa(pts + 2 * n, pts + 2 * n, ec, stack);
  132. if (!memEq(pts, pts + 2 * n, 2 * n))
  133. return FALSE;
  134. }
  135. // вывести f = GF(p) за пределы ec
  136. f = (qr_o*)(state + ec_keep);
  137. memMove(f, objPtr(ec, 0, qr_o), f_keep);
  138. // создать ec = EC_{a-1, b}(f)
  139. hexToRev(t, a), --t[0], hexToRev(t + no, b);
  140. ec = (ec_o*)state;
  141. if (sizeof(stack) < ecpCreateJ_deep(n, f_deep) ||
  142. !ecpCreateJ(ec, f, t, t + no, stack))
  143. return FALSE;
  144. // присоединить f к ec
  145. objAppend(ec, f, 0);
  146. // точка (xbase = 0, ybase) все еще лежит на ec: ybase^2 = b
  147. hexToRev(t, xbase), hexToRev(t + no, ybase);
  148. wwFrom(ec->base, t, no), wwFrom(ec->base + n, t + no, no);
  149. ASSERT(wwIsZero(ec->base, n));
  150. // утроить базовую точку разными способами
  151. if (sizeof(t) < (2 + ec->d) * no ||
  152. sizeof(stack) < utilMax(5,
  153. ec->deep,
  154. ecpIsOnA_deep(n, f_deep),
  155. ecpAddAA_deep(n, f_deep),
  156. ecpSubAA_deep(n, f_deep),
  157. ecMulA_deep(n, ec->d, ec->deep, 1)))
  158. return FALSE;
  159. {
  160. word* pts = (word*)t;
  161. word d = 3;
  162. // удвоить и сложить
  163. if (!ecpIsOnA(ec->base, ec, stack) ||
  164. !ecpAddAA(pts, ec->base, ec->base, ec, stack) ||
  165. !ecpAddAA(pts, pts, ec->base, ec, stack))
  166. return FALSE;
  167. // дважды удвоить и вычесть
  168. if (!ecpAddAA(pts + 2 * n, ec->base, ec->base, ec, stack) ||
  169. !ecpAddAA(pts + 2 * n, pts + 2 * n, pts + 2 * n, ec, stack) ||
  170. !ecpSubAA(pts + 2 * n, pts + 2 * n, ec->base, ec, stack) ||
  171. !memEq(pts, pts + 2 * n, 2 * n))
  172. return FALSE;
  173. ecpNegA(pts + 2 * n, pts + 2 * n, ec);
  174. if (ecpAddAA(pts + 2 * n, pts, pts + 2 * n, ec, stack))
  175. return FALSE;
  176. // вычислить кратную точку
  177. if (!ecMulA(pts + 2 * n, ec->base, ec, &d, 1, stack) ||
  178. !memEq(pts, pts + 2 * n, 2 * n))
  179. return FALSE;
  180. // утроить напрямую
  181. if (!ec->froma || !ec->tpl || !ec->toa)
  182. return FALSE;
  183. ec->froma(pts + 2 * n, ec->base, ec, stack);
  184. ec->tpl(pts + 2 * n, pts + 2 * n, ec, stack);
  185. ec->toa(pts + 2 * n, pts + 2 * n, ec, stack);
  186. if (!memEq(pts, pts + 2 * n, 2 * n))
  187. return FALSE;
  188. }
  189. // все нормально
  190. return TRUE;
  191. }