Beispiel #1
0
 def test_count_bits(self):
     self.assertEquals(0, util.count_bits(0b0))
     self.assertEquals(1, util.count_bits(0b1))
     self.assertEquals(2, util.count_bits(0b10))
     self.assertEquals(2, util.count_bits(0b11))
     self.assertEquals(3, util.count_bits(0b100))
     self.assertEquals(3, util.count_bits(0b101))
     self.assertEquals(3, util.count_bits(0b111))
     self.assertEquals(4, util.count_bits(0b1000))
     self.assertEquals(599, util.count_bits(2**599 - 1))
     self.assertEquals(600, util.count_bits(2**599))
def break_ecdsa(curve_obj, hash_int, hash_num_bits, sig1, sig2, msg1, msg2):
    """Recover the private key from two ECDSA signatures that have been
    generated by accidentally re-using the same random number k.

    Given two signatures (r, s) and (r, s') and two messages msg1,
    msg2, calculate the random number k and using that recover the
    private key, completely breaking the system.

    This is to show the catastrophic failure scenarios inherit in
    using random numbers with (EC)DSA.

    Returns a tuple (k, <private key>).
    """

    (r, s) = sig1
    (r_, s_) = sig2
    if r != r_:
        raise ValueError('cannot attack this')

    e = hash_int(msg1)
    L_n = util.count_bits(curve_obj.order)
    z = e >> max(hash_num_bits - L_n, 0)

    e_ = hash_int(msg2)
    z_ = e_ >> max(hash_num_bits - L_n, 0)

    def div(a, b):
        return (a * numbertheory.inverse_of(b, curve_obj.order)) % curve_obj.order

    k = div(z - z_, s - s_)
    priv = div(s*k - z, r)

    return (k, priv)
def ecdsa_sign(curve_obj, hash_int, hash_num_bits, private_key, message, k=None):
    """Sign message using the private key.

    Returns the signature (r, s).

    @param hash_int: a hash function mapping to an integer, for example
      lambda m: util.be2int(hashlib.sha256(m).digest())
    @param hash_num_bits: the number of bits in the digest above, for
    example 256.
    """

    n = curve_obj.order

    if k is None:
        k = util.randint(1, n - 1)

    e = hash_int(message)
    L_n = util.count_bits(n)
    z = e >> max(hash_num_bits - L_n, 0)

    while True:
        (x1, y1) = curve.mul(k, curve_obj.base_point, curve_obj.curve)
        r = x1 % curve_obj.order
        if r == 0:
            continue

        k_neg = numbertheory.inverse_of(k, n)

        s = (k_neg * (z + r * private_key)) % n
        if s == 0:
            continue

        break

    return (r, s)
def break_ecdsa(curve_obj, hash_int, hash_num_bits, sig1, sig2, msg1, msg2):
    """Recover the private key from two ECDSA signatures that have been
    generated by accidentally re-using the same random number k.

    Given two signatures (r, s) and (r, s') and two messages msg1,
    msg2, calculate the random number k and using that recover the
    private key, completely breaking the system.

    This is to show the catastrophic failure scenarios inherit in
    using random numbers with (EC)DSA.

    Returns a tuple (k, <private key>).
    """

    (r, s) = sig1
    (r_, s_) = sig2
    if r != r_:
        raise ValueError('cannot attack this')

    e = hash_int(msg1)
    L_n = util.count_bits(curve_obj.order)
    z = e >> max(hash_num_bits - L_n, 0)

    e_ = hash_int(msg2)
    z_ = e_ >> max(hash_num_bits - L_n, 0)

    def div(a, b):
        return (a *
                numbertheory.inverse_of(b, curve_obj.order)) % curve_obj.order

    k = div(z - z_, s - s_)
    priv = div(s * k - z, r)

    return (k, priv)
def ecdsa_verify(curve_obj, hash_int, hash_num_bits, public_key, message,
                 signature):
    """Verify that signature is over the message using the public key.

    Returns True if so, False otherwise.

    Otherwise similar to ecdsa_sign() in usage.
    """

    n = curve_obj.order

    # Verify
    if public_key == curve_obj.base_point or \
            curve_obj.curve.invert_point(public_key) == curve_obj.base_point: # XXX: Check inverted too?
        return False

    if not curve_obj.curve.point_on_curve(public_key):
        return False

    if not curve.mul(curve_obj.order, public_key,
                     curve_obj.curve) == curve_obj.curve.neutral_point():
        return False

    (r, s) = signature

    if not 1 <= r <= n - 1:
        return False

    if not 1 <= s <= n - 1:
        return False

    e = hash_int(message)
    L_n = util.count_bits(n)
    z = e >> max(hash_num_bits - L_n, 0)

    # Verify
    w = numbertheory.inverse_of(s, curve_obj.order) % n
    u_1 = (z * w) % n
    u_2 = (r * w) % n

    (x1, y1) = curve_obj.curve.add_points(
        curve.mul(u_1, curve_obj.base_point, curve_obj.curve),
        curve.mul(u_2, public_key, curve_obj.curve))

    return (r % n) == (x1 % n)
def ecdsa_verify(curve_obj, hash_int, hash_num_bits, public_key, message, signature):
    """Verify that signature is over the message using the public key.

    Returns True if so, False otherwise.

    Otherwise similar to ecdsa_sign() in usage.
    """

    n = curve_obj.order

    # Verify
    if public_key == curve_obj.base_point or \
            curve_obj.curve.invert_point(public_key) == curve_obj.base_point: # XXX: Check inverted too?
        return False

    if not curve_obj.curve.point_on_curve(public_key):
        return False

    if not curve.mul(curve_obj.order, public_key, curve_obj.curve) == curve_obj.curve.neutral_point():
        return False

    (r, s) = signature

    if not 1 <= r <= n - 1:
        return False

    if not 1 <= s <= n - 1:
        return False

    e = hash_int(message)
    L_n = util.count_bits(n)
    z = e >> max(hash_num_bits - L_n, 0)

    # Verify
    w = numbertheory.inverse_of(s, curve_obj.order) % n
    u_1 = (z * w) % n
    u_2 = (r * w) % n

    (x1, y1) = curve_obj.curve.add_points(
        curve.mul(u_1, curve_obj.base_point, curve_obj.curve),
        curve.mul(u_2, public_key, curve_obj.curve)
        )

    return (r % n) == (x1 % n)
def ecdsa_sign(curve_obj,
               hash_int,
               hash_num_bits,
               private_key,
               message,
               k=None):
    """Sign message using the private key.

    Returns the signature (r, s).

    @param hash_int: a hash function mapping to an integer, for example
      lambda m: util.be2int(hashlib.sha256(m).digest())
    @param hash_num_bits: the number of bits in the digest above, for
    example 256.
    """

    n = curve_obj.order

    if k is None:
        k = util.randint(1, n - 1)

    e = hash_int(message)
    L_n = util.count_bits(n)
    z = e >> max(hash_num_bits - L_n, 0)

    while True:
        (x1, y1) = curve.mul(k, curve_obj.base_point, curve_obj.curve)
        r = x1 % curve_obj.order
        if r == 0:
            continue

        k_neg = numbertheory.inverse_of(k, n)

        s = (k_neg * (z + r * private_key)) % n
        if s == 0:
            continue

        break

    return (r, s)