Esempio n. 1
0
def p40() -> str:
    msg = b'Assume you\'re a Javascript programmer. That is, you\'re using a naive handrolled ' \
          b'RSA to encrypt without padding.'
    print(f'Encrypting secret message "{msg.decode()}"')
    msg = int(hexlify(msg), 16)

    pairs = []
    for _ in range(3):
        rsa = RSA()
        c = rsa.enc(msg)
        pairs.append((c, rsa.N))
        print(
            f'Generated ciphertext = {str(c)[:15]}... for N = {str(rsa.N)[:15]}...'
        )

    c0, c1, c2 = [c for (c, _) in pairs]
    n0, n1, n2 = [N for (c, N) in pairs]
    m0, m1, m2 = n1 * n2, n0 * n2, n0 * n1

    t0 = (c0 * m0 * invmod(m0, n0))
    t1 = (c1 * m1 * invmod(m1, n1))
    t2 = (c2 * m2 * invmod(m2, n2))
    c = (t0 + t1 + t2) % (n0 * n1 * n2)

    m = kth_root(c, 3)
    m = unhexlify(hex(m)[2:])

    return f'Recovered message "{m.decode()}"'
Esempio n. 2
0
def p46() -> str:
    rsa = RSA()
    m = b64decode(
        'VGhhdCdzIHdoeSBJIGZvdW5kIHlvdSBkb24ndCBwbGF5IGFyb3VuZCB3aXRoIHRoZSBG'
        'dW5reSBDb2xkIE1lZGluYQ==')

    m = int(hexlify(m), 16)
    c = rsa.enc(m)
    bounds = [(0, 1), (1, 1)]

    for _ in range(rsa.N.bit_length()):
        nm = bounds[0][0] * bounds[1][1] + bounds[1][0] * bounds[0][1]
        dm = bounds[0][1] * bounds[1][1] * 2
        gcd = gcd_func(nm, dm)
        nm, dm = nm // gcd, dm // gcd

        c = (pow(2, rsa.e, rsa.N) * c) % rsa.N

        if rsa.dec(c) % 2 == 0:
            bounds[1] = (nm, dm)
        else:
            bounds[0] = (nm, dm)

    recovered = bounds[1][0] * rsa.N // bounds[1][1]
    return f'Recovered message "{unhexlify(hex(recovered)[2:]).decode()}"'
Esempio n. 3
0
def padding_oracle(ctxt: int, rsa: RSA) -> bool:
    ptxt = rsa.dec(ctxt)
    try:
        unpad_pkcs15(int.to_bytes(ptxt, rsa.bitsize // 8, byteorder='big'))
        return True
    except ValueError:
        return False
Esempio n. 4
0
def bb98(rsa: RSA) -> bytes:
    m = pad_pkcs15(b'kick it, CC', rsa.bitsize // 8)
    debug_print(f'Padded message is {hexlify(m)}, {len(m)} bytes long')
    m = int(hexlify(m), 16)

    c = rsa.enc(m)
    B = 2 ** (rsa.bitsize - 16)
    M = {(2*B, 3*B - 1)}
    s = 1
    i = 1

    while not _solution_found(M):
        debug_print(f'Starting round with M {M}')

        if i == 1:
            s = step2a(c, B, rsa)
        elif len(M) != 1:
            s = step2b(c, s, rsa)
        else:
            a, b = next(iter(M))
            s = step2c(c, s, a, b, B, rsa)

        debug_print(f'Found s for this round: {s}')

        M = step3(s, M, B, rsa.N)
        i += 1

    a, _ = next(iter(M))

    padded = int.to_bytes(a, length=rsa.bitsize // 8, byteorder='big')
    debug_print(unpad_pkcs15(padded).decode())
    return unpad_pkcs15(padded)
Esempio n. 5
0
def p47():
    rsa = RSA(bitsize=256)
    m = pkcs15('kick it, CC', 256 / 8)
    m = int(hexlify(m), 16)

    c = rsa.enc(m)
    B = 2**(256 - 16)
    M = [2 * B, 3 * B - 1]
    i = 1

    def update_ctxt(s):
        return (c * pow(s, rsa.e, rsa.N)) % rsa.N

    while not M[0] == M[1]:
        a, b = M[0], M[1]

        if i == 1:
            s = ceiling(rsa.N, 3 * B)
            c_ = update_ctxt(s)

            while not pkcs15_padding_oracle(c_, rsa):
                s += 1
                c_ = update_ctxt(s)

        else:
            r = ceiling(2 * (b * s - 2 * B), rsa.N)
            s = ceiling(2 * B + r * rsa.N, b)
            c_ = update_ctxt(s)

            while not pkcs15_padding_oracle(c_, rsa):
                if s >= (3 * B + r * rsa.N) / a:
                    r += 1
                    s = ceiling(2 * B + r * rsa.N, b)

                else:
                    s += 1

                c_ = update_ctxt(s)

        r = ceiling((a * s - 3 * B + 1), rsa.N)
        M[0] = max(a, ceiling(2 * B + r * rsa.N, s))
        M[1] = min(b, (3 * B - 1 + r * rsa.N) / s)
        i += 1

    hex_data = hex(M[0])[2:-1]
    recovered = unhexlify(hex_data.zfill(len(hex_data) + (len(hex_data) % 2)))
    return 'Recovered message "{}"'.format(validate_pkcs15(recovered))
Esempio n. 6
0
def p41() -> str:
    rsa = RSA()
    N, e = rsa.N, rsa.e

    ptxt = dumps({
        'time': 1356304276,
        'social': '867-00-5309',
    })
    ptxt = int(hexlify(ptxt.encode()), 16)
    ctxt = rsa.enc(ptxt)

    s = 2
    ctxt_ = pow(s, e, N) * ctxt % N
    ptxt_ = rsa.dec(ctxt_)

    recovered = invmod(s, N) * ptxt_ % N
    recovered = unhexlify(hex(recovered)[2:]).decode()
    return 'Recovered data {}'.format(loads(recovered))
Esempio n. 7
0
def p41():
    rsa = RSA()
    N, e = rsa.N, rsa.e

    ptxt = dumps({
        'time': 1356304276,
        'social': '555-55-5555',
    })
    ptxt = int(hexlify(ptxt), 16)
    ctxt = rsa.enc(ptxt)

    s = 2
    ctxt_ = pow(s, e, N) * ctxt % N
    ptxt_ = rsa.dec(ctxt_)

    recovered = invmod(s, N) * ptxt_ % N
    recovered = unhexlify(hex(recovered)[2:-1])
    return 'Recovered data {}'.format(loads(recovered))
Esempio n. 8
0
def p42():
    modsize = 1024
    rsa = RSA(modsize)
    m = b'hi mom'
    h = sha1(m).digest()

    mystr = b'\x00\x01\xff\x00'
    mystr += h
    mystr += ((modsize // 8) - len(mystr)) * b'\x00'

    forged = kth_root(int(hexlify(mystr), 16), rsa.e, rounded=True) + 1
    verified = _verify_sig(m, forged, rsa)

    assert verified
    return f'Message - {m.decode()}\nSignature - {forged}'
Esempio n. 9
0
def p48():
    rsa = RSA(bitsize=768)
    m = pkcs15('kick it, CC', 768 / 8)
    m = int(hexlify(m), 16)

    c = rsa.enc(m)
    B = 2**(768 - 16)
    M = [(2 * B, 3 * B-1)]
    i = 1

    def update_ctxt(s):
        return (c * pow(s, rsa.e, rsa.N)) % rsa.N

    while not (len(M) == 1 and M[0][0] == M[0][1]):
        if i == 1:
            s = ceiling(rsa.N, 3 * B)
            c_ = update_ctxt(s)

            while not pkcs15_padding_oracle(c_, rsa):
                s += 1
                c_ = update_ctxt(s)

        elif len(M) >= 2:
            s += 1
            c_ = update_ctxt(s)

            while not pkcs15_padding_oracle(c_, rsa):
                s += 1
                c_ = update_ctxt(s)

        else:
            a, b = M[0][0], M[0][1]
            r = ceiling(2 * (b*s - 2*B), rsa.N)
            s = ceiling(2*B + r*rsa.N, b)
            c_ = update_ctxt(s)

            while not pkcs15_padding_oracle(c_, rsa):
                if s >= (3*B + r*rsa.N) / a:
                    r += 1
                    s = ceiling(2*B + r*rsa.N, b)

                else:
                    s += 1

                c_ = update_ctxt(s)

        newM = []
        for (a, b) in M:
            rlow = ceiling((a * s - 3 * B + 1), rsa.N)
            rhigh = (b * s - 2 * B) / rsa.N

            for r in range(rlow, rhigh + 1):
                newa = max(a, ceiling(2 * B + r * rsa.N, s))
                newb = min(b, (3 * B - 1 + r * rsa.N) / s)
                newM.append((newa, newb))

        M = list(set(newM))
        i += 1

    hex_data = hex(M[0][0])[2:-1]
    recovered = unhexlify(hex_data.zfill(len(hex_data) + (len(hex_data) % 2)))
    return 'Recovered message "{}"'.format(validate_pkcs15(recovered))
Esempio n. 10
0
def p48() -> str:
    mod_size = 768
    rsa = RSA(bitsize=mod_size)
    return bb98(rsa).decode()
Esempio n. 11
0
    # Obtain the N from the public keys of the RSA objects.
    n0 = rsa0.pub[1]
    n1 = rsa1.pub[1]
    n2 = rsa2.pub[1]

    # Encrypt the integer of the message via all three RSA objects.
    plainnum = int.from_bytes(message, "big")
    c0 = rsa0.encryptnum(plainnum)
    c1 = rsa1.encryptnum(plainnum)
    c2 = rsa2.encryptnum(plainnum)

    # Can't do N/n0 for ms0 instead because floating point operations arent accurate
    N = n0 * n1 * n2
    ms0 = n1 * n2
    ms1 = n0 * n2
    ms2 = n0 * n1

    r0 = (c0 * ms0 * mod_inverse(ms0, n0))
    r1 = (c1 * ms1 * mod_inverse(ms1, n1))
    r2 = (c2 * ms2 * mod_inverse(ms2, n2))

    R = (r0 + r1 + r2) % N
    m = floorRoot(R, 3)

    return m.to_bytes((m.bit_length() + 7) // 8, "big")


message = "This is RSA Broadcast Attack"
RSA_Broadcast_Attack(message.encode(), RSA(256), RSA(256),
                     RSA(256)).decode("utf-8")
Esempio n. 12
0
# Imports
import math
import base64
import decimal
from p39 import RSA
# Given
given_string = "VGhhdCdzIHdoeSBJIGZvdW5kIHlvdSBkb24ndCBwbGF5IGFyb3VuZCB3aXRoIHRoZSBGdW5reSBDb2xkIE1lZGluYQ=="

def check_parity(ciphertext, rsa):
    return rsa.decryptnum(ciphertext)& 1

rsa = RSA(1024)
ciphertext = rsa.encrypt(b"Hello")
print(check_parity(ciphertext, rsa))
# 1

def parity_attack(message, rsa):
    (_, n) = rsa.pub
    ciphertext = rsa.encryptnum(int.from_bytes(message, "big"))

    multiplier = rsa.encryptnum(2)

    lower_bound = decimal.Decimal(0)
    upper_bound = decimal.Decimal(n)

    num_iter = int(math.ceil(math.log(n, 2)))
    decimal.getcontext().prec = num_iter

    for _ in range(num_iter):
        ciphertext = (ciphertext * multiplier) % n
        if check_parity(ciphertext, rsa)& 1:
Esempio n. 13
0
def p47() -> str:
    mod_size = 256
    rsa = RSA(bitsize=mod_size)
    return bb98(rsa).decode()