def secret_key_from_nonce(self, message, nonce, r, s):
     """
     Given a signature, nonce and message, calculates the secret key"""
     numerator = (s*nonce - int(self.hash(message).hexdigest(), 16)) % self.q
     
     r_inv = nt.invmod(r, self.q)
     
     return (numerator * r_inv) % self.q
    def step4(self):

        if len(self.M) == 1:

            if self.M[0][0] == self.M[0][1]:

                return (self.M[0][0] * nt.invmod(1, self.mod)) % self.mod

        self.i += 1
        return 0
    def nonce_from_double_signing(self, message1, s1, message2, s2):
        """Computes the nonce from two message signed with the same nonce"""

        msg_hash1 = int(self.hash(message1).hexdigest(), 16) 
        msg_hash2 = int(self.hash(message2).hexdigest(), 16)

        numerator = (msg_hash1 - msg_hash2) % self.q

        denominator = nt.invmod((s1 - s2) % self.q, self.q)

        return (numerator * denominator) % self.q 
Beispiel #4
0
    def verify(self, message, public_key, r, s):

        s_inv = nt.invmod(s, self.q)

        msg_hash = int(self.hash(message).hexdigest(), 16)
        exp1 = msg_hash * s_inv % self.q

        exp2 = r * s_inv % self.q

        v = ((nt.modexp(self.g, exp1, self.p) *
              nt.modexp(public_key, exp2, self.p)) % self.p) % self.q

        return v == r
Beispiel #5
0
    def sign_message(self, message):

        r = s = 0

        k = secrets.randbelow(self.q)

        r = nt.modexp(self.g, k, self.p) % self.q

        k_inv = nt.invmod(k, self.q)

        msg_hash = int(self.hash(message).hexdigest(), 16)
        s = (k_inv * (msg_hash + self.secret_key * r)) % self.q

        return self.public_key, r, s
Beispiel #6
0
    def __init__(self, e=3, prime_size=1024):

        p = number.getPrime(prime_size)
        q = number.getPrime(prime_size)

        #gcd(e, (p-1)*(q-1)) needs to be 1 for the algorithm to work

        while nt.gcd(e, p - 1) > 1:
            p = number.getPrime(prime_size)
        while nt.gcd(e, q - 1) > 1:
            q = number.getPrime(prime_size)

        self.e = e
        self.n = p * q
        totient = (p - 1) * (q - 1)
        self.d = nt.invmod(e, totient)
Beispiel #7
0
def main():

    oracle = RSAOracle()

    client = rsa.RSAClient()
    client.recv_public_key(*oracle.send_public_key())

    message = b'A secret message'

    #Client encrypts the message
    message_int = int(bso.bytes_to_hex(message), 16)
    ciphertext = client.encrypt(message_int)

    #Client sends ciphertext which gets decrypted

    assert message == bso.hex_to_bytes(hex(oracle.decrypt(ciphertext))[2:])

    #Attacker intercepts the ciphertext and tries to get the plaintext from
    #the oracle. This fails because the oracle only decrypts each plaintext once

    try:
        successfully_decrypted = message == bso.hex_to_bytes(
            hex(oracle.decrypt(ciphertext))[2:])
    except:
        successfully_decrypted = False

    assert successfully_decrypted == False

    #instead the attacker can get the decryption of an alternate ciphertext and
    # convert it to the original message. This attack uses the fat that exponentiation
    # is a homomorphism

    e, n = oracle.send_public_key()

    #S can be any value

    S = 2

    altered_ciphertext = nt.modexp(S, e, n) * ciphertext % n

    altered_message = oracle.decrypt(altered_ciphertext)

    #altered message = S * message

    new_message = altered_message * nt.invmod(S, n) % n
    assert message == bso.hex_to_bytes(hex(new_message)[2:])
Beispiel #8
0
def main():

    server = ChallengeDSAUser(SHA1)
    client = ChallengeDSAUser(SHA1)

    #malicious g parameter
    server.g = client.g = 0
    server.key_generation()
    client.key_generation()

    message = b'henlo'
    signature = server.sign_message(message)

    assert client.verify(message, *signature)
    assert signature[0] == 0
    assert signature[1] == 0

    #since g = 0, any signature will have r = 0 and secret key = 0
    #  but worse still, any signature with r = 0 will verify any message

    new_message = secrets.token_bytes(21)

    assert client.verify(new_message, *signature)

    #new malicious g value
    server.g = client.g = server.p + 1
    server.key_generation()
    client.key_generation()

    signature = server.sign_message(message)
    assert signature[0] == signature[1] == 1
    assert client.verify(message, *signature)

    #we can construct a magic signature for a given public key and any message
    #choose a random public key

    public_key = secrets.randbelow(server.p)

    z = 3  #a magic number (not actually magic in this case, any z will do)

    r = nt.modexp(public_key, z, server.p) % server.q

    s = (r * nt.invmod(z, server.q)) % server.q

    assert client.verify(new_message, public_key, r, s)
    def test_nonce(self, nonce, message, r, s):
        """Tests is a nonce gives the desired signature for a message"""

        message_int = int(self.hash(message).hexdigest(), 16)

        test_r = nt.modexp(self.g, nonce, self.p) % self.q

            #Don't test s if r does not match
            
        if test_r == r:
            secret_key = self.secret_key_from_nonce(message, nonce, r, s)
        
            nonce_inv = nt.invmod(nonce, self.q)

            test_s = (nonce_inv * (message_int + secret_key * r)) % self.q
            
            if test_s == s:
                return secret_key
        
        return 0