def y_from_x(cls, x): """ Returns one of the two possible values for y from x. Used for point decompression. """ a = cls.a; b = cls.b; p = cls.p y_squared = ((x*x+ a)*x + b ) % p # it might be y or p - y y = square_root_mod_prime( y_squared, p ) return y
def y_from_x(cls, x): """ Returns one of the two possible values for y from x. Used for point decompression. """ a = cls.a b = cls.b p = cls.p y_squared = ((x * x + a) * x + b) % p # it might be y or p - y y = square_root_mod_prime(y_squared, p) return y
def from_x(cls, x): """ y^2 = ((a * x^2) / (d * x^2 - 1)) - (1 / (d * x^2 - 1)) For every x coordinate, there are two possible points: (x, y) and (x, -y) """ assert isinstance(x, FQ) xsq = x * x ax2 = JUBJUB_A * xsq dxsqm1 = prime_field_inv(JUBJUB_D * xsq - 1, JUBJUB_Q) ysq = dxsqm1 * (ax2 - 1) y = FQ(square_root_mod_prime(int(ysq), JUBJUB_Q)) return cls(x, y)
def map_to_curve(x, P=curve.p()): x -= 1 y = 0 found = False while not found: x += 1 f_x = (x * x * x + 7) % P try: y = numbertheory.square_root_mod_prime(f_x, P) found = True except Exception as e: pass return Point(curve.p(), curve.a(), curve.b(), x, y)
def from_y(cls, y, sign=None): """ x^2 = (y^2 - 1) / (d * y^2 - a) """ assert isinstance(y, FQ) ysq = y * y lhs = ysq - 1 rhs = JUBJUB_D * ysq - JUBJUB_A xsq = lhs / rhs x = FQ(square_root_mod_prime(int(xsq), JUBJUB_Q)) if sign is not None: # Used for compress & decompress if (x.n & 1) != sign: x = -x else: if is_negative(x): x = -x return cls(x, y)
def uncompress(self, xR): """ Return a new point R from just x-coordinate xR Note - this is not ANSI or SEC format 'x' with leading 2 bits holding (2 + yR mod 2) yR will be incorrect for 50% of runs, but ECDH will still have correct answer """ a = self.a b = self.b p = self.p #t0 = ( xR*xR*xR + a*xR + b ) % p t0 = ((xR*xR + a)*xR + b ) % p t1 = square_root_mod_prime( t0, p ) yR = t1 # it might also be yR = p - t1 R = self.point( xR, yR ) if self.contains_point(R): return R yR = p - t1 R = self.point( xR, yR ) if self.contains_point(R): return R else: EllipticCurveError( "uncompress failed")
def uncompress(self, xR): """ Return a new point R from just x-coordinate xR Note - this is not ANSI or SEC format 'x' with leading 2 bits holding (2 + yR mod 2) yR will be incorrect for 50% of runs, but ECDH will still have correct answer """ a = self.a b = self.b p = self.p #t0 = ( xR*xR*xR + a*xR + b ) % p t0 = ((xR * xR + a) * xR + b) % p t1 = square_root_mod_prime(t0, p) yR = t1 # it might also be yR = p - t1 R = self.point(xR, yR) if self.contains_point(R): return R yR = p - t1 R = self.point(xR, yR) if self.contains_point(R): return R else: EllipticCurveError("uncompress failed")