def verify(self, msg, sig, y): r, s = sig if not(0 < r and r < self.q): raise ValueError('r not between 0 and q (r={})'.format(r)) if not(0 < s and s < self.q): raise ValueError('s not between 0 and q (s={})'.format(s)) w = set5.modinv(s, self.q) u1 = (self.__get_hash__(msg) * w) % self.q u2 = (r * w) % self.q v = ((set5.modexp(self.g, u1, self.p) * set5.modexp(y, u2, self.p)) % self.p) % self.q return v == r
def Step2c(self, M, s, pbar2): # For all (a, b) pairs: for (a, b) in M: # Compute `r` r = ceil(2 * (b*s - 2*self.B), self.N) t = True while t: pbar2.update(1) # Compute `S_{min}`, `S_{max}` Smin, Smax = ceil(2*self.B + r*self.N, b), ceil(3*self.B + r*self.N, a) + 1 # If `S_{min}` exceeds `S_{max}`, go to the next (a, b) pair if Smin >= Smax: t = False # For all integers in range `(S_{min}, S_{max})`: for s in range (Smin, Smax): # Generate `ci` ci = (self.c * set5.modexp(s, self.e, self.N)) % self.N # See if `c(s)^e mod N` is PKCS conforming if self.oracle(ci): pbar2.set_description(('Step 2C: Intermediate s found ({})'.format(s))[:os.get_terminal_size().columns - 33]) # Return found value `s` return s # If no `s` was found, try next `r` r += 1 # If all pairs in `M` are exhausted and yet no `s` was found, raise an exception raise Exception("No values found")
def challenge_46(): print() # Get message, create RSA keypair, generate ciphertext message = base64.b64decode('VGhhdCdzIHdoeSBJIGZvdW5kIHlvdSBkb24ndCBwbGF5IGFyb3VuZCB3aXRoIHRoZSBGdW5reSBDb2xkIE1lZGluYQ==') pub, priv = set5.set_up_rsa(e=3, keysize=1024) ciphertext = set5.encrypt_rsa(set5.bytes_to_int(message), pub) # Set up our Oracle oracle = lambda x: rsa_oracle_plaintext_even(x, priv) # Verify the keypair works assert set5.int_to_bytes(set5.encrypt_rsa(ciphertext, priv)) == message # Set initial lower and upper bound, as well as intermediate ciphertext lower_bound, upper_bound = 0, pub[1] ciphertext_ = ciphertext # Perform the below until the lower and upper bound converge while upper_bound != lower_bound: # Multiply plaintext by multiplying ciphertext by 2**`e` mod `N` ciphertext_ = (ciphertext_ * set5.modexp(2, pub[0], pub[1])) % pub[1] # If the oracle says True, update the upper bound; if False, update the lower bound if oracle(ciphertext_): upper_bound = floor(upper_bound + lower_bound, 2) else: lower_bound = floor(upper_bound + lower_bound, 2) # Create 'Holywood style' output intermediate_result = str(set5.int_to_bytes(upper_bound))[:os.get_terminal_size().columns - 1] fill = " " * (os.get_terminal_size().columns - 1 - len(intermediate_result)) print(colorama.Cursor.UP(1) + intermediate_result + fill) # Print final outputs print(colorama.Cursor.UP(1) + "Result: {}".format(set5.int_to_bytes(upper_bound))) print("Original: {}".format(message))
def sign(self, msg, x): k = random.randrange(2, self.q) r = set5.modexp(self.g, k, self.p) % self.q if k == 0: return self.sign(msg, x) s = (set5.modinv(k, self.q) * (self.__get_hash__(msg) + (x*r))) % self.q if s == 0: return self.sign(msg, x) return (r, s), k
def Step2a(self): pbar = tqdm(desc='Step 2A') # Start at (N // 3B) s = ceil(self.N, 3*self.B) while True: pbar.update(1) # Generate `c_1` c1 = (self.c * set5.modexp(s, self.e, self.N)) % self.N # See if `c(s)^e mod N` is PKCS conforming if self.oracle(c1): pbar.set_description('Step 2A: Initial s found ({})'.format(s)) pbar.close() # Return found value `s` return s % self.N s += 1
def challenge_41(): # Initate a new RSA Oracle oracle = RsaOracle() # Generate a secret secret = random.randrange(2, oracle.public[1] // 2) # Generate a message to send to the RSA oracle msg = set5.encrypt_rsa(secret, oracle.public) # Query 1: try the generated encrypted secret r = oracle.query(msg) # Expected output: the original secret assert r == secret # Query 2: try the generated encrypted secret again r = oracle.query(msg) # Expected output: a None assert r is None e, n = oracle.public s = 2 # Query 3: the attack - try our manipulated value msgp = (set5.modexp(s, e, n) * msg) % n # Expected output: the original secret r = (oracle.query(msgp) // s) % n assert_true(r == secret)
def generate_keypair(self): x = random.randrange(0, self.q) p = set5.modexp(self.g, x, self.p) return (x, p)