def __init__(self, ciphertext, e, modulus, padding_oracle):
        """
        Cracks an rsa ciphertext using a padding oracle. Correct padding is when
        decrypted message is unpacked into byte lenght of modulus bytes, the first
        byte is 0 and second is 2. See Bleichenbacher's 98 paper for details on
        the attack.
        
        Args:
            cipehertext (int): encrypted plaintext for decryption. Assumes the
                original plaintext was correctly padded.
            e (int): public exponent used in rsa
            moduls (int): Modulus used by rsa encryption
            padding_oracle (function): fucntion which decrypts the ciphertext and
                returns true if the padding is correct, false otherwise
        
        returns:
            int: decrypted ciphertext
        """

        self.c = ciphertext
        self.e = e
        self.mod = modulus
        self.oracle = padding_oracle
        self.B = 2**(8 * (bso.byte_len(modulus) - 2))
        self.M = [(2 * self.B, 3 * self.B - 1)]
        self.i = 1
        self.s = ceil_division(self.mod, 3 * self.B) - 1
        assert self.oracle(ciphertext)
示例#2
0
 def check_padding_from_bytes(self, plaintext):
     #Checks bytes of plaintext to determine if padding is valid
     if (plaintext[:2] != b'\x00\x02'
         or len(plaintext) != bso.byte_len(self.n)):
         return False
     else:
         return True
示例#3
0
    def pad(self, plaintext):
        desired_length = bso.byte_len(self.n)
        if len(plaintext) > desired_length - 11:
            raise Exception('Message too long')
 
        plaintext = bytes([0]) + plaintext
        plaintext = secrets.token_bytes(desired_length - len(plaintext) - 2) + plaintext
        plaintext = bytes([0]) + bytes([2]) + plaintext
    
        return plaintext
示例#4
0
    def decrypt_to_bytes_and_check_padding(self, ciphertext):

        #Decrypt a la RSA
        plaintext = nt.modexp(ciphertext, self.d, self.n)

        plaintext = plaintext.to_bytes(bso.byte_len(self.n), 'big')

        #Check the padding before returning the decryption
        if self.check_padding_from_bytes(plaintext):
            return plaintext
        else:
            raise Exception('Invalid padding')
示例#5
0
def main():
    server = RSAPaddingOracle(prime_size = 128)
    client = ChallengeRSAClient()

    e, mod = server.send_public_key()
    client.recv_public_key(e, mod)
    message = b'kick it, CC'    

    ciphertext = client.pad_and_encrypt(message)
    assert server.decrypt_to_bytes_and_check_padding(ciphertext)[-len(message):] == message

    #For debugging
    plaintext = server.decrypt(ciphertext)

    attacker = rsa_attacks.Bleichenbacher(ciphertext, e, mod, server.check_padding_from_ciphertext)
    plaintext = attacker.run()
    assert plaintext.to_bytes(bso.byte_len(mod), 'big') == server.decrypt_to_bytes_and_check_padding(ciphertext)
示例#6
0
 def check_padding_from_ciphertext(self, ciphertext):
     
     #Check padding by looking at numerical range of the decrypted ciphertext
     B = 2**(8*(bso.byte_len(self.n) - 2))
     return 2*B <= self.decrypt(ciphertext) <= 3*B - 1