Esempio n. 1
0
def main_DSA():
    a,A = ec.gen_key(G, Go)  # Alice's key
    msg = b'Everybody knows that the boat is leaking'

    sig = ec.dsa_sign(msg, a)
    assert ec.dsa_verify(msg, sig, A)

    # assume Eve can pick the base point she wants (as if it was
    # part of her public key), then it is trivial to forge a perfectly
    # valid key that verifies the signature
    r,s = sig
    # compute the constants
    sinv = invmodp(s,Go)
    u1 = (ec.H(msg) * sinv) % Go
    u2 = (r * sinv) % Go
    R = u1*G + u2*A
    # forge a key
    e = secrets.randbelow(Go)
    Gforged = invmodp(u1 + u2*e, Go)*R
    E = e*Gforged
    # verify
    print('Verifying with forged ECDSA key...', end=' ', flush=True)
    ec.set_base_point(Gforged, Go)
    assert (Go*Gforged).is_zero()
    assert ec.dsa_verify(msg, sig, E)
    print('ok.\n')
Esempio n. 2
0
    def __add__(self, B):
        if self.is_zero():
            return copy(B)
        if B.is_zero():
            return copy(self)

        if self.x == B.x:
            if (self.y + B.y) % P == 0:  # inverse case
                return Zero()
            else:
                m = ((3 * self.x * self.x + _a) * invmodp(2 * self.y, P)) % P
        else:
            m = ((B.y - self.y) * invmodp(B.x - self.x, P)) % P
        x = (m * m - self.x - B.x) % P
        y = (m * (self.x - x) - self.y) % P
        return Point(x, y)
Esempio n. 3
0
def dsa_verify(msg, sig, Pub):
    r, s = sig
    sinv = invmodp(s, _Go)
    u1 = (H(msg) * sinv) % _Go
    u2 = (r * sinv) % _Go
    R = u1 * _G + u2 * Pub
    return r == R.x % _Go
Esempio n. 4
0
def attack():
    # consider DSA (mod q the order of G):
    #   random k                    (nonce / ephemeral DH private key)
    #   r = (k*G).x                 (ephemeral DH public key)
    #   s = ((H(msg) + d*r) * k^-1  (d the private key to guess)
    # and assume the last l bits (say l=8) of k are constant, say 0,
    # then k = b*2^l for some random b ~ q/2^l
    #   s*b*2^l = H(msg) + d*r
    #   b = -u + d*t for u = -H(msg)*s^-1*2^-l and t = r*s^-1*2^-l
    # with u, d*t ~ q >> q/2^l ~ b (for large enough l)
    # hence we can approx.
    #   0 ~ u - d*t  (mod q)
    #   0 ~ i + m*q - d*t for some integer m
    # say we capture n signatures, for i = 1..n
    #   0 ~ ui + mi*q - d*ti
    # where ui,ti,q are known, mi,d are unknown
    # let B = [q 0 0 .. 0 t1 u1]
    #         [0 q 0 .. 0 t2 u2]
    #         [0 0 q .. 0 t3 u3]
    #                ..
    #         [0 0 0 .. q tn un]
    #         [0 0 0 .. 0 ct  0]  <-- added to squarify the matrix
    #         [0 0 0 .. 0  0 cu]  <-- for some constants ct,cu
    # then B * [m1 .. mn -d 1] ~ [0 .. 0 -d*ct cu]
    q = ec._Go
    l = 8  # <-- the less bits known
    n = 20  # <-- the more signatures needed
    _d, _ = ec.gen_key(ec._G, ec._Go)
    B = []
    T = []
    U = []
    for i in range(n):
        msg = os.urandom(10)
        r, s = biased_sign(msg, _d, l)
        h = ec.H(msg)
        s2l_inv = invmodp(s * (1 << l), q)
        u = (-h * s2l_inv) % q
        t = (r * s2l_inv) % q
        T.append(t)
        U.append(u)
        B.append(Vec([q if j == i else 0 for j in range(n + 2)]))
    ct = Decimal(1) / Decimal(1 << l)
    cu = Decimal(q) / Decimal(1 << l)
    T += [ct, 0]
    U += [0, cu]
    B += [Vec(T), Vec(U)]
    R = LLL(B)
    for v in R:
        if v[-1] == cu:
            d = -v[-2] / ct
            break
    print(d)
    print(_d)
    assert d == _d
Esempio n. 5
0
def montgomery_ladder(u: int, k: int) -> int:
    # we should check that the coordinate u is on the curve
    # (otherwise it would be on the twist)
    # but we do not do it here to allow some of the attacks
    #assert montgomery_is_valid(u)
    u2, w2 = 1, 0
    u3, w3 = u, 1
    for i in range(P.bit_length() - 1, -1, -1):
        b = 1 & (k >> i)
        if b:
            u2, u3 = u3, u2
            w2, w3 = w3, w2
        u3, w3 = pow(u2 * u3 - w2 * w3, 2,
                     P), (u * pow(u2 * w3 - w2 * u3, 2, P)) % P
        u2, w2 = pow(u2 * u2 - w2 * w2, 2,
                     P), (4 * u2 * w2 * (u2 * u2 + _A * u2 * w2 + w2 * w2)) % P
        if b:
            u2, u3 = u3, u2
            w2, w3 = w3, w2
    return (u2 * invmodp(w2, P)) % P
Esempio n. 6
0
    ## Practical attack
    # generate Bob's key
    _b = secrets.randbelow(q)  # private < q
    B = pow(g, _b, p)  # public

    # PH attack
    F = [r for r, m in small_factors((p - 1) // q)]
    X = 0
    R = 1
    for r in F:
        # we skip to the important part: Eve has deduced _b%r
        x = _b % r
        X, R = CRT_combine(X, R, x, r)

    # we know b = X        mod R
    #         b = X + K*R  mod q

    # Rewrite the problem:
    #   B = g^(X + K*R)
    #   B*g^(-X) = (g^R)^K
    Bp = (B * invmodp(pow(g, X, p), p)) % p
    gp = pow(g, R, p)

    # New DL problem:
    #   B' = g'^K  with K in [0, (q-1)/R]
    K = pollard_lambda(Bp, 0, (q - 1) // R, g=gp)
    b_ = X + K * R
    print(b_)
    assert b_ == _b
Esempio n. 7
0
def biased_sign(msg, d, l=8):
    k = secrets.randbelow(ec._Go >> l) << l
    r = (k * ec._G).x % ec._Go
    s = ((ec.H(msg) + d * r) * invmodp(k, ec._Go)) % ec._Go
    return (r, s)
Esempio n. 8
0
def montgomery_v_from_u(u):
    # output is None if no solution
    # if output is v, -v is also solution
    Bv2 = (pow(u, 3, P) + _A * u * u + u) % P
    v2 = (Bv2 * invmodp(_B, P)) % P
    return shanks_tonelli(v2, P)
Esempio n. 9
0
def montgomery_is_valid(u, v=None):
    if v is None:  # single-coordinate check
        v2 = (invmodp(_B, P) * (pow(u, 3, P) + _A * u * u + u)) % P
        return legendre(v2, P) == 1
    # point check
    return (_B * v * v - pow(u, 3, P) - _A * u * u - u) % P == 0
Esempio n. 10
0
def dsa_sign(msg, priv):
    k = 1 + secrets.randbelow(_Go - 1)
    r = (k * _G).x % _Go
    s = ((H(msg) + priv * r) * invmodp(k, _Go)) % _Go
    return (r, s)