def main() -> None: oracle = m47.RSAPaddingOracle(size=768) m = m42.pkcs1v15_pad(data=b"kick it, CC", bits=oracle.pubkey.modulus.bit_length(), block_type=2) c = m39.encrypt(m, oracle.pubkey) m_int = m47.attack(oracle, c) m_prime = b"\x00" + m39.to_bytes(m_int) print(m47.pkcs1v15_unpad(m_prime)) assert m == m_prime
def parity_oracle_attack(c: int, oracle: RSAParityOracle) -> bytes: """Binary search to decrypt via parity oracle""" n = oracle.pubkey.modulus coefficient = m39.encrypt_int(2, oracle.pubkey) a, b = 0, 1 # We operate in the interval [0, 1] instead of [0, n] to avoid # dealing with large floating point division. for i in range(1, n.bit_length() + 1): c = (coefficient * c) % n interval_width = b - a a *= 2 b *= 2 if not oracle.is_even(c): a += interval_width else: b -= interval_width print(m39.to_bytes(n * b // 2**i)) return m39.to_bytes(n * b // 2**n.bit_length())
def recover_message(c: int, server: DecryptionServer) -> bytes: """Recover plaintext via homeomorphic transformation""" e, n = server.public_key # We use a random number so we can perform repeated decryptions s = randint(2, 4096) c_prime = pow(s, e, n) * c % n p_prime = m39.to_int(server.decrypt(c_prime)) s_inverse = m39.invmod(s, n) p = p_prime * s_inverse % n return m39.to_bytes(p)
def main() -> None: m = b"I am a JavaScript programmer" k = [] c = [] for _ in range(3): k_i, c_i = generate_key_and_encrypt(m) k.append(k_i) c.append(c_i) m_prime = m39.to_bytes(broadcast_attack(k, c)) assert m == m_prime print(m_prime.decode())