예제 #1
0
 def _double_point(self, P: Point) -> Point:
     # xR = (2 * xP * yP) / (a * xP^2 + yP^2)
     up_x = 2 * P.x * P.y
     down_x = self.a * P.x * P.x + P.y * P.y
     res_x = (up_x * modinv(down_x, self.p)) % self.p
     # yR = (yP^2 - a * xP * xP) / (2 - a * xP^2 - yP^2)
     up_y = P.y * P.y - self.a * P.x * P.x
     down_y = 2 - self.a * P.x * P.x - P.y * P.y
     res_y = (up_y * modinv(down_y, self.p)) % self.p
     return Point(res_x, res_y, self)
예제 #2
0
 def _add_point(self, P: Point, Q: Point) -> Point:
     # xR = (xP * yQ + yP * xQ) / (1 + b * xP * xQ * yP * yQ)
     up_x = P.x * Q.y + P.y * Q.x
     down_x = 1 + self.b * P.x * Q.x * P.y * Q.y
     res_x = (up_x * modinv(down_x, self.p)) % self.p
     # yR = (yP * yQ - a * xP * xQ) / (1 - b * xP * xQ * yP * yQ)
     up_y = P.y * Q.y - self.a * P.x * Q.x
     down_y = 1 - self.b * P.x * Q.x * P.y * Q.y
     res_y = (up_y * modinv(down_y, self.p)) % self.p
     return Point(res_x, res_y, self)
예제 #3
0
 def compute_y(self, x: int) -> int:
     # (bx^2 - 1) * y^2 = ax^2 - 1
     right = self.a * x * x - 1
     left_scale = (self.b * x * x - 1) % self.p
     inv_scale = modinv(left_scale, self.p)
     right = (right * inv_scale) % self.p
     y = modsqrt(right, self.p)
     return y
예제 #4
0
 def _double_point(self, P: Point) -> Point:
     # s = (3 * xP^2 + a) / (2 * yP)
     # xR = s^2 - 2 * xP
     # yR = yP + s * (xR - xP)
     s = (3 * P.x * P.x + self.a) * modinv(2 * P.y, self.p)
     res_x = (s * s - 2 * P.x) % self.p
     res_y = (P.y + s * (res_x - P.x)) % self.p
     return - Point(res_x, res_y, self)
예제 #5
0
 def _double_point(self, P: Point) -> Point:
     # s = (3 * xP^2 + 2 * a * xP + 1) / (2 * b * yP)
     # xR = b * s^2 - a - 2 * xP
     # yR = yP + s * (xR - xP)
     up = 3 * P.x * P.x + 2 * self.a * P.x + 1
     down = 2 * self.b * P.y
     s = up * modinv(down, self.p)
     res_x = (self.b * s * s - self.a - 2 * P.x) % self.p
     res_y = (P.y + s * (res_x - P.x)) % self.p
     return - Point(res_x, res_y, self)
예제 #6
0
 def _add_point(self, P: Point, Q: Point) -> Point:
     # s = (yP - yQ) / (xP - xQ)
     # xR = b * s^2 - a - xP - xQ
     # yR = yP + s * (xR - xP)
     delta_x = P.x - Q.x
     delta_y = P.y - Q.y
     s = delta_y * modinv(delta_x, self.p)
     res_x = (self.b * s * s - self.a - P.x - Q.x) % self.p
     res_y = (P.y + s * (res_x - P.x)) % self.p
     return - Point(res_x, res_y, self)
예제 #7
0
 def compute_y(self, x: int) -> int:
     right = (x * x * x + self.a * x * x + x) % self.p
     inv_b = modinv(self.b, self.p)
     right = (right * inv_b) % self.p
     y = modsqrt(right, self.p)
     return y
예제 #8
0
 def test_big_prime_exist(self):
     self.assertEqual(modinv(-2**522, BIG_PRIME), 2**520 - 1)
     self.assertEqual(modinv(2**485, BIG_PRIME), 68719476736)
     self.assertEqual(modinv(2**555, BIG_PRIME), 2**487)
예제 #9
0
 def test_small_prime_exist(self):
     self.assertEqual(modinv(-1000, SMALL_PRIME), 42)
     self.assertEqual(modinv(55, SMALL_PRIME), 30)
     self.assertEqual(modinv(1000, SMALL_PRIME), 55)