<commit_before>#!/usr/bin/python3

from FiniteFields import mod_inv, mod_sqrt

# elliptic curve y^2 = x^3 + a * x + b
class EllipticCurve:
  """ Elliptic curve over Fp group"""

  def __init__(self, a, b, prime, G, order):
    assert 4*a*a*a+27*b*b !=0, "zero discriminant"
    self.__a = a
    self.__b = b
    self.__prime = prime

    self.__G = self.tuple_from_point(G)
    self.order = order

  def __y2(self, x):
    assert 0 <= x
    assert x < self.__prime
    # skipping key check: x is not valid if sqrt(y*y) does not exists
    return (x*x*x + self.__a*x + self.__b) % self.__prime

  def y(self, x, odd):
    assert type(odd) == bool or odd in (0, 1), "must be bool or 0/1"
    y2 = self.__y2(x)
    # if root does not exist, mod_sqrt will raise a ValueError
    root = mod_sqrt(y2, self.__prime)
    # switch even/odd root when needed
    return root if (root % 2 + odd) != 1 else self.__prime - root

  def __str__(self):
    result  = "EllipticCurve(a=%s, b=%s)" % (self.__a, self.__b)
    result += "\n prime = 0x%032x" % (self.__prime)
    result += "\n     G =(0x%032x,\n         0x%032x)" % (self.__G)
    result += "\n order = 0x%032x" % (self.order)
    return result

  def __repr__(self):
    result  = "EllipticCurve(%s, %s" % (self.__a, self.__b)
    result += ", 0x%032x" % (self.__prime)
    result += ", (0x%032x,0x%032x)" % (self.__G)
    result += ", 0x%032x)" % (self.order)
    return result
      
  def tuple_from_point(self, P):
    """ Return a tuple (Px, Py) having ensured it belongs to the curve """
    if isinstance(P, bytes):
      if len(P) == 33: # compressed point
        assert P[0] == 0x02 or P[0] == 0x03, "not a compressed point"
        Px = int.from_bytes(P[1:33], 'big')
        assert Px < self.__prime
        Py = self.y(Px, True)
        if (P[0] == 0x03):
          return (Px, Py)
        else:
          return (Px, self.__prime - Py)
      else:            # uncompressed point
        assert len(P) == 65, "not a point"
        assert P[0] == 0x04, "not an uncompressed point"
        Px = int.from_bytes(P[1:33], 'big')
        assert Px < self.__prime
        Py = int.from_bytes(P[34:], 'big')
        assert Py < self.__prime
        assert self.__y2(Px) == Py*Py % self.__prime, "point is not on the ec"
        return (Px, Py)
    elif isinstance(P, tuple):
      assert len(P) == 2, "invalid tuple point length"
      if (P[0] == None and P[1] == None):
        return P
      assert (type(P[0]) == int and type(P[1]) == int) , "invalid non-int tuple point"
      assert P[0] < self.__prime
      assert P[1] < self.__prime
      assert self.__y2(P[0]) == P[1]*P[1] % self.__prime, "point is not on the ec"
      return P
    else:
      raise ValueError("not an elliptic curve point")


  def bytes_from_point(self, P, compressed = True):
    """ Return a 33 bytes compressed (0x02, 0x03) or 65 bytes uncompressed
        (0x04) point ensuring it belongs to the curve
    """
    # if it is already byte, just check that it belongs to the curve
    if isinstance(P, bytes):
      if len(P) == 33: # compressed point<commit_msg>added Hasse Theorem check; extended to bytearray<commit_after>#!/usr/bin/python3

from FiniteFields import mod_inv, mod_sqrt
from math import sqrt

# elliptic curve y^2 = x^3 + a * x + b
class EllipticCurve:
  """ Elliptic curve over Fp group"""

  def __init__(self, a, b, prime, G, order):
    assert 4*a*a*a+27*b*b !=0, "zero discriminant"
    self.__a = a
    self.__b = b
    self.__prime = prime

    self.__G = self.tuple_from_point(G)
    # Hasse Theorem
    t = 2 * sqrt(prime)
    print(prime + 1 + t)
    print(prime + 1 - t)
    assert order <= prime + 1 + t, "order too high"
    assert prime + 1 - t <= order, "order too low"
    self.order = order

  def __y2(self, x):
    assert 0 <= x
    assert x < self.__prime
    # skipping key check: x is not valid if sqrt(y*y) does not exists
    return (x*x*x + self.__a*x + self.__b) % self.__prime

  def y(self, x, odd):
    assert type(odd) == bool or odd in (0, 1), "must be bool or 0/1"
    y2 = self.__y2(x)
    # if root does not exist, mod_sqrt will raise a ValueError
    root = mod_sqrt(y2, self.__prime)
    # switch even/odd root when needed
    return root if (root % 2 + odd) != 1 else self.__prime - root

  def __str__(self):
    result  = "EllipticCurve(a=%s, b=%s)" % (self.__a, self.__b)
    result += "\n prime = 0x%032x" % (self.__prime)
    result += "\n     G =(0x%032x,\n         0x%032x)" % (self.__G)
    result += "\n order = 0x%032x" % (self.order)
    return result

  def __repr__(self):
    result  = "EllipticCurve(%s, %s" % (self.__a, self.__b)
    result += ", 0x%032x" % (self.__prime)
    result += ", (0x%032x,0x%032x)" % (self.__G)
    result += ", 0x%032x)" % (self.order)
    return result
      
  def tuple_from_point(self, P):
    """ Return a tuple (Px, Py) having ensured it belongs to the curve """
    if isinstance(P, bytes) or isinstance(P, bytearray):
      if len(P) == 33: # compressed point
        assert P[0] == 0x02 or P[0] == 0x03, "not a compressed point"
        Px = int.from_bytes(P[1:33], 'big')
        assert Px < self.__prime
        Py = self.y(Px, True)
        if (P[0] == 0x03):
          return (Px, Py)
        else:
          return (Px, self.__prime - Py)
      else:            # uncompressed point
        assert len(P) == 65, "not a point"
        assert P[0] == 0x04, "not an uncompressed point"
        Px = int.from_bytes(P[1:33], 'big')
        assert Px < self.__prime
        Py = int.from_bytes(P[34:], 'big')
        assert Py < self.__prime
        assert self.__y2(Px) == Py*Py % self.__prime, "point is not on the ec"
        return (Px, Py)
    elif isinstance(P, tuple):
      assert len(P) == 2, "invalid tuple point length"
      if (P[0] == None and P[1] == None):
        return P
      assert (type(P[0]) == int and type(P[1]) == int) , "invalid non-int tuple point"
      assert P[0] < self.__prime
      assert P[1] < self.__prime
      assert self.__y2(P[0]) == P[1]*P[1] % self.__prime, "point is not on the ec"
      return P
    else:
      raise ValueError("not an elliptic curve point")


  def bytes_from_point(self, P, compressed = True):
    """ Return a 33 bytes compressed (0x02, 0x03) or 65 bytes uncompressed
        (0x04) point ensuring it belongs to the curve
    """
    # if it is already byte, just check that it belongs to the curve
    if isinstance(P, bytes) or isinstance(P, bytearray):
      if len(P) == 33: # compressed point
{'fraction_non_alphanumeric': 0.1417589175891759, 'fraction_numerical': 0.03305658056580566, 'mean_word_length': 2.4954325631380976, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3067218', 'n_tokens_mistral': 2444, 'n_tokens_neox': 2286, 'n_words': 742}