def generate(): p = getStrongPrime(1024) q = getStrongPrime(1024) n = p * q x = getRandomRange(0, n) while legendre(x, p) != -1 or legendre(x, q) != -1: x = getRandomRange(0, n) return (n, x), (p, q)
def generate(): p = getStrongPrime(1024) q = getStrongPrime(1024) n = p*q x = getRandomRange(0, n) while legendre(x, p) != -1 or legendre(x, q) != -1: x = getRandomRange(0, n) return (n, x), (p, q)
def decrypt(c, sk): p, q = sk m = 0 for z in c: m <<= 1 if legendre(z % p, p) != 1 or legendre(z % q, q) != 1: m += 1 h = '%x' % m l = len(h) return h.zfill(l + l % 2).decode('hex')
def check_pair(pair): p, q = pair print("-----") a = legendre(p, q) b = gmpy2.legendre(p, q) txt = "%d %s %d" % (a, (a == b), b) txt = txt.replace("True", "=").replace("False", "!=") print(txt) print("------") c = legendre(q, p) d = gmpy2.legendre(q, p) txt = "%d %s %d" % (c, c == d, d) txt = txt.replace("True", "=").replace("False", "!=") print(txt)
def square_modulo_root(a, p): if (p - 3) % 4 == 0: x = a**((p - 3) // 4 + 1) % p return x, p - x elif (p - 5) % 8 == 0: k = (p - 5) // 8 if a**(2 * k + 1) % p == 1: x = a**(k + 1) % p return x, p - x else: x = a**(k + 1) * 2**(2 * k + 1) % p return x, p - x else: k = (p - 1) // 8 d, s = gmpy2.remove(p - 1, 2) for num in PRIMES: if gmpy2.legendre(num, p) == -1: b = num break ta, tb = (p - 1) // 2, 0 for r in range(s - 1): ta //= 2 tb //= 2 if a**ta * b**tb % p == p - 1: tb += (p - 1) // 2 x = a**((d + 1) // 2) * b**(tb // 2) % p return x, p - x
def _equal(self, a, b): """Equality testing with secret shared result. This is the probabilistic method based on quadratic reciprocity described in: "Constant-Round Multiparty Computation for Interval Test, Equality Test, and Comparison" by Takashi Nishide and Kazuo Ohta, and fails with probability 1/(2**k) where k is the security parameter of the runtime. """ Zp = a.field yield declareReturn(self, Zp) d = a - b # We will check if d == 0 k = self.options.security_parameter x = [None] * k i = 0 while i < k: z = self.random_bit(Zp) r = self.random(Zp) rp = self.random(Zp) # If 1 - 2z == 1, c will always be a square modulo p if d == 0 # and with probability 1/2 otherwise (except if rp == 0). # If 1 - 2z == -1 it will be non-square. c = yield self.open(d * r + (1 - 2 * z) * rp * rp) if c == 0: continue x[i] = 1 - z if legendre(c.value, Zp.modulus) == 1 else z i += 1 e = self.prod(x) e = yield e #e = yield e returnValue(e)
def eratosthenes(n, lim): Beta = [-1, 2] for num in PRIMES[1:]: if gmpy2.legendre(n, num) == 1: Beta.append(num) if len(Beta) == lim - 1: break m = int(math.sqrt(n)) df = pd.DataFrame({ 'x': interval, 'x + m': [x + m for x in interval], 'b': [q(x, m, n) for x in interval] }) df['lg|b|'] = [math.log(abs(b), 10) for b in df['b']] for p in Beta[1:]: X = [] for x in congruence(m, n, p): X = find_x('+', X, x, p, lim) X = find_x('-', X, x, p, lim) if X == []: Beta.remove(p) else: df[f'lg{p}'] = [(1 if df['x'][i] in X else 0) for i in range(len(interval))] if sum(df[f'lg{p}'].values) == 1: del df[f'lg{p}'] Beta.remove(p) diff = [] for i in range(len(interval)): ans = df['lgb'][i] for p in Beta[1:]: ans -= math.log(p, 10) * df[f'lg{p}'][i] diff.append(ans) df['lg|b| - lgp'] = diff potential_Beta_numbers = df['b'][ df['lg|b| - lgp'] < np.mean(df['lg|b| - lgp'])].values.tolist() vectors, Beta_numbers = [], [] for num in potential_Beta_numbers: factorization = factorization_small_n(num) if np.in1d(factorization, Beta).all(): Beta_numbers.append(num) vectors.append([factorization.count(j) for j in Beta]) df['v'] = [(vectors[Beta_numbers.index(num)] if num in Beta_numbers else 'Not Beta') for num in df['b']] for comb in combination(vectors): if sum_vectors(comb) == len(Beta) * [0]: X, Y = 1, 1 for v in comb: X *= int( df['x + m'][df['b'] == Beta_numbers[vectors.index(v)]]) Y *= int(abs(Beta_numbers[vectors.index(v)])) Y = int(math.sqrt(Y)) d = np.gcd(X + Y, n) if 1 < d < n: return d, df d = np.gcd(X - Y, n) if 1 < d < n: return d, df return 0
def is_residue(self) -> bool: if not _is_prime(self.n): raise NotImplementedError if self.x == 0: return True if self.n == 2: return self.x in (0, 1) return gmpy2.legendre(self.x, self.n) == 1
def time_legendre(): """:performs op_number Legendre symbol evaluations for random integers of length in n_list modulo a prime of the same length :returns an array with the time needed for each integer length""" result = ["Legendre (" + str(op_number) + ")"] for n, p in zip(n_list, prime_list): b_array = get_rand_array(n, op_number) tic = time.perf_counter() _ = [legendre(b, p) for b in b_array] toc = time.perf_counter() result.append(f"{toc - tic:0.3}") return result
def read_100k_prime(): list_primes = [] with open("100k_primes.txt") as fp: for line in fp: list_primes.append(int(line.strip())) legendre_prime = [2] for i in range(1, len(list_primes)): if gmpy2.legendre(N, list_primes[i]) == 1: legendre_prime.append(list_primes[i]) print("len list prime:" + str(len(legendre_prime))) print(legendre_prime[:20]) return legendre_prime
def read_10k_prime(): list_primes = [] with open("primes10000.txt") as fp: for line in fp: list_primes.extend([int(s) for s in re.split(r'\s+', line.strip())[1:]]) legendre_prime = [2] for i in range(1, len(list_primes)): if gmpy2.legendre(N, list_primes[i]) == 1: legendre_prime.append(list_primes[i]) print("len list prime:" + str(len(legendre_prime))) print(legendre_prime[:20]) return legendre_prime
def main(): bits = 512 init = 31337 count = 16 error = 10 limit = 50_000 pt = int.from_bytes(b'the boy who lived', 'big') while True: r, N, ct, flag = load_parameters(('0.0.0.0', 17101)) primes = recover_primes(bits, N, r, r, error, limit) if primes is None: continue for p, q in primes: if p * q == N: break else: continue D = (pt * pt - 4) % N phi = lcm(p - legendre(D, p), q - legendre(D, q)) e = recover_exponent(pt, ct, p, q, phi, init, count) if e is None: continue D = (flag * flag - 4) % N phi = lcm(p - legendre(D, p), q - legendre(D, q)) d = powmod(e, -1, phi) flag = binluc(flag, d, N) print(int(flag).to_bytes(1024, 'big').strip(b'\x00')) break
def __call__(self, value: Union[int, mpz, Integer, Asn1Value]) -> QrValue: if isinstance(value, (int, mpz_type)): value %= self.p if value == 0: raise ValueError("0 not in group") return QrValue(self, value) if isinstance(value, ImgGroupValue): value = value.chosen if not isinstance(value, Integer): raise TypeError(type(value)) value = mpz(int(value)) if not 1 <= value < self.p: raise ValueError("Not a valid group element") if legendre(value, self.p) != 1: raise ValueError("Not a valid group element") return QrValue(self, value)
def __new__(cls, value): if not 2 <= value <= cls.prime - 2 or legendre(value, cls.prime) != 1: raise ValueError('invalid DH public key') instance = super(DHPublicKey, cls).__new__(cls, value) instance.__id__ = None return instance
def is_valid(cls, number): return 2 <= number <= cls.prime - 2 and legendre(number, cls.prime) == 1
def adriens_signs(): # https://math.stackexchange.com/questions/4063802/why-does-an-mod-p-always-result-in-a-number-with-legendre-symbol-as-1 c = [ 67594220461269, 501237540280788, 718316769824518, 296304224247167, 48290626940198, 30829701196032, 521453693392074, 840985324383794, 770420008897119, 745131486581197, 729163531979577, 334563813238599, 289746215495432, 538664937794468, 894085795317163, 983410189487558, 863330928724430, 996272871140947, 352175210511707, 306237700811584, 631393408838583, 589243747914057, 538776819034934, 365364592128161, 454970171810424, 986711310037393, 657756453404881, 388329936724352, 90991447679370, 714742162831112, 62293519842555, 653941126489711, 448552658212336, 970169071154259, 339472870407614, 406225588145372, 205721593331090, 926225022409823, 904451547059845, 789074084078342, 886420071481685, 796827329208633, 433047156347276, 21271315846750, 719248860593631, 534059295222748, 879864647580512, 918055794962142, 635545050939893, 319549343320339, 93008646178282, 926080110625306, 385476640825005, 483740420173050, 866208659796189, 883359067574584, 913405110264883, 898864873510337, 208598541987988, 23412800024088, 911541450703474, 57446699305445, 513296484586451, 180356843554043, 756391301483653, 823695939808936, 452898981558365, 383286682802447, 381394258915860, 385482809649632, 357950424436020, 212891024562585, 906036654538589, 706766032862393, 500658491083279, 134746243085697, 240386541491998, 850341345692155, 826490944132718, 329513332018620, 41046816597282, 396581286424992, 488863267297267, 92023040998362, 529684488438507, 925328511390026, 524897846090435, 413156582909097, 840524616502482, 325719016994120, 402494835113608, 145033960690364, 43932113323388, 683561775499473, 434510534220939, 92584300328516, 763767269974656, 289837041593468, 11468527450938, 628247946152943, 8844724571683, 813851806959975, 72001988637120, 875394575395153, 70667866716476, 75304931994100, 226809172374264, 767059176444181, 45462007920789, 472607315695803, 325973946551448, 64200767729194, 534886246409921, 950408390792175, 492288777130394, 226746605380806, 944479111810431, 776057001143579, 658971626589122, 231918349590349, 699710172246548, 122457405264610, 643115611310737, 999072890586878, 203230862786955, 348112034218733, 240143417330886, 927148962961842, 661569511006072, 190334725550806, 763365444730995, 516228913786395, 846501182194443, 741210200995504, 511935604454925, 687689993302203, 631038090127480, 961606522916414, 138550017953034, 932105540686829, 215285284639233, 772628158955819, 496858298527292, 730971468815108, 896733219370353, 967083685727881, 607660822695530, 650953466617730, 133773994258132, 623283311953090, 436380836970128, 237114930094468, 115451711811481, 674593269112948, 140400921371770, 659335660634071, 536749311958781, 854645598266824, 303305169095255, 91430489108219, 573739385205188, 400604977158702, 728593782212529, 807432219147040, 893541884126828, 183964371201281, 422680633277230, 218817645778789, 313025293025224, 657253930848472, 747562211812373, 83456701182914, 470417289614736, 641146659305859, 468130225316006, 46960547227850, 875638267674897, 662661765336441, 186533085001285, 743250648436106, 451414956181714, 527954145201673, 922589993405001, 242119479617901, 865476357142231, 988987578447349, 430198555146088, 477890180119931, 844464003254807, 503374203275928, 775374254241792, 346653210679737, 789242808338116, 48503976498612, 604300186163323, 475930096252359, 860836853339514, 994513691290102, 591343659366796, 944852018048514, 82396968629164, 152776642436549, 916070996204621, 305574094667054, 981194179562189, 126174175810273, 55636640522694, 44670495393401, 74724541586529, 988608465654705, 870533906709633, 374564052429787, 486493568142979, 469485372072295, 221153171135022, 289713227465073, 952450431038075, 107298466441025, 938262809228861, 253919870663003, 835790485199226, 655456538877798, 595464842927075, 191621819564547 ] a = 288260533169915 p = 1007621497415251 ret = '' for i in c: if legendre(gmpy2.mpz(i), gmpy2.mpz(p)) == 1: ret += '1' else: ret += '0' return ''.join(chr(int(ret[i:i + 8], 2)) for i in range(0, len(ret), 8))
def __new__(cls, value): if not 2 <= value <= cls.prime - 2 or legendre(value, cls.prime) != 1: raise ValueError('invalid SMP public key') return super(SMPPublicKey, cls).__new__(cls, value)
from Crypto.Util.number import * from gmpy2 import legendre flag = bytes_to_long(open("flag.txt", "rb").read()) p, q = getPrime(256), getPrime(256) n = p * q x = getRandomRange(0, n) while legendre(x, p) != -1 or legendre(x, q) != -1: x = getRandomRange(0, n) def gm_encrypt(msg, n, x): y = getRandomRange(0, n) enc = [] while msg: bit = msg & 1 msg >>= 1 enc.append((pow(y, 2) * pow(x, bit)) % n) y += getRandomRange(1, 2**48) return enc print("n =", n) print("x =", x) print("enc =", gm_encrypt(flag, n, x))
def jacobi_bit_mpz(a, n): return gmpy2.legendre(a, n) > 0
def main(): # Test local versions of libraries utils.test_python_version() utils.test_gmpy2_version() utils.test_pari_version() utils.test_pari_seadata() now = datetime.now() # Parse command line arguments parser = argparse.ArgumentParser(description="Generate an Edwards curve over a given prime field, suited for cryptographic purposes.") parser.add_argument("input_file", help="""JSON file containing the BBS parameters and the prime of the underlying field (typically, the output of 03_generate_prime_field_using_bbs.py. """) parser.add_argument("output_file", help="Output file where this script will write the parameter d of the curve and the current BBS parameters.") parser.add_argument("--start", type=int, help="Number of the candidate to start with (default is 1).", default=1) parser.add_argument("--max_nbr_of_tests", type=int, help="Number of candidates to test before stopping the script (default is to continue until success).") parser.add_argument("--fast", help=""" While computing a the curve cardinality with SAE, early exit when the cardinality will obviously be divisible by a small integer > 4. This reduces the time required to find the final curve, but the cardinalities of previous candidates are not fully computed. """, default=False, action="store_true") args = parser.parse_args() # Check arguments print("Checking inputs...") output_file = args.output_file if os.path.exists(output_file): utils.exit_error("The output file '%s' already exists. Exiting."%(output_file)) input_file = args.input_file with open(input_file, "r") as f: data = json.load(f) # Declare a few important variables bbs_p = int(data["bbs_p"]) bbs_q = int(data["bbs_q"]) bbs_n = bbs_p * bbs_q bbs_s = int(data["bbs_s"]) % bbs_n p = int(data["p"]) start = max(int(args.start),1) max_nbr_of_tests = None if args.max_nbr_of_tests: max_nbr_of_tests = int(args.max_nbr_of_tests) if not subroutines.is_strong_strong_prime(bbs_p): utils.exit_error("bbs_p is not a strong strong prime.") if not subroutines.is_strong_strong_prime(bbs_q): utils.exit_error("bbs_q is not a strong strong prime.") if not (subroutines.deterministic_is_pseudo_prime(p) and p%4 == 3): utils.exit_error("p is not a prime congruent to 3 modulo 4.") # Initialize BBS print("Initializing BBS...") bbs = bbsengine.BBS(bbs_p, bbs_q, bbs_s) # Info about the prime field utils.colprint("Prime of the underlying prime field:", "%d (size: %d)"%(p, gmpy2.bit_length(p))) size = gmpy2.bit_length(p) # total number of bits queried to bbs for each test # Skip the first "start" candidates candidate_nbr = start-1 bbs.skipbits(size * (start-1)) # Start looking for "d" while True: if max_nbr_of_tests and candidate_nbr >= start + max_nbr_of_tests - 1: print("Did not find an adequate parameter, starting at candidate %d (included), limiting to %d candidates."%(start, max_nbr_of_tests)) utils.exit_error("Last candidate checked was number %d."%(candidate_nbr)) candidate_nbr += 1 bits = bbs.genbits(size) d = 0 for bit in bits: d = (d << 1) | bit print("The candidate number %d is d = %d (ellapsed time: %s)"%(candidate_nbr, d, str(datetime.now()-now))) # Test 1 if not utils.check(d != 0 and d < p, "d != 0 and d < p", 1): continue # Test 2 if not utils.check(gmpy2.legendre(d, p) == -1, "d is not a square modulo p", 2): continue # Test 3 if args.fast: cardinality = subroutines.sea_edwards(1, d, p, 4) else: cardinality = subroutines.sea_edwards(1, d, p) assert(cardinality % 4 == 0) q = cardinality>>2 if not utils.check(subroutines.deterministic_is_pseudo_prime(q), "The curve cardinality / 4 is prime", 3): continue # Test 4 trace = p+1-cardinality cardinality_twist = p+1+trace assert(cardinality_twist % 4 == 0) q_twist = cardinality_twist>>2 if not utils.check(subroutines.deterministic_is_pseudo_prime(q_twist), "The twist cardinality / 4 is prime", 4): continue # Test 5 if not utils.check(q != p and q_twist != p, "Curve and twist are safe against additive transfer", 5): continue # Test 6 embedding_degree = subroutines.embedding_degree(p, q) if not utils.check(embedding_degree > (q-1) // 100, "Curve is safe against multiplicative transfer", 6): continue # Test 7 embedding_degree_twist = subroutines.embedding_degree(p, q_twist) if not utils.check(embedding_degree_twist > (q_twist-1) // 100, "Twist is safe against multiplicative transfer", 7): continue # Test 8 D = subroutines.cm_field_discriminant(p, trace) if not utils.check(abs(D) >= 2**100, "Absolute value of the discriminant is larger than 2^100", 8): continue break # Find a base point while True: bits = bbs.genbits(size) y = 0 for bit in bits: y = (y<<1) | bit u = int((1 - y**2) * gmpy2.invert(1 - d*y**2, p)) % p if gmpy2.legendre(u, p) == -1: continue x = gmpy2.powmod(u, (p+1) // 4, p) (x,y) = subroutines.add_on_edwards(x, y, x, y, d, p) (x,y) = subroutines.add_on_edwards(x, y, x, y, d, p) if (x, y) == (0, 1): continue assert((x**2 + y**2) % p == (1 + d*x**2*y**2) % p) break # Print some informations utils.colprint("Number of the successful candidate:", str(candidate_nbr)) utils.colprint("Edwards elliptic curve parameter d is:", str(d)) utils.colprint("Number of points:", str(cardinality)) utils.colprint("Number of points on the twist:", str(cardinality_twist)) utils.colprint("Embedding degree of the curve:", "%d"%embedding_degree) utils.colprint("Embedding degree of the twist:", "%d"%embedding_degree_twist) utils.colprint("Discriminant:", "%d"%D) utils.colprint("Trace:", "%d"%trace) utils.colprint("Base point coordinates:", "(%d, %d)"%(x, y)) # Save p, d, x, y, etc. to the output_file print("Saving the parameters to %s"%output_file) bbs_s = bbs.s with open(output_file, "w") as f: json.dump({"p": int(p), "bbs_p": int(bbs_p), "bbs_q": int(bbs_q), "bbs_s": int(bbs_s), "candidate_nbr": int(candidate_nbr), "d": int(d), "cardinality": cardinality, "cardinality_twist": cardinality_twist, "embedding_degree": embedding_degree, "embedding_degree_twist": embedding_degree_twist, "discriminant": D, "trace": trace, "base_point_x": x, "base_point_y": y}, f, sort_keys=True)
def jacobi_bit_mpz(a, n): global legendre_evals legendre_evals += 1 return gmpy2.legendre(a, n) > 0