Esempio n. 1
0
 def print_texts(self):
     print("key {} texts:".format(self.identifier))
     for pair in self.texts:
         if 'cipher' in pair:
             print("Ciphertext: {}".format(hex(pair['cipher'])), end=", ")
         else:
             print("Ciphertext: null", end=", ")
         if 'plain' in pair:
             print("Plaintext: {} (\"{}\")".format(
                 hex(pair['plain']), i2b(pair['plain'], size=self.size)))
         else:
             print("Plaintext: null")
Esempio n. 2
0
def verify_bleichenbacher_middle(message, signature, key, hash_function='sha1'):
    """00 01 garbage 00 ANS1 HASH"""
    hash_msg = getattr(hashlib, hash_function)(message).digest()
    asn1 = hash_asn1[hash_function]
    signature = b2i(signature)

    plain = i2b(key.encrypt(signature), size=1024)
    try:
        plain_hash = plain[plain.index(bytes(b'\x00'), 2) + 1:]  # have ASN1 HASH
    except:
        return False
    if plain[:2] == bytes(b'\x00\x01') and plain_hash == asn1 + hash_msg:
        return True
    return False
Esempio n. 3
0
def md5(data, initial_state=None, padding=None):
    """Compute MD5

    Args:
        data(string)
        initial_state(list of ints)
        padding(string/None): if None, padding will be computed

    Returns:
        digest(string)
    """
    if initial_state is None:
        initial_state = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476]

    if not padding:
        data = add_md_padding(data, endian='little')
    else:
        data += padding
    final_state = merkle_damgard(data, initial_state, compression_function_md5)
    return bytes(b''.join(
        [i2b(x, size=32, endian='little') for x in final_state]))
Esempio n. 4
0
def sha1(data, initial_state=None, padding=None):
    """Compute SHA1

    Args:
        data(string)
        initial_state(list of ints)
        padding(string/None): if None, padding will be computed

    Returns:
        digest(string)
    """
    if initial_state is None:
        initial_state = [
            0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0
        ]

    if not padding:
        data = add_md_padding(data, endian='big')
    else:
        data += padding
    final_state = merkle_damgard(data, initial_state,
                                 compression_function_sha1)
    return bytes(b''.join([i2b(x, size=32) for x in final_state]))
Esempio n. 5
0
def bleichenbacher_signature_forgery(key,
                                     garbage='suffix',
                                     hash_function='sha1'):
    """Bleichenbacher's signature forgery based on bug in verify implementation

    Args:
        key(RSAKey): with small e and at least one plaintext
        garbage(string): middle: 00 01 ff garbage 00 ASN.1 HASH
                         suffix: 00 01 ff 00 ASN.1 HASH garbage
        hash_function(string)

    Returns:
        dict: forged signatures, signatures[no] == signature(key.texts[no]['plain'])
        update key texts
    """
    hash_asn1 = {
        'md5':
        bytes(
            b'\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00\x04\x10'
        ),
        'sha1':
        bytes(b'\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14'),
        'sha256':
        bytes(
            b'\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20'
        ),
        'sha384':
        bytes(
            b'\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04\x30'
        ),
        'sha512':
        bytes(
            b'\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40'
        )
    }
    if garbage not in ['suffix', 'middle']:
        log.critical_error("Bad garbage position, must be suffix or middle")
    if hash_function not in list(hash_asn1.keys()):
        log.critical_error(
            "Hash function {} not implemented".format(hash_function))

    if key.e > 3:
        log.debug("May not work, because e > 3")

    signatures = {}
    if garbage == 'suffix':
        for text_no in range(len(key.texts)):
            if 'plain' in key.texts[text_no] and 'cipher' not in key.texts[
                    text_no]:
                log.info("Forge for plaintext no {} ({})".format(
                    text_no, key.texts[text_no]['plain']))

                hash_callable = getattr(hashlib, hash_function)(i2b(
                    key.texts[text_no]
                    ['plain'])).digest()  # hack to call hashlib.hash_function
                plaintext_prefix = bytes(b'\x00\x01\xff\x00') + hash_asn1[
                    hash_function] + hash_callable

                plaintext = plaintext_prefix + bytes(
                    b'\x00' * (key.size // 8 - len(plaintext_prefix)))
                plaintext = b2i(plaintext)
                for round_error in range(-5, 5):
                    signature, _ = gmpy2.iroot(plaintext, key.e)
                    signature = int(signature + round_error)
                    test_prefix = i2b(gmpy2.powmod(signature, key.e, key.n),
                                      size=key.size)[:len(plaintext_prefix)]
                    if test_prefix == plaintext_prefix:
                        log.info("Got signature: {}".format(signature))
                        log.debug("signature**e % n == {}".format(
                            i2h(gmpy2.powmod(signature, key.e, key.n),
                                size=key.size)))
                        key.texts[text_no]['cipher'] = signature
                        signatures[text_no] = signature
                        break
                else:
                    log.error(
                        "Something wrong, can't compute correct signature")
        return signatures

    elif garbage == 'middle':
        for text_no in range(len(key.texts)):
            if 'plain' in key.texts[text_no] and 'cipher' not in key.texts[
                    text_no]:
                log.info("Forge for plaintext no {} ({})".format(
                    text_no, key.texts[text_no]['plain']))
                hash_callable = getattr(hashlib, hash_function)(i2b(
                    key.texts[text_no]
                    ['plain'])).digest()  # hack to call hashlib.hash_function
                plaintext_suffix = bytes(
                    b'\x00') + hash_asn1[hash_function] + hash_callable
                if b2i(plaintext_suffix) & 1 != 1:
                    log.error(
                        "Plaintext suffix is even, can't compute signature")
                    continue

                # compute suffix
                signature_suffix = 0b1
                for b in range(len(plaintext_suffix) * 8):
                    if (signature_suffix**
                            3) & (1 << b) != b2i(plaintext_suffix) & (1 << b):
                        signature_suffix |= 1 << b
                signature_suffix = i2b(
                    signature_suffix)[-len(plaintext_suffix):]

                # compute prefix
                while True:
                    plaintext_prefix = bytes(b'\x00\x01\xff') + random_bytes(
                        key.size // 8 - 3)
                    signature_prefix, _ = gmpy2.iroot(b2i(plaintext_prefix),
                                                      key.e)
                    signature_prefix = i2b(
                        int(signature_prefix),
                        size=key.size)[:-len(signature_suffix)]

                    signature = b2i(signature_prefix + signature_suffix)
                    test_plaintext = i2b(gmpy2.powmod(signature, key.e, key.n),
                                         size=key.size)
                    if bytes(b'\x00'
                             ) not in test_plaintext[2:-len(plaintext_suffix)]:
                        if test_plaintext[:3] == plaintext_prefix[:3] and test_plaintext[
                                -len(plaintext_suffix):] == plaintext_suffix:
                            log.info("Got signature: {}".format(signature))
                            key.texts[text_no]['cipher'] = signature
                            signatures[text_no] = signature
                            break
                        else:
                            log.error("Something wrong, signature={},"
                                      " signature**{}%{} is {}".format(
                                          signature, key.e, key.n,
                                          [(test_plaintext)]))
                            break
        return signatures
Esempio n. 6
0
def sign(message, key):
    # message = add_rsa_signature_padding(message, size=key.size, hash_function='sha1')
    message = b2i(message)
    signature = pow(message, key.d, key.n)
    return i2b(signature)
Esempio n. 7
0
def decrypt(ciphertext, key):
    ciphertext = b2i(ciphertext)
    plaintext = pow(ciphertext, key.d, key.n)
    return i2b(plaintext)
Esempio n. 8
0
def encrypt(plaintext, key):
    plaintext = b2i(plaintext)
    ciphertext = pow(plaintext, key.e, key.n)
    return i2b(ciphertext)
Esempio n. 9
0
#!/usr/bin/env python

from CryptoAttacks.PublicKey import rsa
from CryptoAttacks.Utils import i2b
from gmpy2 import iroot

with open('../flag_enc.txt', 'rb') as f:
    flag = f.read()
    flag = int.from_bytes(flag, 'big')

key = rsa.RSAKey.import_key('../key.pem')

f = flag
for i in range(0, 300):
    x = iroot(f, key.e)
    if x[1]:
        print(i, i2b(int(x[0])))
        break
    f += key.n