Example #1
0
def attack_rsa(message):
    """
    Performs the e=3 broadcast attack as described above.

    Args:
        message (bytes): The message to send 3 times.

    Returns:
        The message that was sent in, but decrypted from the crazy math.
    """
    server = BadRSAServer()
    c_0, (_, n_0) = server.encrypt_message(message)
    c_1, (_, n_1) = server.encrypt_message(message)
    c_2, (_, n_2) = server.encrypt_message(message)

    m_0 = n_1 * n_2
    m_1 = n_0 * n_2
    m_2 = n_0 * n_1
    c_0 = int.from_bytes(c_0, 'big')
    c_1 = int.from_bytes(c_1, 'big')
    c_2 = int.from_bytes(c_2, 'big')

    result = c_0 * m_0 * c39.invmod(m_0, n_0)
    result += c_1 * m_1 * c39.invmod(m_1, n_1)
    result += c_2 * m_2 * c39.invmod(m_2, n_2)
    result = result % (n_0 * n_1 * n_2)

    result = find_invpow(result, 3)[0]
    return c36.int_to_bytes(result)
Example #2
0
def recover_nonce(msg1, msg2, params):
    """
    Attempts to recover the nonce from the two messages, assuming both messages
    used the same nonce. If they, don't it returns None.

    Args:
        msg1: The first message
        msg2: The second message
        params: The DSA domain parameters

    Returns:
        The (k,x) pair from the two messages if they used the same nonce. If not,
        returns None.
    """
    p, q, g = params
    m1 = msg1.h
    m2 = msg2.h
    s1 = msg1.s
    s2 = msg2.s
    sig1 = msg1.r, msg1.s
    sig2 = msg2.r, msg2.s
    subm = (m1 - m2) % q
    subs = (s1 - s2) % q
    k = (c39.invmod(subs, q) * subm) % q
    x1 = c43.get_x_from_k(msg1.msg, sig1, params, k)
    x2 = c43.get_x_from_k(msg2.msg, sig2, params, k)
    if x1 == x2:
        return k, x1
    return None
Example #3
0
def dsa_sign_with_k(message, params, key, k=0):
    """
    DSA signing operation which captures and returns k.

    Args:
        message: The message to sign for.
        params: DSA domain parameters as a triplet (p,q,g)
        key: The DSA private key (x)
        k: An optional k value for testing

    Returns:
        The DSA signature pair (r,s,k)
    """
    p, q, g = params
    n = len(number.long_to_bytes(q))
    x = key
    if k == 0:
        k = random.randrange(1, q)
    r = pow(g, k, p) % q
    #if r == 0:
    #    dsa_sign(message, params, key)
    h = number.bytes_to_long(sha1(message).digest()[:n])
    xr = x * r
    s = (c39.invmod(k, q) * (h + xr)) % q
    #if s == 0:
    #    dsa_sign(message, params, key)
    return r, s, k
Example #4
0
def dsa_verify(message, signature, params, key):
    """
    DSA signature verification.

    Args:
        message: The message.
        signature: The signature for the message.
        params: The DSA domain parameters as a triplet (p,q,g)
        key: The DSA public key (y)

    Returns:
        True if signature validates
    """
    p, q, g = params
    y = key
    r, s = signature
    if r >= q or s >= q:
        print('F**k up')
        return False
    w = c39.invmod(s, q) % q
    H = number.bytes_to_long(sha1(message).digest())
    u1 = (H * w) % q
    u2 = (r * w) % q
    v = ((pow(g, u1, p) * pow(y, u2, p)) % p) % q
    return v == r
Example #5
0
  def x_recovery(self, m, r, s, k, dgst=hashlib.sha1):
    # recovering x knowing k
    # m - message
    # r,s - public signature
    # k - this should be secret (nounce)

    top = (s*k)-s2i(dgst(m).digest())
    return (top * invmod(r, self.q)) % self.q
Example #6
0
 def sign(self, msg, x=None):
     x = x if x else self.x
     r = 0
     while r == 0:
         k = random.randint(1, self.q - 1)
         r = pow(self.g, k, self.p) % self.q
     s = invmod(k, self.q) * (self.H(msg) + x * r) % self.q
     return r, s
Example #7
0
def verifySignatureHash(H, signature, pub):
    (r, s) = signature
    (p, q, g, y) = pub
    if r <= 0 or r >= q or s <= 0 or s >= q:
        return False
    w = c39.invmod(s, q)
    u1 = (H * w) % q
    u2 = (r * w) % q
    v = ((pow(g, u1, p) * pow(y, u2, p)) % p) % q
    return v == r
Example #8
0
 def verify(self, msg, sig, y=None):
     y = y if y else self.y
     r, s = sig
     assert r in range(1, self.q) and s in range(
         1, self.q), "Invalid signature"
     w = invmod(s, self.q)
     u1 = self.H(msg) * w % self.q
     u2 = r * w % self.q
     v = pow(self.g, u1, self.p) * pow(y, u2, self.p) % self.p % self.q
     return v == r
Example #9
0
 def verify(self, m, r, s, y, dgst=hashlib.sha1):
   # signature verification
   # https://en.wikipedia.org/wiki/Digital_Signature_Algorithm#Verifying
   assert (r > 0 and r < self.q), "wrong r: 0 < r < q"
   assert (s > 0 and s < self.q), "wrong s: 0 < s < q"
   w = invmod(s, self.q)
   u1 = (s2i(dgst(m).digest())*w) % self.q
   u2 = (r*w) % self.q
   v = ((modexp(self.g, u1, self.p)*modexp(y, u2, self.p)) % self.p )% self.q
   assert (v == r), "verification failed, v != r"
   return True
Example #10
0
def signHashWithK(H, pub, priv, k):
    (p, q, g, y) = pub
    x = priv
    r = pow(g, k, p) % q
    if r == 0:
        return None
    kInv = c39.invmod(k, q)
    s = (kInv * (H + x * r)) % q
    if s == 0:
        return None
    return (r, s)
Example #11
0
  def signk(self, m, x, dgst=hashlib.sha1):
    # signing with a leak of the k value
    # m - message
    # x - private key
    # https://en.wikipedia.org/wiki/Digital_Signature_Algorithm#Signing
    r = 0
    k = 0
    while r == 0:
      k = randint(0, self.q)
      r = modexp(self.g, k, self.p) % self.q
    s = (invmod(k, self.q) * (s2i(dgst(m).digest())+(x*r))) % self.q

    return (r, s, k)
Example #12
0
def checkForCommonK(pub, msg1, msg2):
    (p, q, g, y) = pub
    (_, s1, r1, m1) = msg1
    (_, s2, r2, m2) = msg2
    ds = (s1 - s2) % q
    dm = (m1 - m2) % q
    dsInv = c39.invmod(ds, q)
    k = (dm * dsInv) % q
    priv1 = c43.extractKey(m1, r1, s1, k, pub)
    priv2 = c43.extractKey(m2, r2, s2, k, pub)
    if priv1 == priv2 and c43.areValidKeys(pub, priv1) and c43.areValidKeys(
            pub, priv2):
        return (k, priv1)
    return (None, None)
Example #13
0
def get_x_from_k(message, signature, params, k):
    """
    Extracts the private key from the k value.

    Args:
        message: The message
        signature: The signature pair (r,s)
        params: DSA domain params (p,q,g)
        k: The k value used for the signature
    """
    r, s = signature
    p, q, g = params
    sk = (s * k)
    h = number.bytes_to_long(sha1(message).digest())
    x = ((sk - h) * c39.invmod(r, q)) % q
    return x
Example #14
0
def attack_server(server, msg):
    """
    Attacks the RSA server using the attack described in the problem.

    Args:
        server: The server to attack
        msg: The message to use to attack the server

    Returns:
        The decrypted plaintext (even though it aleady has it)
    """
    ctxt, (E, N) = server.encrypt_msg(msg)
    ptxt = server.decrypt_msg(ctxt)
    assert (ptxt == msg)
    S = random.randint(2, N - 1)
    c_prime = (pow(S, E, N) * number.bytes_to_long(ctxt)) % N
    p_prime = server.decrypt_msg(number.long_to_bytes(c_prime))
    p = (number.bytes_to_long(p_prime) * c39.invmod(S, N)) % N
    return number.long_to_bytes(p)
Example #15
0
 def k_dup(self, m1, s1, m2, s2):
   return ((m1-m2) * invmod((s1-s2) % self.q, self.q)) % self.q
Example #16
0
def priv_from_k(hashint, sig, k, q=dsa.q):
    r, s = sig
    return invmod(r, q) * (s * k - hashint) % q
Example #17
0
def priv_from_sig_pair(m1, sig1, m2, sig2, q=dsa.q):
    r1, s1, r2, s2 = sig1 + sig2
    k = invmod((s1 - s2) % q, q) * ((m1 - m2) % q) % q
    x = priv_from_k(m1, sig1, k, q)
    # Return x=None if sigs were not generated with same k
    return k, x if x == priv_from_k(m2, sig2, k, q) else None
Example #18
0
  ct1 = RSA().encrypt(cleartext,pub1)

  print "2. key generation"
  pub2,priv2 = RSA().keygen(l=2048,s=False) # s=False gives e=3
  print "2. encrypting using pub key"
  ct2 = RSA().encrypt(cleartext,pub2)

  assert RSA().decrypt(ct0,priv0) == cleartext, "error on key0"
  assert RSA().decrypt(ct1,priv1) == cleartext, "error on key1"
  assert RSA().decrypt(ct2,priv2) == cleartext, "error on key2"

  # https://en.wikipedia.org/wiki/Coppersmith%27s_Attack#H.C3.A5stad.27s_Broadcast_Attack
  # https://en.wikipedia.org/wiki/Chinese_remainder_theorem

  c_0 = s2i(ct0[0])
  c_1 = s2i(ct1[0])
  c_2 = s2i(ct2[0])
  n_0 = pub0[1]
  n_1 = pub1[1]
  n_2 = pub2[1]
  m_s_0 = n_1 * n_2
  m_s_1 = n_0 * n_2
  m_s_2 = n_0 * n_1

  result  = (c_0 * m_s_0 * invmod(m_s_0, n_0))
  result += (c_1 * m_s_1 * invmod(m_s_1, n_1))
  result += (c_2 * m_s_2 * invmod(m_s_2, n_2))
  result %= (n_0 * n_1 * n_2)

  print i2s(int(pow(Decimal(result),Decimal(1)/Decimal(3)))+1)
Example #19
0
def decrypt_unpadded(ct, oracle):
    e, n = oracle.publickey()
    ct_new = (pow(2, e, n) * ct) % n  # s = 2
    pt_new = oracle.decrypt(ct_new)
    pt = pt_new * invmod(2, n) % n
    return int2bytes(pt)
Example #20
0
 def magic_sign(self, y, z = 20):
   # only if g == p+1
   assert (self.g == self.p+1), "only if g == p+1"
   r = modexp(y, z, self.p) % self.q
   s = r * invmod(z, self.q)
   return (r, s)
Example #21
0
def forge_signature(msg, params, y):
    p, q, g = params
    z = number.bytes_to_long(msg)
    r = pow(y, z, p) % q
    s = (r * c39.invmod(z, q)) % q
    return r, s
Example #22
0
def extractKey(H, r, s, k, pub):
    (p, q, g, y) = pub
    rInv = c39.invmod(r, q)
    return (rInv * (s * k - H)) % q