def our_CRT(y, d, p, q, r): """ Chinese Remainder Theorem as performed with our modular exponentiation and inverse. :param y: :param d: :param p: :param q: :param r: :return: CRT result + computation time """ # time: start = time.time() # Fermat for computing x_p, x_q, x_r: x_p = modular_exponentiation(y % p, d % (p - 1), p) x_q = modular_exponentiation(y % q, d % (q - 1), q) x_r = modular_exponentiation(y % r, d % (r - 1), r) # CRT the school way: N = p * q * r N1 = N // p N2 = N // q N3 = N // r x1 = sympy.mod_inverse(N1, p) x2 = sympy.mod_inverse(N2, q) x3 = sympy.mod_inverse(N3, r) x = ((x_p * x1 * N1) + (x_q * x2 * N2) + (x_r * x3 * N3)) % N # returning CRT result + time return x, time.time() - start
def __init__(self, bits_modulo=2048, e=2**16 + 1): """ Genera una clau RSA (de 2048 bits i amb exponent públic 2**16+1 per defecte). """ self.publicExponent = e self.primeP = sympy.randprime(pow(2, (bits_modulo - 1)), pow(2, bits_modulo)) self.primeQ = sympy.randprime(pow(2, (bits_modulo - 1)), pow(2, bits_modulo)) while not self.p_and_q_coprimes_with_e( ) and self.primeP == self.primeQ: self.primeP = sympy.randprime(pow(2, (bits_modulo - 1)), pow(2, bits_modulo)) self.primeQ = sympy.randprime(pow(2, (bits_modulo - 1)), pow(2, bits_modulo)) self.modulus = self.primeP * self.primeQ self.privateExponent = sympy.mod_inverse( self.publicExponent, (self.primeP - 1) * (self.primeQ - 1)) self.privateExponentModulusPhiP = self.privateExponent % (self.primeP - 1) self.privateExponentModulusPhiQ = self.privateExponent % (self.primeQ - 1) self.inverseQModulusP = sympy.mod_inverse(self.primeQ, self.primeP)
def crack_rsa(e, N): phi_N = (primefactors(N, False)[1] - 1) * (primefactors(N, False)[2] - 1) d = mod_inverse(e, phi_N) #validation of cracked private key if (mod_inverse(d, phi_N) != e): return "ERROR" return (d, N)
def __add__(self, Q): x_1, y_1, x_2, y_2 = self.x, self.y, Q.x, Q.y if (x_1, y_1) == (x_2, y_2): # case where P + P + 0 = 0 (only one point on curve) if y_1 == 0: return Point(self.curve, x_1, y_1) # case where P + P + Q = 0 (two points on curve) s = ((3 * pow(x_1, 2) + self.curve.a) / (mod_inverse(2 * y_1, self.mod))) % self.mod else: # case where P + Q + 0 = 0 (vertical line) if x_1 == x_2: return Point(self.curve, self.x, self.y) # case where P + Q + r = 0 (tree points on curve) s = ((y_2 - y_1) / (mod_inverse(x_2 - x_1, self.mod))) % self.mod self.x = (pow(s, 2) - x_2 - x_1) % self.mod self.y = ((s * (self.x - x_1)) + y_1) % self.mod print(self.x, self.y) # return for drawing the resulting point return Point(self.curve, self.x, -self.y)
def our_CRT(e, d, p, q, y): """ Chinese Remainder Theorem as performed with our modular exponentiation and inverse. :param e: :param d: :param p: :param q: :param y: :return: result + time """ # time: start = time.time() x_q = modular_exponentiation(y % q, d % (q - 1), q) # Hensel: x0 = modular_exponentiation(y % p, d % (p - 1), p) x1 = (((y - modular_exponentiation(x0, e, p * p)) / p) * modular_inverse(e * modular_exponentiation(x0, e - 1, p * p), p)) % p x_p2 = int((x1 * p + x0) % (p * p)) # for CRT: # moduli = [p * p, q] # residues = [x_p2, x_q] # return crt(moduli, residues)[0], time.time() - start # CRT: N = p * p * q N1 = q N2 = p * p x1 = sympy.mod_inverse(N1, p * p) x2 = sympy.mod_inverse(N2, q) x = ((x_p2 * x1 * N1) + (x_q * x2 * N2)) % N return x, time.time() - start
def summ(x1, y1, x2, y2, fp): t1 = y2 - y1 t2 = x2 - x1 x3 = ((t1 * mod_inverse(t2, fp) % fp)**2 - (x1 + x2)) % fp y3 = (-y1 + (t1 * mod_inverse(t2, fp) % fp) * (x1 - x3)) % fp return x3, y3
def compute_free_coef(z, a, prime, x=0): product_of_inverses = [] inverses = np.zeros(int((prime + 1) / 2)) free_coef = 0 check_product = [] for i in a: product_of_inverses = [] # check_product = [] for j in a: if j != i: to_inverse = (i - j) % prime if to_inverse >= int((prime + 1) / 2): if inverses[-to_inverse % prime] == 0: # print("compute inverse") inverses[-to_inverse % prime] = sympy.mod_inverse( -to_inverse % prime, prime) product_of_inverses.append( int((x - j) * (-inverses[-to_inverse % prime]) % prime)) else: if inverses[to_inverse] == 0: # print("compute inverse") inverses[to_inverse] = sympy.mod_inverse( to_inverse, prime) product_of_inverses.append( int((x - j) * inverses[to_inverse] % prime)) check_product.append((x - j) * sympy.mod_inverse( (i - j), prime) % prime) # print(inverses) # print("check:", check_product) # print("product:", product_of_inverses) free_coef += z[i - 1] * np.product(product_of_inverses) # print(free_coef % prime) # print(check_product) return free_coef % prime
def crack_schnorr(s1, s2, w_, open): p, q, g, y = open t1 = s2 * mod_inverse(s2 - w_ * s1, q) t2 = s1 * mod_inverse(s2 - w_ * s1, q) print(g, t1, y, t2) g_ = (naive_mod_pow(g, t1, p) * naive_mod_pow(y, t2, p)) % p y_ = mod_inverse(naive_mod_pow(g_, w_, p), p) return p, q, g_, y_
def summodinak(x1, y1, a, fp): a = a % fp t1 = 3 * x1**2 + a t2 = 2 * y1 x3 = (t1 * mod_inverse(t2, fp) % fp)**2 - 2 * x1 y3 = -y1 + (t1 * mod_inverse(t2, fp) % fp) * (x1 - x3) return x3 % fp, y3 % fp
def __eq__(self, other): """Two points are equal if X/Z of both points are equal """ from sympy import mod_inverse if self.a_24 != other.a_24 or self.mod != other.mod: return False return self.x_cord * mod_inverse(self.z_cord, self.mod) % self.mod ==\ other.x_cord * mod_inverse(other.z_cord, self.mod) % self.mod
def calculate_slope(x1, y1, x2, y2, prime, a): assert x1 == x1 % prime assert y1 == y1 % prime assert x2 == x2 % prime assert y2 == y2 % prime return (mod_inverse(2 * y1, prime) * (3 * x1**2 + a) % prime if (x1, y1) == (x2, y2) else mod_inverse(x2 - x1, prime) * (y2 - y1) % prime)
def checaInv(l, n): inv = True try: mod_inverse(l, n) # Manejamos la excepción que lanza el mod_inverse cuando no existe # el inverso modular para aprovecharlo en la bandera y regresar False except: inv = False return inv
def garner(y, d, p, q, r): start = time.time() mp = pow(y % p, d % (p - 1), p) mq = pow(y % q, d % (q - 1), q) mr = pow(y % r, d % (r - 1), r) x = mp alpha = (((mq - x) % q) * sympy.mod_inverse(mp, q)) % q x += alpha * mp alpha = (((mr - x) % r) * sympy.mod_inverse(mp * mq, r)) % r x += alpha * mp * mq end = time.time() - start return x, end
def Garner(a_, b_, c_, ar_, br_, cr_): a = int(a_) b = int(b_) c = int(c_) ar = int(ar_) br = int(br_) cr = int(cr_) x = ar + (br - ar) * sym.mod_inverse(a, b) % b * a x = x + (cr - x % c) * sym.mod_inverse(a, c) % c * sym.mod_inverse( b, c) % c * a * b #x %= a*b*c #a<b<cのときこの処理は必要ない return x
def reduce(MOD, NITER, POS): difference, initial = 1, 0 for line in data: command, *_, N = line.split() if N == 'stack': difference *= -1 initial += difference elif command == 'cut': initial += int(N) * difference else: difference *= mod_inverse(int(N), MOD) # ...or just use Fermat's little theorem. initial *= mod_inverse(1 - difference, MOD) # Geometric series difference = pow(difference, NITER, MOD) return ((POS - initial) * difference + initial) % MOD
def elliptic_curve_sum(e_curve, p1, p2): lam = 0 # lambda - slope of the line through two points if p1 == p2: # p1 and p2 are the same point lam = (3 * pow(p1.x, 2) + e_curve.a) * sympy.mod_inverse( 2 * p1.y, e_curve.p) else: # p1 and p2 are different lam = (p2.y - p1.y) * sympy.mod_inverse(p2.x - p1.x, e_curve.p) # finding resulting point x_res = (pow(lam, 2) - p1.x - p2.x) % e_curve.p y_res = (lam * (p1.x - x_res) - p1.y) % e_curve.p # returning resulting point res_point = Point(x_res, y_res) return res_point
def reduction_sparse_matrix(boundary_matrix, mod): """Return reduced boundary matrix in column echelon form, basis elements for each column and indices of all zero columns. All operations are done modulo mod. Parameters: boundary matrix -- as in the function sparse_boundary_matrix mod -- positive integer Return: reduced_matrix -- reduced matrix in echelon form in the sparse format, given as a list of pairs which are initially all equal to ([], None) reduced_matrix[i] = (col, j) iff j-th column has lowest nonzero entry in i-th row column col is given in ordered sparse format with lowest entry equal to 1 zero_columns -- a list of indices of zero columns in reduced matrix columns -- a list of dictionaries, columns[i] represents the basis element (chain) for the i-th column columns[i] is a dictionary: key = indeks of a simplex in the total ordering of the filtration value = coefficient (only nonzero) for the simplex in the chain """ m = len(boundary_matrix) reduced_matrix = [([], None) for _ in range(m)] # print_sparse(boundary_matrix) # print('\n') zero_columns = [] columns = [{i: 1} for i in range(m)] # We start with the standard basis. for j in range(m): column = boundary_matrix[j] while len(column) > 0 and len(reduced_matrix[column[0][0]][0]) > 0: # Reduce the column. add_chains(columns[j], columns[reduced_matrix[column[0][0]][1]], - column[0][1], mod) column = add_columns(column, reduced_matrix[column[0][0]][0], - column[0][1], mod) if len(column) > 0: # New pivot column. mult_column(column, sp.mod_inverse(column[0][1], mod), mod) mult_chain(columns[j], sp.mod_inverse(column[0][1], mod), mod) reduced_matrix[column[0][0]] = (column, j) else: # New zero column. zero_columns.append(j) # test_matrix = reduced_matrix[:j+1] + boundary_matrix[j+1:] # print_sparse(test_matrix) # print('\n') # print('boundary_matrix') # print_sparse1(reduced_matrix) return reduced_matrix, zero_columns, columns
def brute_force_attack(n, e, encrypted_data): prime_factors = [] i = 2 while (i * i <= n): if n % i == 0: prime_factors = [i, n / i] break i += 1 p = prime_factors[0] q = prime_factors[1] phi = (p - 1) * (q - 1) # gcd = GCDExtended(e, phi, d, k) # print(d, k) # Private key d = mod_inverse(e, phi) # Decrypted data. decrypted_data = "".join([chr(pow(char, d, n)) for char in encrypted_data]) return decrypted_data
def multiprime_RSA(iterations=10): average_time = 0 for iteration in range(iterations): print("Iteration:", iteration) p, q, r = generate_pqr_primes() e = pow(2, 16) + 1 n = p * q * r phi_n = (p - 1) * (q - 1) * (r - 1) condition = gcd(e, phi_n) while condition != 1: p, q, r = generate_pqr_primes() n = p * q * r phi_n = (p - 1) * (q - 1) * (r - 1) condition(e, phi_n) d = sympy.mod_inverse(e, phi_n) y = encrypt_message("message.txt", n, e) # print("p:", p) # print("q:", q) # print("r:", r) # print("e:", e) # print("d:", d) # print("m:", int.from_bytes(get_message(path="message.txt"), byteorder=sys.byteorder)) # print("y:", y) x_decrypt, time_decrypt = decrypt(y, d, n) x_garner, time_garner = garner(y, d, p, q, r) print("\ty decrypted with python library:", x_decrypt) print("\ty decrypted with Garner:", x_garner) print("\tgarner vs python function time:", time_decrypt/time_garner) average_time += time_decrypt/time_garner print(average_time/10)
def pollig_hellman(base, result, field): """ Function finds a logarithm from given result with given base using Pollig-Hellman's algorythm.\n Algorythm works on cyclic multiplicative groups with simple fields and compound fields.\n :param int base: base of a logarithm\n :param int result: result of a logarithm\n :param int field: field of a cyclic multiplicative group\n """ rng = find_representation(field)[0] ftrs = [] rslt = int() if pow(result, (field - 1) // 2, field) == 1: ftrs.append(0) else: ftrs.append(1) for dgr in range(1, rng): dg = int() index = int() for ftr in ftrs: dg += ftr * (2**index) index += 1 z = (result * pow(mod_inverse(base, field), dg, field)) % field m = ((field - 1) // pow(2, dgr + 1, field)) % field if pow(z, m, field) == 1: ftrs.append(0) else: ftrs.append(1) rslt += ftrs[0] for ftr in range(1, len(ftrs)): rslt += (ftrs[ftr] * pow(2, ftr, field)) % field return rslt
def test_idiv(x, y): xs, ys = Scalar(x), Scalar(y) x = x * sympy.mod_inverse(y, GROUP_ORDER) xs /= ys x %= GROUP_ORDER assert int(xs) == x assert int(ys) == y
def mod(x, modulus): numer, denom = x.as_numer_denom() try: return numer * sympy.mod_inverse(denom, modulus) % modulus except: print('Error: Unable to apply modulus to matrix') exit()
def GenSign(file): signeble_file = open(file, "rb") sing_file = open(file + "_sign.dat", 'wb') readFile = signeble_file.read() sha1Hash = hashlib.sha1(readFile) hash_int = int(sha1Hash.hexdigest(), 16) k = random.randrange(r) while math.gcd(k, r) != 1: k = random.randrange(r) w = pow(g, k, p) s = ((hash_int - x * w) * mod_inverse(k, r)) % (r) sign = el_gamal_sign_file.encode( 'ElGamalSignFile', dict(keyset={ 'key': dict(algid=b'\x80\x06\x02\x00', test='testSign', keydata={'b': b}, param={ 'prime': p, 'r': r, 'generator': g }, ciphertext=dict(w=w, s=s)) }, last={})) sing_file.write(sign) sing_file.close() print("sign generated") return file + "_sign.dat"
def gen_keys(_p: int, _q: int) -> tuple: """Generating private and public keys :param _p: first prime number :param _q: second prime number :return: the public and private key pairs """ # modulus for public and private keys n = _p * _q # totient # see https://simple.wikipedia.org/wiki/Euler's_totient_function phi = (_p - 1) * (_q - 1) # picking e > 1 corpime to phi # see https://simple.wikipedia.org/wiki/Coprime e = secrets.randbelow(phi) + 1 while math.gcd(e, phi) != 1: e = secrets.randbelow(phi) + 1 # evaluate d using Extended Euclidean algorithm # see: https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm d = sympy.mod_inverse(e, phi) # (e, n) -> public key pair # (d, n) -> private key pair return (e, n), (d, n)
def lagrange_coefficient(i: int, ids: List[int]) -> int: result = 1 for j in ids: if i != j: result *= j * sympy.mod_inverse((j - i) % CURVE_ORDER, CURVE_ORDER) result %= CURVE_ORDER return result
def __truediv__(self, other): if (not isinstance(other, Zm)): return NotImplemented elif (self.m != other.m): return NotImplemented else: return Zm(self.data * mod_inverse(other.data, other.m), self.m)
def get_inverse(key_matrix, n): inv_det = sympy.mod_inverse((int(round(numpy.linalg.det(key_matrix)%26))), 26) if n == 2: adj = numpy.zeros(shape=(n, n)) adj[0][0] = key_matrix[1][1] adj[1][1] = key_matrix[0][0] adj[0][1] = (key_matrix[0][1])*-1 adj[1][0] = (key_matrix[1][0])*-1 inv_key_matrix = numpy.dot(inv_det, adj) return inv_key_matrix else: adj = numpy.zeros(shape=(n, n)) flip = True for row in range(3): for col in range(3): tmp = numpy.delete(key_matrix, row, axis=0) tmp = numpy.delete(tmp, col, axis=1) det = int(round(numpy.linalg.det(tmp)))%26 if not flip: det = (det*-1)%26 adj[col][row] = det flip = not flip inv_key_matrix = numpy.dot(inv_det, adj)%26 return inv_key_matrix
def reduce_vect(top_list, vect, mod): """Return the reduced vector and its coefficients with respect to the basis in top_list, working modulo mod. Parameters: top_list -- a list of basis elements as returned in the function complete_basis vect -- a vector to reduce against the basis in top_list Return: vect -- reduced form of the vector top -- top nonzero index in vect (reduced form), if vect reduces to the zero vector then top is None coeffs -- a dictionary: key = index of basis vector in top_list value = coefficient at this basis vector when expanding vect in terms of top_list """ vect = vect.copy() top = None coeffs = dict() n = len(vect) for i in range(n): if (vect[i] % mod) == 0: continue if top_list[i][1] is not None: base = top_list[i][0] inv = sp.mod_inverse(base[i], mod) coeff = (inv * vect[i]) % mod coeffs[i] = coeff for j in range(i, n): vect[j] = (vect[j] - coeff * base[j]) % mod else: top = i break return vect, top, coeffs
def verify(self, id, TR, TRV, Pverification, hashCombination): # Pverification is prover's verifications if id > 20: # firstly, verify id hex_as_int = int(hashCombination, 16) # convert to decimal hex_as_binary = bin(hex_as_int) # convert to binary form for i in range(self.x): # the reason why I used binary_string[i+2] is because python shows 0b at the beginning of a binary # number and it violate the randomness for choosing bit so I start the loop by add 2 to it. if hex_as_binary[i+2] == '0': # we take it and calculate it to the power of e mod n so that it would equal to --- self.verification[i] = (Pverification[i] ** self.Pkey[0]) % self.Pkey[1] else: md5 = hashlib.md5() c = str(id) + str(TR) + str(TRV) md5.update(c.encode('utf-8')) hash = int(md5.hexdigest(), 16) modular_inverse = sympy.mod_inverse(hash, self.Pkey[1]) self.verification[i] = ((Pverification[i] ** self.Pkey[0]) * modular_inverse) % self.Pkey[1] newCombination = str(id) + str(TR) + str(TRV) for i in range(self.x): newCombination += str(self.verification[i]) md5 = hashlib.md5() md5.update(newCombination.encode('utf-8')) newhashCombination = md5.hexdigest() print("Hash combination from verifier: ", newhashCombination) if newhashCombination == hashCombination: return True else: return False
def decrypt_message(self): factors = self.__find_prime_factors(self.__n_coef) if len(factors) != 2: raise ValueError('The N coefficient does not have two factors') phi = self.__calc_eulers_phi_for_primes(factors[0], factors[1]) d_coef = sympy.mod_inverse(self.__e_coef, phi) return self.__rsa_decrypt(d_coef)