def test_dsks(): print("\nTest Duplicate-Signature Key Selection on RSA") keys_sizes = [1024, 2048] for key_size in keys_sizes: for j in range(2): print('test {}, key size {}'.format(j, key_size)) key = RSAKey.generate(key_size) message = randint(1, key.size - 1) signature = key.decrypt(message) n_p, p_order_factors, q_order_factors, e_p, d_p = dsks( message, signature, key.n, smooth_bit_size=30, hash_function=None) key_p = RSAKey(n_p, e=e_p, d=d_p) p_p = product(p_order_factors) + 1 q_p = product(q_order_factors) + 1 assert p_p * q_p == n_p assert key_p.p * key_p.q == n_p assert pow(signature, e_p, n_p) == message assert pow(message, d_p, n_p) == signature
def x_recover(self, y, sign=0): """ Retrieves the x coordinate according to the y one, \ such that point (x,y) is on curve. Args: y (int): y coordinate sign (int): sign of x Returns: int: the computed x coordinate """ q = self.field d = self.d I = pow(2,(q-1)//4,q) if sign: sign = 1 a = (y*y-1)%q b = pow(d*y* y+1,q-2,q) xx = (a*b)%q x = pow(xx,(q+3)//8,q) if (x*x - xx) % q != 0: x = (x*I) % q if x &1 != sign: x = q-x return x
def Bob_Step_2(self, Alice_IP, Bob_IP, Alice_message): b = secrets.randbits(2048) Rb = int(secrets.randbits(256)).to_bytes(32, byteorder=u'big') Gb = int(pow(self.g, b, self.m)).to_bytes(256, byteorder=u'big') Alice = Alice_IP.encode() Bob = Bob_IP.encode() Ra = Alice_message[:32] Ga = Alice_message[32:] Ga_int = int.from_bytes(Ga, byteorder=u'big') Gab = int(pow(Ga_int, b, self.m)).to_bytes(256, byteorder=u'big') Concat_H = Alice + Bob + Ra + Rb + Ga + Gb + Gab hashed_key = sha256() hashed_key.update(Concat_H) self.H_Bob = hashed_key.digest() Decrypted_Sb = self.H_Bob + Bob Decrypted_Sb_int = int.from_bytes(Decrypted_Sb, byteorder=u'big') Sb_int_Sign = pow(Decrypted_Sb_int, RSA_Bob.dBob, RSA_Bob.nBob) Sb = int(Sb_int_Sign).to_bytes(512, byteorder=u'big') message2 = Rb + Gb + Sb print "\n b = " print b del b print "\n Ra (in byte) = " print Ra print "\n Rb (in byte )= " print Rb hashed_key = sha256() hashed_key.update(Gab) self.hashed_key = hashed_key.digest() print "\nBob new hashed key" print binascii.hexlify(bytearray(self.hashed_key)) return message2
def test_faulty(): print("\nTest: faulty") for _ in range(5): key = RSAKey.generate(1024) m = randint(0x13373371, key.n) sp = pow(m, key.d % (key.p - 1), key.p) sq = pow(m, key.d % (key.q - 1), key.q) sq_f = sq ^ randint(1, sq) # random error s_f = crt([sp, sq_f], [key.p, key.q]) % key.n s = crt([sp, sq], [key.p, key.q]) % key.n key.texts.append({'cipher': s_f, 'plain': m}) key_recovered = faulty(key.publickey()) assert key_recovered and key_recovered.d == key.d key.texts = [{'cipher': s}, {'cipher': s_f}] key_recovered = faulty(key.publickey()) assert key_recovered and key_recovered.d == key.d key.texts = [{'cipher': s}, {'cipher': s_f}, {'cipher': randint(1, key.n)}, {'cipher': randint(1, key.n), 'plain': randint(1, key.n)}] key_recovered = faulty(key.publickey()) assert key_recovered and key_recovered.d == key.d key.texts = [{'cipher': s, 'plain': m}] key_recovered = faulty(key.publickey()) assert key_recovered is None
def _add_point(self, P, Q): """ See :func:`Curve.add_point` """ if Q.has_y and P == -Q: return self.infinity if P == Q: return self._mul_point(2, P) x1 = P.x y1 = P.y x2 = Q.x y2 = Q.y p = self.field assert (x2 != x1) invx2x1 = pow(((x2 - x1)) % p, p - 2, p) invx2x1_2 = pow(((x2 - x1) * (x2 - x1)) % p, p - 2, p) invx2x1_3 = pow(((x2 - x1) * (x2 - x1) * (x2 - x1)) % p, p - 2, p) #x3 = # b*(y2-y1)² /(x2-x1)² -a-x1-x2 x3 = (self.b * pow(y2 - y1, 2) * invx2x1_2 - self.a - x1 - x2) % p # y3 = # (2*x1+x2+a)*(y2-y1)/(x2-x1) - b*(y2-y1)³ /(x2-x1)³ -y1 y3 = ((2 * x1 + x2 + self.a) * (y2 - y1) * invx2x1 - self.b * pow(y2 - y1, 3) * invx2x1_3 - y1) % p return Point(x3, y3, self)
def point_add(P1, P2): """ Add `secp256k1` points. Arguments: P1 (list): first `secp256k1` point P2 (list): second `secp256k1` point Returns: `secp256k1` point """ if (P1 is None): return P2 if (P2 is None): return P1 xP1 = P1[0] yP1 = P1[1] xP2 = P2[0] yP2 = P2[1] if (xP1 == xP2): if yP1 != yP2: raise ValueError("One of the point is not on the curve") # P1 == P2 else: lam = (3 * xP1 * xP1 * pow(2 * yP1, p - 2, p)) % p # P1 != P2 else: lam = ((yP2 - yP1) * pow(xP2 - xP1, p - 2, p)) % p x3 = (lam * lam - xP1 - xP2) % p return [x3, (lam * (xP1 - x3) - yP1) % p]
def lift_x(b): x = int_from_bytes(b) if x >= p: return None y_sq = (pow(x, 3, p) + 7) % p y = pow(y_sq, (p + 1) // 4, p) if pow(y, 2, p) != y_sq: return None return [x, y if y & 1 == 0 else p - y]
def y_from_x(x): """ Compute `y` from `x` according to `y²=x³+7`. """ y_sq = (pow(x, 3, p) + 7) % p y = pow(y_sq, (p + 1) // 4, p) if pow(y, 2, p) != y_sq: return None return y
def y_from_x(x): """ Compute :class:`P.y` from :class:`P.x` according to ``y²=x³+7``. """ y_sq = (pow(x, 3, p) + 7) % p y = pow(y_sq, (p + 1) // 4, p) if pow(y, 2, p) != y_sq: return None return y
def __read_temperature(self): ut = c_long(27898) if not self.__test: self.__bus.start_comunication(self.DEVICE_ADDRESS) self.__bus.write_byte(0xF4, 0x2E) sleep(0.45) ut = c_long(self.__bus.read_word(0xF6)).value self.__bus.stop_comunication() x1 = (ut - self.__AC6) * self.__AC5 / pow(2, 15) x2 = self.__MC * pow(2, 11) / (x1 + self.__MD) self.__B5 = x1 + x2 t = (self.__B5 + 8) / pow(2, 4) return float(t) / 10
def x_recover(self, y, sign=0): """ Retrieves the x coordinate according to the y one, \ such that point (x,y) is on curve. Args: y (int): y coordinate sign (int): sign of x Returns: int: the computed x coordinate """ q = self.field a = self.a d = self.d if sign: sign = 1 # #x2 = (y^2-1) * (d*y^2-a)^-1 yy = (y * y) % q u = (1 - yy) % q v = pow(a - d * yy, q - 2, q) xx = (u * v) % q if self.name == 'Ed25519': x = pow(xx, (q + 3) // 8, q) if (x * x - xx) % q != 0: I = pow(2, (q - 1) // 4, q) x = (x * I) % q elif self.name == 'Ed448': x = pow(xx, (q + 1) // 4, q) elif self.name == 'Ed521': x = pow(xx, (q + 1) // 4, q) else: assert False, '%s not supported' % curve.name if x & 1 != sign: x = q - x assert (x * x) % q == xx # over F(q): # a.xx +yy = 1+d.xx.yy # <=> xx(a-d.yy) = 1-yy # <=> xx = (1-yy)/(a-d.yy) # <=> x = +- sqrt((1-yy)/(a-d.yy)) # yy = (y*y)%q # u = (1-yy)%q # v = (a - d*yy)%q # v_1 = pow(v, q-2,q) # xx = (v_1*u)%q # x = self._sqrt(xx,q,sign) # Inherited generic Tonelli–Shanks from Curve return x
def factors_from_d(n, e, d): k = e * d - 1 while True: g = random.randint(2, n - 2) b = k // (2**power_of_two(k)) while b < k: gb = pow(g, b, n) if gb != 1 and gb != n - 1 and pow(gb, 2, n) == 1: if gcd(gb - 1, n) != 1: p = gcd(gb - 1, n) else: p = gcd(gb + 1, n) return p, n // p b *= 2
def Alice_Step_1(self): self.a = int(secrets.randbits(2048)) self.Ra = int(secrets.randbits(256)).to_bytes(32, byteorder=u'big') Ga_int = pow(self.g, self.a, self.m) self.Ga = int(Ga_int).to_bytes(256, byteorder=u'big') message1 = self.Ra + self.Ga return message1
def verify(self, msg, sig, pu_key): """ Verifies a message signature. Args: msg (bytes) : the message hash to verify the signature sig (bytes) : signature to verify pu_key (ecpy.keys.ECPublicKey): key to use for verifying """ curve = pu_key.curve n = curve.order G = curve.generator r, s = decode_sig(sig, self.fmt) if (r == None or s == None or r == 0 or r >= n or s == 0 or s >= n): return False h = int.from_bytes(msg, 'big') if n.bit_length() < h.bit_length(): # h is the 'n.bit_length()' leftmost bits of the received h value, # leading zeroes included (if any). hbyteslen = (h.bit_length() + 7) // 8 h = int(format(h, f'0{8*hbyteslen}b')[:n.bit_length()], 2) c = pow(s, n - 2, n) u1 = (h * c) % n u2 = (r * c) % n u1G = u1 * G u2Q = u2 * pu_key.W GQ = u1G + u2Q if GQ.is_infinity: return False x = GQ.x % n return x == r
def _do_sign(self, msg, pv_key, k): if (pv_key.curve == None): raise ECPyException('private key haz no curve') curve = pv_key.curve n = curve.order G = curve.generator k = k % n msg = int.from_bytes(msg, 'big') Q = G * k kinv = pow(k, n - 2, n) r = Q.x % n if r == 0: return None s = (kinv * (msg + pv_key.d * r)) % n if s == 0: return None sig = encode_sig(r, s, self.fmt) # r = r.to_bytes((r.bit_length()+7)//8, 'big') # s = s.to_bytes((s.bit_length()+7)//8, 'big') # if (r[0] & 0x80) == 0x80 : # r = b'\0'+r # if (s[0] & 0x80) == 0x80 : # s = b'\0'+s # sig = (b'\x30'+int((len(r)+len(s)+4)).to_bytes(1,'big') + # b'\x02'+int(len(r)).to_bytes(1,'big') + r + # b'\x02'+int(len(s)).to_bytes(1,'big') + s ) return sig
def parity_oracle(ciphertext): key = key_1024 ciphertext = b2i(ciphertext) message = pow(ciphertext, key.d, key.n) if message & 1 == 1: return 1 return 0
def verify(message, signature, key): # message = add_rsa_signature_padding(message, size=key.size, hash_function='sha1') message = b2i(message) signature = b2i(signature) if pow(signature, key.e, key.n) == message: return True return False
def verify(self,msg,sig,pu_key): """ Verifies a message signature. Args: msg (bytes) : the message hash to verify the signature sig (bytes) : signature to verify pu_key (ecpy.keys.ECPublicKey): key to use for verifying """ curve = pu_key.curve n = curve.order G = curve.generator r,s = decode_sig(sig, self.fmt) if (r == None or s == None or r == 0 or r >= n or s == 0 or s >= n ) : return False h = int.from_bytes(msg,'big') c = pow(s, n-2, n) u1 = (h*c)%n u2 = (r*c)%n u1G = u1*G u2Q = u2*pu_key.W GQ = u1G+u2Q if GQ.is_infinity: return False x = GQ.x % n return x == r
def enc(self, data): key1 = "0CoJUm6Qyw8W8jud" vi = "0102030405060708" seed = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' p = '010001' m = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7' k = [] for i in range(16): r = random.choice(seed) k.append(r) key2 = ''.join(k) #key2="a8LWv2uAtXjzSfkQ" #pub=rsa.key.PublicKey(int(m,16),int(p,16)) BS = AES.block_size pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS) encry1 = AES.new(key1, AES.MODE_CBC, vi) param = str(base64.b64encode(encry1.encrypt(pad(data))), encoding='utf-8') encry2 = AES.new(key2, AES.MODE_CBC, vi) param = str(base64.b64encode(encry2.encrypt(pad(param))), encoding='utf-8') #f=binascii.hexlify(rsa.encrypt(key2[::-1].encode('utf-8'),pub)).decode('utf-8') e = pow(int(binascii.hexlify(key2[::-1].encode('utf-8')), 16), int(p, 16), int(m, 16)) e = format(e, 'x').zfill(256) #print(key2+'\n',e) return param, e
def _mul_point(self, k, P): """ """ k = bin(k) k = k[2:] sz = len(k) x1 = P.x x2 = 1 z2 = 0 x3 = P.x z3 = 1 for i in range(0, sz): ki = int(k[i]) if ki == 1: x3, z3, x2, z2 = self._ladder_step(x1, x3, z3, x2, z2) else: x2, z2, x3, z3 = self._ladder_step(x1, x2, z2, x3, z3) p = self.field if z2: y2 = None if (P.has_y): x2, y2, z2 = self._ladder_recover_y(P.x, P.y, x2, z2, x3, z3) zinv = pow(z2, (p - 2), p) kx = (x2 * zinv) % p ky = None if y2: ky = (y2 * zinv) % p return Point(kx, ky, self) else: return self.infinity
def small_e_msg(key, ciphertexts=None, max_times=100): """If both e and plaintext are small, ciphertext may exceed modulus only a little Args: key(RSAKey): with small e, at least one ciphertext ciphertexts(list) max_times(int): how many times plaintext**e exceeded modulus maximally Returns: list: recovered plaintexts """ ciphertexts = get_mutable_texts(key, ciphertexts) recovered = [] for ciphertext in ciphertexts: log.debug("Find msg for ciphertext {}".format(ciphertext)) times = 0 for k in range(max_times): msg, is_correct = gmpy2.iroot(ciphertext + times, key.e) if is_correct and pow(msg, key.e, key.n) == ciphertext: msg = int(msg) log.success("Found msg: {}, times=={}".format( i2b(msg), times // key.n)) recovered.append(msg) break times += key.n return recovered
def pkcs15_padding_oracle(ciphertext, **kwargs): kwargs['pkcs15_padding_oracle_calls'][0] += 1 key = kwargs['oracle_key'] ciphertext = b2i(ciphertext) message = pow(ciphertext, key.d, key.n) if message >> (key.size - 16) == 0x0002: return True return
def oaep_padding_oracle(ciphertext, **kwargs): kwargs['manger_padding_oracle_calls'][0] += 1 key = kwargs['oracle_key'] ciphertext = b2i(ciphertext) message = pow(ciphertext, key.d, key.n) if message >> (key.size - 8) == 0x00: return True return
def verify(self, msg, sig, pu_key): """ Verifies a message signature. Args: msg (bytes) : the message hash to verify the signature sig (bytes) : signature to verify pu_key (ecpy.keys.ECPublicKey): key to use for verifying """ curve = pu_key.curve n = pu_key.curve.order G = pu_key.curve.generator size = curve.size >> 3 r, s = decode_sig(sig, self.fmt) if (r == None or r > (pow(2, size * 8) - 1) or s == 0 or s > n - 1): return False hasher = self._hasher() if self.option == "ISO": sG = s * G rW = r * pu_key.W Q = sG - rW xQ = Q.x.to_bytes(size, 'big') yQ = Q.y.to_bytes(size, 'big') hasher.update(xQ + yQ + msg) v = hasher.digest() v = int.from_bytes(v, 'big') elif self.option == "ISOx": sG = s * G rW = r * pu_key.W Q = sG - rW xQ = Q.x.to_bytes(size, 'big') hasher.update(xQ + msg) v = hasher.digest() v = int.from_bytes(v, 'big') elif self.option == "BSI": sG = s * G rW = r * pu_key.W Q = sG + rW xQ = (Q.x).to_bytes(size, 'big') hasher.update(msg + xQ) v = hasher.digest() v = int.from_bytes(v, 'big') elif self.option == "LIBSECP": rb = r.to_bytes(size, 'big') hasher.update(rb + msg) h = hasher.digest() h = int.from_bytes(h, 'big') if h == 0 or h > n: return 0 sG = s * G hW = h * pu_key.W R = sG + hW v = R.x % n return v == r
def fig1_6(): N = 10 J = np.zeros(N) l2_norm_1 = np.copy(J) l2_norm_2 = np.copy(J) h1_norm_1 = np.copy(J) h1_norm_2 = np.copy(J) a = 0 b = 1 # domain for j in range(10): N = int(pow(2, (j + 3))) J[j] = N l2_norm_1[j], h1_norm_1[j] = get_norm(f_u1, a, b, N) for j in range(10): N = int(pow(2, (j + 3))) l2_norm_2[j], h1_norm_2[j] = get_norm(f_u2, a, b, N) # get symbolic values [l2_norm_sym_1, h1_norm_sym_1] = sp_u1(a, b) [l2_norm_sym_2, h1_norm_sym_2] = sp_u2(a, b) # computer errors el2_1 = abs(l2_norm_1 - l2_norm_sym_1) ehs_1 = abs(h1_norm_1 - h1_norm_sym_1) el2_2 = abs(l2_norm_2 - l2_norm_sym_2) ehs_2 = abs(h1_norm_2 - h1_norm_sym_2) # plotting plt.figure(1) ch0.PlotSetup() plt.axis('equal') plt.subplot(1, 2, 1) # plt.loglog(J, el2_1, 'k-') plt.loglog(J, ehs_1, 'k-.') plt.xlabel(r'$J$') plt.ylabel(r'error') plt.title(r'(a)') # plt.subplot(1, 2, 2) plt.loglog(J, el2_2, 'k-') plt.loglog(J, ehs_2, 'k-.') plt.xlabel(r'$J$') plt.title(r'(b)') # plt.tight_layout()
def tonelli_shanks(n, p): """Find r such that r^2 = n % p, r2 == p-r""" if legendre(n, p) != 1: log.critical_error("Not a square root") s = 0 q = p - 1 while q & 1 == 0: s += 1 q >>= 1 if s == 1: return pow(n, (p + 1) // 4, p) z = 1 while legendre(z, p) != -1: z += 1 c = pow(z, q, p) r = pow(n, (q + 1) // 2, p) t = pow(n, q, p) m = s while t != 1: i = 1 while i < m: if pow(t, 2**i, p) == 1: break i += 1 b = pow(c, 2**(m - i - 1), p) r = (r * b) % p t = (t * (b**2)) % p c = pow(b, 2, p) m = i return r
def get_z(r: int, n: int) -> int: """ Получение числа z. @param r: число r @param n: число n @returns z: r ^ 2 (mod n) """ return pow(r, 2, n)
def y_recover(self, x, sign=0): """ """ p = self.field by2 = (x * x * x + self.a * x * x + x) % p binv = pow(self.b, p - 2, p) assert ((binv * self.b) % p == 1) y2 = (binv * by2) % p y = self._sqrt(y2, p, sign) return y
def _sqrt(n, p, sign=0): """ Generic Tonelli–Shanks algorithm """ #check Euler criterion if pow(n, (p - 1) // 2, p) != 1: return None #compute square root p_1 = p - 1 s = 0 q = p_1 while q & 1 == 0: q = q >> 1 s = s + 1 if s == 1: r = pow(n, (p + 1) // 4, p) else: z = 2 while pow(z, (p - 1) // 2, p) == 1: z = z + 1 c = pow(z, q, p) r = pow(n, (q + 1) // 2, p) t = pow(n, q, p) m = s while True: if t == 1: break else: for i in range(1, m): if pow(t, pow(2, i), p) == 1: break b = pow(c, pow(2, m - i - 1), p) r = (r * b) % p t = (t * b * b) % p c = (b * b) % p m = i if sign: sign = 1 if r & 1 != sign: r = p - r return r
def is_on_curve(self, P): """ See :func:`Curve.is_on_curve` """ p = self.field x = P.x right = (x * x * x + self.a * x * x + x) % p if P.has_y: y = P.y left = (self.b * y * y) % p return left == right else: #check equation has a solution according to Euler criterion return pow(right, (p - 1) // 2, p) == 1
# So, pick a smaller (32-bit capable) range to iterate over. # # New iterable range object with slicing support for i in range(2**30)[:10]: pass # Other iterators: map, zip, filter my_iter = zip(range(3), ['a', 'b', 'c']) assert my_iter != list(my_iter) # The round() function behaves as it does in Python 3, using # "Banker's Rounding" to the nearest even last digit: assert round(0.1250, 2) == 0.12 # pow() supports fractional exponents of negative numbers like in Py3: z = pow(-1, 0.5) # Compatible output from isinstance() across Py2/3: assert isinstance(2**64, int) # long integers assert isinstance(u'blah', str) assert isinstance('blah', str) # only if unicode_literals is in effect # Py3-style iterators written as new-style classes (subclasses of # future.types.newobject) are automatically backward compatible with Py2: class Upper(object): def __init__(self, iterable): self._iter = iter(iterable) def __next__(self): # note the Py3 interface return next(self._iter).upper() def __iter__(self): return self
def rsaEncrypt(text, pubKey, modulus): text = text[::-1] rs = pow(int(binascii.hexlify(text), 16), int(pubKey, 16), int(modulus, 16)) return format(rs, 'x').zfill(256)