Esempio n. 1
0
def challenge_46():
    print()
    # Get message, create RSA keypair, generate ciphertext
    message = base64.b64decode('VGhhdCdzIHdoeSBJIGZvdW5kIHlvdSBkb24ndCBwbGF5IGFyb3VuZCB3aXRoIHRoZSBGdW5reSBDb2xkIE1lZGluYQ==')
    pub, priv = set5.set_up_rsa(e=3, keysize=1024)
    ciphertext = set5.encrypt_rsa(set5.bytes_to_int(message), pub)
    # Set up our Oracle
    oracle = lambda x: rsa_oracle_plaintext_even(x, priv)
    # Verify the keypair works
    assert set5.int_to_bytes(set5.encrypt_rsa(ciphertext, priv)) == message
    # Set initial lower and upper bound, as well as intermediate ciphertext
    lower_bound, upper_bound = 0, pub[1]
    ciphertext_ = ciphertext

    # Perform the below until the lower and upper bound converge
    while upper_bound != lower_bound:
        # Multiply plaintext by multiplying ciphertext by 2**`e` mod `N`
        ciphertext_ = (ciphertext_ * set5.modexp(2, pub[0], pub[1])) % pub[1]
        # If the oracle says True, update the upper bound; if False, update the lower bound
        if oracle(ciphertext_):
            upper_bound = floor(upper_bound + lower_bound, 2)
        else:
            lower_bound = floor(upper_bound + lower_bound, 2)
        # Create 'Holywood style' output
        intermediate_result = str(set5.int_to_bytes(upper_bound))[:os.get_terminal_size().columns - 1]
        fill = " " * (os.get_terminal_size().columns - 1 - len(intermediate_result))
        print(colorama.Cursor.UP(1) + intermediate_result + fill)

    # Print final outputs
    print(colorama.Cursor.UP(1) + "Result:   {}".format(set5.int_to_bytes(upper_bound)))
    print("Original: {}".format(message))
Esempio n. 2
0
 def query(self, msg):
     # Generate hash of given message
     msg_hash = set4.hmac_sha1(b'', bytes(msg)).hexdigest()
     # If hash was seen before, ignore request
     if msg_hash in self.seen_hashes: return None
     # Add hash to list of seen hashes
     self.seen_hashes.append(msg_hash)
     # Return decrypted message
     return set5.encrypt_rsa(msg, self.__private__)
Esempio n. 3
0
 def verify(self, msg, signature):
     print('Message to verify: {}'.format(msg))
     decrypted_sig = set5.int_to_bytes(int(set5.encrypt_rsa(signature, self.public)))
     match = re.search(b'\x01\xff*\x00(.{20})', decrypted_sig, re.DOTALL)
     if match is None:
         raise ValueError("Invalid padding.")
     expected_digest = hashlib.sha1(msg).digest()
     print('Digest expected: {}'.format(expected_digest))
     obtained_digest = match.group(1)
     print('Digest obtained: {}'.format(obtained_digest))
     return expected_digest == obtained_digest
Esempio n. 4
0
def challenge_48():
    # Set up new RSA instance, this time with bigger key length
    pub, priv = set5.set_up_rsa(e=3, keysize=768)
    # Prepare message
    message = pad_PKCS(b'I don\'t know, Marge. Trying is the first step towards failure - Homer Simpson', k=(pub[1].bit_length() + 7) // 8)
    # Get ciphertext using generated RSA instance
    ciphertext = set5.encrypt_rsa(set5.bytes_to_int(message), pub)
    # Set up our Oracle
    oracle = lambda x: rsa_oracle_02(x, priv)
    assert oracle(ciphertext)

    # Perform the actual attack: set up bleichenbacher98 instance
    bb98 = bleichenbacher98(ciphertext, pub, oracle)
    # Run the attack
    found_message = bb98.solve()
    print("Found message:", found_message)

    # Verify the found message equals our original plaintext
    assert_true(found_message == message)
Esempio n. 5
0
def challenge_47():
    # Set up new RSA instance
    pub, priv = set5.set_up_rsa(e=3, keysize=256)
    # Prepare message
    message = pad_PKCS(b'kick it, CC', k=(pub[1].bit_length() + 7) // 8)
    # Get ciphertext using generated RSA instance
    ciphertext = set5.encrypt_rsa(set5.bytes_to_int(message), pub)
    # Set up our Oracle
    oracle = lambda x: rsa_oracle_02(x, priv)
    assert oracle(ciphertext)

    # Perform the actual attack: set up bleichenbacher98 instance
    bb98 = bleichenbacher98(ciphertext, pub, oracle)
    # Run the attack
    found_message = bb98.solve()
    print("Found message:", found_message)

    # Verify the found message equals our original plaintext
    assert_true(found_message == message)
Esempio n. 6
0
def challenge_41():
    # Initate a new RSA Oracle
    oracle = RsaOracle()
    # Generate a secret
    secret = random.randrange(2, oracle.public[1] // 2)
    # Generate a message to send to the RSA oracle
    msg = set5.encrypt_rsa(secret, oracle.public)

    # Query 1: try the generated encrypted secret
    r = oracle.query(msg)
    # Expected output: the original secret
    assert r == secret
    # Query 2: try the generated encrypted secret again
    r = oracle.query(msg)
    # Expected output: a None
    assert r is None

    e, n = oracle.public
    s = 2
    # Query 3: the attack - try our manipulated value
    msgp = (set5.modexp(s, e, n) * msg) % n
    # Expected output: the original secret
    r = (oracle.query(msgp) // s) % n
    assert_true(r == secret)
Esempio n. 7
0
 def sign(self, msg):
     digest = hashlib.sha1(msg).digest()
     sgn = set5.bytes_to_int(b'\x00\x01' + (b'\xff' * (128 - len(digest) - 3)) + b'\x00' + digest)
     if sgn > self.public[1]:
         raise ValueError("Message to big for public key")
     return set5.encrypt_rsa(sgn, self.__private__)
Esempio n. 8
0
def rsa_oracle_02(ciphertext, priv):
    plaintext = set5.int_to_bytes(set5.encrypt_rsa(ciphertext, priv)).rjust((priv[1].bit_length() + 7) // 8, b'\x00')
    return plaintext[0:2] == b'\x00\x02'
Esempio n. 9
0
def rsa_oracle_plaintext_even(ciphertext, priv):
    return set5.encrypt_rsa(ciphertext, priv) % 2 == 0