def __init__(self, n=331337, seed=42): """ create a new prng using a finite field of order n. n must be prime, as we basically use the integers mod some prime (Z mod p). Jeremy Kun's code lets us make this actual arithmetic code quite nice. We do take a performance hit, but not a *ton* """ """ TERRIBLE CHOICE: self.P = Point(C,F(32770),F(85186)) Q = 5*P """ """ seeds with not-incredibly-terrible initial cycles: 2819, some seeds lead to idntical cycles, but there are at least 3 distinct cycles! identical cycles: 4342,2819 """ #don't need to keep field or curve beyond constructor F = FiniteField(n, 1) C = EllipticCurve(a=F(1), b=F(1)) #choice of curve assumes default self.state = F(seed).n #this gives a 'cycle' of 71 elements... self.Q = Point(C, F(153116), F(171795)) # <Q> has order 6257 self.P = Point(C, F(285710), F(143307))
def get_state(p): """ given the prng p, get the 2 candidate current states of p """ out = p.get_num() F = p.P.x.field C = p.P.curve e = F(3) #backdoor! prime = p.P.x.p val = out * out * out + C.a * out + C.b points = [Point(C, F(out), F(y)) for y in tonelli_shanks(val.n, prime)] #print("points: ",points) states = [(e.n * T).x.n for T in points] #as both candidates are additive inverses of #one another, they have the same x coordinates return states[0]
def __init__(self, out): """ given the initial output, init out guesser so we can guess all remaining outputs """ prime = 331337 F = FiniteField(prime, 1) C = EllipticCurve(a=F(1), b=F(1)) e = F(3) #backdoor! we'd have to pre-compute this val = out * out * out + C.a * out + C.b print(time.time(), ":", "finding points...") points = [Point(C, F(out), F(y)) for y in tonelli_shanks(val.n, prime)] #print("points: ",points) print(time.time(), ":", "recovering states...") states = [(e.n * T).x.n for T in points] #as both candidates are additive inverses of #one another, they have the same x coordinates print(time.time(), ":", "making prng") self.p = prng(seed=states[0])
def find_point(C, x): """ C: elliptic curve x: x coordinate (FiniteField object) attempts to find a point on the curve C with x coordinate x. Only one of the points is returned, as the other can be trivially found with negation """ F = C.a.field try: # y^2 = x^3 + ax + b val = x * x * x + C.a * x + C.b y = tonelli_shanks(val.n, F.p)[0] #print("point:",x,y) return Point(C, F(x), F(y)) except Exception: #print("no possible point") return None #not a residue => no point on curve
def __init__(self, out): """ given the initial output, init out guesser so we can guess all remaining outputs """ prime = 331337 F = FiniteField(prime, 1) C = EllipticCurve(a=F(1), b=F(1)) e = F(3) #backdoor! we'd have to pre-compute this xs = [(i << 15) | out for i in range(16)] print("xs:", xs) vals = [x * x * x + C.a * x + C.b for x in xs] print("vals:", vals) print(time.time(), ":", "finding roots...") # at this point, *some* vals won't be quadratic # residues, thus invalid points. But, we must # associate each possible preimage with its root coords = [] # list of tuples (x,y) for i in range(len(xs)): try: t = tonelli_shanks(vals[i].n, prime) coords.append((xs[i], t[0])) coords.append((xs[i], t[1])) except Exception: # not quadratic residue pass print("coords:", coords) print(time.time(), ":", "making points...") points = [Point(C, F(c[0]), F(c[1])) for c in coords] print(time.time(), ":", "recovering states...") states = [(e.n * T).x.n for T in points] print("states:", states) print(time.time(), ":", "generating candidates...") self.candidates = [prng(seed=s) for s in states]