def test_edge(self): with mock.patch("random.randint") as random_mock: random_mock.side_effect=random.Random(34).randint primes = [rsa.get_prime(3) for _ in range(10)] self.assertTrue(all((int(p) in (2, 3, 5, 7) for p in primes))) for b in (3, 4, 5, 10, 20): for i in range(3): prime = rsa.get_prime(b) self.assertTrue(rsa.isprime(prime)) self.assertTrue(prime < 2 ** b)
def test(tcount, bits=256): n = rsa.get_prime(bits / 8, 20) p = rsa.random.randint(1, n) p1 = (rsa.random.randint(1, n), rsa.random.randint(1, n)) q = curve_q(p1[0], p1[1], p, n) p2 = mulp(p, q, n, p1, rsa.random.randint(1, n)) c1 = [rsa.random.randint(1, n) for i in xrange(tcount)] c2 = [rsa.random.randint(1, n) for i in xrange(tcount)] c = zip(c1, c2) t = time.time() for i, j in c: from_projective(addf(p, q, n, mulf(p, q, n, to_projective(p1), i), mulf(p, q, n, to_projective(p2), j)), n) t1 = time.time() - t t = time.time() for i, j in c: muladdp(p, q, n, p1, i, p2, j) t2 = time.time() - t return tcount, t1, t2
def test(tcount, bits=256): n = rsa.get_prime(bits / 8, 20) p = rsa.random.randint(1, n) p1 = (rsa.random.randint(1, n), rsa.random.randint(1, n)) q = curve_q(p1[0], p1[1], p, n) p2 = mulp(p, q, n, p1, rsa.random.randint(1, n)) c1 = [rsa.random.randint(1, n) for i in range(tcount)] c2 = [rsa.random.randint(1, n) for i in range(tcount)] c = zip(c1, c2) t = time.time() for i, j in c: from_projective( addf(p, q, n, mulf(p, q, n, to_projective(p1), i), mulf(p, q, n, to_projective(p2), j)), n) t1 = time.time() - t t = time.time() for i, j in c: muladdp(p, q, n, p1, i, p2, j) t2 = time.time() - t return tcount, t1, t2
# Reconstruct the y-coordinate when curve parameters, x and the sign-bit of # the y coordinate are given: def y_from_x(x, p, q, n, sign): '''Return the y coordinate over curve (p, q, n) for given (x, sign)''' # optimized form of (x**3 - p*x - q) % n a = (((x * x) % n - p) * x - q) % n if __name__ == "__main__": import rsa import time t = time.time() n = rsa.get_prime(256 / 8, 20) tp = time.time() - t p = rsa.random.randint(1, n) p1 = (rsa.random.randint(1, n), rsa.random.randint(1, n)) q = curve_q(p1[0], p1[1], p, n) r1 = rsa.random.randint(1, n) r2 = rsa.random.randint(1, n) q1 = mulp(p, q, n, p1, r1) q2 = mulp(p, q, n, p1, r2) s1 = mulp(p, q, n, q1, r2) s2 = mulp(p, q, n, q2, r1) s1 == s2 tt = time.time() - t def test(tcount, bits=256): n = rsa.get_prime(bits / 8, 20)
#!/usr/local/bin/python import rsa FLAG = 'ractf{S0m3t1mesS1zeDoesM4773r}' p = 17 q = rsa.get_prime() e = 65537 state = rsa.solve_for(p=p, q=q, e=e) pt = int.from_bytes(FLAG.encode(), 'big') ct = rsa.encrypt(state, pt, as_bytes=False) print('n:', state[0]) print('e:', e) print('ct:', ct)
# Reconstruct the y-coordinate when curve parameters, x and the sign-bit of # the y coordinate are given: def y_from_x(x, p, q, n, sign): """Return the y coordinate over curve (p, q, n) for given (x, sign)""" # optimized form of (x**3 - p*x - q) % n a = (((x * x) % n - p) * x - q) % n if __name__ == "__main__": import rsa import time t = time.time() n = rsa.get_prime(256 / 8, 20) tp = time.time() - t p = rsa.random.randint(1, n) p1 = (rsa.random.randint(1, n), rsa.random.randint(1, n)) q = curve_q(p1[0], p1[1], p, n) r1 = rsa.random.randint(1, n) r2 = rsa.random.randint(1, n) q1 = mulp(p, q, n, p1, r1) q2 = mulp(p, q, n, p1, r2) s1 = mulp(p, q, n, q1, r2) s2 = mulp(p, q, n, q2, r1) s1 == s2 tt = time.time() - t def test(tcount, bits=256): n = rsa.get_prime(bits / 8, 20)
def test(tcount, bits=256): n = rsa.get_prime(bits / 8, 20) p = rsa.random.randint(1, n) p1 = (rsa.random.randint(1, n), rsa.random.randint(1, n)) q = curve_q(p1[0], p1[1], p, n) p2 = mulp(p, q, n, p1, rsa.random.randint(1, n))
# SCALAR MULTIPLICATION ------------------------------------------------------- # scalar multiplication p1 * c = p1 + p1 + ... + p1 (c times) in O(log(n))def mul(p, q, n, p1, c): '''multiply point p1 by scalar c over curve (p, q, n)''' res = None while c > 0: if c & 1: res = add(p, q, n, res, p1) c >>= 1 # c = c / 2 p1 = add(p, q, n, p1, p1) # p1 = p1 * 2 return res # this method allows _signed_bin() to choose between 1 and -1. It will select# the sign which leaves the higher number of zeroes in the binary# representation (the higher GDB).def _gbd(n): '''Compute second greatest base-2 divisor''' i = 1 if n <= 0: return 0 while not n % i: i <<= 1 return i >> 2 # This method transforms n into a binary representation having signed bits.# A signed binary expansion contains more zero-bits hence reducing the number# of additions required by a multiplication algorithm.## Example: 15 ( 0b1111 ) can be written as 16 - 1, resulting in (1,0,0,0,-1)# and saving 2 additions. Subtraction can be performed as# efficiently as addition.def _signed_bin(n): '''Transform n into an optimized signed binary representation''' r = [] while n > 1: if n & 1: cp = _gbd(n + 1) cn = _gbd(n - 1) if cp > cn: # -1 leaves more zeroes -> subtract -1 (= +1) r.append(-1) n += 1 else: # +1 leaves more zeroes -> subtract +1 (= -1) r.append(+1) n -= 1 else: r.append(0) # be glad about one more zero n >>= 1 r.append(n) return r[::-1] # This multiplication algorithm combines signed binary expansion and# fast addition using projective coordinates resulting in 5 to 10 times# faster multiplication.def mulf(p, q, n, jp1, c): '''Multiply point jp1 by c in projective coordinates''' sb = _signed_bin(c) res = None jp0 = neg(jp1, n) # additive inverse of jp1 to be used fot bit -1 for s in sb: res = doublef(p, q, n, res) if s: res = addf(p, q, n, res, jp1) if s > 0 else \ addf(p, q, n, res, jp0) return res # Encapsulates mulf() in order to enable flat coordinates (x, y)def mulp(p, q, n, p1, c): '''Multiply point p by c using fast multiplication''' return from_projective(mulf(p, q, n, to_projective(p1), c), n) # Sum of two products using Shamir's trick and signed binary expansiondef muladdf(p, q, n, jp1, c1, jp2, c2): '''Efficiently compute c1 * jp1 + c2 * jp2 in projective coordinates''' s1 = _signed_bin(c1) s2 = _signed_bin(c2) diff = len(s2) - len(s1) if diff > 0: s1 = [0] * diff + s1 elif diff < 0: s2 = [0] * -diff + s2 jp1p2 = addf(p, q, n, jp1, jp2) jp1n2 = addf(p, q, n, jp1, neg(jp2, n)) precomp = ((None, jp2, neg(jp2, n)), (jp1, jp1p2, jp1n2), (neg(jp1, n), neg(jp1n2, n), neg(jp1p2, n))) res = None for i, j in zip(s1, s2): res = doublef(p, q, n, res) if i or j: res = addf(p, q, n, res, precomp[i][j]) return res # Encapsulate muladdf()def muladdp(p, q, n, p1, c1, p2, c2): '''Efficiently compute c1 * p1 + c2 * p2 in (x, y)-coordinates''' return from_projective(muladdf(p, q, n, to_projective(p1), c1, to_projective(p2), c2), n) # POINT COMPRESSION ----------------------------------------------------------- # Compute the square root modulo n # Determine the sign-bit of a point allowing to reconstruct y-coordinates# when x and the sign-bit are given:def sign_bit(p1): '''Return the signedness of a point p1''' return p1[1] % 2 if p1 else 0 # Reconstruct the y-coordinate when curve parameters, x and the sign-bit of# the y coordinate are given:def y_from_x(x, p, q, n, sign): '''Return the y coordinate over curve (p, q, n) for given (x, sign)''' # optimized form of (x**3 - p*x - q) % n a = (((x * x) % n - p) * x - q) % n if __name__ == "__main__": import rsa import time t = time.time() n = rsa.get_prime(256 / 8, 20) tp = time.time() - t p = rsa.random.randint(1, n) p1 = (rsa.random.randint(1, n), rsa.random.randint(1, n)) q = curve_q(p1[0], p1[1], p, n) r1 = rsa.random.randint(1, n) r2 = rsa.random.randint(1, n) q1 = mulp(p, q, n, p1, r1) q2 = mulp(p, q, n, p1, r2) s1 = mulp(p, q, n, q1, r2) s2 = mulp(p, q, n, q2, r1) s1 == s2 tt = time.time() - t def test(tcount, bits=256): n = rsa.get_prime(bits / 8, 20) p = rsa.random.randint(1, n) p1 = (rsa.random.randint(1, n), rsa.random.randint(1, n)) q = curve_q(p1[0], p1[1], p, n) p2 = mulp(p, q, n, p1, rsa.random.randint(1, n)) c1 = [rsa.random.randint(1, n) for i in xrange(tcount)] c2 = [rsa.random.randint(1, n) for i in xrange(tcount)] c = zip(c1, c2) t = time.time() for i, j in c: from_projective(addf(p, q, n, mulf(p, q, n, to_projective(p1), i), mulf(p, q, n, to_projective(p2), j)), n) t1 = time.time() - t t = time.time() for i, j in c: muladdp(p, q, n, p1, i, p2, j) t2 = time.time() - t return tcount, t1, t2
import rsa import random prime_pool = [] for _ in range(10): prime_pool.append(rsa.get_prime(512)) def get_prime(): return random.choice(prime_pool) def gen_challenge(): r = random.randint(0, 4) if r == 0: p = get_prime() q = get_prime() have = {'p': p, 'q': q} need = {'n': p * q} elif r == 1: p = get_prime() q = get_prime() n = p * q have = {'p': p, 'n': n} need = {'q': q} elif r == 2: p = get_prime() q = get_prime()