diff --git a/amicable.sage b/amicable.sage index 9b3cd71..a9847bd 100644 --- a/amicable.sage +++ b/amicable.sage @@ -10,7 +10,7 @@ from itertools import combinations # p and q should each be ~ L bits. -DEFAULT_TWOADICITY = 21 +DEFAULT_TWOADICITY = 32 DEFAULT_STRETCH = 0 COEFFICIENT_RANGE = (5,) @@ -19,14 +19,10 @@ COEFFICIENT_RANGE = (5,) ACCEPTABLE_PRIMES = (5,) #ACCEPTABLE_PRIMES = Primes() -# -# It is well known that if g is neither a square nor a cube in Fp, then all -# possible group orders an elliptic curve E : y^2 = x^3 + b can have over Fp -# occur as the order of one of the 6 twists with b \in {1, g, g^2, g^3, g^4, g^5}. +TWIST_SECURITY = 120 +REQUIRE_PRIMITIVE = True +REQUIRE_HALFZERO = True -# : -# If p = 2 (mod 3) then all elements are cubes. -# If p = 1 (mod 3) then a is a cube iff a^((p-1)/3) = 1. # section 2: # [...] the order of a curve satisfying the norm equation 3V^2 = 4p - t^2 has one @@ -39,12 +35,11 @@ ACCEPTABLE_PRIMES = (5,) # = 3(V-1)^2 + 6(V-1) + (t-1)^2 + 2(t-1) + 4 # p = 3((V-1)/2)^2 + 3(V-1)/2 + ((t-1)/2)^2 + (t-1)/2 + 1 # -# So p-1 will be a multiple of 2^twoadicity, and so will (p+1-t)-1 = (p-1)-(t-1). +# So p-1 will be a multiple of 2^twoadicity, and so will q-1 for q in +# { p + 1 - t, p + 1 + (t-3V)/2 }. # -# We'd also like both p and q to be 1 (mod 3), so that we have efficient endomorphisms -# on both curves. We explicitly check p = 1 (mod 3), and then if t is chosen to be -# 1 (mod 3) then p+1-t will be 1 (mod 3) (but we must still check q since it -# is not necessarily that order). +# We'd also like both p and q to be 1 (mod 6), so that we have efficient endomorphisms +# on both curves. def low_hamming_order(L, twoadicity, wid, processes): Vlen = (L-1)//2 + 1 @@ -69,16 +64,17 @@ def low_hamming_order(L, twoadicity, wid, processes): if p % 6 == 1 and is_pseudoprime(p): yield (p, t, V) + def near_powerof2_order(L, twoadicity, wid, processes): trailing_zeros = twoadicity+1 Vbase = isqrt((1<<(L+1))//3) >> trailing_zeros - for Voffset in symmetric_range(10000, base=wid, step=processes): + for Voffset in symmetric_range(100000, base=wid, step=processes): V = ((Vbase + Voffset) << trailing_zeros) + 1 assert(((V-1)/2) % (1 << twoadicity) == 0) tmp = (1<<(L+1)) - 3*V^2 if tmp < 0: continue tbase = isqrt(tmp) >> trailing_zeros - for toffset in symmetric_range(10000): + for toffset in symmetric_range(100000): t = ((tbase + toffset) << trailing_zeros) + 1 assert(((t-1)/2) % (1<>(L//2) != 1<<(L - 1 - L//2): + continue + if p > 1<<(L-1) and p % 6 == 1 and is_pseudoprime(p): yield (p, t, V) -def find_nonsquare_noncube(p): - for g_int in xrange(2, 1000): - g = Mod(g_int, p) - if g^((p-1)//3) != 1 and g^((p-1)//2) != 1: - return g - return None - def symmetric_range(n, base=0, step=1): for i in xrange(base, n, step): yield -i @@ -109,34 +101,100 @@ def find_nice_curves(strategy, L, twoadicity, stretch, wid, processes): for (q, qdesc) in ((p + 1 - t, "p + 1 - t"), (p + 1 + (t-3*V)//2, "p + 1 + (t-3*V)/2")): - if q > 1<<(L-1) and q % 6 == 1 and q % (1<>(L//2) != 1<<(L - 1 - L//2): + continue + + if q not in (p, p+1, p-1) and q > 1<<(L-1) and q % 6 == 1 and q % (1<