Ejemplo n.º 1
0
    def compute_params(s, m=None, a=None, b=None):
        """Compute parameters and initial seed for LCG prng
        next_state = a*state + b mod m

        Args:
            s(list): subsequent outputs from LCG oracle starting with seed
            m(int/None)
            a(int/None)
            b(int/None)

        Returns:
            a, b, m(int)
        """
        if m is None:
            t = [s[n + 1] - s[n] for n in range(len(s) - 1)]
            u = [abs(t[n + 2] * t[n] - t[n + 1]**2) for n in range(len(t) - 2)]
            m = gcd(*u)
            log.success("m = {}".format(m))

        if a is None:
            if gcd(s[1] - s[0], m) == 1:
                a = (s[2] - s[1]) * invmod(s[1] - s[0], m)
            elif gcd(s[2] - s[0], m) == 1:
                a = (s[3] - s[1]) * invmod(s[2] - s[0], m)
            else:
                log.critical_error("a not found")
            a = a % m
            log.success("a = {}".format(a))

        if b is None:
            b = (s[1] - s[0] * a) % m
            log.success("b = {}".format(b))

        return a, b, m
Ejemplo n.º 2
0
def factors_from_d(n, e, d):
    """Factorize n to p and q given e and d"""
    k = e * d - 1
    while True:
        g = random.randint(2, n - 2)
        b = k // (2**power_of_two(k))
        while b < k:
            gb = gmpy2.powmod(g, b, n)
            if gb != 1 and gb != n - 1 and gmpy2.powmod(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
Ejemplo n.º 3
0
def test_wiener(tries=10):
    print("\nTest: wiener")
    for _ in range(tries):
        n_size = 1024
        p = random_prime(n_size // 2)
        q = random_prime(n_size // 2)
        n = p * q
        phi = (p - 1) * (q - 1)
        while True:
            d = getrandbits(n_size // 4)
            if gcd(phi, d) == 1 and 81 * pow(d, 4) < n:
                break
        e = invmod(d, phi)
        key = RSAKey.construct(int(n), int(e))
        key_recovered = wiener(key.publickey())
        if key_recovered:
            assert key_recovered.d == d
        else:
            print("Not recovered")
Ejemplo n.º 4
0
def guess_key_size(ciphertext, max_key_size=40):
    """Given sentence xored with short key, guess key size
    From: http://trustedsignal.blogspot.com/2015/06/xord-play-normalized-hamming-distance.html

    Args:
         ciphertext(string)
         max_key_size(int)

    Returns:
        list: sorted list of tuples (key_size, probability),
        note that most probable key size not necessary have the largest probability
    """
    if not max_key_size:
        max_key_size = len(ciphertext)/4

    result = {}
    for key_size in range(1, max_key_size):
        blocks = re.findall('.' * key_size, ciphertext, re.DOTALL)
        if len(blocks) < 2:
            break

        diff = i = 0
        while i < len(blocks) - 1:
            if len(blocks[i]) != len(blocks[i + 1]):  # not full-length block
                break
            diff += hamming_distance(blocks[i], blocks[i + 1])
            i += 1
        result[key_size] = diff / float(i)  # average
        result[key_size] /= float(key_size)  # normalize
    result = sorted(list(result.items()), key=operator.itemgetter(1))

    # now part from given link, case one
    # gcd12 = gcd(result[0][0], result[1][0])
    # gcd13 = gcd(result[0][0], result[2][0])
    # gcd23 = gcd(result[1][0], result[2][0])
    # print gcd12, gcd13, gcd23
    # if (gcd12 != 1) and (gcd12 in [x[0] for x in result[:5]]):
    #     if (gcd12 == gcd13 and gcd12 == gcd23) or (gcd12 == result[0][0] or gcd12 == result[1][0]):
    #         #remove key_size == gcd12 from result list and add it to the beginning
    #         for x in result:
    #             if x[0] == gcd12:
    #                 result.remove(x)
    #                 break
    #         result[0] == (gcd12, 1.0)

    # from link, case two; yep, black magic it is
    gcd_frequencies = defaultdict(lambda: 0)
    for gcd_pairs in itertools.combinations(result[:10], 2):
        gcd_tmp = gcd(gcd_pairs[0][0], gcd_pairs[1][0])
        gcd_frequencies[gcd_tmp] += 1
    gcd_frequencies = sorted(list(gcd_frequencies.items()), key=operator.itemgetter(1), reverse=True)

    key_sizes = [x[0] for x in result[:10]]
    distances = [x[1] for x in result[:10]]
    for guessed_most_probable_key_size in gcd_frequencies[:5]:
        if guessed_most_probable_key_size[0] != 1 and guessed_most_probable_key_size[1] != 0 and \
                        guessed_most_probable_key_size[0] in key_sizes:
            gmks_position = result[key_sizes.index(guessed_most_probable_key_size[0])]
            if gmks_position[1] < max(distances):
                result.remove(gmks_position)
                result = [gmks_position] + result
    log.info("Guessed key size: {}".format(result))
    return result