def pohe(g, h, p, order, factors): """ Pohlig-Hellman-Algorithm :param g: :param h: :param p: :param order: :param factors: :return: alpha """ alphas = [] for p_i, e_i in factors: # CRT p_e = p_i ** e_i # necessarily < p order_i = p_e - 1 print('Mod {}^{} = {}...'.format(p_i, e_i, p_e)) # compute all the l l = [] a_i = 0 for k in range(e_i): # k is the exponent base = me(g, order // p_i, p) # compute power (power = base**lk) tmp_exp = 0 for j in range(k): tmp_exp += l[j] * p_i ** j tmp_base = me(g, order // (p_i ** (k + 1)), p) tmp_power = me(tmp_base, tmp_exp, p) tmp_power = modinv(tmp_power, p) power = (me(h, order // (p_i ** (k + 1)), p) * tmp_power) % p # baby-step-giant-step lk = bsgs(power, base, order, p) % p_i l.append(lk) a_i += lk * p_i ** k print('\tFound l_{} = {}'.format(k, lk)) alphas.append(a_i) print('alpha for p_i {} = {}'.format(p_i, a_i)) # reverse CRT: construct alpha from all a_i alpha = 0 for i in range(len(factors)): p_i, e_i = factors[i] p_e = p_i ** e_i product = alphas[i] for j in range(len(factors)): if j == i: continue p_e_j = factors[j][0] ** factors[j][1] product *= p_e_j * modinv(p_e_j, p_e) product %= order alpha += product alpha %= order print('---- Final alpha: {} -----'.format(alpha)) return alpha
def generate_key(modulus_length): prime_length = modulus_length // 2 # public exponent e = 3 # generate first prime number p = 4 while (p - 1) % e == 0: p = utils.generate_prime(prime_length) # generate second prime number q = p while q == p or (q - 1) % e == 0: q = utils.generate_prime(prime_length) n = p * q phi = (p - 1) * (q - 1) d = utils.modinv(e, phi) public_key = (n, e) secret_key = (n, d) return public_key, secret_key
def sign(msg, g, p, x): m = msg_hash(msg) k = prime_with(p - 1) r = pow(g, k, p) s = ((m - x * r) * modinv(k, p - 1)) % (p - 1) return (r, s)
def TME1(): a = int(input("a = ")) b = int(input("b = ")) n = int(input("n = ")) ia = modinv(a, n) print(-b * ia) return
def decrypt_affine(self, cipher, a=None, b=None): ''' P = (a^-1 * (C - b)) % 26 ''' if a is None and b is None: a, b = self.key return ''.join([ chr((( modinv(a, 26)*(ord(c) - ord('A') - b) ) % 26) + ord('A')) for c in cipher ])
def decrypt(text, offset, factor=1): """Decrypts text letter : character """ if type(text) is not str: raise CaesarError('Can only decrypt strings.') offset = offset % 26 if factor % 2 == 0 or factor % 13 == 0: raise CaesarError("factor value must not be divisible by 2 or 13.") factor = factor % 26 factor_inv = utils.modinv(factor, 26) def decrypt_letter(letter): """Decrypts a single letter letter : character """ if not utils.is_letter(letter): raise CaesarError("`letter` must be a single English \ capital letter.") A = ord('A') return chr((factor_inv * (ord(letter) - A - offset)) % 26 + A) return ''.join([decrypt_letter(letter) for letter in utils.fix_text(text)])
def pollard_rho(curve, g, f, n, init_a=1, init_b=0, max_tries=3): if max_tries == 0: return None # ri1 = ai1*g + bi1*f ag = curve.mult(init_a, g) bf = curve.mult(init_b, f) ag_bf = curve.add(ag, bf) ri1, ai1, bi1 = ag_bf, init_a, init_b ri2, ai2, bi2 = ag_bf, init_a, init_b # One step for ri1, 2 steps for ri2 ri1, ai1, bi1 = pollard_rho_step(curve, g, f, n, ri1, ai1, bi1) ri2, ai2, bi2 = pollard_rho_step(curve, g, f, n, ri2, ai2, bi2) ri2, ai2, bi2 = pollard_rho_step(curve, g, f, n, ri2, ai2, bi2) while ri1 != ri2: ri1, ai1, bi1 = pollard_rho_step(curve, g, f, n, ri1, ai1, bi1) ri2, ai2, bi2 = pollard_rho_step(curve, g, f, n, ri2, ai2, bi2) ri2, ai2, bi2 = pollard_rho_step(curve, g, f, n, ri2, ai2, bi2) # Now, ri1 = ri2 # ai1*g + bi1*f = ai2*g + bi2*f # (ai1-ai2)*g = (bi2-bi1)*f # x = (ai1-ai2)/(bi2-bi1) = (ai2-ai1)/(bi1-bi2) # An edge case where we get 0*G = 0*F. In this case we start from scratch, # but with random(different) initial values. The probability that this will # continuously fail should be fairly low. Nonetheless, we exit after `max_tries` failures if (bi1 - bi2) % n == 0: return pollard_rho(curve, g, f, n, init_a + randrange(0, n), init_b + randrange(0, n), max_tries - 1) x = ((ai2 - ai1) * modinv(bi1 - bi2, n)) % n return x
def decrypt_mh(message, private_key): """Decrypt an incoming message using a private key 1. Extract w, q, and r from the private key 2. Compute s, the modular inverse of r mod q, using the Extended Euclidean algorithm (implemented at `utils.modinv(r, q)`) 3. For each byte-sized chunk, compute c' = cs (mod q) 4. Solve the superincreasing subset sum using c' and w to recover the original byte 5. Reconsitite the encrypted bytes to get the original message back @param message Encrypted message chunks @type message list of ints @param private_key The private key of the recipient @type private_key 3-tuple of w, q, and r @return bytearray or str of decrypted characters """ w, q, r = private_key s = utils.modinv(r, q) result = '' for chunk in message: c_prime = chunk * s % q w_rev = w[::-1] byte = [0] * len(w) for i, w_i in enumerate(w_rev): if w_i <= c_prime: byte[i] = 1 c_prime -= w_i result += chr(utils.bits_to_byte(byte[::-1])) return result
def signing(self, message): m = self.__encode_md5(message) self.K = random.randint(1, self.q-1) while gcd(self.K, self.q-1) != 1: self.K = random.randint(1, self.q-1) s1 = pow(self.a, self.K, self.q) s2 = modinv(self.K, self.q-1)*(m - self.X*s1)%(self.q-1) return s1, s2
def keygen(self): p = sp.randprime(2**64, 2**128) q = sp.randprime(2**64, 2**128) n = p * q j_n = (p - 1) * (q - 1) e = coprime(j_n) d = modinv(e, j_n) return (d, n, e)
def sign(self, message): m = text_to_hash(message) y, g, p = self.public_key x = self.private_key k = self._get_k() a = pow(g, k, p) inv_k = modinv(k, p - 1) b = (m - x * a) * inv_k % (p - 1) return a, b
def add(self, pt1, pt2): if pt1.is_origin(): return pt2 if pt2.is_origin(): return pt1 if (pt1.y + pt2.y) % self.p == 0 and pt1.x == pt2.x: return self.origin() if pt1.x == pt2.x and pt1.y == pt2.y: temp = (((3 * pt1.x * pt1.x) + self.a) * modinv(2 * pt1.y, self.p)) % self.p else: temp = ((pt2.y - pt1.y) * modinv(pt2.x - pt1.x, self.p)) % self.p x = (temp * temp - pt1.x - pt2.x) % self.p y = (temp * (pt1.x - x) - pt1.y) % self.p pt = ec_point(x, y) self.assert_check(pt) return pt
def smart(curve, P, Q): A = curve.a x1, y1 = hensel_lift(curve, P) x2, y2 = hensel_lift(curve, Q) lifted_p = curve.p**2 lifted_a = (y2**2 - y1**2 - (x2**3 - x1**3)) lifted_a = (lifted_a * modinv(x2 - x1, lifted_p)) % lifted_p lifted_b = (y1**2 - x1**3 - A * x1) % lifted_p modulo = curve.p**2 # do not verify curve params lifted_curve = ec_curve(lifted_a, lifted_b, lifted_p, verify=False) lifted_pt1 = lifted_curve.mult(curve.p - 1, lifted_curve(x1, y1)) lifted_pt2 = lifted_curve.mult(curve.p - 1, lifted_curve(x2, y2)) dx1 = ((lifted_pt1.x - x1) // curve.p) % modulo dy1 = ((lifted_pt2.x - x2) // curve.p) % modulo dx2 = lifted_pt1.y - y1 dy2 = lifted_pt2.y - y2 m = (dy1 * dx2 * modinv(dx1 * dy2, modulo)) % modulo return m % curve.p
def M(n): fs = [p**pp for p, pp in factorize(n)] f2 = [n // f * modinv(n // f, f) % n for f in fs] ans = 0 for i in range(2**len(fs)): cur = sum(f2[j] for j in range(len(fs)) if i & (1 << j)) ans = max(ans, cur % n) return ans
def test_montgomery(): random.seed(42) k, n, d = 4, 2, 0 c = point.Curve() c.a, c.b, c.p = 4, 20, 29 c.r = 256 c.r_minus1 = utils.modinv(c.r - c.p, c.p) # r > p c.r2 = (c.r**2) % c.p c.pp = (2**(k*(d+1))) - utils.modinv(c.p, 2**(k*(d+1))) c.pt = (c.pp % (2**(k*(d+1)))) * c.p c.k, c.n, c.d = k, n, d c2 = utils.convert_curve_to_montgomery(c, c.p, c.r, c.r2) p1s = point_simple.Point(1, 5) p2s = point_simple.Point(20, 3) p1 = point.Point(1, 5) p2 = point.Point(20, 3) p1 = utils.convert_point_to_montgomery(p1, c.p, c.r, c.r2) p2 = utils.convert_point_to_montgomery(p2, c.p, c.r, c.r2) p3s = point_simple.add_simple(p1s, p1s, c) p3 = point.add_montgomery(p1, p1, c2) p3 = utils.convert_point_to_standard(p3, c.p, c.r) p3 = utils.projective_to_standard(p3, c) if(p3s.x != p3.x or p3s.y != p3.y): print "Addition is broken!" exit(1) p3 = point.add_montgomery(p1, p2, c2) p3 = utils.convert_point_to_standard(p3, c.p, c.r) p3 = utils.projective_to_standard(p3, c) p3s = point_simple.add_simple(p1s, p2s, c) if(p3s.x != p3.x or p3s.y != p3.y): print "Addition is broken!" exit(1)
def decrypt(self, criptotext): message = "" for c in criptotext: punto, x = c s = (pow(punto[0], 3) + self.curve.A*punto[0] + self.curve.B) % self.curve.p while not is_square(s): s += self.curve.p raiz = int(math.sqrt(s)) if punto[1]==1: raiz *= -1 pt_desc = ec.scalar_multiplication((punto[0], raiz), self.s, self.curve) valorFinal = (x * modinv(pt_desc[0]%self.curve.p, self.curve.p)) % self.p message += self.alphabet[valorFinal] return message
def add_simple(p1, p2, c): p1.z = 0 p2.z = 0 inf = Point() if(p1 == inf): return p2 if(p2 == inf): return p1 l = 1 if(p1 == p2): if(p1.y == 0): return inf l = (((3 * (p1.x**2) % c.p) % c.p) + c.a) % c.p l = (l * modinv(2*p1.y, c.p)) % c.p else: if(p1.x == p2.x): return inf l = (p2.y - p1.y) % c.p l = (l * modinv((p2.x - p1.x) % c.p, c.p)) % c.p p3 = Point() p3.x = (((l*l) % c.p) - ((p1.x + p2.x) % c.p)) % c.p p3.y = ((l * ((p1.x - p3.x) % c.p)) % c.p - p1.y) % c.p return p3
def decrypt_mh(message, private_key): """Decrypt an incoming message using a private key 1. Extract w, q, and r from the private key 2. Compute s, the modular inverse of r mod q, using the Extended Euclidean algorithm (implemented at `utils.modinv(r, q)`) 3. For each byte-sized chunk, compute c' = cs (mod q) 4. Solve the superincreasing subset sum using c' and w to recover the original byte 5. Reconsitite the encrypted bytes to get the original message back @param message Encrypted message chunks @type message list of ints @param private_key The private key of the recipient @type private_key 3-tuple of w, q, and r @return bytearray or str of decrypted characters complex math, and the explanations are on https://github.com/stanfordpython/python-assignments/blob/master/assign1/README.md """ message_decrypt = [] w, q, r = private_key c = message s = utils.modinv(r, q) c_Prime = [] for char1, char2 in zip(message, w): #a_n = utils.byte_to_bits(ord(char)) #c.append( sum([x*y for x,y in zip(a_n, b_n)]) ) c_Prime.append(char1*s%q) # Solve the superincreasing subset sum using c' and w to recover the original byte for letter in c_Prime: temp = letter zzz = [] for char in w[::-1]: if temp >= char: temp -= char zzz.append(1) else: zzz.append(0) message_decrypt.append( chr(utils.bits_to_byte(zzz[::-1])) ) return ''.join(message_decrypt)
def send_answer(group_id, answer, public_keys, user_index, p, q, x_i): g_y_i = modulo_multiply(public_keys[:user_index], p) * modinv( modulo_multiply(public_keys[user_index + 1:], p), p) # if veto if answer == 1: exponent = random.randint(0, q - 1) else: exponent = x_i # (g^{y_i})^ g_c_i_y_i = modulo_pow(g_y_i, exponent, p) requests.post( f"{SERVER_URL}/group/{group_id}/vote", data={"vote": g_c_i_y_i}, verify=False, )
def gen_priv_key(n): knapsack_vector = [ random.randint((2**(i - 1) - 1) * (2**n), (2**(i - 1) * (2**n))) for i in range(1, n + 1) ] modulus = random.randint(2**(2 * n + 1) + 1, 2**(2 * n + 2) - 1) while True: w_inv = random.randint(2, modulus - 2) if math.gcd(w_inv, modulus) == 1: break w = modinv(w_inv, modulus) return { 'a_prim': knapsack_vector, 'w': w, 'w_inv': w_inv, 'modulus': modulus, }
def fiat_shamir(self, L, R, P): """Generates a challenge value x from the "transcript" up to this point, using the previous hash, and uses the L and R values from the current iteration, and commitment P. Returned is the value of the challenge and its modular inverse, as well as the squares of those values, both as integers and binary strings, for convenience. """ xb = hashlib.sha256("".join([self.fsstate] + [str(_) for _ in [L, R, P]])).digest() self.fsstate = xb x = decode(xb, 256) % N x_sq = (x * x) % N xinv = modinv(x, N) x_sq_inv = (xinv * xinv) % N x_sqb, xinvb, x_sq_invb = [ encode(_, 256, 32) for _ in [x_sq, xinv, x_sq_inv] ] return (x, xb, x_sq, x_sqb, xinv, xinvb, x_sq_inv, x_sq_invb)
def decipher(self, criptotext): """ Descifra el mensaje recuperando el texto plano siempre y cuando haya sido cifrado con el cifrado afín. Parámetro: criptotext -- el mensaje a descifrar. """ dic={}#Dada la letra obtendremos su indice for i in range(len(self.alphabet)): dic[self.alphabet[i]] = i new_message="" #Aplicamos la formula para descifrar el mensaje usando el #algoritmo extendido de euclides para poder encontrar el modular inverso del numero for i in criptotext: new_message+= self.alphabet[(modinv(self.A, len(self.alphabet))*(dic[i] - self.B) % len(self.alphabet))] return new_message
def __init__(self, a: int, b: int, p: int, order: int = None, verify: bool = True): self.p = p self.a = a % p self.b = b % p a4 = 4 * (self.a**3) b27 = 27 * (self.b**2) a4b27 = a4 + b27 self.discriminant = -16 * a4b27 if verify: assert isprime( p), f"{p} is not prime and verify=True in curve params" assert self.discriminant != 0, f"discriminant {self.discriminant} != 0 and verify=True in curve params" self.j_invariant = 1728 + (a4 * modinv(a4b27, self.p)) self.card = order
def bsgs(h, g, order, p): """ Baby-Step-Giant-Step algorithm :param h: g^a :param g: g :param order: order of the group :return: a """ max_list_size = 50000000 m = min(sqrtm(order, p), max_list_size) # list size m_giant = order // m + 1 l = {} # baby steps power = 1 for i in range(m + 1): if i > 0: # faster than calling me every iteration power *= g power %= p l[power] = i # giant steps # g^(-j*m) = (g^-m)^j gminv = modinv(me(g, m, p) % p, p) gminv_j = gminv power = 1 for j in range(m_giant + 1): if j > 0: # faster than calling me every iteration power *= gminv_j power %= p z = (power * h) % p if z in l: # found! i = l[z] a = (i + j * m) % order return a # not found return None
def decrypt_mh(message, private_key): """Decrypt an incoming message using a private key. Following the outline of the handout, you will need to: 1. Extract w, q, and r from the private key. 2. Compute s, the modular inverse of r mod q, using the Extended Euclidean algorithm (implemented for you at `utils.modinv(r, q)`) 3. For each byte-sized chunk, compute c' = cs (mod q) 4. Solve the superincreasing subset sum problem using c' and w to recover the original plaintext byte. 5. Reconstitute the decrypted bytes to form the original message. :param message: Encrypted message chunks. :type message: list of ints :param private_key: The private key of the recipient (you). :type private_key: 3-tuple of w, q, and r :returns: bytearray or str of decrypted characters """ plaintext = [] (w, q, r) = private_key w_seq = list(w) n = len(w_seq) s = utils.modinv(r, q) for chunk in message: c = chunk * s % q print(c) alpha = [0] * len(w_seq) while c > 0: max_w_ind = 0 while w_seq[max_w_ind] <= c: max_w_ind += 1 if max_w_ind >= n: break if max_w_ind > 0: max_w_ind -= 1 c -= w_seq[max_w_ind] alpha[max_w_ind] = 1 plaintext.append(chr(utils.bits_to_byte(alpha))) return plaintext
def init_asym_key(is_client): if is_client: p = 3136666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666313 q = 3130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001183811000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000313 p1q1 = 9817766666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666670379887169999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999868533333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333332913475031999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999889344 n = 9817766666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666670379887169999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999874799999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999581325509666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666555969 else: p = 262641725682127839334668938847190331798311145333616792958372838424857156775007227102454928148183167823211534641943299795962309579874682913568608650959193370824474863282145037585560618568778906679404993323367715662527874977471424467472818616772123866421714232029284828476022113987781717658486369598393166193032285497153837454766280540159 q = 1357911131517193133353739515355575971737577799193959799111113115117119131133135137139151153155157159171173175177179191193195197199311313315317319331333335337339351353355357359371373375377379391393395397399511513515517519531533535537539551553555557559571573575577579591593595597599711713715717719731733735737739751753755757759771 p1q1 = 356644122904646457852499602347524156507174390136009247712353815755646024496037172622143518964975128825130286514080704742796667108474987831191018350950474273866002102276256204821917798997344429811579551036427931632160027755615469206884341989791425882965139555633729680961753531307429384131685187536265971374229677283297296199726262570199844444846074490909237009199214584948274744025059837855042663253503317322749974093852969723202432993253172732373126211278665570242752797366587342079290772234755716489053248405176862032307451968502682676607826140044221793217557204694793133501557346193212066671570792229108422899589042187213282710832047367190550286939155601843660 n = 356644122904646457852499602347524156507174390136009247712353815755646024496037172622143518964975128825130286514080704742796667108474987831191018350950474273866002102276256204821917798997344429811579551036427931632160027755615469206884341989791425882965139555633729680961753531307429384131685187536265971374229677283297296199726525211926884483816926352981437939046368472065345938617212170492578633525395443680985564159140304044180801687066289207346267712051735450355632719332863854781448582435377212879994166383117014314364236353219445789669865528537210737216563558849104808921534617984812925075624393934689800214847240270527393596756813388425443876147677640143589 start_time = time.time() # p1q1 = (p - 1) * (q - 1) # n = p * q e = find_coprime(p1q1) d = modinv(p1q1, n) print(f'Initialized RSA in: {time.time() - start_time}sec') return n, e, d, q, p
def decrypt_mh(message, private_key): """ :param message: Encrypted message chunks. :type message: list of ints :param private_key: The private key of the recipient (you). :type private_key: 3-tuple of w, q, and r :returns: bytearray or str of decrypted characters """ print('Decrypting message (crypto.py) ' + str(message)) # Your implementation here. (w, q, r) = private_key s = utils.modinv(r, q) c = [] for i in message: c.append((i * s) % q) plain_in_bits = [] for i in c: helper = [] for j in w[::-1]: if j <= i: i -= j helper.insert(0, 1) else: helper.insert(0, 0) plain_in_bits += helper plain = '' for i in range(math.ceil(len(plain_in_bits) / 8)): plain += (chr(utils.bits_to_byte(plain_in_bits[i * 8:i * 8 + 8]))) print("Plain text (crypto.py)", plain) return plain
def decrypt_mh(message, private_key): """Decrypt an incoming message using a private key. Following the outline of the handout, you will need to: 1. Extract w, q, and r from the private key. 2. Compute s, the modular inverse of r mod q, using the Extended Euclidean algorithm (implemented for you at `utils.modinv(r, q)`) 3. For each byte-sized chunk, compute c' = cs (mod q) 4. Solve the superincreasing subset sum problem using c' and w to recover the original plaintext byte. 5. Reconstitute the decrypted bytes to form the original message. :param message: Encrypted message chunks. :type message: list of ints :param private_key: The private key of the recipient (you). :type private_key: 3-tuple of w, q, and r :returns: bytearray or str of decrypted characters """ (w, q, r) = private_key s = utils.modinv(r, q) nn = len(message) result = bytearray(nn) for i in range(0, nn): c = message[i] * s % q bits = [0] * 8 for j in range(7, -1, -1): if c >= w[j]: bits[j] = 1 c -= w[j] result[i] = utils.bits_to_byte(bits) return result
def solve_with_unknown_increment_and_multiplier(modulus, samples): multiplier = (((samples[2] - samples[1]) % modulus) * utils.modinv( (samples[1] - samples[0]) % modulus, modulus)) % modulus increment = solve_with_unknown_increment(multiplier, modulus, samples) return multiplier, increment
def factordb(n): f = FactorDB(n) f.connect() return f.get_factor_list() c = int(input("==> c = ")) n = int(input("==> n = ")) e = int(input("==> e = ")) primes = factordb(n) print(primes) phi = 1 for i in primes: phi *= i - 1 print(phi) d = modinv(e, phi) m = pow(c, d, n) convert(m) except IndexError: slowprint("[-] Sorry Can't Factorize n ") except ImportError: slowprint("\n[-] Module Not Setup") except ValueError: slowprint("\n[-] c,n,e Must Be Integer Number") except KeyboardInterrupt: exit() except: slowprint("[-] False Attack !")
def test(): #print "Binary Montgomery:" x, y, z, w, p, r = 18, 5, 22, 18, 29, 256 expected = (((x*y - z)*w)**2%p) r2 = (r**2) % p bm = utils.binary_montgomery x, y, z, w = bm(x, r2, p, r), bm(y, r2, p, r), bm(z, r2, p, r), bm(w, r2, p, r) ret = bm(x, y, p, r) ret = utils.sub_mod(ret, z, p) ret = bm(ret, w, p, r) ret = bm(ret, ret, p, r); ret = utils.convert_int_to_standard(ret, p, r) if(expected != ret): print "Binary Montgomery multiplication is broken" exit(1) c = point.Curve() c.a, c.b, c.p = 4, 20, 29 c.r = 256 c.r_minus1 = utils.modinv(c.r - c.p, c.p) # r > p c.r2 = (c.r**2) % c.p c2 = utils.convert_curve_to_montgomery(c, c.p, c.r, c.r2) #print "Addition:" p1s = point_simple.Point(1, 5) p2s = point_simple.Point(20, 3) p1 = point.Point(1, 5) p2 = point.Point(20, 3) p1 = utils.convert_point_to_montgomery(p1, c.p, c.r, c.r2) p2 = utils.convert_point_to_montgomery(p2, c.p, c.r, c.r2) p3s = point_simple.add_simple(p1s, p1s, c) p3 = point.add(p1, p1, c2) p3 = utils.convert_point_to_standard(p3, c.p, c.r) p3 = utils.projective_to_standard(p3, c) if(p3s.x != p3.x or p3s.y != p3.y): print "addition is broken!" exit(1) p3 = point.add(p1, p2, c2) p3 = utils.convert_point_to_standard(p3, c.p, c.r) p3 = utils.projective_to_standard(p3, c) p3s = point_simple.add_simple(p1s, p2s, c) if(p3s.x != p3.x or p3s.y != p3.y): print "addition is broken!" exit(1) p2 = point.Point() p3 = point.add(p2, p1, c2) p3 = utils.convert_point_to_standard(p3, c.p, c.r) p3 = utils.projective_to_standard(p3, c) p2s = point_simple.Point() p3s = point_simple.add_simple(p1s, p2s, c) if(p3s.x != p3.x or p3s.y != p3.y): print "addition is broken!" exit(1) #print "Multiplication:" for i in xrange(37): p3 = point.multiply(p1, i, c2) p3 = utils.convert_point_to_standard(p3, c.p, c.r) p3 = utils.projective_to_standard(p3, c) p3s = point_simple.multiply_simple(p1s, i, c) if(p3s.x != p3.x or p3s.y != p3.y): print "Point multiplication is broken!" exit(1) test_montgomery() #test_nist_p256() print "All tests successful!"
def chinese_remainder_theorem(p, q, dp, dq, chipher_text): q_inv = modinv(p, q) m1 = pow(chipher_text, dp, p) m2 = pow(chipher_text, dq, q) h = (q_inv * (m1 - m2)) % p return m2 + h * q
from utils import primes, modinv limit = 1000000 ps = list(primes(limit + 100))[2:] res = 0 for p1, p2 in zip(ps, ps[1:]): if p1 > limit: break power10 = 10 ** len(str(p1)) res += ((p2 - p1) * modinv(power10, p2) % p2) * power10 + p1 print res
def generate_proof(self, value): """Given the value value, follow the algorithm laid out on p.16, 17 (section 4.2) of paper for prover side. """ # generate Pederson commitment for value self.fsstate = "" self.value = value self.gamma = os.urandom(32) pc = PC(encode(self.value, 256, minlen=32), blinding=self.gamma) # generate the 3 conditions self.V = pc.get_commitment() self.aL = Vector(value, self.bitlength) self.aR = self.aL.subtract([1] * self.bitlength) # assert checks assert self.aL.hadamard(self.aR).v == Vector([0] * self.bitlength).v assert self.aL.inner_product(PowerVector(2, self.bitlength)) == value # Get the commitment A self.alpha = self.get_blinding_value() # print("Maybe") self.A = VPC(self.aL.v, self.aR.v, vtype="int", u=getNUMS(255).serialize()) self.A.set_blinding(c=self.alpha) self.A.get_commitment() # get the 3 corresponding blinding vectors/values to convert proof into zero knowledge self.rho = self.get_blinding_value() self.sL = self.get_blinding_vector() self.sR = self.get_blinding_vector() # create a commitment to the blinding vector self.S = VPC(self.sL.v, self.sR.v, vtype="int", u=getNUMS(255).serialize()) self.S.set_blinding(c=self.rho) self.S.get_commitment() # generate the challenges y and z as per fiat shamir hueristic self.y, self.z = self.fiat_shamir([self.V, self.A.P, self.S.P]) self.z2 = (self.z * self.z) % N self.zv = Vector([self.z] * self.bitlength) #construct l(X) and r(X) coefficients; l[0] = constant term, l[1] linear term, #same for r(X) self.l = [] self.l.append(self.aL.subtract(self.zv)) self.l.append(self.sL) self.yn = PowerVector(self.y, self.bitlength) self.r = [] #0th coeff is y^n o (aR + z.1^n) + z^2 . 2^n self.r.append( self.yn.hadamard(self.aR.add(self.zv)).add( PowerVector(2, self.bitlength).scalar_mult(self.z2))) self.r.append(self.yn.hadamard(self.sR)) #constant term of t(X) = <l(X), r(X)> is the inner product of the #constant terms of l(X) and r(X) self.t0 = self.l[0].inner_product(self.r[0]) self.t1 = (self.l[0].inner_product(self.r[1]) + (self.l[1].inner_product(self.r[0]))) % N self.t2 = self.l[1].inner_product(self.r[1]) # we have constructed the polynomials l(x) r(x) and t(x) upto here self.tau1 = self.get_blinding_value() self.tau2 = self.get_blinding_value() self.T1 = PC(self.t1, blinding=self.tau1) self.T2 = PC(self.t2, blinding=self.tau2) # Since we know the values of we must also send commiments to remaining polynomial. # this is similar to what I did in vecotrs proving dot product # After commiting to the value we get the next challenge x66 self.x_1 = self.fiat_shamir( [self.T1.get_commitment(), self.T2.get_commitment()], nret=1)[0] self.mu = (self.alpha + self.rho * self.x_1) % N self.tau_x = (self.tau1 * self.x_1 + self.tau2 * self.x_1 * self.x_1 + \ self.z2 * decode(self.gamma, 256)) % N #lx and rx are vector-valued first degree polynomials evaluated at #the challenge value self.x_1 self.lx = self.l[0].add(self.l[1].scalar_mult(self.x_1)) self.rx = self.r[0].add(self.r[1].scalar_mult(self.x_1)) self.t = (self.t0 + self.t1 * self.x_1 + self.t2 * self.x_1 * self.x_1) % N assert self.t == self.lx.inner_product(self.rx) #Prover will now send tau_x, mu and t to verifier, and inner product argument #can be verified from this data. self.hprime = [] self.yinv = modinv(self.y, N) for i in range(1, self.bitlength + 1): self.hprime.append( ecmult(pow(self.yinv, i - 1, N), self.A.h[i - 1], False)) self.uchallenge = self.fiat_shamir([self.tau_x, self.mu, self.t], nret=1)[0] self.U = ecmult(self.uchallenge, getG(True), False) #On the prover side, need to construct an inner product argument: self.iproof = IPC(self.lx.v, self.rx.v, vtype="int", h=self.hprime, u=self.U) self.proof = self.iproof.generate_proof() #At this point we have a valid data set, but here is included a #sanity check that the inner product proof we've generated, actually verifies: self.iproof2 = IPC([1] * self.bitlength, [2] * self.bitlength, vtype="int", h=self.hprime, u=self.U) ak, bk, lk, rk = self.proof assert self.iproof2.verify_proof(ak, bk, self.iproof.get_commitment(), lk, rk)
def verify(self, Ap, Sp, T1p, T2p, tau_x, mu, t, proof, V): """Takes as input an already-deserialized rangeproof, along with the pedersen commitment V to the value (not here known), and checks if the proof verifies. """ #wipe FS state: self.fsstate = "" #compute the challenges to find y, z, x self.y, self.z = self.fiat_shamir([V, Ap, Sp]) self.z2 = (self.z * self.z) % N self.zv = Vector([self.z] * self.bitlength) self.x_1 = self.fiat_shamir([T1p, T2p], nret=1)[0] self.hprime = [] self.yinv = modinv(self.y, N) for i in range(1, self.bitlength + 1): self.hprime.append( ecmult(pow(self.yinv, i - 1, N), getNUMS(self.bitlength + i).serialize(), False)) #construction of verification equation (61) #cmopute the dangling term onen = PowerVector(1, self.bitlength) twon = PowerVector(2, self.bitlength) yn = PowerVector(self.y, self.bitlength) self.k = (yn.inner_product(onen) * -self.z2) % N self.k = (self.k - (onen.inner_product(twon) * (pow(self.z, 3, N)))) % N self.gexp = (self.k + self.z * onen.inner_product(yn)) % N # this computes PC of <l,r> with t_x self.lhs = PC(t, blinding=tau_x).get_commitment() self.rhs = ecmult(self.gexp, getG(True), False) self.vz2 = ecmult((self.z * self.z) % N, V, False) self.rhs = ecadd_pubkeys([self.rhs, self.vz2], False) self.rhs = ecadd_pubkeys( [self.rhs, ecmult(self.x_1, T1p, False)], False) self.rhs = ecadd_pubkeys( [self.rhs, ecmult((self.x_1 * self.x_1) % N, T2p, False)], False) if not self.lhs == self.rhs: print("(61) verification check failed") print(binascii.hexlify(self.lhs)) print(binascii.hexlify(self.rhs)) return False #reconstruct P (62) # standard commitment check self.P = Ap self.P = ecadd_pubkeys([ecmult(self.x_1, Sp, False), self.P], False) # upto here P = A + x*S #now add g*^(-z) for i in range(self.bitlength): self.P = ecadd_pubkeys([ ecmult(-self.z % N, getNUMS(i + 1).serialize(), False), self.P ], False) # upto here P = A + x*S - g^(-z) #zynz22n is the exponent of hprime self.zynz22n = yn.scalar_mult(self.z).add( PowerVector(2, self.bitlength).scalar_mult(self.z2)) for i in range(self.bitlength): self.P = ecadd_pubkeys( [ecmult(self.zynz22n.v[i], self.hprime[i], False), self.P], False) # Here P value is computed correctly self.uchallenge = self.fiat_shamir([tau_x, mu, t], nret=1)[0] self.U = ecmult(self.uchallenge, getG(True), False) self.P = ecadd_pubkeys([ecmult(t, self.U, False), self.P], False) #P should now be : A + xS + -zG* + (zy^n+z^2.2^n)H'* + tU #One can show algebraically (the working is omitted from the paper) #that this will be the same as an inner product commitment to #(lx, rx) vectors (whose inner product is t), thus the variable 'proof' #can be passed into the IPC verify call, which should pass. #input to inner product proof is P.h^-(mu) self.Pprime = ecadd_pubkeys( [self.P, ecmult(-mu % N, getNUMS(255).serialize(), False)], False) #Now we can verify the inner product proof a, b, L, R = proof #dummy vals for constructor of verifier IPC self.iproof = IPC(["\x01"] * self.bitlength, ["\x02"] * self.bitlength, h=self.hprime, u=self.U) #self.iproof.P = self.Pprime if not self.iproof.verify_proof(a, b, self.Pprime, L, R): return False return True