def test_crack_shared_cipher():
    ciphertext = 'Call me Ishmael.'

    keypair0 = RSAKeypair.create(e=3)
    keypair1 = RSAKeypair.create(e=3)
    keypair2 = RSAKeypair.create(e=3)

    c0 = rsa_encrypt(ciphertext, keypair0)
    c1 = rsa_encrypt(ciphertext, keypair1)
    c2 = rsa_encrypt(ciphertext, keypair2)

    n0 = keypair0.exponent
    n1 = keypair1.exponent
    n2 = keypair2.exponent
    m_s_0 = n1 * n2
    m_s_1 = n0 * n2
    m_s_2 = n0 * n1

    assert all(gcd(n, n_) == 1 for n, n_ in combinations([n0, n1, n2], 2))

    result, _ = crt_inductive([
        (c0 * m_s_0 * mod_inverse(m_s_0, n0), keypair0.exponent),
        (c1 * m_s_1 * mod_inverse(m_s_1, n1), n1),
        (c2 * m_s_2 * mod_inverse(m_s_2, n2), n2),
    ])
    cube_root, is_exact = iroot(mpz(result), 3)
    assert is_exact, 'Cube root should have been exact'
    assert unhexlify('{:02x}'.format(cube_root)).decode() == ciphertext
Exemple #2
0
def brute_force_digest(digest, h, r, p):
    assert pow(h, r, p) == 1, 'Element h should have had order r'
    # h has order r so the digest must have value h^x where 0 <= x < r - 1
    # Must include x = r (so K would be 1)
    for x in range(1, r + 1):
        d = sha1('crazy flamboyant for the rap enjoyment'.encode())
        d.update(str(pow(h, x, p)).encode())
        candidate_digest = d.digest()

        if digest == candidate_digest:
            return x

    raise ValueError(f'Could not find h^x such that h^x = K mod p')


def find_residues(j, p, secret):
    for r in small_factors(j):
        h = find_element_of_order(r, p)
        # Simulates getting a message from Bob using the secret (h)
        digest = encrypt_digest(h, secret, p)
        b = brute_force_digest(digest, h, r, p)
        yield (b, r)


if __name__ == '__main__':
    crt_moduli = list(find_residues(j, p, bob_secret))
    x, _ = crt_inductive(crt_moduli)
    assert bob_secret == x
    print(f'All done!  Successfully cracked bob_secret using '
          f'{len(crt_moduli)} samples')
Exemple #3
0
    order_curve2 = 233970423115425145544350131142039591210
    bad_curve3 = WeierstrassCurve(p, -95051, 727)
    order_curve3 = 233970423115425145545378039958152057148
    bad_curves = [bad_curve1, bad_curve2, bad_curve3]
    curve_orders = [order_curve1, order_curve2, order_curve3]

    crt_residues = []
    for bad_curve, bad_curve_order in zip(bad_curves, curve_orders):
        print(f'Computing residues for {bad_curve}')
        crt_residues += list(
            subgroup_confinement_residues(bob_keypair, bad_curve,
                                          bad_curve_order))
        # Must remove duplicates because the given bad curves might end up
        # with the same residues.  In the event of a bug where we have
        # different residue values mod the same prime the algorithm will
        # still explode.
        crt_residues = list(set(crt_residues))
        q = reduce(mul, map(itemgetter(1), crt_residues), 1)
        if q > given_order:
            break

    for m, r in crt_residues:
        assert bob_keypair.secret % r == m

    # Ready to attack
    x, _ = crt_inductive(crt_residues)

    assert x == bob_keypair.secret, 'Brute forced secret with bogus points'
    print(f'All done!  Used {len(crt_residues)} residues to determine '
          f'{x} == {bob_keypair.secret}')
            return b + xT - xW

    raise ValueError('Kangaroo sequences did not intersect')


# g^705485 = y1
# print(kangaroo_attack(pseudorandom_map, N, g, 0, 2**20, y1))
assert pow(g, 705485, p) == y1
# g^359579674340 = y2
# print(kangaroo_attack(pseudorandom_map, N, g, 0, 2**40, y2))
assert pow(g, 359579674340, p) == y2

if __name__ == '__main__':
    bob_secret = randint(0, q)
    residues = list(find_residues(j, p, bob_secret))
    n, r = crt_inductive(residues)
    print(f'secret_key = {n} mod {r}')
    assert bob_secret % r == n, 'Bob secret did not satisfy expected relationship'

    # We know {secret key} = n mod r
    # So {secret key} = n + m * r - must find m
    # Through a series of algebraic transformations, we have:
    # y' = g^{m * r}
    # y' = (g^{r})^m
    g_ = pow(g, r, p)
    # This is the Diffie-Hellman public key (and so public)
    y = pow(g, bob_secret, p)
    g_inverse = pow(g, p - 2, p)
    assert (g * g_inverse) % p == 1, 'g_inverse was not inverse of g'

    y_ = (y * pow(g_inverse, n, p)) % p
    print(f'{alice_keypair.secret} (alice secret)')

    # if calculate_residues:
    residues = subgroup_confinement_residues(curve, alice_keypair, twist_order)
    residues_list = list(residues)
    # else:
    #     residues_list = [
    #         (4, 11), (46, 107), (15, 197), (721, 1621),
    #         (36413, 105143), (140928, 405373), (3842, 2323367)]

    print(f'Residues: {residues_list}')
    option1, option2 = filter_moduli(curve, alice_keypair, twist_order,
                                     residues_list)

    # So these values are actually duplicative since r1 == r2 and m2 = r1 - m1
    m1, r = crt_inductive(option1)
    m2, r_ = crt_inductive(option2)
    assert r == r_
    assert alice_keypair.secret % r in [m1, r - m1]
    assert alice_keypair.secret % r in [m1, m2]
    # So we can forget about m2 for now and just work with m1.
    # So n is either r - m1 or m1
    # x = n + m * r --> n is known, m is unknown

    # We know alice_public is g^alice_secret
    # y = alice_public

    print(f'We know {alice_keypair.secret} = ±{m1} + m * {r}.  Solve for m')

    x1 = curve_kangaroo_attack(point, m1, r)
    x2 = curve_kangaroo_attack(point, r - m1, r)